]> Git Repo - qemu.git/blame - target-mips/translate.c
target-mips: add TLBINV support
[qemu.git] / target-mips / translate.c
CommitLineData
6af0bf9c
FB
1/*
2 * MIPS32 emulation for qemu: main translation routines.
5fafdf24 3 *
6af0bf9c 4 * Copyright (c) 2004-2005 Jocelyn Mayer
6ea83fed 5 * Copyright (c) 2006 Marius Groeger (FPU operations)
bb8a53ad 6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
3c824109 7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
4133498f 8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
6af0bf9c
FB
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
8167ee88 21 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
6af0bf9c
FB
22 */
23
6af0bf9c 24#include "cpu.h"
76cad711 25#include "disas/disas.h"
57fec1fe 26#include "tcg-op.h"
f08b6170 27#include "exec/cpu_ldst.h"
6af0bf9c 28
2ef6175a
RH
29#include "exec/helper-proto.h"
30#include "exec/helper-gen.h"
0a2672b7 31#include "sysemu/kvm.h"
a7812ae4 32
a7e30d84
LV
33#include "trace-tcg.h"
34
35
fb7729e2 36#define MIPS_DEBUG_DISAS 0
c570fd16 37//#define MIPS_DEBUG_SIGN_EXTENSIONS
6af0bf9c 38
7a387fff
TS
39/* MIPS major opcodes */
40#define MASK_OP_MAJOR(op) (op & (0x3F << 26))
e37e863f
FB
41
42enum {
43 /* indirect opcode tables */
7a387fff
TS
44 OPC_SPECIAL = (0x00 << 26),
45 OPC_REGIMM = (0x01 << 26),
46 OPC_CP0 = (0x10 << 26),
47 OPC_CP1 = (0x11 << 26),
48 OPC_CP2 = (0x12 << 26),
49 OPC_CP3 = (0x13 << 26),
50 OPC_SPECIAL2 = (0x1C << 26),
51 OPC_SPECIAL3 = (0x1F << 26),
e37e863f 52 /* arithmetic with immediate */
7a387fff
TS
53 OPC_ADDI = (0x08 << 26),
54 OPC_ADDIU = (0x09 << 26),
55 OPC_SLTI = (0x0A << 26),
56 OPC_SLTIU = (0x0B << 26),
324d9e32 57 /* logic with immediate */
7a387fff
TS
58 OPC_ANDI = (0x0C << 26),
59 OPC_ORI = (0x0D << 26),
60 OPC_XORI = (0x0E << 26),
61 OPC_LUI = (0x0F << 26),
324d9e32 62 /* arithmetic with immediate */
7a387fff
TS
63 OPC_DADDI = (0x18 << 26),
64 OPC_DADDIU = (0x19 << 26),
e37e863f 65 /* Jump and branches */
7a387fff
TS
66 OPC_J = (0x02 << 26),
67 OPC_JAL = (0x03 << 26),
68 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
69 OPC_BEQL = (0x14 << 26),
70 OPC_BNE = (0x05 << 26),
71 OPC_BNEL = (0x15 << 26),
72 OPC_BLEZ = (0x06 << 26),
73 OPC_BLEZL = (0x16 << 26),
74 OPC_BGTZ = (0x07 << 26),
75 OPC_BGTZL = (0x17 << 26),
b231c103 76 OPC_JALX = (0x1D << 26),
d4ea6acd 77 OPC_DAUI = (0x1D << 26),
e37e863f 78 /* Load and stores */
7a387fff
TS
79 OPC_LDL = (0x1A << 26),
80 OPC_LDR = (0x1B << 26),
81 OPC_LB = (0x20 << 26),
82 OPC_LH = (0x21 << 26),
83 OPC_LWL = (0x22 << 26),
84 OPC_LW = (0x23 << 26),
364d4831 85 OPC_LWPC = OPC_LW | 0x5,
7a387fff
TS
86 OPC_LBU = (0x24 << 26),
87 OPC_LHU = (0x25 << 26),
88 OPC_LWR = (0x26 << 26),
89 OPC_LWU = (0x27 << 26),
90 OPC_SB = (0x28 << 26),
91 OPC_SH = (0x29 << 26),
92 OPC_SWL = (0x2A << 26),
93 OPC_SW = (0x2B << 26),
94 OPC_SDL = (0x2C << 26),
95 OPC_SDR = (0x2D << 26),
96 OPC_SWR = (0x2E << 26),
97 OPC_LL = (0x30 << 26),
98 OPC_LLD = (0x34 << 26),
99 OPC_LD = (0x37 << 26),
364d4831 100 OPC_LDPC = OPC_LD | 0x5,
7a387fff
TS
101 OPC_SC = (0x38 << 26),
102 OPC_SCD = (0x3C << 26),
103 OPC_SD = (0x3F << 26),
e37e863f 104 /* Floating point load/store */
7a387fff
TS
105 OPC_LWC1 = (0x31 << 26),
106 OPC_LWC2 = (0x32 << 26),
107 OPC_LDC1 = (0x35 << 26),
108 OPC_LDC2 = (0x36 << 26),
109 OPC_SWC1 = (0x39 << 26),
110 OPC_SWC2 = (0x3A << 26),
111 OPC_SDC1 = (0x3D << 26),
112 OPC_SDC2 = (0x3E << 26),
31837be3
YK
113 /* Compact Branches */
114 OPC_BLEZALC = (0x06 << 26),
115 OPC_BGEZALC = (0x06 << 26),
116 OPC_BGEUC = (0x06 << 26),
117 OPC_BGTZALC = (0x07 << 26),
118 OPC_BLTZALC = (0x07 << 26),
119 OPC_BLTUC = (0x07 << 26),
120 OPC_BOVC = (0x08 << 26),
121 OPC_BEQZALC = (0x08 << 26),
122 OPC_BEQC = (0x08 << 26),
123 OPC_BLEZC = (0x16 << 26),
124 OPC_BGEZC = (0x16 << 26),
125 OPC_BGEC = (0x16 << 26),
126 OPC_BGTZC = (0x17 << 26),
127 OPC_BLTZC = (0x17 << 26),
128 OPC_BLTC = (0x17 << 26),
129 OPC_BNVC = (0x18 << 26),
130 OPC_BNEZALC = (0x18 << 26),
131 OPC_BNEC = (0x18 << 26),
132 OPC_BC = (0x32 << 26),
133 OPC_BEQZC = (0x36 << 26),
134 OPC_JIC = (0x36 << 26),
135 OPC_BALC = (0x3A << 26),
136 OPC_BNEZC = (0x3E << 26),
137 OPC_JIALC = (0x3E << 26),
7a387fff
TS
138 /* MDMX ASE specific */
139 OPC_MDMX = (0x1E << 26),
e37e863f 140 /* Cache and prefetch */
7a387fff
TS
141 OPC_CACHE = (0x2F << 26),
142 OPC_PREF = (0x33 << 26),
d4ea6acd
LA
143 /* PC-relative address computation / loads */
144 OPC_PCREL = (0x3B << 26),
145};
146
147/* PC-relative address computation / loads */
148#define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
149#define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
150enum {
151 /* Instructions determined by bits 19 and 20 */
152 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
153 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
154 OPC_LWUPC = OPC_PCREL | (2 << 19),
155
156 /* Instructions determined by bits 16 ... 20 */
157 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
158 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
159
160 /* Other */
161 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
e37e863f
FB
162};
163
164/* MIPS special opcodes */
7a387fff
TS
165#define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
166
e37e863f
FB
167enum {
168 /* Shifts */
7a387fff 169 OPC_SLL = 0x00 | OPC_SPECIAL,
e37e863f
FB
170 /* NOP is SLL r0, r0, 0 */
171 /* SSNOP is SLL r0, r0, 1 */
7a387fff
TS
172 /* EHB is SLL r0, r0, 3 */
173 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
ea63e2c3 174 OPC_ROTR = OPC_SRL | (1 << 21),
7a387fff
TS
175 OPC_SRA = 0x03 | OPC_SPECIAL,
176 OPC_SLLV = 0x04 | OPC_SPECIAL,
e189e748 177 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
ea63e2c3 178 OPC_ROTRV = OPC_SRLV | (1 << 6),
7a387fff
TS
179 OPC_SRAV = 0x07 | OPC_SPECIAL,
180 OPC_DSLLV = 0x14 | OPC_SPECIAL,
181 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
ea63e2c3 182 OPC_DROTRV = OPC_DSRLV | (1 << 6),
7a387fff
TS
183 OPC_DSRAV = 0x17 | OPC_SPECIAL,
184 OPC_DSLL = 0x38 | OPC_SPECIAL,
185 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
ea63e2c3 186 OPC_DROTR = OPC_DSRL | (1 << 21),
7a387fff
TS
187 OPC_DSRA = 0x3B | OPC_SPECIAL,
188 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
189 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
ea63e2c3 190 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
7a387fff 191 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
e37e863f 192 /* Multiplication / division */
7a387fff
TS
193 OPC_MULT = 0x18 | OPC_SPECIAL,
194 OPC_MULTU = 0x19 | OPC_SPECIAL,
195 OPC_DIV = 0x1A | OPC_SPECIAL,
196 OPC_DIVU = 0x1B | OPC_SPECIAL,
197 OPC_DMULT = 0x1C | OPC_SPECIAL,
198 OPC_DMULTU = 0x1D | OPC_SPECIAL,
199 OPC_DDIV = 0x1E | OPC_SPECIAL,
200 OPC_DDIVU = 0x1F | OPC_SPECIAL,
b42ee5e1 201
e37e863f 202 /* 2 registers arithmetic / logic */
7a387fff
TS
203 OPC_ADD = 0x20 | OPC_SPECIAL,
204 OPC_ADDU = 0x21 | OPC_SPECIAL,
205 OPC_SUB = 0x22 | OPC_SPECIAL,
206 OPC_SUBU = 0x23 | OPC_SPECIAL,
207 OPC_AND = 0x24 | OPC_SPECIAL,
208 OPC_OR = 0x25 | OPC_SPECIAL,
209 OPC_XOR = 0x26 | OPC_SPECIAL,
210 OPC_NOR = 0x27 | OPC_SPECIAL,
211 OPC_SLT = 0x2A | OPC_SPECIAL,
212 OPC_SLTU = 0x2B | OPC_SPECIAL,
213 OPC_DADD = 0x2C | OPC_SPECIAL,
214 OPC_DADDU = 0x2D | OPC_SPECIAL,
215 OPC_DSUB = 0x2E | OPC_SPECIAL,
216 OPC_DSUBU = 0x2F | OPC_SPECIAL,
e37e863f 217 /* Jumps */
7a387fff
TS
218 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
219 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
e37e863f 220 /* Traps */
7a387fff
TS
221 OPC_TGE = 0x30 | OPC_SPECIAL,
222 OPC_TGEU = 0x31 | OPC_SPECIAL,
223 OPC_TLT = 0x32 | OPC_SPECIAL,
224 OPC_TLTU = 0x33 | OPC_SPECIAL,
225 OPC_TEQ = 0x34 | OPC_SPECIAL,
226 OPC_TNE = 0x36 | OPC_SPECIAL,
e37e863f 227 /* HI / LO registers load & stores */
7a387fff
TS
228 OPC_MFHI = 0x10 | OPC_SPECIAL,
229 OPC_MTHI = 0x11 | OPC_SPECIAL,
230 OPC_MFLO = 0x12 | OPC_SPECIAL,
231 OPC_MTLO = 0x13 | OPC_SPECIAL,
e37e863f 232 /* Conditional moves */
7a387fff
TS
233 OPC_MOVZ = 0x0A | OPC_SPECIAL,
234 OPC_MOVN = 0x0B | OPC_SPECIAL,
e37e863f 235
b691d9d2
LA
236 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
237 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
238
7a387fff 239 OPC_MOVCI = 0x01 | OPC_SPECIAL,
e37e863f
FB
240
241 /* Special */
a0d700e4 242 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
7a387fff
TS
243 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
244 OPC_BREAK = 0x0D | OPC_SPECIAL,
a0d700e4 245 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
7a387fff
TS
246 OPC_SYNC = 0x0F | OPC_SPECIAL,
247
7a387fff
TS
248 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
249 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
7a387fff
TS
250 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
251 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
252};
253
b42ee5e1
LA
254/* R6 Multiply and Divide instructions have the same Opcode
255 and function field as legacy OPC_MULT[U]/OPC_DIV[U] */
256#define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
257
258enum {
259 R6_OPC_MUL = OPC_MULT | (2 << 6),
260 R6_OPC_MUH = OPC_MULT | (3 << 6),
261 R6_OPC_MULU = OPC_MULTU | (2 << 6),
262 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
263 R6_OPC_DIV = OPC_DIV | (2 << 6),
264 R6_OPC_MOD = OPC_DIV | (3 << 6),
265 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
266 R6_OPC_MODU = OPC_DIVU | (3 << 6),
267
268 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
269 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
270 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
271 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
272 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
273 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
274 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
275 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
4267d3e6
LA
276
277 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
278 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
279 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
280 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
281 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
d4ea6acd
LA
282
283 OPC_LSA = 0x05 | OPC_SPECIAL,
284 OPC_DLSA = 0x15 | OPC_SPECIAL,
b42ee5e1
LA
285};
286
e9c71dd1
TS
287/* Multiplication variants of the vr54xx. */
288#define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
289
290enum {
291 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
292 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
293 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
294 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
295 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
296 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
297 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
298 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
299 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
300 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
301 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
302 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
303 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
304 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
305};
306
7a387fff
TS
307/* REGIMM (rt field) opcodes */
308#define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
309
310enum {
311 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
312 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
313 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
314 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
315 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
316 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
317 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
318 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
319 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
320 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
321 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
322 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
323 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
324 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
325 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
d4ea6acd
LA
326
327 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
328 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
e37e863f
FB
329};
330
7a387fff
TS
331/* Special2 opcodes */
332#define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
333
e37e863f 334enum {
7a387fff
TS
335 /* Multiply & xxx operations */
336 OPC_MADD = 0x00 | OPC_SPECIAL2,
337 OPC_MADDU = 0x01 | OPC_SPECIAL2,
338 OPC_MUL = 0x02 | OPC_SPECIAL2,
339 OPC_MSUB = 0x04 | OPC_SPECIAL2,
340 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
161f85e6
AJ
341 /* Loongson 2F */
342 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
343 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
344 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
345 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
346 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
347 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
348 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
349 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
350 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
351 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
352 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
353 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
e37e863f 354 /* Misc */
7a387fff
TS
355 OPC_CLZ = 0x20 | OPC_SPECIAL2,
356 OPC_CLO = 0x21 | OPC_SPECIAL2,
357 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
358 OPC_DCLO = 0x25 | OPC_SPECIAL2,
e37e863f 359 /* Special */
7a387fff
TS
360 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
361};
362
363/* Special3 opcodes */
364#define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
365
366enum {
367 OPC_EXT = 0x00 | OPC_SPECIAL3,
368 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
369 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
370 OPC_DEXT = 0x03 | OPC_SPECIAL3,
371 OPC_INS = 0x04 | OPC_SPECIAL3,
372 OPC_DINSM = 0x05 | OPC_SPECIAL3,
373 OPC_DINSU = 0x06 | OPC_SPECIAL3,
374 OPC_DINS = 0x07 | OPC_SPECIAL3,
ead9360e
TS
375 OPC_FORK = 0x08 | OPC_SPECIAL3,
376 OPC_YIELD = 0x09 | OPC_SPECIAL3,
7a387fff
TS
377 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
378 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
379 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
161f85e6
AJ
380
381 /* Loongson 2E */
382 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
383 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
384 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
385 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
386 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
387 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
388 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
389 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
390 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
391 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
392 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
393 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
9b1a1d68
JL
394
395 /* MIPS DSP Load */
396 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
461c08df
JL
397 /* MIPS DSP Arithmetic */
398 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
461c08df 399 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
461c08df 400 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
461c08df 401 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
461c08df
JL
402 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
403 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
404 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
461c08df 405 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
77c5fa8b
JL
406 /* MIPS DSP GPR-Based Shift Sub-class */
407 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
77c5fa8b 408 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
77c5fa8b
JL
409 /* MIPS DSP Multiply Sub-class insns */
410 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
411 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
412 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
77c5fa8b 413 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
1cb6686c
JL
414 /* DSP Bit/Manipulation Sub-class */
415 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
1cb6686c 416 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
df6126a7 417 /* MIPS DSP Append Sub-class */
26690560 418 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
26690560 419 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
b53371ed
JL
420 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
421 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
b53371ed 422 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
4368b29a
LA
423
424 /* R6 */
bf7910c6
LA
425 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
426 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
4368b29a
LA
427 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
428 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
bf7910c6
LA
429 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
430 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
e37e863f
FB
431};
432
7a387fff
TS
433/* BSHFL opcodes */
434#define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
435
e37e863f 436enum {
15eacb9b
YK
437 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
438 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
439 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
440 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp */
441 OPC_ALIGN_END = (0x0B << 6) | OPC_BSHFL, /* 010.00 to 010.11 */
442 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
e37e863f
FB
443};
444
7a387fff
TS
445/* DBSHFL opcodes */
446#define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
447
e37e863f 448enum {
15eacb9b
YK
449 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
450 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
451 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp */
452 OPC_DALIGN_END = (0x0F << 6) | OPC_DBSHFL, /* 01.000 to 01.111 */
453 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
e37e863f
FB
454};
455
e45a93e2
JL
456/* MIPS DSP REGIMM opcodes */
457enum {
458 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
e45a93e2 459 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
e45a93e2
JL
460};
461
9b1a1d68
JL
462#define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
463/* MIPS DSP Load */
464enum {
465 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
466 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
467 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
9b1a1d68 468 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
9b1a1d68
JL
469};
470
461c08df
JL
471#define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
472enum {
473 /* MIPS DSP Arithmetic Sub-class */
474 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
475 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
476 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
477 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
478 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
479 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
480 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
481 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
482 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
483 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
484 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
485 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
486 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
487 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
488 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
489 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
490 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
491 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
a22260ae
JL
492 /* MIPS DSP Multiply Sub-class insns */
493 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
494 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
495 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
496 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
497 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
498 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
461c08df
JL
499};
500
501#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
502#define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
503enum {
504 /* MIPS DSP Arithmetic Sub-class */
505 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
506 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
507 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
508 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
509 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
510 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
511 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
512 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
513 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
514 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
515 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
516 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
a22260ae
JL
517 /* MIPS DSP Multiply Sub-class insns */
518 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
519 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
520 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
521 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
461c08df
JL
522};
523
524#define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
525enum {
526 /* MIPS DSP Arithmetic Sub-class */
527 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
528 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
529 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
530 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
531 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
532 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
533 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
534 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
535 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
536 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
537 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
538 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
539 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
1cb6686c
JL
540 /* DSP Bit/Manipulation Sub-class */
541 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
542 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
543 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
544 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
545 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
461c08df
JL
546};
547
548#define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
549enum {
550 /* MIPS DSP Arithmetic Sub-class */
551 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
552 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
553 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
554 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
555 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
556 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
557 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
26690560
JL
558 /* DSP Compare-Pick Sub-class */
559 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
560 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
561 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
562 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
563 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
564 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
565 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
566 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
567 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
568 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
569 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
570 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
571 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
572 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
573 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
461c08df 574};
a22260ae 575
77c5fa8b
JL
576#define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
577enum {
578 /* MIPS DSP GPR-Based Shift Sub-class */
579 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
580 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
581 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
582 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
583 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
584 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
585 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
586 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
587 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
588 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
589 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
590 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
591 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
592 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
593 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
594 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
595 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
596 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
597 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
598 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
599 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
600 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
601};
461c08df 602
a22260ae
JL
603#define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
604enum {
605 /* MIPS DSP Multiply Sub-class insns */
606 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
607 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
608 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
609 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
610 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
611 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
612 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
613 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
614 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
615 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
616 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
617 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
618 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
619 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
620 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
621 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
622 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
623 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
624 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
625 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
626 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
627 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
628};
629
1cb6686c
JL
630#define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
631enum {
632 /* DSP Bit/Manipulation Sub-class */
633 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
634};
635
26690560
JL
636#define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
637enum {
df6126a7 638 /* MIPS DSP Append Sub-class */
26690560
JL
639 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
640 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
641 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
642};
643
b53371ed
JL
644#define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
645enum {
646 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
647 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
648 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
649 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
650 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
651 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
652 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
653 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
654 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
655 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
656 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
657 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
658 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
659 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
660 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
661 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
662 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
663 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
664};
665
461c08df
JL
666#define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
667enum {
668 /* MIPS DSP Arithmetic Sub-class */
669 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
670 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
671 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
672 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
673 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
674 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
675 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
676 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
677 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
678 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
679 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
680 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
681 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
682 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
683 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
684 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
685 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
1cb6686c
JL
686 /* DSP Bit/Manipulation Sub-class */
687 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
688 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
689 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
690 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
691 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
692 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
461c08df 693};
461c08df 694
461c08df
JL
695#define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
696enum {
a22260ae
JL
697 /* MIPS DSP Multiply Sub-class insns */
698 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
699 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
700 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
701 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
702 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
461c08df
JL
703 /* MIPS DSP Arithmetic Sub-class */
704 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
705 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
706 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
707 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
708 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
709 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
710 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
711 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
712 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
713 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
714 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
715 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
716 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
717 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
718 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
719 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
720 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
721 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
722 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
723 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
724 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
725};
461c08df 726
461c08df
JL
727#define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
728enum {
26690560
JL
729 /* DSP Compare-Pick Sub-class */
730 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
731 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
732 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
733 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
734 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
735 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
736 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
737 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
738 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
739 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
740 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
741 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
742 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
743 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
744 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
745 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
746 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
747 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
748 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
461c08df
JL
749 /* MIPS DSP Arithmetic Sub-class */
750 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
751 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
752 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
753 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
754 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
755 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
756 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
757 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
758};
461c08df 759
26690560
JL
760#define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
761enum {
df6126a7 762 /* DSP Append Sub-class */
26690560
JL
763 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
764 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
765 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
766 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
767};
26690560 768
b53371ed
JL
769#define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
770enum {
771 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
772 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
773 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
774 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
775 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
776 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
777 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
778 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
779 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
780 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
781 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
782 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
783 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
784 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
785 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
786 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
787 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
788 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
789 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
790 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
791 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
792 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
793};
794
1cb6686c
JL
795#define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
796enum {
797 /* DSP Bit/Manipulation Sub-class */
798 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
799};
1cb6686c 800
a22260ae
JL
801#define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
802enum {
803 /* MIPS DSP Multiply Sub-class insns */
804 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
805 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
806 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
807 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
808 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
809 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
810 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
811 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
812 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
813 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
814 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
815 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
816 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
817 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
818 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
819 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
820 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
821 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
822 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
823 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
824 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
825 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
826 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
827 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
828 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
829 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
830};
a22260ae 831
77c5fa8b
JL
832#define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
833enum {
834 /* MIPS DSP GPR-Based Shift Sub-class */
835 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
836 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
837 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
838 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
839 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
840 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
841 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
842 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
843 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
844 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
845 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
846 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
847 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
848 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
849 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
850 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
851 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
852 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
853 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
854 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
855 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
856 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
857 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
858 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
859 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
860 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
861};
77c5fa8b 862
7a387fff
TS
863/* Coprocessor 0 (rs field) */
864#define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
865
6ea83fed 866enum {
7a387fff
TS
867 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
868 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
869 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
870 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
ead9360e 871 OPC_MFTR = (0x08 << 21) | OPC_CP0,
7a387fff
TS
872 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
873 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
ead9360e 874 OPC_MTTR = (0x0C << 21) | OPC_CP0,
7a387fff
TS
875 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
876 OPC_C0 = (0x10 << 21) | OPC_CP0,
877 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
878 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
6ea83fed 879};
7a387fff
TS
880
881/* MFMC0 opcodes */
b48cfdff 882#define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
7a387fff
TS
883
884enum {
ead9360e
TS
885 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
886 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
887 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
888 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
7a387fff
TS
889 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
890 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
891};
892
893/* Coprocessor 0 (with rs == C0) */
894#define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
895
896enum {
897 OPC_TLBR = 0x01 | OPC_C0,
898 OPC_TLBWI = 0x02 | OPC_C0,
9456c2fb
LA
899 OPC_TLBINV = 0x03 | OPC_C0,
900 OPC_TLBINVF = 0x04 | OPC_C0,
7a387fff
TS
901 OPC_TLBWR = 0x06 | OPC_C0,
902 OPC_TLBP = 0x08 | OPC_C0,
903 OPC_RFE = 0x10 | OPC_C0,
904 OPC_ERET = 0x18 | OPC_C0,
905 OPC_DERET = 0x1F | OPC_C0,
906 OPC_WAIT = 0x20 | OPC_C0,
907};
908
909/* Coprocessor 1 (rs field) */
910#define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
911
bf4120ad
NF
912/* Values for the fmt field in FP instructions */
913enum {
914 /* 0 - 15 are reserved */
e459440a
AJ
915 FMT_S = 16, /* single fp */
916 FMT_D = 17, /* double fp */
917 FMT_E = 18, /* extended fp */
918 FMT_Q = 19, /* quad fp */
919 FMT_W = 20, /* 32-bit fixed */
920 FMT_L = 21, /* 64-bit fixed */
921 FMT_PS = 22, /* paired single fp */
bf4120ad
NF
922 /* 23 - 31 are reserved */
923};
924
7a387fff
TS
925enum {
926 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
927 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
928 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
5a5012ec 929 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
7a387fff
TS
930 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
931 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
932 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
5a5012ec 933 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
7a387fff 934 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
5a5012ec
TS
935 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
936 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
e459440a
AJ
937 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
938 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
939 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
940 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
941 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
942 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
943 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
31837be3
YK
944 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
945 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
7a387fff
TS
946};
947
5a5012ec
TS
948#define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
949#define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
950
7a387fff
TS
951enum {
952 OPC_BC1F = (0x00 << 16) | OPC_BC1,
953 OPC_BC1T = (0x01 << 16) | OPC_BC1,
954 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
955 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
956};
957
5a5012ec
TS
958enum {
959 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
960 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
961};
962
963enum {
964 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
965 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
966};
7a387fff
TS
967
968#define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
e0c84da7
TS
969
970enum {
971 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
972 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
973 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
974 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
975 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
976 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
977 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
978 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
979 OPC_BC2 = (0x08 << 21) | OPC_CP2,
31837be3
YK
980 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
981 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
e0c84da7
TS
982};
983
bd277fa1
RH
984#define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
985
986enum {
987 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
988 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
989 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
990 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
991 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
992 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
993 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
994 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
995
996 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
997 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
998 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
999 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1000 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1001 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1002 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1003 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1004
1005 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1006 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1007 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1008 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1009 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1010 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1011 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1012 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1013
1014 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1015 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1016 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1017 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1018 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1019 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1020 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1021 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1022
1023 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1024 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1025 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1026 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1027 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1028 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1029
1030 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1031 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1032 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1033 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1034 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1035 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1036
1037 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1038 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1039 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1040 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1041 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1042 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1043
1044 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1045 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1046 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1047 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1048 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1049 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1050
1051 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1052 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1053 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1054 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1055 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1056 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1057
1058 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1059 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1060 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1061 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1062 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1063 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1064
1065 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1066 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1067 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1068 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1069 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1070 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1071
1072 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1073 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1074 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1075 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1076 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1077 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1078};
1079
1080
e0c84da7
TS
1081#define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1082
1083enum {
1084 OPC_LWXC1 = 0x00 | OPC_CP3,
1085 OPC_LDXC1 = 0x01 | OPC_CP3,
1086 OPC_LUXC1 = 0x05 | OPC_CP3,
1087 OPC_SWXC1 = 0x08 | OPC_CP3,
1088 OPC_SDXC1 = 0x09 | OPC_CP3,
1089 OPC_SUXC1 = 0x0D | OPC_CP3,
1090 OPC_PREFX = 0x0F | OPC_CP3,
1091 OPC_ALNV_PS = 0x1E | OPC_CP3,
1092 OPC_MADD_S = 0x20 | OPC_CP3,
1093 OPC_MADD_D = 0x21 | OPC_CP3,
1094 OPC_MADD_PS = 0x26 | OPC_CP3,
1095 OPC_MSUB_S = 0x28 | OPC_CP3,
1096 OPC_MSUB_D = 0x29 | OPC_CP3,
1097 OPC_MSUB_PS = 0x2E | OPC_CP3,
1098 OPC_NMADD_S = 0x30 | OPC_CP3,
fbcc6828 1099 OPC_NMADD_D = 0x31 | OPC_CP3,
e0c84da7
TS
1100 OPC_NMADD_PS= 0x36 | OPC_CP3,
1101 OPC_NMSUB_S = 0x38 | OPC_CP3,
1102 OPC_NMSUB_D = 0x39 | OPC_CP3,
1103 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1104};
1105
39454628 1106/* global register indices */
a7812ae4
PB
1107static TCGv_ptr cpu_env;
1108static TCGv cpu_gpr[32], cpu_PC;
340fff72 1109static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
41db4607
AJ
1110static TCGv cpu_dspctrl, btarget, bcond;
1111static TCGv_i32 hflags;
a7812ae4 1112static TCGv_i32 fpu_fcr0, fpu_fcr31;
d73ee8a2 1113static TCGv_i64 fpu_f64[32];
aa0bf00b 1114
1a7ff922 1115static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
4636401d 1116static target_ulong gen_opc_btarget[OPC_BUF_SIZE];
1a7ff922 1117
022c62cb 1118#include "exec/gen-icount.h"
2e70f6ef 1119
895c2d04 1120#define gen_helper_0e0i(name, arg) do { \
a7812ae4 1121 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
895c2d04 1122 gen_helper_##name(cpu_env, helper_tmp); \
a7812ae4
PB
1123 tcg_temp_free_i32(helper_tmp); \
1124 } while(0)
be24bb4f 1125
895c2d04 1126#define gen_helper_0e1i(name, arg1, arg2) do { \
a7812ae4 1127 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
895c2d04 1128 gen_helper_##name(cpu_env, arg1, helper_tmp); \
a7812ae4
PB
1129 tcg_temp_free_i32(helper_tmp); \
1130 } while(0)
be24bb4f 1131
895c2d04
BS
1132#define gen_helper_1e0i(name, ret, arg1) do { \
1133 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1134 gen_helper_##name(ret, cpu_env, helper_tmp); \
1135 tcg_temp_free_i32(helper_tmp); \
1136 } while(0)
1137
1138#define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1139 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1140 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1141 tcg_temp_free_i32(helper_tmp); \
1142 } while(0)
1143
1144#define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1145 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1146 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1147 tcg_temp_free_i32(helper_tmp); \
1148 } while(0)
1149
1150#define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
a7812ae4 1151 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
895c2d04 1152 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
a7812ae4
PB
1153 tcg_temp_free_i32(helper_tmp); \
1154 } while(0)
be24bb4f 1155
895c2d04 1156#define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
a7812ae4 1157 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
895c2d04 1158 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
a7812ae4
PB
1159 tcg_temp_free_i32(helper_tmp); \
1160 } while(0)
c239529e 1161
8e9ade68
TS
1162typedef struct DisasContext {
1163 struct TranslationBlock *tb;
1164 target_ulong pc, saved_pc;
1165 uint32_t opcode;
7b270ef2 1166 int singlestep_enabled;
d75c135e 1167 int insn_flags;
5ab5c041 1168 int32_t CP0_Config1;
8e9ade68
TS
1169 /* Routine used to access memory */
1170 int mem_idx;
1171 uint32_t hflags, saved_hflags;
1172 int bstate;
1173 target_ulong btarget;
d279279e 1174 bool ulri;
e98c0d17 1175 int kscrexist;
7207c7f9 1176 bool rxi;
9456c2fb 1177 int ie;
8e9ade68
TS
1178} DisasContext;
1179
1180enum {
1181 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
d077b6f7 1182 * exception condition */
8e9ade68
TS
1183 BS_STOP = 1, /* We want to stop translation for any reason */
1184 BS_BRANCH = 2, /* We reached a branch condition */
1185 BS_EXCP = 3, /* We reached an exception condition */
1186};
1187
d73ee8a2
RH
1188static const char * const regnames[] = {
1189 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1190 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1191 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1192 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1193};
6af0bf9c 1194
d73ee8a2
RH
1195static const char * const regnames_HI[] = {
1196 "HI0", "HI1", "HI2", "HI3",
1197};
4b2eb8d2 1198
d73ee8a2
RH
1199static const char * const regnames_LO[] = {
1200 "LO0", "LO1", "LO2", "LO3",
1201};
4b2eb8d2 1202
d73ee8a2
RH
1203static const char * const fregnames[] = {
1204 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1205 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1206 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1207 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1208};
958fb4a9 1209
fb7729e2
RH
1210#define MIPS_DEBUG(fmt, ...) \
1211 do { \
1212 if (MIPS_DEBUG_DISAS) { \
1213 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
1214 TARGET_FMT_lx ": %08x " fmt "\n", \
1215 ctx->pc, ctx->opcode , ## __VA_ARGS__); \
1216 } \
1217 } while (0)
1218
1219#define LOG_DISAS(...) \
1220 do { \
1221 if (MIPS_DEBUG_DISAS) { \
1222 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
1223 } \
1224 } while (0)
958fb4a9 1225
8e9ade68 1226#define MIPS_INVAL(op) \
8e9ade68 1227 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
fb7729e2 1228 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F))
ead9360e 1229
8e9ade68
TS
1230/* General purpose registers moves. */
1231static inline void gen_load_gpr (TCGv t, int reg)
aaa9128a 1232{
8e9ade68
TS
1233 if (reg == 0)
1234 tcg_gen_movi_tl(t, 0);
1235 else
4b2eb8d2 1236 tcg_gen_mov_tl(t, cpu_gpr[reg]);
aaa9128a
TS
1237}
1238
8e9ade68 1239static inline void gen_store_gpr (TCGv t, int reg)
aaa9128a 1240{
8e9ade68 1241 if (reg != 0)
4b2eb8d2 1242 tcg_gen_mov_tl(cpu_gpr[reg], t);
aaa9128a
TS
1243}
1244
8e9ade68 1245/* Moves to/from shadow registers. */
be24bb4f 1246static inline void gen_load_srsgpr (int from, int to)
aaa9128a 1247{
d9bea114 1248 TCGv t0 = tcg_temp_new();
be24bb4f
TS
1249
1250 if (from == 0)
d9bea114 1251 tcg_gen_movi_tl(t0, 0);
8e9ade68 1252 else {
d9bea114 1253 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 1254 TCGv_ptr addr = tcg_temp_new_ptr();
aaa9128a 1255
7db13fae 1256 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
1257 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1258 tcg_gen_andi_i32(t2, t2, 0xf);
1259 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1260 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 1261 tcg_gen_add_ptr(addr, cpu_env, addr);
aaa9128a 1262
d9bea114 1263 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
a7812ae4 1264 tcg_temp_free_ptr(addr);
d9bea114 1265 tcg_temp_free_i32(t2);
8e9ade68 1266 }
d9bea114
AJ
1267 gen_store_gpr(t0, to);
1268 tcg_temp_free(t0);
aaa9128a
TS
1269}
1270
be24bb4f 1271static inline void gen_store_srsgpr (int from, int to)
aaa9128a 1272{
be24bb4f 1273 if (to != 0) {
d9bea114
AJ
1274 TCGv t0 = tcg_temp_new();
1275 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 1276 TCGv_ptr addr = tcg_temp_new_ptr();
be24bb4f 1277
d9bea114 1278 gen_load_gpr(t0, from);
7db13fae 1279 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
1280 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1281 tcg_gen_andi_i32(t2, t2, 0xf);
1282 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1283 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 1284 tcg_gen_add_ptr(addr, cpu_env, addr);
be24bb4f 1285
d9bea114 1286 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
a7812ae4 1287 tcg_temp_free_ptr(addr);
d9bea114
AJ
1288 tcg_temp_free_i32(t2);
1289 tcg_temp_free(t0);
8e9ade68 1290 }
aaa9128a
TS
1291}
1292
aaa9128a 1293/* Floating point register moves. */
d73ee8a2 1294static void gen_load_fpr32(TCGv_i32 t, int reg)
aa0bf00b 1295{
d73ee8a2 1296 tcg_gen_trunc_i64_i32(t, fpu_f64[reg]);
6ea83fed
FB
1297}
1298
d73ee8a2 1299static void gen_store_fpr32(TCGv_i32 t, int reg)
aa0bf00b 1300{
d73ee8a2
RH
1301 TCGv_i64 t64 = tcg_temp_new_i64();
1302 tcg_gen_extu_i32_i64(t64, t);
1303 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1304 tcg_temp_free_i64(t64);
6d066274
AJ
1305}
1306
7f6613ce 1307static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
6d066274 1308{
7f6613ce
PJ
1309 if (ctx->hflags & MIPS_HFLAG_F64) {
1310 TCGv_i64 t64 = tcg_temp_new_i64();
1311 tcg_gen_shri_i64(t64, fpu_f64[reg], 32);
1312 tcg_gen_trunc_i64_i32(t, t64);
1313 tcg_temp_free_i64(t64);
1314 } else {
1315 gen_load_fpr32(t, reg | 1);
1316 }
6d066274
AJ
1317}
1318
7f6613ce 1319static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
6d066274 1320{
7f6613ce
PJ
1321 if (ctx->hflags & MIPS_HFLAG_F64) {
1322 TCGv_i64 t64 = tcg_temp_new_i64();
1323 tcg_gen_extu_i32_i64(t64, t);
1324 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1325 tcg_temp_free_i64(t64);
1326 } else {
1327 gen_store_fpr32(t, reg | 1);
1328 }
aa0bf00b 1329}
6ea83fed 1330
d73ee8a2 1331static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 1332{
f364515c 1333 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 1334 tcg_gen_mov_i64(t, fpu_f64[reg]);
f364515c 1335 } else {
d73ee8a2 1336 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
aa0bf00b
TS
1337 }
1338}
6ea83fed 1339
d73ee8a2 1340static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 1341{
f364515c 1342 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 1343 tcg_gen_mov_i64(fpu_f64[reg], t);
f364515c 1344 } else {
d73ee8a2
RH
1345 TCGv_i64 t0;
1346 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1347 t0 = tcg_temp_new_i64();
6d066274 1348 tcg_gen_shri_i64(t0, t, 32);
d73ee8a2 1349 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
6d066274 1350 tcg_temp_free_i64(t0);
aa0bf00b
TS
1351 }
1352}
6ea83fed 1353
d94536f4 1354static inline int get_fp_bit (int cc)
a16336e4 1355{
d94536f4
AJ
1356 if (cc)
1357 return 24 + cc;
1358 else
1359 return 23;
a16336e4
TS
1360}
1361
30898801 1362/* Tests */
8e9ade68
TS
1363static inline void gen_save_pc(target_ulong pc)
1364{
1eb75d4a 1365 tcg_gen_movi_tl(cpu_PC, pc);
8e9ade68 1366}
30898801 1367
356265ae 1368static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
6af0bf9c 1369{
d12d51d5 1370 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
6af0bf9c 1371 if (do_save_pc && ctx->pc != ctx->saved_pc) {
9b9e4393 1372 gen_save_pc(ctx->pc);
6af0bf9c
FB
1373 ctx->saved_pc = ctx->pc;
1374 }
1375 if (ctx->hflags != ctx->saved_hflags) {
41db4607 1376 tcg_gen_movi_i32(hflags, ctx->hflags);
6af0bf9c 1377 ctx->saved_hflags = ctx->hflags;
364d4831 1378 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
5a5012ec 1379 case MIPS_HFLAG_BR:
5a5012ec
TS
1380 break;
1381 case MIPS_HFLAG_BC:
5a5012ec 1382 case MIPS_HFLAG_BL:
5a5012ec 1383 case MIPS_HFLAG_B:
d077b6f7 1384 tcg_gen_movi_tl(btarget, ctx->btarget);
5a5012ec 1385 break;
6af0bf9c
FB
1386 }
1387 }
1388}
1389
7db13fae 1390static inline void restore_cpu_state (CPUMIPSState *env, DisasContext *ctx)
5a5012ec 1391{
fd4a04eb 1392 ctx->saved_hflags = ctx->hflags;
364d4831 1393 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
fd4a04eb 1394 case MIPS_HFLAG_BR:
fd4a04eb
TS
1395 break;
1396 case MIPS_HFLAG_BC:
1397 case MIPS_HFLAG_BL:
39454628 1398 case MIPS_HFLAG_B:
fd4a04eb 1399 ctx->btarget = env->btarget;
fd4a04eb 1400 break;
5a5012ec
TS
1401 }
1402}
1403
356265ae 1404static inline void
48d38ca5 1405generate_exception_err (DisasContext *ctx, int excp, int err)
aaa9128a 1406{
a7812ae4
PB
1407 TCGv_i32 texcp = tcg_const_i32(excp);
1408 TCGv_i32 terr = tcg_const_i32(err);
aaa9128a 1409 save_cpu_state(ctx, 1);
895c2d04 1410 gen_helper_raise_exception_err(cpu_env, texcp, terr);
a7812ae4
PB
1411 tcg_temp_free_i32(terr);
1412 tcg_temp_free_i32(texcp);
aaa9128a
TS
1413}
1414
356265ae 1415static inline void
48d38ca5 1416generate_exception (DisasContext *ctx, int excp)
aaa9128a 1417{
6af0bf9c 1418 save_cpu_state(ctx, 1);
895c2d04 1419 gen_helper_0e0i(raise_exception, excp);
6af0bf9c
FB
1420}
1421
48d38ca5 1422/* Addresses computation */
941694d0 1423static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
4ad40f36 1424{
941694d0 1425 tcg_gen_add_tl(ret, arg0, arg1);
48d38ca5
TS
1426
1427#if defined(TARGET_MIPS64)
01f72885 1428 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
941694d0 1429 tcg_gen_ext32s_i64(ret, ret);
48d38ca5
TS
1430 }
1431#endif
4ad40f36
FB
1432}
1433
31837be3
YK
1434/* Addresses computation (translation time) */
1435static target_long addr_add(DisasContext *ctx, target_long base,
1436 target_long offset)
1437{
1438 target_long sum = base + offset;
1439
1440#if defined(TARGET_MIPS64)
1441 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1442 sum = (int32_t)sum;
1443 }
1444#endif
1445 return sum;
1446}
1447
356265ae 1448static inline void check_cp0_enabled(DisasContext *ctx)
387a8fe5 1449{
fe253235 1450 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
c2c65dab 1451 generate_exception_err(ctx, EXCP_CpU, 0);
387a8fe5
TS
1452}
1453
356265ae 1454static inline void check_cp1_enabled(DisasContext *ctx)
5e755519 1455{
fe253235 1456 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
5e755519
TS
1457 generate_exception_err(ctx, EXCP_CpU, 1);
1458}
1459
b8aa4598
TS
1460/* Verify that the processor is running with COP1X instructions enabled.
1461 This is associated with the nabla symbol in the MIPS32 and MIPS64
1462 opcode tables. */
1463
356265ae 1464static inline void check_cop1x(DisasContext *ctx)
b8aa4598
TS
1465{
1466 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
1467 generate_exception(ctx, EXCP_RI);
1468}
1469
1470/* Verify that the processor is running with 64-bit floating-point
1471 operations enabled. */
1472
356265ae 1473static inline void check_cp1_64bitmode(DisasContext *ctx)
5e755519 1474{
b8aa4598 1475 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
5e755519
TS
1476 generate_exception(ctx, EXCP_RI);
1477}
1478
1479/*
1480 * Verify if floating point register is valid; an operation is not defined
1481 * if bit 0 of any register specification is set and the FR bit in the
1482 * Status register equals zero, since the register numbers specify an
1483 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1484 * in the Status register equals one, both even and odd register numbers
1485 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1486 *
1487 * Multiple 64 bit wide registers can be checked by calling
1488 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1489 */
356265ae 1490static inline void check_cp1_registers(DisasContext *ctx, int regs)
5e755519 1491{
fe253235 1492 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
5e755519
TS
1493 generate_exception(ctx, EXCP_RI);
1494}
1495
853c3240
JL
1496/* Verify that the processor is running with DSP instructions enabled.
1497 This is enabled by CP0 Status register MX(24) bit.
1498 */
1499
1500static inline void check_dsp(DisasContext *ctx)
1501{
1502 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
ad153f15
AJ
1503 if (ctx->insn_flags & ASE_DSP) {
1504 generate_exception(ctx, EXCP_DSPDIS);
1505 } else {
1506 generate_exception(ctx, EXCP_RI);
1507 }
853c3240
JL
1508 }
1509}
1510
1511static inline void check_dspr2(DisasContext *ctx)
1512{
1513 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
ad153f15
AJ
1514 if (ctx->insn_flags & ASE_DSP) {
1515 generate_exception(ctx, EXCP_DSPDIS);
1516 } else {
1517 generate_exception(ctx, EXCP_RI);
1518 }
853c3240
JL
1519 }
1520}
1521
3a95e3a7 1522/* This code generates a "reserved instruction" exception if the
e189e748 1523 CPU does not support the instruction set corresponding to flags. */
d75c135e 1524static inline void check_insn(DisasContext *ctx, int flags)
3a95e3a7 1525{
d75c135e 1526 if (unlikely(!(ctx->insn_flags & flags))) {
3a95e3a7 1527 generate_exception(ctx, EXCP_RI);
d75c135e 1528 }
3a95e3a7
TS
1529}
1530
fecd2646
LA
1531/* This code generates a "reserved instruction" exception if the
1532 CPU has corresponding flag set which indicates that the instruction
1533 has been removed. */
1534static inline void check_insn_opc_removed(DisasContext *ctx, int flags)
1535{
1536 if (unlikely(ctx->insn_flags & flags)) {
1537 generate_exception(ctx, EXCP_RI);
1538 }
1539}
1540
c7986fd6 1541#ifdef TARGET_MIPS64
e189e748
TS
1542/* This code generates a "reserved instruction" exception if 64-bit
1543 instructions are not enabled. */
356265ae 1544static inline void check_mips_64(DisasContext *ctx)
e189e748 1545{
fe253235 1546 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
e189e748
TS
1547 generate_exception(ctx, EXCP_RI);
1548}
c7986fd6 1549#endif
e189e748 1550
8153667c
NF
1551/* Define small wrappers for gen_load_fpr* so that we have a uniform
1552 calling interface for 32 and 64-bit FPRs. No sense in changing
1553 all callers for gen_load_fpr32 when we need the CTX parameter for
1554 this one use. */
1555#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y)
1556#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1557#define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1558static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1559 int ft, int fs, int cc) \
1560{ \
1561 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
1562 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
1563 switch (ifmt) { \
1564 case FMT_PS: \
1565 check_cp1_64bitmode(ctx); \
1566 break; \
1567 case FMT_D: \
1568 if (abs) { \
1569 check_cop1x(ctx); \
1570 } \
1571 check_cp1_registers(ctx, fs | ft); \
1572 break; \
1573 case FMT_S: \
1574 if (abs) { \
1575 check_cop1x(ctx); \
1576 } \
1577 break; \
1578 } \
1579 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
1580 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
1581 switch (n) { \
895c2d04
BS
1582 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
1583 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
1584 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
1585 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
1586 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
1587 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
1588 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
1589 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
1590 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
1591 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
1592 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
1593 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
1594 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
1595 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
1596 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
1597 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
8153667c
NF
1598 default: abort(); \
1599 } \
1600 tcg_temp_free_i##bits (fp0); \
1601 tcg_temp_free_i##bits (fp1); \
1602}
1603
1604FOP_CONDS(, 0, d, FMT_D, 64)
1605FOP_CONDS(abs, 1, d, FMT_D, 64)
1606FOP_CONDS(, 0, s, FMT_S, 32)
1607FOP_CONDS(abs, 1, s, FMT_S, 32)
1608FOP_CONDS(, 0, ps, FMT_PS, 64)
1609FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1610#undef FOP_CONDS
3f493883
YK
1611
1612#define FOP_CONDNS(fmt, ifmt, bits, STORE) \
1613static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
1614 int ft, int fs, int fd) \
1615{ \
1616 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1617 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
1618 switch (ifmt) { \
1619 case FMT_D: \
1620 check_cp1_registers(ctx, fs | ft | fd); \
1621 break; \
1622 } \
1623 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
1624 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
1625 switch (n) { \
1626 case 0: \
1627 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
1628 break; \
1629 case 1: \
1630 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
1631 break; \
1632 case 2: \
1633 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
1634 break; \
1635 case 3: \
1636 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
1637 break; \
1638 case 4: \
1639 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
1640 break; \
1641 case 5: \
1642 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
1643 break; \
1644 case 6: \
1645 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
1646 break; \
1647 case 7: \
1648 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
1649 break; \
1650 case 8: \
1651 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
1652 break; \
1653 case 9: \
1654 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
1655 break; \
1656 case 10: \
1657 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
1658 break; \
1659 case 11: \
1660 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
1661 break; \
1662 case 12: \
1663 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
1664 break; \
1665 case 13: \
1666 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
1667 break; \
1668 case 14: \
1669 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
1670 break; \
1671 case 15: \
1672 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
1673 break; \
1674 case 17: \
1675 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
1676 break; \
1677 case 18: \
1678 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
1679 break; \
1680 case 19: \
1681 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
1682 break; \
1683 case 25: \
1684 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
1685 break; \
1686 case 26: \
1687 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
1688 break; \
1689 case 27: \
1690 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
1691 break; \
1692 default: \
1693 abort(); \
1694 } \
1695 STORE; \
1696 tcg_temp_free_i ## bits (fp0); \
1697 tcg_temp_free_i ## bits (fp1); \
1698}
1699
1700FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
1701FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(fp0, fd))
1702#undef FOP_CONDNS
8153667c
NF
1703#undef gen_ldcmp_fpr32
1704#undef gen_ldcmp_fpr64
1705
958fb4a9 1706/* load/store instructions. */
e7139c44 1707#ifdef CONFIG_USER_ONLY
d9bea114 1708#define OP_LD_ATOMIC(insn,fname) \
5c13fdfd 1709static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
d9bea114
AJ
1710{ \
1711 TCGv t0 = tcg_temp_new(); \
1712 tcg_gen_mov_tl(t0, arg1); \
1713 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
7db13fae
AF
1714 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
1715 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
d9bea114 1716 tcg_temp_free(t0); \
aaa9128a 1717}
e7139c44
AJ
1718#else
1719#define OP_LD_ATOMIC(insn,fname) \
5c13fdfd 1720static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
e7139c44 1721{ \
895c2d04 1722 gen_helper_1e1i(insn, ret, arg1, ctx->mem_idx); \
e7139c44
AJ
1723}
1724#endif
aaa9128a
TS
1725OP_LD_ATOMIC(ll,ld32s);
1726#if defined(TARGET_MIPS64)
1727OP_LD_ATOMIC(lld,ld64);
1728#endif
1729#undef OP_LD_ATOMIC
1730
590bc601
PB
1731#ifdef CONFIG_USER_ONLY
1732#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
5c13fdfd 1733static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
590bc601
PB
1734{ \
1735 TCGv t0 = tcg_temp_new(); \
1736 int l1 = gen_new_label(); \
1737 int l2 = gen_new_label(); \
1738 \
1739 tcg_gen_andi_tl(t0, arg2, almask); \
1740 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
7db13fae 1741 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
590bc601
PB
1742 generate_exception(ctx, EXCP_AdES); \
1743 gen_set_label(l1); \
7db13fae 1744 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
590bc601
PB
1745 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
1746 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
7db13fae
AF
1747 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
1748 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
895c2d04 1749 gen_helper_0e0i(raise_exception, EXCP_SC); \
590bc601
PB
1750 gen_set_label(l2); \
1751 tcg_gen_movi_tl(t0, 0); \
1752 gen_store_gpr(t0, rt); \
1753 tcg_temp_free(t0); \
1754}
1755#else
1756#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
5c13fdfd 1757static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
590bc601
PB
1758{ \
1759 TCGv t0 = tcg_temp_new(); \
895c2d04 1760 gen_helper_1e2i(insn, t0, arg1, arg2, ctx->mem_idx); \
590bc601 1761 gen_store_gpr(t0, rt); \
590bc601
PB
1762 tcg_temp_free(t0); \
1763}
1764#endif
590bc601 1765OP_ST_ATOMIC(sc,st32,ld32s,0x3);
aaa9128a 1766#if defined(TARGET_MIPS64)
590bc601 1767OP_ST_ATOMIC(scd,st64,ld64,0x7);
aaa9128a
TS
1768#endif
1769#undef OP_ST_ATOMIC
1770
662d7485
NF
1771static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
1772 int base, int16_t offset)
1773{
1774 if (base == 0) {
1775 tcg_gen_movi_tl(addr, offset);
1776 } else if (offset == 0) {
1777 gen_load_gpr(addr, base);
1778 } else {
1779 tcg_gen_movi_tl(addr, offset);
1780 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
1781 }
1782}
1783
364d4831
NF
1784static target_ulong pc_relative_pc (DisasContext *ctx)
1785{
1786 target_ulong pc = ctx->pc;
1787
1788 if (ctx->hflags & MIPS_HFLAG_BMASK) {
1789 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
1790
1791 pc -= branch_bytes;
1792 }
1793
1794 pc &= ~(target_ulong)3;
1795 return pc;
1796}
1797
5c13fdfd 1798/* Load */
d75c135e
AJ
1799static void gen_ld(DisasContext *ctx, uint32_t opc,
1800 int rt, int base, int16_t offset)
6af0bf9c 1801{
5c13fdfd 1802 const char *opn = "ld";
fc40787a 1803 TCGv t0, t1, t2;
afa88c3a 1804
d75c135e 1805 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
afa88c3a
AJ
1806 /* Loongson CPU uses a load to zero register for prefetch.
1807 We emulate it as a NOP. On other CPU we must perform the
1808 actual memory access. */
1809 MIPS_DEBUG("NOP");
1810 return;
1811 }
6af0bf9c 1812
afa88c3a 1813 t0 = tcg_temp_new();
662d7485 1814 gen_base_offset_addr(ctx, t0, base, offset);
afa88c3a 1815
6af0bf9c 1816 switch (opc) {
d26bc211 1817#if defined(TARGET_MIPS64)
6e473128 1818 case OPC_LWU:
5f68f5ae 1819 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
78723684 1820 gen_store_gpr(t0, rt);
6e473128
TS
1821 opn = "lwu";
1822 break;
6af0bf9c 1823 case OPC_LD:
5f68f5ae 1824 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
78723684 1825 gen_store_gpr(t0, rt);
6af0bf9c
FB
1826 opn = "ld";
1827 break;
7a387fff 1828 case OPC_LLD:
bf7910c6 1829 case R6_OPC_LLD:
b835e919 1830 save_cpu_state(ctx, 1);
5c13fdfd 1831 op_ld_lld(t0, t0, ctx);
78723684 1832 gen_store_gpr(t0, rt);
7a387fff
TS
1833 opn = "lld";
1834 break;
6af0bf9c 1835 case OPC_LDL:
3cee3050 1836 t1 = tcg_temp_new();
fc40787a
AJ
1837 tcg_gen_andi_tl(t1, t0, 7);
1838#ifndef TARGET_WORDS_BIGENDIAN
1839 tcg_gen_xori_tl(t1, t1, 7);
1840#endif
1841 tcg_gen_shli_tl(t1, t1, 3);
1842 tcg_gen_andi_tl(t0, t0, ~7);
5f68f5ae 1843 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
fc40787a
AJ
1844 tcg_gen_shl_tl(t0, t0, t1);
1845 tcg_gen_xori_tl(t1, t1, 63);
1846 t2 = tcg_const_tl(0x7fffffffffffffffull);
1847 tcg_gen_shr_tl(t2, t2, t1);
78723684 1848 gen_load_gpr(t1, rt);
fc40787a
AJ
1849 tcg_gen_and_tl(t1, t1, t2);
1850 tcg_temp_free(t2);
1851 tcg_gen_or_tl(t0, t0, t1);
3cee3050 1852 tcg_temp_free(t1);
fc40787a 1853 gen_store_gpr(t0, rt);
6af0bf9c
FB
1854 opn = "ldl";
1855 break;
6af0bf9c 1856 case OPC_LDR:
3cee3050 1857 t1 = tcg_temp_new();
fc40787a
AJ
1858 tcg_gen_andi_tl(t1, t0, 7);
1859#ifdef TARGET_WORDS_BIGENDIAN
1860 tcg_gen_xori_tl(t1, t1, 7);
1861#endif
1862 tcg_gen_shli_tl(t1, t1, 3);
1863 tcg_gen_andi_tl(t0, t0, ~7);
5f68f5ae 1864 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
fc40787a
AJ
1865 tcg_gen_shr_tl(t0, t0, t1);
1866 tcg_gen_xori_tl(t1, t1, 63);
1867 t2 = tcg_const_tl(0xfffffffffffffffeull);
1868 tcg_gen_shl_tl(t2, t2, t1);
78723684 1869 gen_load_gpr(t1, rt);
fc40787a
AJ
1870 tcg_gen_and_tl(t1, t1, t2);
1871 tcg_temp_free(t2);
1872 tcg_gen_or_tl(t0, t0, t1);
3cee3050 1873 tcg_temp_free(t1);
fc40787a 1874 gen_store_gpr(t0, rt);
6af0bf9c
FB
1875 opn = "ldr";
1876 break;
364d4831 1877 case OPC_LDPC:
3cee3050 1878 t1 = tcg_const_tl(pc_relative_pc(ctx));
364d4831 1879 gen_op_addr_add(ctx, t0, t0, t1);
3cee3050 1880 tcg_temp_free(t1);
5f68f5ae 1881 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
364d4831 1882 gen_store_gpr(t0, rt);
5c13fdfd 1883 opn = "ldpc";
364d4831 1884 break;
6af0bf9c 1885#endif
364d4831 1886 case OPC_LWPC:
3cee3050 1887 t1 = tcg_const_tl(pc_relative_pc(ctx));
364d4831 1888 gen_op_addr_add(ctx, t0, t0, t1);
3cee3050 1889 tcg_temp_free(t1);
5f68f5ae 1890 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
364d4831 1891 gen_store_gpr(t0, rt);
5c13fdfd 1892 opn = "lwpc";
364d4831 1893 break;
6af0bf9c 1894 case OPC_LW:
5f68f5ae 1895 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
78723684 1896 gen_store_gpr(t0, rt);
6af0bf9c
FB
1897 opn = "lw";
1898 break;
6af0bf9c 1899 case OPC_LH:
5f68f5ae 1900 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
78723684 1901 gen_store_gpr(t0, rt);
6af0bf9c
FB
1902 opn = "lh";
1903 break;
6af0bf9c 1904 case OPC_LHU:
5f68f5ae 1905 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUW);
78723684 1906 gen_store_gpr(t0, rt);
6af0bf9c
FB
1907 opn = "lhu";
1908 break;
1909 case OPC_LB:
5f68f5ae 1910 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
78723684 1911 gen_store_gpr(t0, rt);
6af0bf9c
FB
1912 opn = "lb";
1913 break;
6af0bf9c 1914 case OPC_LBU:
5f68f5ae 1915 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
78723684 1916 gen_store_gpr(t0, rt);
6af0bf9c
FB
1917 opn = "lbu";
1918 break;
1919 case OPC_LWL:
3cee3050 1920 t1 = tcg_temp_new();
fc40787a
AJ
1921 tcg_gen_andi_tl(t1, t0, 3);
1922#ifndef TARGET_WORDS_BIGENDIAN
1923 tcg_gen_xori_tl(t1, t1, 3);
1924#endif
1925 tcg_gen_shli_tl(t1, t1, 3);
1926 tcg_gen_andi_tl(t0, t0, ~3);
5f68f5ae 1927 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
fc40787a
AJ
1928 tcg_gen_shl_tl(t0, t0, t1);
1929 tcg_gen_xori_tl(t1, t1, 31);
1930 t2 = tcg_const_tl(0x7fffffffull);
1931 tcg_gen_shr_tl(t2, t2, t1);
6958549d 1932 gen_load_gpr(t1, rt);
fc40787a
AJ
1933 tcg_gen_and_tl(t1, t1, t2);
1934 tcg_temp_free(t2);
1935 tcg_gen_or_tl(t0, t0, t1);
3cee3050 1936 tcg_temp_free(t1);
fc40787a
AJ
1937 tcg_gen_ext32s_tl(t0, t0);
1938 gen_store_gpr(t0, rt);
6af0bf9c
FB
1939 opn = "lwl";
1940 break;
6af0bf9c 1941 case OPC_LWR:
3cee3050 1942 t1 = tcg_temp_new();
fc40787a
AJ
1943 tcg_gen_andi_tl(t1, t0, 3);
1944#ifdef TARGET_WORDS_BIGENDIAN
1945 tcg_gen_xori_tl(t1, t1, 3);
1946#endif
1947 tcg_gen_shli_tl(t1, t1, 3);
1948 tcg_gen_andi_tl(t0, t0, ~3);
5f68f5ae 1949 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
fc40787a
AJ
1950 tcg_gen_shr_tl(t0, t0, t1);
1951 tcg_gen_xori_tl(t1, t1, 31);
1952 t2 = tcg_const_tl(0xfffffffeull);
1953 tcg_gen_shl_tl(t2, t2, t1);
6958549d 1954 gen_load_gpr(t1, rt);
fc40787a
AJ
1955 tcg_gen_and_tl(t1, t1, t2);
1956 tcg_temp_free(t2);
1957 tcg_gen_or_tl(t0, t0, t1);
3cee3050 1958 tcg_temp_free(t1);
c728154b 1959 tcg_gen_ext32s_tl(t0, t0);
fc40787a 1960 gen_store_gpr(t0, rt);
6af0bf9c
FB
1961 opn = "lwr";
1962 break;
6af0bf9c 1963 case OPC_LL:
4368b29a 1964 case R6_OPC_LL:
e7139c44 1965 save_cpu_state(ctx, 1);
5c13fdfd 1966 op_ld_ll(t0, t0, ctx);
78723684 1967 gen_store_gpr(t0, rt);
6af0bf9c
FB
1968 opn = "ll";
1969 break;
d66c7132 1970 }
2abf314d 1971 (void)opn; /* avoid a compiler warning */
d66c7132
AJ
1972 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1973 tcg_temp_free(t0);
d66c7132
AJ
1974}
1975
5c13fdfd
AJ
1976/* Store */
1977static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
1978 int base, int16_t offset)
1979{
1980 const char *opn = "st";
1981 TCGv t0 = tcg_temp_new();
1982 TCGv t1 = tcg_temp_new();
1983
1984 gen_base_offset_addr(ctx, t0, base, offset);
1985 gen_load_gpr(t1, rt);
1986 switch (opc) {
1987#if defined(TARGET_MIPS64)
1988 case OPC_SD:
5f68f5ae 1989 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
5c13fdfd
AJ
1990 opn = "sd";
1991 break;
1992 case OPC_SDL:
1993 save_cpu_state(ctx, 1);
895c2d04 1994 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
5c13fdfd
AJ
1995 opn = "sdl";
1996 break;
1997 case OPC_SDR:
1998 save_cpu_state(ctx, 1);
895c2d04 1999 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
5c13fdfd
AJ
2000 opn = "sdr";
2001 break;
2002#endif
2003 case OPC_SW:
5f68f5ae 2004 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
5c13fdfd
AJ
2005 opn = "sw";
2006 break;
2007 case OPC_SH:
5f68f5ae 2008 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW);
5c13fdfd
AJ
2009 opn = "sh";
2010 break;
2011 case OPC_SB:
5f68f5ae 2012 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_8);
5c13fdfd
AJ
2013 opn = "sb";
2014 break;
2015 case OPC_SWL:
2016 save_cpu_state(ctx, 1);
895c2d04 2017 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
5c13fdfd
AJ
2018 opn = "swl";
2019 break;
2020 case OPC_SWR:
2021 save_cpu_state(ctx, 1);
895c2d04 2022 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
5c13fdfd
AJ
2023 opn = "swr";
2024 break;
2025 }
2abf314d 2026 (void)opn; /* avoid a compiler warning */
5c13fdfd
AJ
2027 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
2028 tcg_temp_free(t0);
2029 tcg_temp_free(t1);
2030}
2031
2032
d66c7132
AJ
2033/* Store conditional */
2034static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
2035 int base, int16_t offset)
2036{
2037 const char *opn = "st_cond";
2038 TCGv t0, t1;
2039
2d2826b9 2040#ifdef CONFIG_USER_ONLY
d66c7132 2041 t0 = tcg_temp_local_new();
d66c7132 2042 t1 = tcg_temp_local_new();
2d2826b9
AJ
2043#else
2044 t0 = tcg_temp_new();
2045 t1 = tcg_temp_new();
2046#endif
2047 gen_base_offset_addr(ctx, t0, base, offset);
d66c7132
AJ
2048 gen_load_gpr(t1, rt);
2049 switch (opc) {
2050#if defined(TARGET_MIPS64)
2051 case OPC_SCD:
bf7910c6 2052 case R6_OPC_SCD:
b835e919 2053 save_cpu_state(ctx, 1);
5c13fdfd 2054 op_st_scd(t1, t0, rt, ctx);
d66c7132
AJ
2055 opn = "scd";
2056 break;
2057#endif
6af0bf9c 2058 case OPC_SC:
4368b29a 2059 case R6_OPC_SC:
e7139c44 2060 save_cpu_state(ctx, 1);
5c13fdfd 2061 op_st_sc(t1, t0, rt, ctx);
6af0bf9c
FB
2062 opn = "sc";
2063 break;
6af0bf9c 2064 }
2abf314d 2065 (void)opn; /* avoid a compiler warning */
6af0bf9c 2066 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
78723684 2067 tcg_temp_free(t1);
d66c7132 2068 tcg_temp_free(t0);
6af0bf9c
FB
2069}
2070
6ea83fed 2071/* Load and store */
7a387fff 2072static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
356265ae 2073 int base, int16_t offset)
6ea83fed 2074{
923617a3 2075 const char *opn = "flt_ldst";
4e2474d6 2076 TCGv t0 = tcg_temp_new();
6ea83fed 2077
662d7485 2078 gen_base_offset_addr(ctx, t0, base, offset);
6ea83fed 2079 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 2080 memory access. */
6ea83fed
FB
2081 switch (opc) {
2082 case OPC_LWC1:
b6d96bed 2083 {
a7812ae4 2084 TCGv_i32 fp0 = tcg_temp_new_i32();
5f68f5ae 2085 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL);
b6d96bed 2086 gen_store_fpr32(fp0, ft);
a7812ae4 2087 tcg_temp_free_i32(fp0);
b6d96bed 2088 }
6ea83fed
FB
2089 opn = "lwc1";
2090 break;
2091 case OPC_SWC1:
b6d96bed 2092 {
a7812ae4 2093 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 2094 gen_load_fpr32(fp0, ft);
5f68f5ae 2095 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
a7812ae4 2096 tcg_temp_free_i32(fp0);
b6d96bed 2097 }
6ea83fed
FB
2098 opn = "swc1";
2099 break;
2100 case OPC_LDC1:
b6d96bed 2101 {
a7812ae4 2102 TCGv_i64 fp0 = tcg_temp_new_i64();
5f68f5ae 2103 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
b6d96bed 2104 gen_store_fpr64(ctx, fp0, ft);
a7812ae4 2105 tcg_temp_free_i64(fp0);
b6d96bed 2106 }
6ea83fed
FB
2107 opn = "ldc1";
2108 break;
2109 case OPC_SDC1:
b6d96bed 2110 {
a7812ae4 2111 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 2112 gen_load_fpr64(ctx, fp0, ft);
5f68f5ae 2113 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
a7812ae4 2114 tcg_temp_free_i64(fp0);
b6d96bed 2115 }
6ea83fed
FB
2116 opn = "sdc1";
2117 break;
2118 default:
923617a3 2119 MIPS_INVAL(opn);
e397ee33 2120 generate_exception(ctx, EXCP_RI);
78723684 2121 goto out;
6ea83fed 2122 }
2abf314d 2123 (void)opn; /* avoid a compiler warning */
6ea83fed 2124 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
78723684
TS
2125 out:
2126 tcg_temp_free(t0);
6ea83fed 2127}
6ea83fed 2128
5ab5c041
AJ
2129static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2130 int rs, int16_t imm)
26ebe468 2131{
5ab5c041 2132 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
26ebe468
NF
2133 check_cp1_enabled(ctx);
2134 gen_flt_ldst(ctx, op, rt, rs, imm);
2135 } else {
2136 generate_exception_err(ctx, EXCP_CpU, 1);
2137 }
2138}
2139
6af0bf9c 2140/* Arithmetic with immediate operand */
d75c135e
AJ
2141static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2142 int rt, int rs, int16_t imm)
6af0bf9c 2143{
324d9e32 2144 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
923617a3 2145 const char *opn = "imm arith";
6af0bf9c 2146
7a387fff 2147 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
ead9360e
TS
2148 /* If no destination, treat it as a NOP.
2149 For addi, we must generate the overflow exception when needed. */
6af0bf9c 2150 MIPS_DEBUG("NOP");
324d9e32 2151 return;
6af0bf9c
FB
2152 }
2153 switch (opc) {
2154 case OPC_ADDI:
48d38ca5 2155 {
324d9e32
AJ
2156 TCGv t0 = tcg_temp_local_new();
2157 TCGv t1 = tcg_temp_new();
2158 TCGv t2 = tcg_temp_new();
48d38ca5
TS
2159 int l1 = gen_new_label();
2160
324d9e32
AJ
2161 gen_load_gpr(t1, rs);
2162 tcg_gen_addi_tl(t0, t1, uimm);
2163 tcg_gen_ext32s_tl(t0, t0);
48d38ca5 2164
324d9e32
AJ
2165 tcg_gen_xori_tl(t1, t1, ~uimm);
2166 tcg_gen_xori_tl(t2, t0, uimm);
2167 tcg_gen_and_tl(t1, t1, t2);
2168 tcg_temp_free(t2);
2169 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2170 tcg_temp_free(t1);
48d38ca5
TS
2171 /* operands of same sign, result different sign */
2172 generate_exception(ctx, EXCP_OVERFLOW);
2173 gen_set_label(l1);
78723684 2174 tcg_gen_ext32s_tl(t0, t0);
324d9e32
AJ
2175 gen_store_gpr(t0, rt);
2176 tcg_temp_free(t0);
48d38ca5 2177 }
6af0bf9c
FB
2178 opn = "addi";
2179 break;
2180 case OPC_ADDIU:
324d9e32
AJ
2181 if (rs != 0) {
2182 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2183 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2184 } else {
2185 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2186 }
6af0bf9c
FB
2187 opn = "addiu";
2188 break;
d26bc211 2189#if defined(TARGET_MIPS64)
7a387fff 2190 case OPC_DADDI:
48d38ca5 2191 {
324d9e32
AJ
2192 TCGv t0 = tcg_temp_local_new();
2193 TCGv t1 = tcg_temp_new();
2194 TCGv t2 = tcg_temp_new();
48d38ca5
TS
2195 int l1 = gen_new_label();
2196
324d9e32
AJ
2197 gen_load_gpr(t1, rs);
2198 tcg_gen_addi_tl(t0, t1, uimm);
48d38ca5 2199
324d9e32
AJ
2200 tcg_gen_xori_tl(t1, t1, ~uimm);
2201 tcg_gen_xori_tl(t2, t0, uimm);
2202 tcg_gen_and_tl(t1, t1, t2);
2203 tcg_temp_free(t2);
2204 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2205 tcg_temp_free(t1);
48d38ca5
TS
2206 /* operands of same sign, result different sign */
2207 generate_exception(ctx, EXCP_OVERFLOW);
2208 gen_set_label(l1);
324d9e32
AJ
2209 gen_store_gpr(t0, rt);
2210 tcg_temp_free(t0);
48d38ca5 2211 }
7a387fff
TS
2212 opn = "daddi";
2213 break;
2214 case OPC_DADDIU:
324d9e32
AJ
2215 if (rs != 0) {
2216 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2217 } else {
2218 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2219 }
7a387fff
TS
2220 opn = "daddiu";
2221 break;
2222#endif
324d9e32 2223 }
2abf314d 2224 (void)opn; /* avoid a compiler warning */
324d9e32
AJ
2225 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2226}
2227
2228/* Logic with immediate operand */
d75c135e 2229static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
9fa77488 2230 int rt, int rs, int16_t imm)
324d9e32
AJ
2231{
2232 target_ulong uimm;
324d9e32
AJ
2233
2234 if (rt == 0) {
2235 /* If no destination, treat it as a NOP. */
2236 MIPS_DEBUG("NOP");
2237 return;
2238 }
2239 uimm = (uint16_t)imm;
2240 switch (opc) {
6af0bf9c 2241 case OPC_ANDI:
324d9e32
AJ
2242 if (likely(rs != 0))
2243 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2244 else
2245 tcg_gen_movi_tl(cpu_gpr[rt], 0);
7c2c3ea3
EJ
2246 MIPS_DEBUG("andi %s, %s, " TARGET_FMT_lx, regnames[rt],
2247 regnames[rs], uimm);
6af0bf9c
FB
2248 break;
2249 case OPC_ORI:
324d9e32
AJ
2250 if (rs != 0)
2251 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2252 else
2253 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
7c2c3ea3
EJ
2254 MIPS_DEBUG("ori %s, %s, " TARGET_FMT_lx, regnames[rt],
2255 regnames[rs], uimm);
6af0bf9c
FB
2256 break;
2257 case OPC_XORI:
324d9e32
AJ
2258 if (likely(rs != 0))
2259 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2260 else
2261 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
7c2c3ea3
EJ
2262 MIPS_DEBUG("xori %s, %s, " TARGET_FMT_lx, regnames[rt],
2263 regnames[rs], uimm);
6af0bf9c
FB
2264 break;
2265 case OPC_LUI:
d4ea6acd
LA
2266 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
2267 /* OPC_AUI */
2268 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2269 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2270 MIPS_DEBUG("aui %s, %s, %04x", regnames[rt], regnames[rs], imm);
2271 } else {
2272 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2273 MIPS_DEBUG("lui %s, " TARGET_FMT_lx, regnames[rt], uimm);
2274 }
7c2c3ea3
EJ
2275 break;
2276
2277 default:
2278 MIPS_DEBUG("Unknown logical immediate opcode %08x", opc);
6af0bf9c 2279 break;
324d9e32 2280 }
324d9e32
AJ
2281}
2282
2283/* Set on less than with immediate operand */
d75c135e 2284static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
9fa77488 2285 int rt, int rs, int16_t imm)
324d9e32
AJ
2286{
2287 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2288 const char *opn = "imm arith";
2289 TCGv t0;
2290
2291 if (rt == 0) {
2292 /* If no destination, treat it as a NOP. */
2293 MIPS_DEBUG("NOP");
2294 return;
2295 }
2296 t0 = tcg_temp_new();
2297 gen_load_gpr(t0, rs);
2298 switch (opc) {
2299 case OPC_SLTI:
e68dd28f 2300 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
2301 opn = "slti";
2302 break;
2303 case OPC_SLTIU:
e68dd28f 2304 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
2305 opn = "sltiu";
2306 break;
2307 }
2abf314d 2308 (void)opn; /* avoid a compiler warning */
324d9e32
AJ
2309 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2310 tcg_temp_free(t0);
2311}
2312
2313/* Shifts with immediate operand */
d75c135e 2314static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
324d9e32
AJ
2315 int rt, int rs, int16_t imm)
2316{
2317 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2318 const char *opn = "imm shift";
2319 TCGv t0;
2320
2321 if (rt == 0) {
2322 /* If no destination, treat it as a NOP. */
2323 MIPS_DEBUG("NOP");
2324 return;
2325 }
2326
2327 t0 = tcg_temp_new();
2328 gen_load_gpr(t0, rs);
2329 switch (opc) {
6af0bf9c 2330 case OPC_SLL:
78723684 2331 tcg_gen_shli_tl(t0, t0, uimm);
324d9e32 2332 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
6af0bf9c
FB
2333 opn = "sll";
2334 break;
2335 case OPC_SRA:
324d9e32 2336 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
6af0bf9c
FB
2337 opn = "sra";
2338 break;
2339 case OPC_SRL:
ea63e2c3
NF
2340 if (uimm != 0) {
2341 tcg_gen_ext32u_tl(t0, t0);
2342 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2343 } else {
2344 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
5a63bcb2 2345 }
ea63e2c3
NF
2346 opn = "srl";
2347 break;
2348 case OPC_ROTR:
2349 if (uimm != 0) {
2350 TCGv_i32 t1 = tcg_temp_new_i32();
2351
2352 tcg_gen_trunc_tl_i32(t1, t0);
2353 tcg_gen_rotri_i32(t1, t1, uimm);
2354 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2355 tcg_temp_free_i32(t1);
3399e30f
NF
2356 } else {
2357 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
ea63e2c3
NF
2358 }
2359 opn = "rotr";
7a387fff 2360 break;
d26bc211 2361#if defined(TARGET_MIPS64)
7a387fff 2362 case OPC_DSLL:
324d9e32 2363 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
2364 opn = "dsll";
2365 break;
2366 case OPC_DSRA:
324d9e32 2367 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
2368 opn = "dsra";
2369 break;
2370 case OPC_DSRL:
ea63e2c3
NF
2371 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2372 opn = "dsrl";
2373 break;
2374 case OPC_DROTR:
2375 if (uimm != 0) {
2376 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3399e30f
NF
2377 } else {
2378 tcg_gen_mov_tl(cpu_gpr[rt], t0);
5a63bcb2 2379 }
ea63e2c3 2380 opn = "drotr";
7a387fff
TS
2381 break;
2382 case OPC_DSLL32:
324d9e32 2383 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
2384 opn = "dsll32";
2385 break;
2386 case OPC_DSRA32:
324d9e32 2387 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
2388 opn = "dsra32";
2389 break;
2390 case OPC_DSRL32:
ea63e2c3
NF
2391 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2392 opn = "dsrl32";
2393 break;
2394 case OPC_DROTR32:
2395 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2396 opn = "drotr32";
6af0bf9c 2397 break;
7a387fff 2398#endif
6af0bf9c 2399 }
2abf314d 2400 (void)opn; /* avoid a compiler warning */
93b12ccc 2401 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
78723684 2402 tcg_temp_free(t0);
6af0bf9c
FB
2403}
2404
2405/* Arithmetic */
d75c135e
AJ
2406static void gen_arith(DisasContext *ctx, uint32_t opc,
2407 int rd, int rs, int rt)
6af0bf9c 2408{
923617a3 2409 const char *opn = "arith";
6af0bf9c 2410
7a387fff
TS
2411 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2412 && opc != OPC_DADD && opc != OPC_DSUB) {
ead9360e
TS
2413 /* If no destination, treat it as a NOP.
2414 For add & sub, we must generate the overflow exception when needed. */
6af0bf9c 2415 MIPS_DEBUG("NOP");
460f00c4 2416 return;
185f0762 2417 }
460f00c4 2418
6af0bf9c
FB
2419 switch (opc) {
2420 case OPC_ADD:
48d38ca5 2421 {
460f00c4
AJ
2422 TCGv t0 = tcg_temp_local_new();
2423 TCGv t1 = tcg_temp_new();
2424 TCGv t2 = tcg_temp_new();
48d38ca5
TS
2425 int l1 = gen_new_label();
2426
460f00c4
AJ
2427 gen_load_gpr(t1, rs);
2428 gen_load_gpr(t2, rt);
2429 tcg_gen_add_tl(t0, t1, t2);
2430 tcg_gen_ext32s_tl(t0, t0);
2431 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 2432 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 2433 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
2434 tcg_temp_free(t2);
2435 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2436 tcg_temp_free(t1);
48d38ca5
TS
2437 /* operands of same sign, result different sign */
2438 generate_exception(ctx, EXCP_OVERFLOW);
2439 gen_set_label(l1);
460f00c4
AJ
2440 gen_store_gpr(t0, rd);
2441 tcg_temp_free(t0);
48d38ca5 2442 }
6af0bf9c
FB
2443 opn = "add";
2444 break;
2445 case OPC_ADDU:
460f00c4
AJ
2446 if (rs != 0 && rt != 0) {
2447 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2448 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2449 } else if (rs == 0 && rt != 0) {
2450 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2451 } else if (rs != 0 && rt == 0) {
2452 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2453 } else {
2454 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2455 }
6af0bf9c
FB
2456 opn = "addu";
2457 break;
2458 case OPC_SUB:
48d38ca5 2459 {
460f00c4
AJ
2460 TCGv t0 = tcg_temp_local_new();
2461 TCGv t1 = tcg_temp_new();
2462 TCGv t2 = tcg_temp_new();
48d38ca5
TS
2463 int l1 = gen_new_label();
2464
460f00c4
AJ
2465 gen_load_gpr(t1, rs);
2466 gen_load_gpr(t2, rt);
2467 tcg_gen_sub_tl(t0, t1, t2);
2468 tcg_gen_ext32s_tl(t0, t0);
2469 tcg_gen_xor_tl(t2, t1, t2);
2470 tcg_gen_xor_tl(t1, t0, t1);
2471 tcg_gen_and_tl(t1, t1, t2);
2472 tcg_temp_free(t2);
2473 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2474 tcg_temp_free(t1);
31e3104f 2475 /* operands of different sign, first operand and result different sign */
48d38ca5
TS
2476 generate_exception(ctx, EXCP_OVERFLOW);
2477 gen_set_label(l1);
460f00c4
AJ
2478 gen_store_gpr(t0, rd);
2479 tcg_temp_free(t0);
48d38ca5 2480 }
6af0bf9c
FB
2481 opn = "sub";
2482 break;
2483 case OPC_SUBU:
460f00c4
AJ
2484 if (rs != 0 && rt != 0) {
2485 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2486 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2487 } else if (rs == 0 && rt != 0) {
2488 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
6bb72b18 2489 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
460f00c4
AJ
2490 } else if (rs != 0 && rt == 0) {
2491 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2492 } else {
2493 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2494 }
6af0bf9c
FB
2495 opn = "subu";
2496 break;
d26bc211 2497#if defined(TARGET_MIPS64)
7a387fff 2498 case OPC_DADD:
48d38ca5 2499 {
460f00c4
AJ
2500 TCGv t0 = tcg_temp_local_new();
2501 TCGv t1 = tcg_temp_new();
2502 TCGv t2 = tcg_temp_new();
48d38ca5
TS
2503 int l1 = gen_new_label();
2504
460f00c4
AJ
2505 gen_load_gpr(t1, rs);
2506 gen_load_gpr(t2, rt);
2507 tcg_gen_add_tl(t0, t1, t2);
2508 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 2509 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 2510 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
2511 tcg_temp_free(t2);
2512 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2513 tcg_temp_free(t1);
48d38ca5
TS
2514 /* operands of same sign, result different sign */
2515 generate_exception(ctx, EXCP_OVERFLOW);
2516 gen_set_label(l1);
460f00c4
AJ
2517 gen_store_gpr(t0, rd);
2518 tcg_temp_free(t0);
48d38ca5 2519 }
7a387fff
TS
2520 opn = "dadd";
2521 break;
2522 case OPC_DADDU:
460f00c4
AJ
2523 if (rs != 0 && rt != 0) {
2524 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2525 } else if (rs == 0 && rt != 0) {
2526 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2527 } else if (rs != 0 && rt == 0) {
2528 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2529 } else {
2530 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2531 }
7a387fff
TS
2532 opn = "daddu";
2533 break;
2534 case OPC_DSUB:
48d38ca5 2535 {
460f00c4
AJ
2536 TCGv t0 = tcg_temp_local_new();
2537 TCGv t1 = tcg_temp_new();
2538 TCGv t2 = tcg_temp_new();
48d38ca5
TS
2539 int l1 = gen_new_label();
2540
460f00c4
AJ
2541 gen_load_gpr(t1, rs);
2542 gen_load_gpr(t2, rt);
2543 tcg_gen_sub_tl(t0, t1, t2);
2544 tcg_gen_xor_tl(t2, t1, t2);
2545 tcg_gen_xor_tl(t1, t0, t1);
2546 tcg_gen_and_tl(t1, t1, t2);
2547 tcg_temp_free(t2);
2548 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2549 tcg_temp_free(t1);
31e3104f 2550 /* operands of different sign, first operand and result different sign */
48d38ca5
TS
2551 generate_exception(ctx, EXCP_OVERFLOW);
2552 gen_set_label(l1);
460f00c4
AJ
2553 gen_store_gpr(t0, rd);
2554 tcg_temp_free(t0);
48d38ca5 2555 }
7a387fff
TS
2556 opn = "dsub";
2557 break;
2558 case OPC_DSUBU:
460f00c4
AJ
2559 if (rs != 0 && rt != 0) {
2560 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2561 } else if (rs == 0 && rt != 0) {
2562 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2563 } else if (rs != 0 && rt == 0) {
2564 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2565 } else {
2566 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2567 }
7a387fff
TS
2568 opn = "dsubu";
2569 break;
2570#endif
460f00c4
AJ
2571 case OPC_MUL:
2572 if (likely(rs != 0 && rt != 0)) {
2573 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2574 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2575 } else {
2576 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2577 }
2578 opn = "mul";
6af0bf9c 2579 break;
460f00c4 2580 }
2abf314d 2581 (void)opn; /* avoid a compiler warning */
460f00c4
AJ
2582 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2583}
2584
2585/* Conditional move */
d75c135e 2586static void gen_cond_move(DisasContext *ctx, uint32_t opc,
9fa77488 2587 int rd, int rs, int rt)
460f00c4
AJ
2588{
2589 const char *opn = "cond move";
acf12465 2590 TCGv t0, t1, t2;
460f00c4
AJ
2591
2592 if (rd == 0) {
acf12465 2593 /* If no destination, treat it as a NOP. */
460f00c4
AJ
2594 MIPS_DEBUG("NOP");
2595 return;
2596 }
2597
acf12465
AJ
2598 t0 = tcg_temp_new();
2599 gen_load_gpr(t0, rt);
2600 t1 = tcg_const_tl(0);
2601 t2 = tcg_temp_new();
2602 gen_load_gpr(t2, rs);
460f00c4
AJ
2603 switch (opc) {
2604 case OPC_MOVN:
acf12465 2605 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
460f00c4 2606 opn = "movn";
6af0bf9c 2607 break;
460f00c4 2608 case OPC_MOVZ:
acf12465 2609 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
460f00c4
AJ
2610 opn = "movz";
2611 break;
b691d9d2
LA
2612 case OPC_SELNEZ:
2613 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
2614 opn = "selnez";
2615 break;
2616 case OPC_SELEQZ:
2617 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
2618 opn = "seleqz";
2619 break;
460f00c4 2620 }
acf12465
AJ
2621 tcg_temp_free(t2);
2622 tcg_temp_free(t1);
2623 tcg_temp_free(t0);
460f00c4 2624
2abf314d 2625 (void)opn; /* avoid a compiler warning */
460f00c4
AJ
2626 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2627}
2628
2629/* Logic */
d75c135e 2630static void gen_logic(DisasContext *ctx, uint32_t opc,
9fa77488 2631 int rd, int rs, int rt)
460f00c4
AJ
2632{
2633 const char *opn = "logic";
2634
2635 if (rd == 0) {
2636 /* If no destination, treat it as a NOP. */
2637 MIPS_DEBUG("NOP");
2638 return;
2639 }
2640
2641 switch (opc) {
6af0bf9c 2642 case OPC_AND:
460f00c4
AJ
2643 if (likely(rs != 0 && rt != 0)) {
2644 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2645 } else {
2646 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2647 }
6af0bf9c
FB
2648 opn = "and";
2649 break;
2650 case OPC_NOR:
460f00c4
AJ
2651 if (rs != 0 && rt != 0) {
2652 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2653 } else if (rs == 0 && rt != 0) {
2654 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2655 } else if (rs != 0 && rt == 0) {
2656 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2657 } else {
2658 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2659 }
6af0bf9c
FB
2660 opn = "nor";
2661 break;
2662 case OPC_OR:
460f00c4
AJ
2663 if (likely(rs != 0 && rt != 0)) {
2664 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2665 } else if (rs == 0 && rt != 0) {
2666 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2667 } else if (rs != 0 && rt == 0) {
2668 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2669 } else {
2670 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2671 }
6af0bf9c
FB
2672 opn = "or";
2673 break;
2674 case OPC_XOR:
460f00c4
AJ
2675 if (likely(rs != 0 && rt != 0)) {
2676 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2677 } else if (rs == 0 && rt != 0) {
2678 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2679 } else if (rs != 0 && rt == 0) {
2680 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2681 } else {
2682 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2683 }
6af0bf9c
FB
2684 opn = "xor";
2685 break;
460f00c4 2686 }
2abf314d 2687 (void)opn; /* avoid a compiler warning */
460f00c4
AJ
2688 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2689}
2690
2691/* Set on lower than */
d75c135e 2692static void gen_slt(DisasContext *ctx, uint32_t opc,
9fa77488 2693 int rd, int rs, int rt)
460f00c4
AJ
2694{
2695 const char *opn = "slt";
2696 TCGv t0, t1;
2697
2698 if (rd == 0) {
2699 /* If no destination, treat it as a NOP. */
2700 MIPS_DEBUG("NOP");
2701 return;
2702 }
2703
2704 t0 = tcg_temp_new();
2705 t1 = tcg_temp_new();
2706 gen_load_gpr(t0, rs);
2707 gen_load_gpr(t1, rt);
2708 switch (opc) {
2709 case OPC_SLT:
e68dd28f 2710 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
460f00c4 2711 opn = "slt";
6af0bf9c 2712 break;
460f00c4 2713 case OPC_SLTU:
e68dd28f 2714 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
460f00c4
AJ
2715 opn = "sltu";
2716 break;
2717 }
2abf314d 2718 (void)opn; /* avoid a compiler warning */
460f00c4
AJ
2719 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2720 tcg_temp_free(t0);
2721 tcg_temp_free(t1);
2722}
20c4c97c 2723
460f00c4 2724/* Shifts */
d75c135e
AJ
2725static void gen_shift(DisasContext *ctx, uint32_t opc,
2726 int rd, int rs, int rt)
460f00c4
AJ
2727{
2728 const char *opn = "shifts";
2729 TCGv t0, t1;
20c4c97c 2730
460f00c4
AJ
2731 if (rd == 0) {
2732 /* If no destination, treat it as a NOP.
2733 For add & sub, we must generate the overflow exception when needed. */
2734 MIPS_DEBUG("NOP");
2735 return;
2736 }
2737
2738 t0 = tcg_temp_new();
2739 t1 = tcg_temp_new();
2740 gen_load_gpr(t0, rs);
2741 gen_load_gpr(t1, rt);
2742 switch (opc) {
6af0bf9c 2743 case OPC_SLLV:
78723684
TS
2744 tcg_gen_andi_tl(t0, t0, 0x1f);
2745 tcg_gen_shl_tl(t0, t1, t0);
460f00c4 2746 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6af0bf9c
FB
2747 opn = "sllv";
2748 break;
2749 case OPC_SRAV:
78723684 2750 tcg_gen_andi_tl(t0, t0, 0x1f);
460f00c4 2751 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
6af0bf9c
FB
2752 opn = "srav";
2753 break;
2754 case OPC_SRLV:
ea63e2c3
NF
2755 tcg_gen_ext32u_tl(t1, t1);
2756 tcg_gen_andi_tl(t0, t0, 0x1f);
2757 tcg_gen_shr_tl(t0, t1, t0);
2758 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2759 opn = "srlv";
2760 break;
2761 case OPC_ROTRV:
2762 {
2763 TCGv_i32 t2 = tcg_temp_new_i32();
2764 TCGv_i32 t3 = tcg_temp_new_i32();
2765
2766 tcg_gen_trunc_tl_i32(t2, t0);
2767 tcg_gen_trunc_tl_i32(t3, t1);
2768 tcg_gen_andi_i32(t2, t2, 0x1f);
2769 tcg_gen_rotr_i32(t2, t3, t2);
2770 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
2771 tcg_temp_free_i32(t2);
2772 tcg_temp_free_i32(t3);
2773 opn = "rotrv";
5a63bcb2 2774 }
7a387fff 2775 break;
d26bc211 2776#if defined(TARGET_MIPS64)
7a387fff 2777 case OPC_DSLLV:
78723684 2778 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 2779 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
2780 opn = "dsllv";
2781 break;
2782 case OPC_DSRAV:
78723684 2783 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 2784 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
2785 opn = "dsrav";
2786 break;
2787 case OPC_DSRLV:
ea63e2c3
NF
2788 tcg_gen_andi_tl(t0, t0, 0x3f);
2789 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
2790 opn = "dsrlv";
2791 break;
2792 case OPC_DROTRV:
2793 tcg_gen_andi_tl(t0, t0, 0x3f);
2794 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
2795 opn = "drotrv";
6af0bf9c 2796 break;
7a387fff 2797#endif
6af0bf9c 2798 }
2abf314d 2799 (void)opn; /* avoid a compiler warning */
6af0bf9c 2800 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
78723684
TS
2801 tcg_temp_free(t0);
2802 tcg_temp_free(t1);
6af0bf9c
FB
2803}
2804
2805/* Arithmetic on HI/LO registers */
26135ead 2806static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
6af0bf9c 2807{
923617a3 2808 const char *opn = "hilo";
6af0bf9c
FB
2809
2810 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
ead9360e 2811 /* Treat as NOP. */
6af0bf9c 2812 MIPS_DEBUG("NOP");
a1f6684d 2813 return;
6af0bf9c 2814 }
4133498f 2815
4133498f
JL
2816 if (acc != 0) {
2817 check_dsp(ctx);
2818 }
2819
6af0bf9c
FB
2820 switch (opc) {
2821 case OPC_MFHI:
4133498f
JL
2822#if defined(TARGET_MIPS64)
2823 if (acc != 0) {
2824 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
2825 } else
2826#endif
2827 {
2828 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
2829 }
6af0bf9c
FB
2830 opn = "mfhi";
2831 break;
2832 case OPC_MFLO:
4133498f
JL
2833#if defined(TARGET_MIPS64)
2834 if (acc != 0) {
2835 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
2836 } else
2837#endif
2838 {
2839 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
2840 }
6af0bf9c
FB
2841 opn = "mflo";
2842 break;
2843 case OPC_MTHI:
4133498f
JL
2844 if (reg != 0) {
2845#if defined(TARGET_MIPS64)
2846 if (acc != 0) {
2847 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
2848 } else
2849#endif
2850 {
2851 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
2852 }
2853 } else {
2854 tcg_gen_movi_tl(cpu_HI[acc], 0);
2855 }
6af0bf9c
FB
2856 opn = "mthi";
2857 break;
2858 case OPC_MTLO:
4133498f
JL
2859 if (reg != 0) {
2860#if defined(TARGET_MIPS64)
2861 if (acc != 0) {
2862 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
2863 } else
2864#endif
2865 {
2866 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
2867 }
2868 } else {
2869 tcg_gen_movi_tl(cpu_LO[acc], 0);
2870 }
6af0bf9c
FB
2871 opn = "mtlo";
2872 break;
6af0bf9c 2873 }
2abf314d 2874 (void)opn; /* avoid a compiler warning */
6af0bf9c
FB
2875 MIPS_DEBUG("%s %s", opn, regnames[reg]);
2876}
2877
d4ea6acd
LA
2878static inline void gen_r6_ld(target_long addr, int reg, int memidx,
2879 TCGMemOp memop)
2880{
2881 TCGv t0 = tcg_const_tl(addr);
2882 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
2883 gen_store_gpr(t0, reg);
2884 tcg_temp_free(t0);
2885}
2886
2887static inline void gen_pcrel(DisasContext *ctx, int rs, int16_t imm)
2888{
2889 target_long offset;
2890 target_long addr;
2891
2892 switch (MASK_OPC_PCREL_TOP2BITS(ctx->opcode)) {
2893 case OPC_ADDIUPC:
2894 if (rs != 0) {
2895 offset = sextract32(ctx->opcode << 2, 0, 21);
2896 addr = addr_add(ctx, ctx->pc, offset);
2897 tcg_gen_movi_tl(cpu_gpr[rs], addr);
2898 }
2899 break;
2900 case R6_OPC_LWPC:
2901 offset = sextract32(ctx->opcode << 2, 0, 21);
2902 addr = addr_add(ctx, ctx->pc, offset);
2903 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
2904 break;
2905#if defined(TARGET_MIPS64)
2906 case OPC_LWUPC:
2907 check_mips_64(ctx);
2908 offset = sextract32(ctx->opcode << 2, 0, 21);
2909 addr = addr_add(ctx, ctx->pc, offset);
2910 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
2911 break;
2912#endif
2913 default:
2914 switch (MASK_OPC_PCREL_TOP5BITS(ctx->opcode)) {
2915 case OPC_AUIPC:
2916 if (rs != 0) {
2917 offset = imm << 16;
2918 addr = addr_add(ctx, ctx->pc, offset);
2919 tcg_gen_movi_tl(cpu_gpr[rs], addr);
2920 }
2921 break;
2922 case OPC_ALUIPC:
2923 if (rs != 0) {
2924 offset = imm << 16;
2925 addr = ~0xFFFF & addr_add(ctx, ctx->pc, offset);
2926 tcg_gen_movi_tl(cpu_gpr[rs], addr);
2927 }
2928 break;
2929#if defined(TARGET_MIPS64)
2930 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
2931 case R6_OPC_LDPC + (1 << 16):
2932 case R6_OPC_LDPC + (2 << 16):
2933 case R6_OPC_LDPC + (3 << 16):
2934 check_mips_64(ctx);
2935 offset = sextract32(ctx->opcode << 3, 0, 21);
2936 addr = addr_add(ctx, (ctx->pc & ~0x7), offset);
2937 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
2938 break;
2939#endif
2940 default:
2941 MIPS_INVAL("OPC_PCREL");
2942 generate_exception(ctx, EXCP_RI);
2943 break;
2944 }
2945 break;
2946 }
2947}
2948
b42ee5e1
LA
2949static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
2950{
2951 const char *opn = "r6 mul/div";
2952 TCGv t0, t1;
2953
2954 if (rd == 0) {
2955 /* Treat as NOP. */
2956 MIPS_DEBUG("NOP");
2957 return;
2958 }
2959
2960 t0 = tcg_temp_new();
2961 t1 = tcg_temp_new();
2962
2963 gen_load_gpr(t0, rs);
2964 gen_load_gpr(t1, rt);
2965
2966 switch (opc) {
2967 case R6_OPC_DIV:
2968 {
2969 TCGv t2 = tcg_temp_new();
2970 TCGv t3 = tcg_temp_new();
2971 tcg_gen_ext32s_tl(t0, t0);
2972 tcg_gen_ext32s_tl(t1, t1);
2973 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
2974 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
2975 tcg_gen_and_tl(t2, t2, t3);
2976 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
2977 tcg_gen_or_tl(t2, t2, t3);
2978 tcg_gen_movi_tl(t3, 0);
2979 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
2980 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2981 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2982 tcg_temp_free(t3);
2983 tcg_temp_free(t2);
2984 }
2985 opn = "div";
2986 break;
2987 case R6_OPC_MOD:
2988 {
2989 TCGv t2 = tcg_temp_new();
2990 TCGv t3 = tcg_temp_new();
2991 tcg_gen_ext32s_tl(t0, t0);
2992 tcg_gen_ext32s_tl(t1, t1);
2993 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
2994 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
2995 tcg_gen_and_tl(t2, t2, t3);
2996 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
2997 tcg_gen_or_tl(t2, t2, t3);
2998 tcg_gen_movi_tl(t3, 0);
2999 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3000 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3001 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3002 tcg_temp_free(t3);
3003 tcg_temp_free(t2);
3004 }
3005 opn = "mod";
3006 break;
3007 case R6_OPC_DIVU:
3008 {
3009 TCGv t2 = tcg_const_tl(0);
3010 TCGv t3 = tcg_const_tl(1);
3011 tcg_gen_ext32u_tl(t0, t0);
3012 tcg_gen_ext32u_tl(t1, t1);
3013 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3014 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3015 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3016 tcg_temp_free(t3);
3017 tcg_temp_free(t2);
3018 }
3019 opn = "divu";
3020 break;
3021 case R6_OPC_MODU:
3022 {
3023 TCGv t2 = tcg_const_tl(0);
3024 TCGv t3 = tcg_const_tl(1);
3025 tcg_gen_ext32u_tl(t0, t0);
3026 tcg_gen_ext32u_tl(t1, t1);
3027 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3028 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3029 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3030 tcg_temp_free(t3);
3031 tcg_temp_free(t2);
3032 }
3033 opn = "modu";
3034 break;
3035 case R6_OPC_MUL:
3036 {
3037 TCGv_i32 t2 = tcg_temp_new_i32();
3038 TCGv_i32 t3 = tcg_temp_new_i32();
3039 tcg_gen_trunc_tl_i32(t2, t0);
3040 tcg_gen_trunc_tl_i32(t3, t1);
3041 tcg_gen_mul_i32(t2, t2, t3);
3042 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3043 tcg_temp_free_i32(t2);
3044 tcg_temp_free_i32(t3);
3045 }
3046 opn = "mul";
3047 break;
3048 case R6_OPC_MUH:
3049 {
3050 TCGv_i32 t2 = tcg_temp_new_i32();
3051 TCGv_i32 t3 = tcg_temp_new_i32();
3052 tcg_gen_trunc_tl_i32(t2, t0);
3053 tcg_gen_trunc_tl_i32(t3, t1);
3054 tcg_gen_muls2_i32(t2, t3, t2, t3);
3055 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3056 tcg_temp_free_i32(t2);
3057 tcg_temp_free_i32(t3);
3058 }
3059 opn = "muh";
3060 break;
3061 case R6_OPC_MULU:
3062 {
3063 TCGv_i32 t2 = tcg_temp_new_i32();
3064 TCGv_i32 t3 = tcg_temp_new_i32();
3065 tcg_gen_trunc_tl_i32(t2, t0);
3066 tcg_gen_trunc_tl_i32(t3, t1);
3067 tcg_gen_mul_i32(t2, t2, t3);
3068 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3069 tcg_temp_free_i32(t2);
3070 tcg_temp_free_i32(t3);
3071 }
3072 opn = "mulu";
3073 break;
3074 case R6_OPC_MUHU:
3075 {
3076 TCGv_i32 t2 = tcg_temp_new_i32();
3077 TCGv_i32 t3 = tcg_temp_new_i32();
3078 tcg_gen_trunc_tl_i32(t2, t0);
3079 tcg_gen_trunc_tl_i32(t3, t1);
3080 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3081 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3082 tcg_temp_free_i32(t2);
3083 tcg_temp_free_i32(t3);
3084 }
3085 opn = "muhu";
3086 break;
3087#if defined(TARGET_MIPS64)
3088 case R6_OPC_DDIV:
3089 {
3090 TCGv t2 = tcg_temp_new();
3091 TCGv t3 = tcg_temp_new();
3092 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3093 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3094 tcg_gen_and_tl(t2, t2, t3);
3095 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3096 tcg_gen_or_tl(t2, t2, t3);
3097 tcg_gen_movi_tl(t3, 0);
3098 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3099 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3100 tcg_temp_free(t3);
3101 tcg_temp_free(t2);
3102 }
3103 opn = "ddiv";
3104 break;
3105 case R6_OPC_DMOD:
3106 {
3107 TCGv t2 = tcg_temp_new();
3108 TCGv t3 = tcg_temp_new();
3109 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3110 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3111 tcg_gen_and_tl(t2, t2, t3);
3112 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3113 tcg_gen_or_tl(t2, t2, t3);
3114 tcg_gen_movi_tl(t3, 0);
3115 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3116 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3117 tcg_temp_free(t3);
3118 tcg_temp_free(t2);
3119 }
3120 opn = "dmod";
3121 break;
3122 case R6_OPC_DDIVU:
3123 {
3124 TCGv t2 = tcg_const_tl(0);
3125 TCGv t3 = tcg_const_tl(1);
3126 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3127 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3128 tcg_temp_free(t3);
3129 tcg_temp_free(t2);
3130 }
3131 opn = "ddivu";
3132 break;
3133 case R6_OPC_DMODU:
3134 {
3135 TCGv t2 = tcg_const_tl(0);
3136 TCGv t3 = tcg_const_tl(1);
3137 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3138 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3139 tcg_temp_free(t3);
3140 tcg_temp_free(t2);
3141 }
3142 opn = "dmodu";
3143 break;
3144 case R6_OPC_DMUL:
3145 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3146 opn = "dmul";
3147 break;
3148 case R6_OPC_DMUH:
3149 {
3150 TCGv t2 = tcg_temp_new();
3151 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3152 tcg_temp_free(t2);
3153 }
3154 opn = "dmuh";
3155 break;
3156 case R6_OPC_DMULU:
3157 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3158 opn = "dmulu";
3159 break;
3160 case R6_OPC_DMUHU:
3161 {
3162 TCGv t2 = tcg_temp_new();
3163 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3164 tcg_temp_free(t2);
3165 }
3166 opn = "dmuhu";
3167 break;
3168#endif
3169 default:
3170 MIPS_INVAL(opn);
3171 generate_exception(ctx, EXCP_RI);
3172 goto out;
3173 }
3174 (void)opn; /* avoid a compiler warning */
3175 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
3176 out:
3177 tcg_temp_free(t0);
3178 tcg_temp_free(t1);
3179}
3180
26135ead
RS
3181static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3182 int acc, int rs, int rt)
6af0bf9c 3183{
923617a3 3184 const char *opn = "mul/div";
d45f89f4
AJ
3185 TCGv t0, t1;
3186
51127181
AJ
3187 t0 = tcg_temp_new();
3188 t1 = tcg_temp_new();
6af0bf9c 3189
78723684
TS
3190 gen_load_gpr(t0, rs);
3191 gen_load_gpr(t1, rt);
51127181 3192
26135ead
RS
3193 if (acc != 0) {
3194 check_dsp(ctx);
3195 }
3196
6af0bf9c
FB
3197 switch (opc) {
3198 case OPC_DIV:
48d38ca5 3199 {
51127181
AJ
3200 TCGv t2 = tcg_temp_new();
3201 TCGv t3 = tcg_temp_new();
d45f89f4
AJ
3202 tcg_gen_ext32s_tl(t0, t0);
3203 tcg_gen_ext32s_tl(t1, t1);
51127181
AJ
3204 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3205 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3206 tcg_gen_and_tl(t2, t2, t3);
3207 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3208 tcg_gen_or_tl(t2, t2, t3);
3209 tcg_gen_movi_tl(t3, 0);
3210 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
26135ead
RS
3211 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3212 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3213 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3214 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
51127181
AJ
3215 tcg_temp_free(t3);
3216 tcg_temp_free(t2);
48d38ca5 3217 }
6af0bf9c
FB
3218 opn = "div";
3219 break;
3220 case OPC_DIVU:
48d38ca5 3221 {
51127181
AJ
3222 TCGv t2 = tcg_const_tl(0);
3223 TCGv t3 = tcg_const_tl(1);
0c0ed03b
AJ
3224 tcg_gen_ext32u_tl(t0, t0);
3225 tcg_gen_ext32u_tl(t1, t1);
51127181 3226 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
26135ead
RS
3227 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3228 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3229 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3230 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
51127181
AJ
3231 tcg_temp_free(t3);
3232 tcg_temp_free(t2);
48d38ca5 3233 }
6af0bf9c
FB
3234 opn = "divu";
3235 break;
3236 case OPC_MULT:
214c465f 3237 {
ce1dd5d1
RH
3238 TCGv_i32 t2 = tcg_temp_new_i32();
3239 TCGv_i32 t3 = tcg_temp_new_i32();
ce1dd5d1
RH
3240 tcg_gen_trunc_tl_i32(t2, t0);
3241 tcg_gen_trunc_tl_i32(t3, t1);
3242 tcg_gen_muls2_i32(t2, t3, t2, t3);
3243 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3244 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3245 tcg_temp_free_i32(t2);
3246 tcg_temp_free_i32(t3);
214c465f 3247 }
6af0bf9c
FB
3248 opn = "mult";
3249 break;
3250 case OPC_MULTU:
214c465f 3251 {
ce1dd5d1
RH
3252 TCGv_i32 t2 = tcg_temp_new_i32();
3253 TCGv_i32 t3 = tcg_temp_new_i32();
ce1dd5d1
RH
3254 tcg_gen_trunc_tl_i32(t2, t0);
3255 tcg_gen_trunc_tl_i32(t3, t1);
3256 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3257 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3258 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3259 tcg_temp_free_i32(t2);
3260 tcg_temp_free_i32(t3);
214c465f 3261 }
6af0bf9c
FB
3262 opn = "multu";
3263 break;
d26bc211 3264#if defined(TARGET_MIPS64)
7a387fff 3265 case OPC_DDIV:
48d38ca5 3266 {
51127181
AJ
3267 TCGv t2 = tcg_temp_new();
3268 TCGv t3 = tcg_temp_new();
3269 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3270 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3271 tcg_gen_and_tl(t2, t2, t3);
3272 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3273 tcg_gen_or_tl(t2, t2, t3);
3274 tcg_gen_movi_tl(t3, 0);
3275 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
26135ead
RS
3276 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3277 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
51127181
AJ
3278 tcg_temp_free(t3);
3279 tcg_temp_free(t2);
48d38ca5 3280 }
7a387fff
TS
3281 opn = "ddiv";
3282 break;
3283 case OPC_DDIVU:
48d38ca5 3284 {
51127181
AJ
3285 TCGv t2 = tcg_const_tl(0);
3286 TCGv t3 = tcg_const_tl(1);
3287 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
26135ead
RS
3288 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3289 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
51127181
AJ
3290 tcg_temp_free(t3);
3291 tcg_temp_free(t2);
48d38ca5 3292 }
7a387fff
TS
3293 opn = "ddivu";
3294 break;
3295 case OPC_DMULT:
26135ead 3296 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
7a387fff
TS
3297 opn = "dmult";
3298 break;
3299 case OPC_DMULTU:
26135ead 3300 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
7a387fff
TS
3301 opn = "dmultu";
3302 break;
3303#endif
6af0bf9c 3304 case OPC_MADD:
214c465f 3305 {
d45f89f4
AJ
3306 TCGv_i64 t2 = tcg_temp_new_i64();
3307 TCGv_i64 t3 = tcg_temp_new_i64();
3308
3309 tcg_gen_ext_tl_i64(t2, t0);
3310 tcg_gen_ext_tl_i64(t3, t1);
3311 tcg_gen_mul_i64(t2, t2, t3);
4133498f 3312 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
3313 tcg_gen_add_i64(t2, t2, t3);
3314 tcg_temp_free_i64(t3);
3315 tcg_gen_trunc_i64_tl(t0, t2);
3316 tcg_gen_shri_i64(t2, t2, 32);
3317 tcg_gen_trunc_i64_tl(t1, t2);
3318 tcg_temp_free_i64(t2);
4133498f
JL
3319 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3320 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
214c465f 3321 }
6af0bf9c
FB
3322 opn = "madd";
3323 break;
3324 case OPC_MADDU:
4133498f 3325 {
d45f89f4
AJ
3326 TCGv_i64 t2 = tcg_temp_new_i64();
3327 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 3328
78723684
TS
3329 tcg_gen_ext32u_tl(t0, t0);
3330 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
3331 tcg_gen_extu_tl_i64(t2, t0);
3332 tcg_gen_extu_tl_i64(t3, t1);
3333 tcg_gen_mul_i64(t2, t2, t3);
4133498f 3334 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
3335 tcg_gen_add_i64(t2, t2, t3);
3336 tcg_temp_free_i64(t3);
3337 tcg_gen_trunc_i64_tl(t0, t2);
3338 tcg_gen_shri_i64(t2, t2, 32);
3339 tcg_gen_trunc_i64_tl(t1, t2);
3340 tcg_temp_free_i64(t2);
4133498f
JL
3341 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3342 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
214c465f 3343 }
6af0bf9c
FB
3344 opn = "maddu";
3345 break;
3346 case OPC_MSUB:
214c465f 3347 {
d45f89f4
AJ
3348 TCGv_i64 t2 = tcg_temp_new_i64();
3349 TCGv_i64 t3 = tcg_temp_new_i64();
3350
3351 tcg_gen_ext_tl_i64(t2, t0);
3352 tcg_gen_ext_tl_i64(t3, t1);
3353 tcg_gen_mul_i64(t2, t2, t3);
4133498f 3354 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 3355 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4
AJ
3356 tcg_temp_free_i64(t3);
3357 tcg_gen_trunc_i64_tl(t0, t2);
3358 tcg_gen_shri_i64(t2, t2, 32);
3359 tcg_gen_trunc_i64_tl(t1, t2);
3360 tcg_temp_free_i64(t2);
4133498f
JL
3361 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3362 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
214c465f 3363 }
6af0bf9c
FB
3364 opn = "msub";
3365 break;
3366 case OPC_MSUBU:
214c465f 3367 {
d45f89f4
AJ
3368 TCGv_i64 t2 = tcg_temp_new_i64();
3369 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 3370
78723684
TS
3371 tcg_gen_ext32u_tl(t0, t0);
3372 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
3373 tcg_gen_extu_tl_i64(t2, t0);
3374 tcg_gen_extu_tl_i64(t3, t1);
3375 tcg_gen_mul_i64(t2, t2, t3);
4133498f 3376 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 3377 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4
AJ
3378 tcg_temp_free_i64(t3);
3379 tcg_gen_trunc_i64_tl(t0, t2);
3380 tcg_gen_shri_i64(t2, t2, 32);
3381 tcg_gen_trunc_i64_tl(t1, t2);
3382 tcg_temp_free_i64(t2);
4133498f
JL
3383 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3384 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
214c465f 3385 }
6af0bf9c
FB
3386 opn = "msubu";
3387 break;
3388 default:
923617a3 3389 MIPS_INVAL(opn);
6af0bf9c 3390 generate_exception(ctx, EXCP_RI);
78723684 3391 goto out;
6af0bf9c 3392 }
2abf314d 3393 (void)opn; /* avoid a compiler warning */
6af0bf9c 3394 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
78723684
TS
3395 out:
3396 tcg_temp_free(t0);
3397 tcg_temp_free(t1);
6af0bf9c
FB
3398}
3399
e9c71dd1
TS
3400static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
3401 int rd, int rs, int rt)
3402{
3403 const char *opn = "mul vr54xx";
f157bfe1
AJ
3404 TCGv t0 = tcg_temp_new();
3405 TCGv t1 = tcg_temp_new();
e9c71dd1 3406
6c5c1e20
TS
3407 gen_load_gpr(t0, rs);
3408 gen_load_gpr(t1, rt);
e9c71dd1
TS
3409
3410 switch (opc) {
3411 case OPC_VR54XX_MULS:
895c2d04 3412 gen_helper_muls(t0, cpu_env, t0, t1);
e9c71dd1 3413 opn = "muls";
6958549d 3414 break;
e9c71dd1 3415 case OPC_VR54XX_MULSU:
895c2d04 3416 gen_helper_mulsu(t0, cpu_env, t0, t1);
e9c71dd1 3417 opn = "mulsu";
6958549d 3418 break;
e9c71dd1 3419 case OPC_VR54XX_MACC:
895c2d04 3420 gen_helper_macc(t0, cpu_env, t0, t1);
e9c71dd1 3421 opn = "macc";
6958549d 3422 break;
e9c71dd1 3423 case OPC_VR54XX_MACCU:
895c2d04 3424 gen_helper_maccu(t0, cpu_env, t0, t1);
e9c71dd1 3425 opn = "maccu";
6958549d 3426 break;
e9c71dd1 3427 case OPC_VR54XX_MSAC:
895c2d04 3428 gen_helper_msac(t0, cpu_env, t0, t1);
e9c71dd1 3429 opn = "msac";
6958549d 3430 break;
e9c71dd1 3431 case OPC_VR54XX_MSACU:
895c2d04 3432 gen_helper_msacu(t0, cpu_env, t0, t1);
e9c71dd1 3433 opn = "msacu";
6958549d 3434 break;
e9c71dd1 3435 case OPC_VR54XX_MULHI:
895c2d04 3436 gen_helper_mulhi(t0, cpu_env, t0, t1);
e9c71dd1 3437 opn = "mulhi";
6958549d 3438 break;
e9c71dd1 3439 case OPC_VR54XX_MULHIU:
895c2d04 3440 gen_helper_mulhiu(t0, cpu_env, t0, t1);
e9c71dd1 3441 opn = "mulhiu";
6958549d 3442 break;
e9c71dd1 3443 case OPC_VR54XX_MULSHI:
895c2d04 3444 gen_helper_mulshi(t0, cpu_env, t0, t1);
e9c71dd1 3445 opn = "mulshi";
6958549d 3446 break;
e9c71dd1 3447 case OPC_VR54XX_MULSHIU:
895c2d04 3448 gen_helper_mulshiu(t0, cpu_env, t0, t1);
e9c71dd1 3449 opn = "mulshiu";
6958549d 3450 break;
e9c71dd1 3451 case OPC_VR54XX_MACCHI:
895c2d04 3452 gen_helper_macchi(t0, cpu_env, t0, t1);
e9c71dd1 3453 opn = "macchi";
6958549d 3454 break;
e9c71dd1 3455 case OPC_VR54XX_MACCHIU:
895c2d04 3456 gen_helper_macchiu(t0, cpu_env, t0, t1);
e9c71dd1 3457 opn = "macchiu";
6958549d 3458 break;
e9c71dd1 3459 case OPC_VR54XX_MSACHI:
895c2d04 3460 gen_helper_msachi(t0, cpu_env, t0, t1);
e9c71dd1 3461 opn = "msachi";
6958549d 3462 break;
e9c71dd1 3463 case OPC_VR54XX_MSACHIU:
895c2d04 3464 gen_helper_msachiu(t0, cpu_env, t0, t1);
e9c71dd1 3465 opn = "msachiu";
6958549d 3466 break;
e9c71dd1
TS
3467 default:
3468 MIPS_INVAL("mul vr54xx");
3469 generate_exception(ctx, EXCP_RI);
6c5c1e20 3470 goto out;
e9c71dd1 3471 }
6c5c1e20 3472 gen_store_gpr(t0, rd);
2abf314d 3473 (void)opn; /* avoid a compiler warning */
e9c71dd1 3474 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
6c5c1e20
TS
3475
3476 out:
3477 tcg_temp_free(t0);
3478 tcg_temp_free(t1);
e9c71dd1
TS
3479}
3480
7a387fff 3481static void gen_cl (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
3482 int rd, int rs)
3483{
923617a3 3484 const char *opn = "CLx";
20e1fb52 3485 TCGv t0;
6c5c1e20 3486
6af0bf9c 3487 if (rd == 0) {
ead9360e 3488 /* Treat as NOP. */
6af0bf9c 3489 MIPS_DEBUG("NOP");
20e1fb52 3490 return;
6af0bf9c 3491 }
20e1fb52 3492 t0 = tcg_temp_new();
6c5c1e20 3493 gen_load_gpr(t0, rs);
6af0bf9c
FB
3494 switch (opc) {
3495 case OPC_CLO:
4267d3e6 3496 case R6_OPC_CLO:
20e1fb52 3497 gen_helper_clo(cpu_gpr[rd], t0);
6af0bf9c
FB
3498 opn = "clo";
3499 break;
3500 case OPC_CLZ:
4267d3e6 3501 case R6_OPC_CLZ:
20e1fb52 3502 gen_helper_clz(cpu_gpr[rd], t0);
6af0bf9c
FB
3503 opn = "clz";
3504 break;
d26bc211 3505#if defined(TARGET_MIPS64)
7a387fff 3506 case OPC_DCLO:
4267d3e6 3507 case R6_OPC_DCLO:
20e1fb52 3508 gen_helper_dclo(cpu_gpr[rd], t0);
7a387fff
TS
3509 opn = "dclo";
3510 break;
3511 case OPC_DCLZ:
4267d3e6 3512 case R6_OPC_DCLZ:
20e1fb52 3513 gen_helper_dclz(cpu_gpr[rd], t0);
7a387fff
TS
3514 opn = "dclz";
3515 break;
3516#endif
6af0bf9c 3517 }
2abf314d 3518 (void)opn; /* avoid a compiler warning */
6af0bf9c 3519 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
6c5c1e20 3520 tcg_temp_free(t0);
6af0bf9c
FB
3521}
3522
161f85e6 3523/* Godson integer instructions */
bd277fa1
RH
3524static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3525 int rd, int rs, int rt)
161f85e6
AJ
3526{
3527 const char *opn = "loongson";
3528 TCGv t0, t1;
3529
3530 if (rd == 0) {
3531 /* Treat as NOP. */
3532 MIPS_DEBUG("NOP");
3533 return;
3534 }
3535
3536 switch (opc) {
3537 case OPC_MULT_G_2E:
3538 case OPC_MULT_G_2F:
3539 case OPC_MULTU_G_2E:
3540 case OPC_MULTU_G_2F:
3541#if defined(TARGET_MIPS64)
3542 case OPC_DMULT_G_2E:
3543 case OPC_DMULT_G_2F:
3544 case OPC_DMULTU_G_2E:
3545 case OPC_DMULTU_G_2F:
3546#endif
3547 t0 = tcg_temp_new();
3548 t1 = tcg_temp_new();
3549 break;
3550 default:
3551 t0 = tcg_temp_local_new();
3552 t1 = tcg_temp_local_new();
3553 break;
3554 }
3555
3556 gen_load_gpr(t0, rs);
3557 gen_load_gpr(t1, rt);
3558
3559 switch (opc) {
3560 case OPC_MULT_G_2E:
3561 case OPC_MULT_G_2F:
3562 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3563 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3564 opn = "mult.g";
3565 break;
3566 case OPC_MULTU_G_2E:
3567 case OPC_MULTU_G_2F:
3568 tcg_gen_ext32u_tl(t0, t0);
3569 tcg_gen_ext32u_tl(t1, t1);
3570 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3571 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3572 opn = "multu.g";
3573 break;
3574 case OPC_DIV_G_2E:
3575 case OPC_DIV_G_2F:
3576 {
3577 int l1 = gen_new_label();
3578 int l2 = gen_new_label();
3579 int l3 = gen_new_label();
3580 tcg_gen_ext32s_tl(t0, t0);
3581 tcg_gen_ext32s_tl(t1, t1);
3582 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3583 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3584 tcg_gen_br(l3);
3585 gen_set_label(l1);
3586 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3587 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3588 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3589 tcg_gen_br(l3);
3590 gen_set_label(l2);
3591 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3592 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3593 gen_set_label(l3);
3594 }
3595 opn = "div.g";
3596 break;
3597 case OPC_DIVU_G_2E:
3598 case OPC_DIVU_G_2F:
3599 {
3600 int l1 = gen_new_label();
3601 int l2 = gen_new_label();
3602 tcg_gen_ext32u_tl(t0, t0);
3603 tcg_gen_ext32u_tl(t1, t1);
3604 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3605 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3606 tcg_gen_br(l2);
3607 gen_set_label(l1);
3608 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3609 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3610 gen_set_label(l2);
3611 }
3612 opn = "divu.g";
3613 break;
3614 case OPC_MOD_G_2E:
3615 case OPC_MOD_G_2F:
3616 {
3617 int l1 = gen_new_label();
3618 int l2 = gen_new_label();
3619 int l3 = gen_new_label();
3620 tcg_gen_ext32u_tl(t0, t0);
3621 tcg_gen_ext32u_tl(t1, t1);
3622 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3623 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3624 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3625 gen_set_label(l1);
3626 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3627 tcg_gen_br(l3);
3628 gen_set_label(l2);
3629 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3630 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3631 gen_set_label(l3);
3632 }
3633 opn = "mod.g";
3634 break;
3635 case OPC_MODU_G_2E:
3636 case OPC_MODU_G_2F:
3637 {
3638 int l1 = gen_new_label();
3639 int l2 = gen_new_label();
3640 tcg_gen_ext32u_tl(t0, t0);
3641 tcg_gen_ext32u_tl(t1, t1);
3642 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3643 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3644 tcg_gen_br(l2);
3645 gen_set_label(l1);
3646 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3647 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3648 gen_set_label(l2);
3649 }
3650 opn = "modu.g";
3651 break;
3652#if defined(TARGET_MIPS64)
3653 case OPC_DMULT_G_2E:
3654 case OPC_DMULT_G_2F:
3655 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3656 opn = "dmult.g";
3657 break;
3658 case OPC_DMULTU_G_2E:
3659 case OPC_DMULTU_G_2F:
3660 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3661 opn = "dmultu.g";
3662 break;
3663 case OPC_DDIV_G_2E:
3664 case OPC_DDIV_G_2F:
3665 {
3666 int l1 = gen_new_label();
3667 int l2 = gen_new_label();
3668 int l3 = gen_new_label();
3669 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3670 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3671 tcg_gen_br(l3);
3672 gen_set_label(l1);
3673 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3674 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3675 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3676 tcg_gen_br(l3);
3677 gen_set_label(l2);
3678 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3679 gen_set_label(l3);
3680 }
3681 opn = "ddiv.g";
3682 break;
3683 case OPC_DDIVU_G_2E:
3684 case OPC_DDIVU_G_2F:
3685 {
3686 int l1 = gen_new_label();
3687 int l2 = gen_new_label();
3688 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3689 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3690 tcg_gen_br(l2);
3691 gen_set_label(l1);
3692 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3693 gen_set_label(l2);
3694 }
3695 opn = "ddivu.g";
3696 break;
3697 case OPC_DMOD_G_2E:
3698 case OPC_DMOD_G_2F:
3699 {
3700 int l1 = gen_new_label();
3701 int l2 = gen_new_label();
3702 int l3 = gen_new_label();
3703 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3704 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3705 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3706 gen_set_label(l1);
3707 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3708 tcg_gen_br(l3);
3709 gen_set_label(l2);
3710 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3711 gen_set_label(l3);
3712 }
3713 opn = "dmod.g";
3714 break;
3715 case OPC_DMODU_G_2E:
3716 case OPC_DMODU_G_2F:
3717 {
3718 int l1 = gen_new_label();
3719 int l2 = gen_new_label();
3720 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3721 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3722 tcg_gen_br(l2);
3723 gen_set_label(l1);
3724 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3725 gen_set_label(l2);
3726 }
3727 opn = "dmodu.g";
3728 break;
3729#endif
3730 }
3731
2abf314d 3732 (void)opn; /* avoid a compiler warning */
161f85e6
AJ
3733 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
3734 tcg_temp_free(t0);
3735 tcg_temp_free(t1);
3736}
3737
bd277fa1
RH
3738/* Loongson multimedia instructions */
3739static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
3740{
3741 const char *opn = "loongson_cp2";
3742 uint32_t opc, shift_max;
3743 TCGv_i64 t0, t1;
3744
3745 opc = MASK_LMI(ctx->opcode);
3746 switch (opc) {
3747 case OPC_ADD_CP2:
3748 case OPC_SUB_CP2:
3749 case OPC_DADD_CP2:
3750 case OPC_DSUB_CP2:
3751 t0 = tcg_temp_local_new_i64();
3752 t1 = tcg_temp_local_new_i64();
3753 break;
3754 default:
3755 t0 = tcg_temp_new_i64();
3756 t1 = tcg_temp_new_i64();
3757 break;
3758 }
3759
3760 gen_load_fpr64(ctx, t0, rs);
3761 gen_load_fpr64(ctx, t1, rt);
3762
3763#define LMI_HELPER(UP, LO) \
3764 case OPC_##UP: gen_helper_##LO(t0, t0, t1); opn = #LO; break
3765#define LMI_HELPER_1(UP, LO) \
3766 case OPC_##UP: gen_helper_##LO(t0, t0); opn = #LO; break
3767#define LMI_DIRECT(UP, LO, OP) \
3768 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); opn = #LO; break
3769
3770 switch (opc) {
3771 LMI_HELPER(PADDSH, paddsh);
3772 LMI_HELPER(PADDUSH, paddush);
3773 LMI_HELPER(PADDH, paddh);
3774 LMI_HELPER(PADDW, paddw);
3775 LMI_HELPER(PADDSB, paddsb);
3776 LMI_HELPER(PADDUSB, paddusb);
3777 LMI_HELPER(PADDB, paddb);
3778
3779 LMI_HELPER(PSUBSH, psubsh);
3780 LMI_HELPER(PSUBUSH, psubush);
3781 LMI_HELPER(PSUBH, psubh);
3782 LMI_HELPER(PSUBW, psubw);
3783 LMI_HELPER(PSUBSB, psubsb);
3784 LMI_HELPER(PSUBUSB, psubusb);
3785 LMI_HELPER(PSUBB, psubb);
3786
3787 LMI_HELPER(PSHUFH, pshufh);
3788 LMI_HELPER(PACKSSWH, packsswh);
3789 LMI_HELPER(PACKSSHB, packsshb);
3790 LMI_HELPER(PACKUSHB, packushb);
3791
3792 LMI_HELPER(PUNPCKLHW, punpcklhw);
3793 LMI_HELPER(PUNPCKHHW, punpckhhw);
3794 LMI_HELPER(PUNPCKLBH, punpcklbh);
3795 LMI_HELPER(PUNPCKHBH, punpckhbh);
3796 LMI_HELPER(PUNPCKLWD, punpcklwd);
3797 LMI_HELPER(PUNPCKHWD, punpckhwd);
3798
3799 LMI_HELPER(PAVGH, pavgh);
3800 LMI_HELPER(PAVGB, pavgb);
3801 LMI_HELPER(PMAXSH, pmaxsh);
3802 LMI_HELPER(PMINSH, pminsh);
3803 LMI_HELPER(PMAXUB, pmaxub);
3804 LMI_HELPER(PMINUB, pminub);
3805
3806 LMI_HELPER(PCMPEQW, pcmpeqw);
3807 LMI_HELPER(PCMPGTW, pcmpgtw);
3808 LMI_HELPER(PCMPEQH, pcmpeqh);
3809 LMI_HELPER(PCMPGTH, pcmpgth);
3810 LMI_HELPER(PCMPEQB, pcmpeqb);
3811 LMI_HELPER(PCMPGTB, pcmpgtb);
3812
3813 LMI_HELPER(PSLLW, psllw);
3814 LMI_HELPER(PSLLH, psllh);
3815 LMI_HELPER(PSRLW, psrlw);
3816 LMI_HELPER(PSRLH, psrlh);
3817 LMI_HELPER(PSRAW, psraw);
3818 LMI_HELPER(PSRAH, psrah);
3819
3820 LMI_HELPER(PMULLH, pmullh);
3821 LMI_HELPER(PMULHH, pmulhh);
3822 LMI_HELPER(PMULHUH, pmulhuh);
3823 LMI_HELPER(PMADDHW, pmaddhw);
3824
3825 LMI_HELPER(PASUBUB, pasubub);
3826 LMI_HELPER_1(BIADD, biadd);
3827 LMI_HELPER_1(PMOVMSKB, pmovmskb);
3828
3829 LMI_DIRECT(PADDD, paddd, add);
3830 LMI_DIRECT(PSUBD, psubd, sub);
3831 LMI_DIRECT(XOR_CP2, xor, xor);
3832 LMI_DIRECT(NOR_CP2, nor, nor);
3833 LMI_DIRECT(AND_CP2, and, and);
3834 LMI_DIRECT(PANDN, pandn, andc);
3835 LMI_DIRECT(OR, or, or);
3836
3837 case OPC_PINSRH_0:
3838 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
3839 opn = "pinsrh_0";
3840 break;
3841 case OPC_PINSRH_1:
3842 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
3843 opn = "pinsrh_1";
3844 break;
3845 case OPC_PINSRH_2:
3846 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
3847 opn = "pinsrh_2";
3848 break;
3849 case OPC_PINSRH_3:
3850 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
3851 opn = "pinsrh_3";
3852 break;
3853
3854 case OPC_PEXTRH:
3855 tcg_gen_andi_i64(t1, t1, 3);
3856 tcg_gen_shli_i64(t1, t1, 4);
3857 tcg_gen_shr_i64(t0, t0, t1);
3858 tcg_gen_ext16u_i64(t0, t0);
3859 opn = "pextrh";
3860 break;
3861
3862 case OPC_ADDU_CP2:
3863 tcg_gen_add_i64(t0, t0, t1);
3864 tcg_gen_ext32s_i64(t0, t0);
3865 opn = "addu";
3866 break;
3867 case OPC_SUBU_CP2:
3868 tcg_gen_sub_i64(t0, t0, t1);
3869 tcg_gen_ext32s_i64(t0, t0);
3870 opn = "addu";
3871 break;
3872
3873 case OPC_SLL_CP2:
3874 opn = "sll";
3875 shift_max = 32;
3876 goto do_shift;
3877 case OPC_SRL_CP2:
3878 opn = "srl";
3879 shift_max = 32;
3880 goto do_shift;
3881 case OPC_SRA_CP2:
3882 opn = "sra";
3883 shift_max = 32;
3884 goto do_shift;
3885 case OPC_DSLL_CP2:
3886 opn = "dsll";
3887 shift_max = 64;
3888 goto do_shift;
3889 case OPC_DSRL_CP2:
3890 opn = "dsrl";
3891 shift_max = 64;
3892 goto do_shift;
3893 case OPC_DSRA_CP2:
3894 opn = "dsra";
3895 shift_max = 64;
3896 goto do_shift;
3897 do_shift:
3898 /* Make sure shift count isn't TCG undefined behaviour. */
3899 tcg_gen_andi_i64(t1, t1, shift_max - 1);
3900
3901 switch (opc) {
3902 case OPC_SLL_CP2:
3903 case OPC_DSLL_CP2:
3904 tcg_gen_shl_i64(t0, t0, t1);
3905 break;
3906 case OPC_SRA_CP2:
3907 case OPC_DSRA_CP2:
3908 /* Since SRA is UndefinedResult without sign-extended inputs,
3909 we can treat SRA and DSRA the same. */
3910 tcg_gen_sar_i64(t0, t0, t1);
3911 break;
3912 case OPC_SRL_CP2:
3913 /* We want to shift in zeros for SRL; zero-extend first. */
3914 tcg_gen_ext32u_i64(t0, t0);
3915 /* FALLTHRU */
3916 case OPC_DSRL_CP2:
3917 tcg_gen_shr_i64(t0, t0, t1);
3918 break;
3919 }
3920
3921 if (shift_max == 32) {
3922 tcg_gen_ext32s_i64(t0, t0);
3923 }
3924
3925 /* Shifts larger than MAX produce zero. */
3926 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
3927 tcg_gen_neg_i64(t1, t1);
3928 tcg_gen_and_i64(t0, t0, t1);
3929 break;
3930
3931 case OPC_ADD_CP2:
3932 case OPC_DADD_CP2:
3933 {
3934 TCGv_i64 t2 = tcg_temp_new_i64();
3935 int lab = gen_new_label();
3936
3937 tcg_gen_mov_i64(t2, t0);
3938 tcg_gen_add_i64(t0, t1, t2);
3939 if (opc == OPC_ADD_CP2) {
3940 tcg_gen_ext32s_i64(t0, t0);
3941 }
3942 tcg_gen_xor_i64(t1, t1, t2);
3943 tcg_gen_xor_i64(t2, t2, t0);
3944 tcg_gen_andc_i64(t1, t2, t1);
3945 tcg_temp_free_i64(t2);
3946 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
3947 generate_exception(ctx, EXCP_OVERFLOW);
3948 gen_set_label(lab);
3949
3950 opn = (opc == OPC_ADD_CP2 ? "add" : "dadd");
3951 break;
3952 }
3953
3954 case OPC_SUB_CP2:
3955 case OPC_DSUB_CP2:
3956 {
3957 TCGv_i64 t2 = tcg_temp_new_i64();
3958 int lab = gen_new_label();
3959
3960 tcg_gen_mov_i64(t2, t0);
3961 tcg_gen_sub_i64(t0, t1, t2);
3962 if (opc == OPC_SUB_CP2) {
3963 tcg_gen_ext32s_i64(t0, t0);
3964 }
3965 tcg_gen_xor_i64(t1, t1, t2);
3966 tcg_gen_xor_i64(t2, t2, t0);
3967 tcg_gen_and_i64(t1, t1, t2);
3968 tcg_temp_free_i64(t2);
3969 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
3970 generate_exception(ctx, EXCP_OVERFLOW);
3971 gen_set_label(lab);
3972
3973 opn = (opc == OPC_SUB_CP2 ? "sub" : "dsub");
3974 break;
3975 }
3976
3977 case OPC_PMULUW:
3978 tcg_gen_ext32u_i64(t0, t0);
3979 tcg_gen_ext32u_i64(t1, t1);
3980 tcg_gen_mul_i64(t0, t0, t1);
3981 opn = "pmuluw";
3982 break;
3983
3984 case OPC_SEQU_CP2:
3985 case OPC_SEQ_CP2:
3986 case OPC_SLTU_CP2:
3987 case OPC_SLT_CP2:
3988 case OPC_SLEU_CP2:
3989 case OPC_SLE_CP2:
3990 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
3991 FD field is the CC field? */
3992 default:
3993 MIPS_INVAL(opn);
3994 generate_exception(ctx, EXCP_RI);
3995 return;
3996 }
3997
3998#undef LMI_HELPER
3999#undef LMI_DIRECT
4000
4001 gen_store_fpr64(ctx, t0, rd);
4002
4003 (void)opn; /* avoid a compiler warning */
4004 MIPS_DEBUG("%s %s, %s, %s", opn,
4005 fregnames[rd], fregnames[rs], fregnames[rt]);
4006 tcg_temp_free_i64(t0);
4007 tcg_temp_free_i64(t1);
4008}
4009
6af0bf9c 4010/* Traps */
7a387fff 4011static void gen_trap (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
4012 int rs, int rt, int16_t imm)
4013{
4014 int cond;
cdc0faa6 4015 TCGv t0 = tcg_temp_new();
1ba74fb8 4016 TCGv t1 = tcg_temp_new();
6af0bf9c
FB
4017
4018 cond = 0;
4019 /* Load needed operands */
4020 switch (opc) {
4021 case OPC_TEQ:
4022 case OPC_TGE:
4023 case OPC_TGEU:
4024 case OPC_TLT:
4025 case OPC_TLTU:
4026 case OPC_TNE:
4027 /* Compare two registers */
4028 if (rs != rt) {
be24bb4f
TS
4029 gen_load_gpr(t0, rs);
4030 gen_load_gpr(t1, rt);
6af0bf9c
FB
4031 cond = 1;
4032 }
179e32bb 4033 break;
6af0bf9c
FB
4034 case OPC_TEQI:
4035 case OPC_TGEI:
4036 case OPC_TGEIU:
4037 case OPC_TLTI:
4038 case OPC_TLTIU:
4039 case OPC_TNEI:
4040 /* Compare register to immediate */
4041 if (rs != 0 || imm != 0) {
be24bb4f
TS
4042 gen_load_gpr(t0, rs);
4043 tcg_gen_movi_tl(t1, (int32_t)imm);
6af0bf9c
FB
4044 cond = 1;
4045 }
4046 break;
4047 }
4048 if (cond == 0) {
4049 switch (opc) {
4050 case OPC_TEQ: /* rs == rs */
4051 case OPC_TEQI: /* r0 == 0 */
4052 case OPC_TGE: /* rs >= rs */
4053 case OPC_TGEI: /* r0 >= 0 */
4054 case OPC_TGEU: /* rs >= rs unsigned */
4055 case OPC_TGEIU: /* r0 >= 0 unsigned */
4056 /* Always trap */
cdc0faa6 4057 generate_exception(ctx, EXCP_TRAP);
6af0bf9c
FB
4058 break;
4059 case OPC_TLT: /* rs < rs */
4060 case OPC_TLTI: /* r0 < 0 */
4061 case OPC_TLTU: /* rs < rs unsigned */
4062 case OPC_TLTIU: /* r0 < 0 unsigned */
4063 case OPC_TNE: /* rs != rs */
4064 case OPC_TNEI: /* r0 != 0 */
ead9360e 4065 /* Never trap: treat as NOP. */
cdc0faa6 4066 break;
6af0bf9c
FB
4067 }
4068 } else {
cdc0faa6
AJ
4069 int l1 = gen_new_label();
4070
6af0bf9c
FB
4071 switch (opc) {
4072 case OPC_TEQ:
4073 case OPC_TEQI:
cdc0faa6 4074 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6af0bf9c
FB
4075 break;
4076 case OPC_TGE:
4077 case OPC_TGEI:
cdc0faa6 4078 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6af0bf9c
FB
4079 break;
4080 case OPC_TGEU:
4081 case OPC_TGEIU:
cdc0faa6 4082 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6af0bf9c
FB
4083 break;
4084 case OPC_TLT:
4085 case OPC_TLTI:
cdc0faa6 4086 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6af0bf9c
FB
4087 break;
4088 case OPC_TLTU:
4089 case OPC_TLTIU:
cdc0faa6 4090 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6af0bf9c
FB
4091 break;
4092 case OPC_TNE:
4093 case OPC_TNEI:
cdc0faa6 4094 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6af0bf9c 4095 break;
6af0bf9c 4096 }
cdc0faa6 4097 generate_exception(ctx, EXCP_TRAP);
08ba7963
TS
4098 gen_set_label(l1);
4099 }
be24bb4f
TS
4100 tcg_temp_free(t0);
4101 tcg_temp_free(t1);
6af0bf9c
FB
4102}
4103
356265ae 4104static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
c53be334 4105{
6e256c93
FB
4106 TranslationBlock *tb;
4107 tb = ctx->tb;
7b270ef2
NF
4108 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
4109 likely(!ctx->singlestep_enabled)) {
57fec1fe 4110 tcg_gen_goto_tb(n);
9b9e4393 4111 gen_save_pc(dest);
8cfd0495 4112 tcg_gen_exit_tb((uintptr_t)tb + n);
6e256c93 4113 } else {
9b9e4393 4114 gen_save_pc(dest);
7b270ef2
NF
4115 if (ctx->singlestep_enabled) {
4116 save_cpu_state(ctx, 0);
895c2d04 4117 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
7b270ef2 4118 }
57fec1fe 4119 tcg_gen_exit_tb(0);
6e256c93 4120 }
c53be334
FB
4121}
4122
6af0bf9c 4123/* Branches (before delay slot) */
7a387fff 4124static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
7dca4ad0 4125 int insn_bytes,
b231c103
YK
4126 int rs, int rt, int32_t offset,
4127 int delayslot_size)
6af0bf9c 4128{
d077b6f7 4129 target_ulong btgt = -1;
3ad4bb2d 4130 int blink = 0;
2fdbad25 4131 int bcond_compute = 0;
1ba74fb8
AJ
4132 TCGv t0 = tcg_temp_new();
4133 TCGv t1 = tcg_temp_new();
3ad4bb2d
TS
4134
4135 if (ctx->hflags & MIPS_HFLAG_BMASK) {
923617a3 4136#ifdef MIPS_DEBUG_DISAS
d12d51d5 4137 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
923617a3 4138#endif
3ad4bb2d 4139 generate_exception(ctx, EXCP_RI);
6c5c1e20 4140 goto out;
3ad4bb2d 4141 }
6af0bf9c 4142
6af0bf9c
FB
4143 /* Load needed operands */
4144 switch (opc) {
4145 case OPC_BEQ:
4146 case OPC_BEQL:
4147 case OPC_BNE:
4148 case OPC_BNEL:
4149 /* Compare two registers */
4150 if (rs != rt) {
6c5c1e20
TS
4151 gen_load_gpr(t0, rs);
4152 gen_load_gpr(t1, rt);
2fdbad25 4153 bcond_compute = 1;
6af0bf9c 4154 }
7dca4ad0 4155 btgt = ctx->pc + insn_bytes + offset;
6af0bf9c
FB
4156 break;
4157 case OPC_BGEZ:
4158 case OPC_BGEZAL:
4159 case OPC_BGEZALL:
4160 case OPC_BGEZL:
4161 case OPC_BGTZ:
4162 case OPC_BGTZL:
4163 case OPC_BLEZ:
4164 case OPC_BLEZL:
4165 case OPC_BLTZ:
4166 case OPC_BLTZAL:
4167 case OPC_BLTZALL:
4168 case OPC_BLTZL:
4169 /* Compare to zero */
4170 if (rs != 0) {
6c5c1e20 4171 gen_load_gpr(t0, rs);
2fdbad25 4172 bcond_compute = 1;
6af0bf9c 4173 }
7dca4ad0 4174 btgt = ctx->pc + insn_bytes + offset;
6af0bf9c 4175 break;
e45a93e2
JL
4176 case OPC_BPOSGE32:
4177#if defined(TARGET_MIPS64)
4178 case OPC_BPOSGE64:
4179 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
4180#else
4181 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4182#endif
4183 bcond_compute = 1;
4184 btgt = ctx->pc + insn_bytes + offset;
4185 break;
6af0bf9c
FB
4186 case OPC_J:
4187 case OPC_JAL:
364d4831 4188 case OPC_JALX:
6af0bf9c 4189 /* Jump to immediate */
7dca4ad0 4190 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
6af0bf9c
FB
4191 break;
4192 case OPC_JR:
4193 case OPC_JALR:
4194 /* Jump to register */
7a387fff
TS
4195 if (offset != 0 && offset != 16) {
4196 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
cbeb0857 4197 others are reserved. */
923617a3 4198 MIPS_INVAL("jump hint");
6af0bf9c 4199 generate_exception(ctx, EXCP_RI);
6c5c1e20 4200 goto out;
6af0bf9c 4201 }
d077b6f7 4202 gen_load_gpr(btarget, rs);
6af0bf9c
FB
4203 break;
4204 default:
4205 MIPS_INVAL("branch/jump");
4206 generate_exception(ctx, EXCP_RI);
6c5c1e20 4207 goto out;
6af0bf9c 4208 }
2fdbad25 4209 if (bcond_compute == 0) {
6af0bf9c
FB
4210 /* No condition to be computed */
4211 switch (opc) {
4212 case OPC_BEQ: /* rx == rx */
4213 case OPC_BEQL: /* rx == rx likely */
4214 case OPC_BGEZ: /* 0 >= 0 */
4215 case OPC_BGEZL: /* 0 >= 0 likely */
4216 case OPC_BLEZ: /* 0 <= 0 */
4217 case OPC_BLEZL: /* 0 <= 0 likely */
4218 /* Always take */
4ad40f36 4219 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
4220 MIPS_DEBUG("balways");
4221 break;
4222 case OPC_BGEZAL: /* 0 >= 0 */
4223 case OPC_BGEZALL: /* 0 >= 0 likely */
4224 /* Always take and link */
4225 blink = 31;
4ad40f36 4226 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
4227 MIPS_DEBUG("balways and link");
4228 break;
4229 case OPC_BNE: /* rx != rx */
4230 case OPC_BGTZ: /* 0 > 0 */
4231 case OPC_BLTZ: /* 0 < 0 */
ead9360e 4232 /* Treat as NOP. */
6af0bf9c 4233 MIPS_DEBUG("bnever (NOP)");
6c5c1e20 4234 goto out;
eeef26cd 4235 case OPC_BLTZAL: /* 0 < 0 */
3c824109
NF
4236 /* Handle as an unconditional branch to get correct delay
4237 slot checking. */
4238 blink = 31;
b231c103 4239 btgt = ctx->pc + insn_bytes + delayslot_size;
3c824109 4240 ctx->hflags |= MIPS_HFLAG_B;
9898128f 4241 MIPS_DEBUG("bnever and link");
3c824109 4242 break;
eeef26cd 4243 case OPC_BLTZALL: /* 0 < 0 likely */
1ba74fb8 4244 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
9898128f
TS
4245 /* Skip the instruction in the delay slot */
4246 MIPS_DEBUG("bnever, link and skip");
4247 ctx->pc += 4;
6c5c1e20 4248 goto out;
6af0bf9c
FB
4249 case OPC_BNEL: /* rx != rx likely */
4250 case OPC_BGTZL: /* 0 > 0 likely */
6af0bf9c
FB
4251 case OPC_BLTZL: /* 0 < 0 likely */
4252 /* Skip the instruction in the delay slot */
4253 MIPS_DEBUG("bnever and skip");
9898128f 4254 ctx->pc += 4;
6c5c1e20 4255 goto out;
6af0bf9c 4256 case OPC_J:
4ad40f36 4257 ctx->hflags |= MIPS_HFLAG_B;
d077b6f7 4258 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
6af0bf9c 4259 break;
364d4831
NF
4260 case OPC_JALX:
4261 ctx->hflags |= MIPS_HFLAG_BX;
4262 /* Fallthrough */
6af0bf9c
FB
4263 case OPC_JAL:
4264 blink = 31;
4ad40f36 4265 ctx->hflags |= MIPS_HFLAG_B;
d077b6f7 4266 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
6af0bf9c
FB
4267 break;
4268 case OPC_JR:
4ad40f36 4269 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
4270 MIPS_DEBUG("jr %s", regnames[rs]);
4271 break;
4272 case OPC_JALR:
4273 blink = rt;
4ad40f36 4274 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
4275 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
4276 break;
4277 default:
4278 MIPS_INVAL("branch/jump");
4279 generate_exception(ctx, EXCP_RI);
6c5c1e20 4280 goto out;
6af0bf9c
FB
4281 }
4282 } else {
4283 switch (opc) {
4284 case OPC_BEQ:
e68dd28f 4285 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
923617a3 4286 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
d077b6f7 4287 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
4288 goto not_likely;
4289 case OPC_BEQL:
e68dd28f 4290 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
923617a3 4291 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
d077b6f7 4292 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
4293 goto likely;
4294 case OPC_BNE:
e68dd28f 4295 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
923617a3 4296 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
d077b6f7 4297 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
4298 goto not_likely;
4299 case OPC_BNEL:
e68dd28f 4300 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
923617a3 4301 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
d077b6f7 4302 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
4303 goto likely;
4304 case OPC_BGEZ:
e68dd28f 4305 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
d077b6f7 4306 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
4307 goto not_likely;
4308 case OPC_BGEZL:
e68dd28f 4309 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
d077b6f7 4310 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
4311 goto likely;
4312 case OPC_BGEZAL:
e68dd28f 4313 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
d077b6f7 4314 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
4315 blink = 31;
4316 goto not_likely;
4317 case OPC_BGEZALL:
e68dd28f 4318 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c 4319 blink = 31;
d077b6f7 4320 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
4321 goto likely;
4322 case OPC_BGTZ:
e68dd28f 4323 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
d077b6f7 4324 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
4325 goto not_likely;
4326 case OPC_BGTZL:
e68dd28f 4327 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
d077b6f7 4328 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
4329 goto likely;
4330 case OPC_BLEZ:
e68dd28f 4331 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
d077b6f7 4332 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
4333 goto not_likely;
4334 case OPC_BLEZL:
e68dd28f 4335 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
d077b6f7 4336 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
4337 goto likely;
4338 case OPC_BLTZ:
e68dd28f 4339 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
d077b6f7 4340 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
4341 goto not_likely;
4342 case OPC_BLTZL:
e68dd28f 4343 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
d077b6f7 4344 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 4345 goto likely;
e45a93e2
JL
4346 case OPC_BPOSGE32:
4347 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
4348 MIPS_DEBUG("bposge32 " TARGET_FMT_lx, btgt);
4349 goto not_likely;
4350#if defined(TARGET_MIPS64)
4351 case OPC_BPOSGE64:
4352 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
4353 MIPS_DEBUG("bposge64 " TARGET_FMT_lx, btgt);
4354 goto not_likely;
4355#endif
6af0bf9c 4356 case OPC_BLTZAL:
e68dd28f 4357 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 4358 blink = 31;
d077b6f7 4359 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 4360 not_likely:
4ad40f36 4361 ctx->hflags |= MIPS_HFLAG_BC;
6af0bf9c
FB
4362 break;
4363 case OPC_BLTZALL:
e68dd28f 4364 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 4365 blink = 31;
d077b6f7 4366 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 4367 likely:
4ad40f36 4368 ctx->hflags |= MIPS_HFLAG_BL;
6af0bf9c 4369 break;
c53f4a62
TS
4370 default:
4371 MIPS_INVAL("conditional branch/jump");
4372 generate_exception(ctx, EXCP_RI);
6c5c1e20 4373 goto out;
6af0bf9c 4374 }
6af0bf9c 4375 }
923617a3 4376 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
d077b6f7 4377 blink, ctx->hflags, btgt);
9b9e4393 4378
d077b6f7 4379 ctx->btarget = btgt;
b231c103
YK
4380
4381 switch (delayslot_size) {
4382 case 2:
4383 ctx->hflags |= MIPS_HFLAG_BDS16;
4384 break;
4385 case 4:
4386 ctx->hflags |= MIPS_HFLAG_BDS32;
4387 break;
4388 }
4389
6af0bf9c 4390 if (blink > 0) {
b231c103 4391 int post_delay = insn_bytes + delayslot_size;
364d4831
NF
4392 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
4393
364d4831 4394 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
6af0bf9c 4395 }
6c5c1e20
TS
4396
4397 out:
364d4831
NF
4398 if (insn_bytes == 2)
4399 ctx->hflags |= MIPS_HFLAG_B16;
6c5c1e20
TS
4400 tcg_temp_free(t0);
4401 tcg_temp_free(t1);
6af0bf9c
FB
4402}
4403
7a387fff
TS
4404/* special3 bitfield operations */
4405static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
356265ae 4406 int rs, int lsb, int msb)
7a387fff 4407{
a7812ae4
PB
4408 TCGv t0 = tcg_temp_new();
4409 TCGv t1 = tcg_temp_new();
6c5c1e20
TS
4410
4411 gen_load_gpr(t1, rs);
7a387fff
TS
4412 switch (opc) {
4413 case OPC_EXT:
4414 if (lsb + msb > 31)
4415 goto fail;
505ad7c2
AJ
4416 tcg_gen_shri_tl(t0, t1, lsb);
4417 if (msb != 31) {
4418 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
4419 } else {
4420 tcg_gen_ext32s_tl(t0, t0);
4421 }
7a387fff 4422 break;
c6d6dd7c 4423#if defined(TARGET_MIPS64)
7a387fff 4424 case OPC_DEXTM:
505ad7c2
AJ
4425 tcg_gen_shri_tl(t0, t1, lsb);
4426 if (msb != 31) {
4427 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
4428 }
7a387fff
TS
4429 break;
4430 case OPC_DEXTU:
505ad7c2
AJ
4431 tcg_gen_shri_tl(t0, t1, lsb + 32);
4432 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
7a387fff
TS
4433 break;
4434 case OPC_DEXT:
505ad7c2
AJ
4435 tcg_gen_shri_tl(t0, t1, lsb);
4436 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
7a387fff 4437 break;
c6d6dd7c 4438#endif
7a387fff
TS
4439 case OPC_INS:
4440 if (lsb > msb)
4441 goto fail;
6c5c1e20 4442 gen_load_gpr(t0, rt);
e0d002f1 4443 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
505ad7c2 4444 tcg_gen_ext32s_tl(t0, t0);
7a387fff 4445 break;
c6d6dd7c 4446#if defined(TARGET_MIPS64)
7a387fff 4447 case OPC_DINSM:
6c5c1e20 4448 gen_load_gpr(t0, rt);
e0d002f1 4449 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb + 32 - lsb + 1);
7a387fff
TS
4450 break;
4451 case OPC_DINSU:
6c5c1e20 4452 gen_load_gpr(t0, rt);
e0d002f1 4453 tcg_gen_deposit_tl(t0, t0, t1, lsb + 32, msb - lsb + 1);
7a387fff
TS
4454 break;
4455 case OPC_DINS:
6c5c1e20 4456 gen_load_gpr(t0, rt);
e0d002f1 4457 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
7a387fff 4458 break;
c6d6dd7c 4459#endif
7a387fff
TS
4460 default:
4461fail:
4462 MIPS_INVAL("bitops");
4463 generate_exception(ctx, EXCP_RI);
6c5c1e20
TS
4464 tcg_temp_free(t0);
4465 tcg_temp_free(t1);
7a387fff
TS
4466 return;
4467 }
6c5c1e20
TS
4468 gen_store_gpr(t0, rt);
4469 tcg_temp_free(t0);
4470 tcg_temp_free(t1);
7a387fff
TS
4471}
4472
49bcf33c
AJ
4473static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
4474{
3a55fa47 4475 TCGv t0;
49bcf33c 4476
3a55fa47
AJ
4477 if (rd == 0) {
4478 /* If no destination, treat it as a NOP. */
4479 MIPS_DEBUG("NOP");
4480 return;
4481 }
4482
4483 t0 = tcg_temp_new();
4484 gen_load_gpr(t0, rt);
49bcf33c
AJ
4485 switch (op2) {
4486 case OPC_WSBH:
3a55fa47
AJ
4487 {
4488 TCGv t1 = tcg_temp_new();
4489
4490 tcg_gen_shri_tl(t1, t0, 8);
4491 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
4492 tcg_gen_shli_tl(t0, t0, 8);
4493 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
4494 tcg_gen_or_tl(t0, t0, t1);
4495 tcg_temp_free(t1);
4496 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4497 }
49bcf33c
AJ
4498 break;
4499 case OPC_SEB:
3a55fa47 4500 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
4501 break;
4502 case OPC_SEH:
3a55fa47 4503 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
4504 break;
4505#if defined(TARGET_MIPS64)
4506 case OPC_DSBH:
3a55fa47
AJ
4507 {
4508 TCGv t1 = tcg_temp_new();
4509
4510 tcg_gen_shri_tl(t1, t0, 8);
4511 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
4512 tcg_gen_shli_tl(t0, t0, 8);
4513 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
4514 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4515 tcg_temp_free(t1);
4516 }
49bcf33c
AJ
4517 break;
4518 case OPC_DSHD:
3a55fa47
AJ
4519 {
4520 TCGv t1 = tcg_temp_new();
4521
4522 tcg_gen_shri_tl(t1, t0, 16);
4523 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
4524 tcg_gen_shli_tl(t0, t0, 16);
4525 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
4526 tcg_gen_or_tl(t0, t0, t1);
4527 tcg_gen_shri_tl(t1, t0, 32);
4528 tcg_gen_shli_tl(t0, t0, 32);
4529 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4530 tcg_temp_free(t1);
4531 }
49bcf33c
AJ
4532 break;
4533#endif
4534 default:
4535 MIPS_INVAL("bsfhl");
4536 generate_exception(ctx, EXCP_RI);
4537 tcg_temp_free(t0);
49bcf33c
AJ
4538 return;
4539 }
49bcf33c 4540 tcg_temp_free(t0);
49bcf33c
AJ
4541}
4542
f1aa6320 4543#ifndef CONFIG_USER_ONLY
0eaef5aa 4544/* CP0 (MMU and control) */
d9bea114 4545static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
4f57689a 4546{
d9bea114 4547 TCGv_i32 t0 = tcg_temp_new_i32();
4f57689a 4548
d9bea114
AJ
4549 tcg_gen_ld_i32(t0, cpu_env, off);
4550 tcg_gen_ext_i32_tl(arg, t0);
4551 tcg_temp_free_i32(t0);
4f57689a
TS
4552}
4553
d9bea114 4554static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
4f57689a 4555{
d9bea114
AJ
4556 tcg_gen_ld_tl(arg, cpu_env, off);
4557 tcg_gen_ext32s_tl(arg, arg);
4f57689a
TS
4558}
4559
d9bea114 4560static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
f1aa6320 4561{
d9bea114 4562 TCGv_i32 t0 = tcg_temp_new_i32();
f1aa6320 4563
d9bea114
AJ
4564 tcg_gen_trunc_tl_i32(t0, arg);
4565 tcg_gen_st_i32(t0, cpu_env, off);
4566 tcg_temp_free_i32(t0);
f1aa6320
TS
4567}
4568
d9bea114 4569static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
f1aa6320 4570{
d9bea114
AJ
4571 tcg_gen_ext32s_tl(arg, arg);
4572 tcg_gen_st_tl(arg, cpu_env, off);
f1aa6320
TS
4573}
4574
e98c0d17
LA
4575static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
4576{
4577 if (ctx->insn_flags & ISA_MIPS32R6) {
4578 tcg_gen_movi_tl(arg, 0);
4579 } else {
4580 tcg_gen_movi_tl(arg, ~0);
4581 }
4582}
4583
d75c135e 4584static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
873eb012 4585{
7a387fff 4586 const char *rn = "invalid";
873eb012 4587
e189e748 4588 if (sel != 0)
d75c135e 4589 check_insn(ctx, ISA_MIPS32);
e189e748 4590
873eb012
TS
4591 switch (reg) {
4592 case 0:
7a387fff
TS
4593 switch (sel) {
4594 case 0:
7db13fae 4595 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7a387fff
TS
4596 rn = "Index";
4597 break;
4598 case 1:
d75c135e 4599 check_insn(ctx, ASE_MT);
895c2d04 4600 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7a387fff 4601 rn = "MVPControl";
ead9360e 4602 break;
7a387fff 4603 case 2:
d75c135e 4604 check_insn(ctx, ASE_MT);
895c2d04 4605 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7a387fff 4606 rn = "MVPConf0";
ead9360e 4607 break;
7a387fff 4608 case 3:
d75c135e 4609 check_insn(ctx, ASE_MT);
895c2d04 4610 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7a387fff 4611 rn = "MVPConf1";
ead9360e 4612 break;
7a387fff
TS
4613 default:
4614 goto die;
4615 }
873eb012
TS
4616 break;
4617 case 1:
7a387fff
TS
4618 switch (sel) {
4619 case 0:
895c2d04 4620 gen_helper_mfc0_random(arg, cpu_env);
7a387fff 4621 rn = "Random";
2423f660 4622 break;
7a387fff 4623 case 1:
d75c135e 4624 check_insn(ctx, ASE_MT);
7db13fae 4625 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7a387fff 4626 rn = "VPEControl";
ead9360e 4627 break;
7a387fff 4628 case 2:
d75c135e 4629 check_insn(ctx, ASE_MT);
7db13fae 4630 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7a387fff 4631 rn = "VPEConf0";
ead9360e 4632 break;
7a387fff 4633 case 3:
d75c135e 4634 check_insn(ctx, ASE_MT);
7db13fae 4635 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7a387fff 4636 rn = "VPEConf1";
ead9360e 4637 break;
7a387fff 4638 case 4:
d75c135e 4639 check_insn(ctx, ASE_MT);
7db13fae 4640 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
7a387fff 4641 rn = "YQMask";
ead9360e 4642 break;
7a387fff 4643 case 5:
d75c135e 4644 check_insn(ctx, ASE_MT);
7db13fae 4645 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
7a387fff 4646 rn = "VPESchedule";
ead9360e 4647 break;
7a387fff 4648 case 6:
d75c135e 4649 check_insn(ctx, ASE_MT);
7db13fae 4650 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7a387fff 4651 rn = "VPEScheFBack";
ead9360e 4652 break;
7a387fff 4653 case 7:
d75c135e 4654 check_insn(ctx, ASE_MT);
7db13fae 4655 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7a387fff 4656 rn = "VPEOpt";
ead9360e 4657 break;
7a387fff
TS
4658 default:
4659 goto die;
4660 }
873eb012
TS
4661 break;
4662 case 2:
7a387fff
TS
4663 switch (sel) {
4664 case 0:
7db13fae 4665 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
7207c7f9
LA
4666#if defined(TARGET_MIPS64)
4667 if (ctx->rxi) {
4668 TCGv tmp = tcg_temp_new();
4669 tcg_gen_andi_tl(tmp, arg, (3ull << 62));
4670 tcg_gen_shri_tl(tmp, tmp, 32);
4671 tcg_gen_or_tl(arg, arg, tmp);
4672 tcg_temp_free(tmp);
4673 }
4674#endif
d9bea114 4675 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
4676 rn = "EntryLo0";
4677 break;
7a387fff 4678 case 1:
d75c135e 4679 check_insn(ctx, ASE_MT);
895c2d04 4680 gen_helper_mfc0_tcstatus(arg, cpu_env);
2423f660 4681 rn = "TCStatus";
ead9360e 4682 break;
7a387fff 4683 case 2:
d75c135e 4684 check_insn(ctx, ASE_MT);
895c2d04 4685 gen_helper_mfc0_tcbind(arg, cpu_env);
2423f660 4686 rn = "TCBind";
ead9360e 4687 break;
7a387fff 4688 case 3:
d75c135e 4689 check_insn(ctx, ASE_MT);
895c2d04 4690 gen_helper_mfc0_tcrestart(arg, cpu_env);
2423f660 4691 rn = "TCRestart";
ead9360e 4692 break;
7a387fff 4693 case 4:
d75c135e 4694 check_insn(ctx, ASE_MT);
895c2d04 4695 gen_helper_mfc0_tchalt(arg, cpu_env);
2423f660 4696 rn = "TCHalt";
ead9360e 4697 break;
7a387fff 4698 case 5:
d75c135e 4699 check_insn(ctx, ASE_MT);
895c2d04 4700 gen_helper_mfc0_tccontext(arg, cpu_env);
2423f660 4701 rn = "TCContext";
ead9360e 4702 break;
7a387fff 4703 case 6:
d75c135e 4704 check_insn(ctx, ASE_MT);
895c2d04 4705 gen_helper_mfc0_tcschedule(arg, cpu_env);
2423f660 4706 rn = "TCSchedule";
ead9360e 4707 break;
7a387fff 4708 case 7:
d75c135e 4709 check_insn(ctx, ASE_MT);
895c2d04 4710 gen_helper_mfc0_tcschefback(arg, cpu_env);
2423f660 4711 rn = "TCScheFBack";
ead9360e 4712 break;
7a387fff
TS
4713 default:
4714 goto die;
4715 }
873eb012
TS
4716 break;
4717 case 3:
7a387fff
TS
4718 switch (sel) {
4719 case 0:
7db13fae 4720 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
7207c7f9
LA
4721#if defined(TARGET_MIPS64)
4722 if (ctx->rxi) {
4723 TCGv tmp = tcg_temp_new();
4724 tcg_gen_andi_tl(tmp, arg, (3ull << 62));
4725 tcg_gen_shri_tl(tmp, tmp, 32);
4726 tcg_gen_or_tl(arg, arg, tmp);
4727 tcg_temp_free(tmp);
4728 }
4729#endif
d9bea114 4730 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
4731 rn = "EntryLo1";
4732 break;
7a387fff
TS
4733 default:
4734 goto die;
1579a72e 4735 }
873eb012
TS
4736 break;
4737 case 4:
7a387fff
TS
4738 switch (sel) {
4739 case 0:
7db13fae 4740 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
d9bea114 4741 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
4742 rn = "Context";
4743 break;
7a387fff 4744 case 1:
d9bea114 4745// gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
2423f660 4746 rn = "ContextConfig";
d279279e 4747 goto die;
2423f660 4748// break;
d279279e
PJ
4749 case 2:
4750 if (ctx->ulri) {
4751 tcg_gen_ld32s_tl(arg, cpu_env,
4752 offsetof(CPUMIPSState,
4753 active_tc.CP0_UserLocal));
4754 rn = "UserLocal";
4755 } else {
4756 tcg_gen_movi_tl(arg, 0);
4757 }
4758 break;
7a387fff
TS
4759 default:
4760 goto die;
1579a72e 4761 }
873eb012
TS
4762 break;
4763 case 5:
7a387fff
TS
4764 switch (sel) {
4765 case 0:
7db13fae 4766 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
2423f660
TS
4767 rn = "PageMask";
4768 break;
7a387fff 4769 case 1:
d75c135e 4770 check_insn(ctx, ISA_MIPS32R2);
7db13fae 4771 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
2423f660
TS
4772 rn = "PageGrain";
4773 break;
7a387fff
TS
4774 default:
4775 goto die;
1579a72e 4776 }
873eb012
TS
4777 break;
4778 case 6:
7a387fff
TS
4779 switch (sel) {
4780 case 0:
7db13fae 4781 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
2423f660
TS
4782 rn = "Wired";
4783 break;
7a387fff 4784 case 1:
d75c135e 4785 check_insn(ctx, ISA_MIPS32R2);
7db13fae 4786 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
2423f660 4787 rn = "SRSConf0";
ead9360e 4788 break;
7a387fff 4789 case 2:
d75c135e 4790 check_insn(ctx, ISA_MIPS32R2);
7db13fae 4791 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
2423f660 4792 rn = "SRSConf1";
ead9360e 4793 break;
7a387fff 4794 case 3:
d75c135e 4795 check_insn(ctx, ISA_MIPS32R2);
7db13fae 4796 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
2423f660 4797 rn = "SRSConf2";
ead9360e 4798 break;
7a387fff 4799 case 4:
d75c135e 4800 check_insn(ctx, ISA_MIPS32R2);
7db13fae 4801 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
2423f660 4802 rn = "SRSConf3";
ead9360e 4803 break;
7a387fff 4804 case 5:
d75c135e 4805 check_insn(ctx, ISA_MIPS32R2);
7db13fae 4806 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
2423f660 4807 rn = "SRSConf4";
ead9360e 4808 break;
7a387fff
TS
4809 default:
4810 goto die;
1579a72e 4811 }
873eb012 4812 break;
8c0fdd85 4813 case 7:
7a387fff
TS
4814 switch (sel) {
4815 case 0:
d75c135e 4816 check_insn(ctx, ISA_MIPS32R2);
7db13fae 4817 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
2423f660
TS
4818 rn = "HWREna";
4819 break;
7a387fff
TS
4820 default:
4821 goto die;
1579a72e 4822 }
8c0fdd85 4823 break;
873eb012 4824 case 8:
7a387fff
TS
4825 switch (sel) {
4826 case 0:
7db13fae 4827 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
d9bea114 4828 tcg_gen_ext32s_tl(arg, arg);
f0b3f3ae 4829 rn = "BadVAddr";
2423f660 4830 break;
7a387fff
TS
4831 default:
4832 goto die;
4833 }
873eb012
TS
4834 break;
4835 case 9:
7a387fff
TS
4836 switch (sel) {
4837 case 0:
2e70f6ef
PB
4838 /* Mark as an IO operation because we read the time. */
4839 if (use_icount)
4840 gen_io_start();
895c2d04 4841 gen_helper_mfc0_count(arg, cpu_env);
2e70f6ef
PB
4842 if (use_icount) {
4843 gen_io_end();
2e70f6ef 4844 }
55807224
EI
4845 /* Break the TB to be able to take timer interrupts immediately
4846 after reading count. */
4847 ctx->bstate = BS_STOP;
2423f660
TS
4848 rn = "Count";
4849 break;
4850 /* 6,7 are implementation dependent */
7a387fff
TS
4851 default:
4852 goto die;
2423f660 4853 }
873eb012
TS
4854 break;
4855 case 10:
7a387fff
TS
4856 switch (sel) {
4857 case 0:
7db13fae 4858 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
d9bea114 4859 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
4860 rn = "EntryHi";
4861 break;
7a387fff
TS
4862 default:
4863 goto die;
1579a72e 4864 }
873eb012
TS
4865 break;
4866 case 11:
7a387fff
TS
4867 switch (sel) {
4868 case 0:
7db13fae 4869 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
2423f660
TS
4870 rn = "Compare";
4871 break;
4872 /* 6,7 are implementation dependent */
7a387fff
TS
4873 default:
4874 goto die;
2423f660 4875 }
873eb012
TS
4876 break;
4877 case 12:
7a387fff
TS
4878 switch (sel) {
4879 case 0:
7db13fae 4880 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
2423f660
TS
4881 rn = "Status";
4882 break;
7a387fff 4883 case 1:
d75c135e 4884 check_insn(ctx, ISA_MIPS32R2);
7db13fae 4885 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
2423f660
TS
4886 rn = "IntCtl";
4887 break;
7a387fff 4888 case 2:
d75c135e 4889 check_insn(ctx, ISA_MIPS32R2);
7db13fae 4890 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
2423f660
TS
4891 rn = "SRSCtl";
4892 break;
7a387fff 4893 case 3:
d75c135e 4894 check_insn(ctx, ISA_MIPS32R2);
7db13fae 4895 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
2423f660 4896 rn = "SRSMap";
fd88b6ab 4897 break;
7a387fff
TS
4898 default:
4899 goto die;
4900 }
873eb012
TS
4901 break;
4902 case 13:
7a387fff
TS
4903 switch (sel) {
4904 case 0:
7db13fae 4905 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
2423f660
TS
4906 rn = "Cause";
4907 break;
7a387fff
TS
4908 default:
4909 goto die;
4910 }
873eb012
TS
4911 break;
4912 case 14:
7a387fff
TS
4913 switch (sel) {
4914 case 0:
7db13fae 4915 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
d9bea114 4916 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
4917 rn = "EPC";
4918 break;
7a387fff
TS
4919 default:
4920 goto die;
1579a72e 4921 }
873eb012
TS
4922 break;
4923 case 15:
7a387fff
TS
4924 switch (sel) {
4925 case 0:
7db13fae 4926 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
2423f660
TS
4927 rn = "PRid";
4928 break;
7a387fff 4929 case 1:
d75c135e 4930 check_insn(ctx, ISA_MIPS32R2);
7db13fae 4931 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
2423f660
TS
4932 rn = "EBase";
4933 break;
7a387fff
TS
4934 default:
4935 goto die;
4936 }
873eb012
TS
4937 break;
4938 case 16:
4939 switch (sel) {
4940 case 0:
7db13fae 4941 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
873eb012
TS
4942 rn = "Config";
4943 break;
4944 case 1:
7db13fae 4945 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
873eb012
TS
4946 rn = "Config1";
4947 break;
7a387fff 4948 case 2:
7db13fae 4949 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7a387fff
TS
4950 rn = "Config2";
4951 break;
4952 case 3:
7db13fae 4953 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7a387fff
TS
4954 rn = "Config3";
4955 break;
b4160af1
PJ
4956 case 4:
4957 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
4958 rn = "Config4";
4959 break;
b4dd99a3
PJ
4960 case 5:
4961 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
4962 rn = "Config5";
4963 break;
e397ee33
TS
4964 /* 6,7 are implementation dependent */
4965 case 6:
7db13fae 4966 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
e397ee33
TS
4967 rn = "Config6";
4968 break;
4969 case 7:
7db13fae 4970 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
e397ee33
TS
4971 rn = "Config7";
4972 break;
873eb012 4973 default:
873eb012
TS
4974 goto die;
4975 }
4976 break;
4977 case 17:
7a387fff
TS
4978 switch (sel) {
4979 case 0:
895c2d04 4980 gen_helper_mfc0_lladdr(arg, cpu_env);
2423f660
TS
4981 rn = "LLAddr";
4982 break;
7a387fff
TS
4983 default:
4984 goto die;
4985 }
873eb012
TS
4986 break;
4987 case 18:
7a387fff 4988 switch (sel) {
fd88b6ab 4989 case 0 ... 7:
895c2d04 4990 gen_helper_1e0i(mfc0_watchlo, arg, sel);
2423f660
TS
4991 rn = "WatchLo";
4992 break;
7a387fff
TS
4993 default:
4994 goto die;
4995 }
873eb012
TS
4996 break;
4997 case 19:
7a387fff 4998 switch (sel) {
fd88b6ab 4999 case 0 ...7:
895c2d04 5000 gen_helper_1e0i(mfc0_watchhi, arg, sel);
2423f660
TS
5001 rn = "WatchHi";
5002 break;
7a387fff
TS
5003 default:
5004 goto die;
5005 }
873eb012 5006 break;
8c0fdd85 5007 case 20:
7a387fff
TS
5008 switch (sel) {
5009 case 0:
d26bc211 5010#if defined(TARGET_MIPS64)
d75c135e 5011 check_insn(ctx, ISA_MIPS3);
7db13fae 5012 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
d9bea114 5013 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
5014 rn = "XContext";
5015 break;
703eaf37 5016#endif
7a387fff
TS
5017 default:
5018 goto die;
5019 }
8c0fdd85
TS
5020 break;
5021 case 21:
7a387fff
TS
5022 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5023 switch (sel) {
5024 case 0:
7db13fae 5025 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
2423f660
TS
5026 rn = "Framemask";
5027 break;
7a387fff
TS
5028 default:
5029 goto die;
5030 }
8c0fdd85
TS
5031 break;
5032 case 22:
d9bea114 5033 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
5034 rn = "'Diagnostic"; /* implementation dependent */
5035 break;
873eb012 5036 case 23:
7a387fff
TS
5037 switch (sel) {
5038 case 0:
895c2d04 5039 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
2423f660
TS
5040 rn = "Debug";
5041 break;
7a387fff 5042 case 1:
d9bea114 5043// gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
2423f660
TS
5044 rn = "TraceControl";
5045// break;
7a387fff 5046 case 2:
d9bea114 5047// gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
2423f660
TS
5048 rn = "TraceControl2";
5049// break;
7a387fff 5050 case 3:
d9bea114 5051// gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
2423f660
TS
5052 rn = "UserTraceData";
5053// break;
7a387fff 5054 case 4:
d9bea114 5055// gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
2423f660
TS
5056 rn = "TraceBPC";
5057// break;
7a387fff
TS
5058 default:
5059 goto die;
5060 }
873eb012
TS
5061 break;
5062 case 24:
7a387fff
TS
5063 switch (sel) {
5064 case 0:
f0b3f3ae 5065 /* EJTAG support */
7db13fae 5066 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
d9bea114 5067 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
5068 rn = "DEPC";
5069 break;
7a387fff
TS
5070 default:
5071 goto die;
5072 }
873eb012 5073 break;
8c0fdd85 5074 case 25:
7a387fff
TS
5075 switch (sel) {
5076 case 0:
7db13fae 5077 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
2423f660 5078 rn = "Performance0";
7a387fff
TS
5079 break;
5080 case 1:
d9bea114 5081// gen_helper_mfc0_performance1(arg);
2423f660
TS
5082 rn = "Performance1";
5083// break;
7a387fff 5084 case 2:
d9bea114 5085// gen_helper_mfc0_performance2(arg);
2423f660
TS
5086 rn = "Performance2";
5087// break;
7a387fff 5088 case 3:
d9bea114 5089// gen_helper_mfc0_performance3(arg);
2423f660
TS
5090 rn = "Performance3";
5091// break;
7a387fff 5092 case 4:
d9bea114 5093// gen_helper_mfc0_performance4(arg);
2423f660
TS
5094 rn = "Performance4";
5095// break;
7a387fff 5096 case 5:
d9bea114 5097// gen_helper_mfc0_performance5(arg);
2423f660
TS
5098 rn = "Performance5";
5099// break;
7a387fff 5100 case 6:
d9bea114 5101// gen_helper_mfc0_performance6(arg);
2423f660
TS
5102 rn = "Performance6";
5103// break;
7a387fff 5104 case 7:
d9bea114 5105// gen_helper_mfc0_performance7(arg);
2423f660
TS
5106 rn = "Performance7";
5107// break;
7a387fff
TS
5108 default:
5109 goto die;
5110 }
8c0fdd85
TS
5111 break;
5112 case 26:
d9bea114 5113 tcg_gen_movi_tl(arg, 0); /* unimplemented */
da80682b
AJ
5114 rn = "ECC";
5115 break;
8c0fdd85 5116 case 27:
7a387fff 5117 switch (sel) {
7a387fff 5118 case 0 ... 3:
d9bea114 5119 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
5120 rn = "CacheErr";
5121 break;
7a387fff
TS
5122 default:
5123 goto die;
5124 }
8c0fdd85 5125 break;
873eb012
TS
5126 case 28:
5127 switch (sel) {
5128 case 0:
7a387fff
TS
5129 case 2:
5130 case 4:
5131 case 6:
7db13fae 5132 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
873eb012
TS
5133 rn = "TagLo";
5134 break;
5135 case 1:
7a387fff
TS
5136 case 3:
5137 case 5:
5138 case 7:
7db13fae 5139 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
873eb012
TS
5140 rn = "DataLo";
5141 break;
5142 default:
873eb012
TS
5143 goto die;
5144 }
5145 break;
8c0fdd85 5146 case 29:
7a387fff
TS
5147 switch (sel) {
5148 case 0:
5149 case 2:
5150 case 4:
5151 case 6:
7db13fae 5152 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7a387fff
TS
5153 rn = "TagHi";
5154 break;
5155 case 1:
5156 case 3:
5157 case 5:
5158 case 7:
7db13fae 5159 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7a387fff
TS
5160 rn = "DataHi";
5161 break;
5162 default:
5163 goto die;
5164 }
8c0fdd85 5165 break;
873eb012 5166 case 30:
7a387fff
TS
5167 switch (sel) {
5168 case 0:
7db13fae 5169 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
d9bea114 5170 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
5171 rn = "ErrorEPC";
5172 break;
7a387fff
TS
5173 default:
5174 goto die;
5175 }
873eb012
TS
5176 break;
5177 case 31:
7a387fff
TS
5178 switch (sel) {
5179 case 0:
f0b3f3ae 5180 /* EJTAG support */
7db13fae 5181 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
5182 rn = "DESAVE";
5183 break;
e98c0d17
LA
5184 case 2 ... 7:
5185 if (ctx->kscrexist & (1 << sel)) {
5186 tcg_gen_ld_tl(arg, cpu_env,
5187 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
5188 tcg_gen_ext32s_tl(arg, arg);
5189 rn = "KScratch";
5190 } else {
5191 gen_mfc0_unimplemented(ctx, arg);
5192 }
5193 break;
7a387fff
TS
5194 default:
5195 goto die;
5196 }
873eb012
TS
5197 break;
5198 default:
873eb012
TS
5199 goto die;
5200 }
2abf314d 5201 (void)rn; /* avoid a compiler warning */
d12d51d5 5202 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
873eb012
TS
5203 return;
5204
5205die:
d12d51d5 5206 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
873eb012
TS
5207 generate_exception(ctx, EXCP_RI);
5208}
5209
d75c135e 5210static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8c0fdd85 5211{
7a387fff
TS
5212 const char *rn = "invalid";
5213
e189e748 5214 if (sel != 0)
d75c135e 5215 check_insn(ctx, ISA_MIPS32);
e189e748 5216
2e70f6ef
PB
5217 if (use_icount)
5218 gen_io_start();
5219
8c0fdd85
TS
5220 switch (reg) {
5221 case 0:
7a387fff
TS
5222 switch (sel) {
5223 case 0:
895c2d04 5224 gen_helper_mtc0_index(cpu_env, arg);
7a387fff
TS
5225 rn = "Index";
5226 break;
5227 case 1:
d75c135e 5228 check_insn(ctx, ASE_MT);
895c2d04 5229 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7a387fff 5230 rn = "MVPControl";
ead9360e 5231 break;
7a387fff 5232 case 2:
d75c135e 5233 check_insn(ctx, ASE_MT);
ead9360e 5234 /* ignored */
7a387fff 5235 rn = "MVPConf0";
ead9360e 5236 break;
7a387fff 5237 case 3:
d75c135e 5238 check_insn(ctx, ASE_MT);
ead9360e 5239 /* ignored */
7a387fff 5240 rn = "MVPConf1";
ead9360e 5241 break;
7a387fff
TS
5242 default:
5243 goto die;
5244 }
8c0fdd85
TS
5245 break;
5246 case 1:
7a387fff
TS
5247 switch (sel) {
5248 case 0:
2423f660 5249 /* ignored */
7a387fff 5250 rn = "Random";
2423f660 5251 break;
7a387fff 5252 case 1:
d75c135e 5253 check_insn(ctx, ASE_MT);
895c2d04 5254 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7a387fff 5255 rn = "VPEControl";
ead9360e 5256 break;
7a387fff 5257 case 2:
d75c135e 5258 check_insn(ctx, ASE_MT);
895c2d04 5259 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7a387fff 5260 rn = "VPEConf0";
ead9360e 5261 break;
7a387fff 5262 case 3:
d75c135e 5263 check_insn(ctx, ASE_MT);
895c2d04 5264 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7a387fff 5265 rn = "VPEConf1";
ead9360e 5266 break;
7a387fff 5267 case 4:
d75c135e 5268 check_insn(ctx, ASE_MT);
895c2d04 5269 gen_helper_mtc0_yqmask(cpu_env, arg);
7a387fff 5270 rn = "YQMask";
ead9360e 5271 break;
7a387fff 5272 case 5:
d75c135e 5273 check_insn(ctx, ASE_MT);
7db13fae 5274 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
7a387fff 5275 rn = "VPESchedule";
ead9360e 5276 break;
7a387fff 5277 case 6:
d75c135e 5278 check_insn(ctx, ASE_MT);
7db13fae 5279 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7a387fff 5280 rn = "VPEScheFBack";
ead9360e 5281 break;
7a387fff 5282 case 7:
d75c135e 5283 check_insn(ctx, ASE_MT);
895c2d04 5284 gen_helper_mtc0_vpeopt(cpu_env, arg);
7a387fff 5285 rn = "VPEOpt";
ead9360e 5286 break;
7a387fff
TS
5287 default:
5288 goto die;
5289 }
8c0fdd85
TS
5290 break;
5291 case 2:
7a387fff
TS
5292 switch (sel) {
5293 case 0:
895c2d04 5294 gen_helper_mtc0_entrylo0(cpu_env, arg);
2423f660
TS
5295 rn = "EntryLo0";
5296 break;
7a387fff 5297 case 1:
d75c135e 5298 check_insn(ctx, ASE_MT);
895c2d04 5299 gen_helper_mtc0_tcstatus(cpu_env, arg);
2423f660 5300 rn = "TCStatus";
ead9360e 5301 break;
7a387fff 5302 case 2:
d75c135e 5303 check_insn(ctx, ASE_MT);
895c2d04 5304 gen_helper_mtc0_tcbind(cpu_env, arg);
2423f660 5305 rn = "TCBind";
ead9360e 5306 break;
7a387fff 5307 case 3:
d75c135e 5308 check_insn(ctx, ASE_MT);
895c2d04 5309 gen_helper_mtc0_tcrestart(cpu_env, arg);
2423f660 5310 rn = "TCRestart";
ead9360e 5311 break;
7a387fff 5312 case 4:
d75c135e 5313 check_insn(ctx, ASE_MT);
895c2d04 5314 gen_helper_mtc0_tchalt(cpu_env, arg);
2423f660 5315 rn = "TCHalt";
ead9360e 5316 break;
7a387fff 5317 case 5:
d75c135e 5318 check_insn(ctx, ASE_MT);
895c2d04 5319 gen_helper_mtc0_tccontext(cpu_env, arg);
2423f660 5320 rn = "TCContext";
ead9360e 5321 break;
7a387fff 5322 case 6:
d75c135e 5323 check_insn(ctx, ASE_MT);
895c2d04 5324 gen_helper_mtc0_tcschedule(cpu_env, arg);
2423f660 5325 rn = "TCSchedule";
ead9360e 5326 break;
7a387fff 5327 case 7:
d75c135e 5328 check_insn(ctx, ASE_MT);
895c2d04 5329 gen_helper_mtc0_tcschefback(cpu_env, arg);
2423f660 5330 rn = "TCScheFBack";
ead9360e 5331 break;
7a387fff
TS
5332 default:
5333 goto die;
5334 }
8c0fdd85
TS
5335 break;
5336 case 3:
7a387fff
TS
5337 switch (sel) {
5338 case 0:
895c2d04 5339 gen_helper_mtc0_entrylo1(cpu_env, arg);
2423f660
TS
5340 rn = "EntryLo1";
5341 break;
7a387fff
TS
5342 default:
5343 goto die;
876d4b07 5344 }
8c0fdd85
TS
5345 break;
5346 case 4:
7a387fff
TS
5347 switch (sel) {
5348 case 0:
895c2d04 5349 gen_helper_mtc0_context(cpu_env, arg);
2423f660
TS
5350 rn = "Context";
5351 break;
7a387fff 5352 case 1:
895c2d04 5353// gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
2423f660 5354 rn = "ContextConfig";
d279279e 5355 goto die;
2423f660 5356// break;
d279279e
PJ
5357 case 2:
5358 if (ctx->ulri) {
5359 tcg_gen_st_tl(arg, cpu_env,
5360 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5361 rn = "UserLocal";
5362 }
5363 break;
7a387fff
TS
5364 default:
5365 goto die;
876d4b07 5366 }
8c0fdd85
TS
5367 break;
5368 case 5:
7a387fff
TS
5369 switch (sel) {
5370 case 0:
895c2d04 5371 gen_helper_mtc0_pagemask(cpu_env, arg);
2423f660
TS
5372 rn = "PageMask";
5373 break;
7a387fff 5374 case 1:
d75c135e 5375 check_insn(ctx, ISA_MIPS32R2);
895c2d04 5376 gen_helper_mtc0_pagegrain(cpu_env, arg);
2423f660
TS
5377 rn = "PageGrain";
5378 break;
7a387fff
TS
5379 default:
5380 goto die;
876d4b07 5381 }
8c0fdd85
TS
5382 break;
5383 case 6:
7a387fff
TS
5384 switch (sel) {
5385 case 0:
895c2d04 5386 gen_helper_mtc0_wired(cpu_env, arg);
2423f660
TS
5387 rn = "Wired";
5388 break;
7a387fff 5389 case 1:
d75c135e 5390 check_insn(ctx, ISA_MIPS32R2);
895c2d04 5391 gen_helper_mtc0_srsconf0(cpu_env, arg);
2423f660 5392 rn = "SRSConf0";
ead9360e 5393 break;
7a387fff 5394 case 2:
d75c135e 5395 check_insn(ctx, ISA_MIPS32R2);
895c2d04 5396 gen_helper_mtc0_srsconf1(cpu_env, arg);
2423f660 5397 rn = "SRSConf1";
ead9360e 5398 break;
7a387fff 5399 case 3:
d75c135e 5400 check_insn(ctx, ISA_MIPS32R2);
895c2d04 5401 gen_helper_mtc0_srsconf2(cpu_env, arg);
2423f660 5402 rn = "SRSConf2";
ead9360e 5403 break;
7a387fff 5404 case 4:
d75c135e 5405 check_insn(ctx, ISA_MIPS32R2);
895c2d04 5406 gen_helper_mtc0_srsconf3(cpu_env, arg);
2423f660 5407 rn = "SRSConf3";
ead9360e 5408 break;
7a387fff 5409 case 5:
d75c135e 5410 check_insn(ctx, ISA_MIPS32R2);
895c2d04 5411 gen_helper_mtc0_srsconf4(cpu_env, arg);
2423f660 5412 rn = "SRSConf4";
ead9360e 5413 break;
7a387fff
TS
5414 default:
5415 goto die;
876d4b07 5416 }
8c0fdd85
TS
5417 break;
5418 case 7:
7a387fff
TS
5419 switch (sel) {
5420 case 0:
d75c135e 5421 check_insn(ctx, ISA_MIPS32R2);
895c2d04 5422 gen_helper_mtc0_hwrena(cpu_env, arg);
d279279e 5423 ctx->bstate = BS_STOP;
2423f660
TS
5424 rn = "HWREna";
5425 break;
7a387fff
TS
5426 default:
5427 goto die;
876d4b07 5428 }
8c0fdd85
TS
5429 break;
5430 case 8:
7a387fff 5431 /* ignored */
f0b3f3ae 5432 rn = "BadVAddr";
8c0fdd85
TS
5433 break;
5434 case 9:
7a387fff
TS
5435 switch (sel) {
5436 case 0:
895c2d04 5437 gen_helper_mtc0_count(cpu_env, arg);
2423f660
TS
5438 rn = "Count";
5439 break;
876d4b07 5440 /* 6,7 are implementation dependent */
7a387fff
TS
5441 default:
5442 goto die;
876d4b07 5443 }
8c0fdd85
TS
5444 break;
5445 case 10:
7a387fff
TS
5446 switch (sel) {
5447 case 0:
895c2d04 5448 gen_helper_mtc0_entryhi(cpu_env, arg);
2423f660
TS
5449 rn = "EntryHi";
5450 break;
7a387fff
TS
5451 default:
5452 goto die;
876d4b07 5453 }
8c0fdd85
TS
5454 break;
5455 case 11:
7a387fff
TS
5456 switch (sel) {
5457 case 0:
895c2d04 5458 gen_helper_mtc0_compare(cpu_env, arg);
2423f660
TS
5459 rn = "Compare";
5460 break;
5461 /* 6,7 are implementation dependent */
7a387fff
TS
5462 default:
5463 goto die;
876d4b07 5464 }
8c0fdd85
TS
5465 break;
5466 case 12:
7a387fff
TS
5467 switch (sel) {
5468 case 0:
867abc7e 5469 save_cpu_state(ctx, 1);
895c2d04 5470 gen_helper_mtc0_status(cpu_env, arg);
8487327a
TS
5471 /* BS_STOP isn't good enough here, hflags may have changed. */
5472 gen_save_pc(ctx->pc + 4);
5473 ctx->bstate = BS_EXCP;
2423f660
TS
5474 rn = "Status";
5475 break;
7a387fff 5476 case 1:
d75c135e 5477 check_insn(ctx, ISA_MIPS32R2);
895c2d04 5478 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a
TS
5479 /* Stop translation as we may have switched the execution mode */
5480 ctx->bstate = BS_STOP;
2423f660
TS
5481 rn = "IntCtl";
5482 break;
7a387fff 5483 case 2:
d75c135e 5484 check_insn(ctx, ISA_MIPS32R2);
895c2d04 5485 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a
TS
5486 /* Stop translation as we may have switched the execution mode */
5487 ctx->bstate = BS_STOP;
2423f660
TS
5488 rn = "SRSCtl";
5489 break;
7a387fff 5490 case 3:
d75c135e 5491 check_insn(ctx, ISA_MIPS32R2);
7db13fae 5492 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a
TS
5493 /* Stop translation as we may have switched the execution mode */
5494 ctx->bstate = BS_STOP;
2423f660 5495 rn = "SRSMap";
fd88b6ab 5496 break;
7a387fff
TS
5497 default:
5498 goto die;
876d4b07 5499 }
8c0fdd85
TS
5500 break;
5501 case 13:
7a387fff
TS
5502 switch (sel) {
5503 case 0:
867abc7e 5504 save_cpu_state(ctx, 1);
895c2d04 5505 gen_helper_mtc0_cause(cpu_env, arg);
2423f660
TS
5506 rn = "Cause";
5507 break;
7a387fff
TS
5508 default:
5509 goto die;
876d4b07 5510 }
8c0fdd85
TS
5511 break;
5512 case 14:
7a387fff
TS
5513 switch (sel) {
5514 case 0:
7db13fae 5515 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
2423f660
TS
5516 rn = "EPC";
5517 break;
7a387fff
TS
5518 default:
5519 goto die;
876d4b07 5520 }
8c0fdd85
TS
5521 break;
5522 case 15:
7a387fff
TS
5523 switch (sel) {
5524 case 0:
2423f660
TS
5525 /* ignored */
5526 rn = "PRid";
5527 break;
7a387fff 5528 case 1:
d75c135e 5529 check_insn(ctx, ISA_MIPS32R2);
895c2d04 5530 gen_helper_mtc0_ebase(cpu_env, arg);
2423f660
TS
5531 rn = "EBase";
5532 break;
7a387fff
TS
5533 default:
5534 goto die;
1579a72e 5535 }
8c0fdd85
TS
5536 break;
5537 case 16:
5538 switch (sel) {
5539 case 0:
895c2d04 5540 gen_helper_mtc0_config0(cpu_env, arg);
7a387fff 5541 rn = "Config";
2423f660
TS
5542 /* Stop translation as we may have switched the execution mode */
5543 ctx->bstate = BS_STOP;
7a387fff
TS
5544 break;
5545 case 1:
e397ee33 5546 /* ignored, read only */
7a387fff
TS
5547 rn = "Config1";
5548 break;
5549 case 2:
895c2d04 5550 gen_helper_mtc0_config2(cpu_env, arg);
7a387fff 5551 rn = "Config2";
2423f660
TS
5552 /* Stop translation as we may have switched the execution mode */
5553 ctx->bstate = BS_STOP;
8c0fdd85 5554 break;
7a387fff 5555 case 3:
e397ee33 5556 /* ignored, read only */
7a387fff
TS
5557 rn = "Config3";
5558 break;
b4160af1
PJ
5559 case 4:
5560 gen_helper_mtc0_config4(cpu_env, arg);
5561 rn = "Config4";
5562 ctx->bstate = BS_STOP;
5563 break;
b4dd99a3
PJ
5564 case 5:
5565 gen_helper_mtc0_config5(cpu_env, arg);
5566 rn = "Config5";
5567 /* Stop translation as we may have switched the execution mode */
5568 ctx->bstate = BS_STOP;
5569 break;
e397ee33
TS
5570 /* 6,7 are implementation dependent */
5571 case 6:
5572 /* ignored */
5573 rn = "Config6";
5574 break;
5575 case 7:
5576 /* ignored */
5577 rn = "Config7";
5578 break;
8c0fdd85
TS
5579 default:
5580 rn = "Invalid config selector";
5581 goto die;
5582 }
5583 break;
5584 case 17:
7a387fff
TS
5585 switch (sel) {
5586 case 0:
895c2d04 5587 gen_helper_mtc0_lladdr(cpu_env, arg);
2423f660
TS
5588 rn = "LLAddr";
5589 break;
7a387fff
TS
5590 default:
5591 goto die;
5592 }
8c0fdd85
TS
5593 break;
5594 case 18:
7a387fff 5595 switch (sel) {
fd88b6ab 5596 case 0 ... 7:
895c2d04 5597 gen_helper_0e1i(mtc0_watchlo, arg, sel);
2423f660
TS
5598 rn = "WatchLo";
5599 break;
7a387fff
TS
5600 default:
5601 goto die;
5602 }
8c0fdd85
TS
5603 break;
5604 case 19:
7a387fff 5605 switch (sel) {
fd88b6ab 5606 case 0 ... 7:
895c2d04 5607 gen_helper_0e1i(mtc0_watchhi, arg, sel);
2423f660
TS
5608 rn = "WatchHi";
5609 break;
7a387fff
TS
5610 default:
5611 goto die;
5612 }
8c0fdd85
TS
5613 break;
5614 case 20:
7a387fff
TS
5615 switch (sel) {
5616 case 0:
d26bc211 5617#if defined(TARGET_MIPS64)
d75c135e 5618 check_insn(ctx, ISA_MIPS3);
895c2d04 5619 gen_helper_mtc0_xcontext(cpu_env, arg);
2423f660
TS
5620 rn = "XContext";
5621 break;
703eaf37 5622#endif
7a387fff
TS
5623 default:
5624 goto die;
5625 }
8c0fdd85
TS
5626 break;
5627 case 21:
7a387fff
TS
5628 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5629 switch (sel) {
5630 case 0:
895c2d04 5631 gen_helper_mtc0_framemask(cpu_env, arg);
2423f660
TS
5632 rn = "Framemask";
5633 break;
7a387fff
TS
5634 default:
5635 goto die;
5636 }
5637 break;
8c0fdd85 5638 case 22:
7a387fff
TS
5639 /* ignored */
5640 rn = "Diagnostic"; /* implementation dependent */
2423f660 5641 break;
8c0fdd85 5642 case 23:
7a387fff
TS
5643 switch (sel) {
5644 case 0:
895c2d04 5645 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8487327a
TS
5646 /* BS_STOP isn't good enough here, hflags may have changed. */
5647 gen_save_pc(ctx->pc + 4);
5648 ctx->bstate = BS_EXCP;
2423f660
TS
5649 rn = "Debug";
5650 break;
7a387fff 5651 case 1:
895c2d04 5652// gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
2423f660 5653 rn = "TraceControl";
8487327a
TS
5654 /* Stop translation as we may have switched the execution mode */
5655 ctx->bstate = BS_STOP;
2423f660 5656// break;
7a387fff 5657 case 2:
895c2d04 5658// gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
2423f660 5659 rn = "TraceControl2";
8487327a
TS
5660 /* Stop translation as we may have switched the execution mode */
5661 ctx->bstate = BS_STOP;
2423f660 5662// break;
7a387fff 5663 case 3:
8487327a
TS
5664 /* Stop translation as we may have switched the execution mode */
5665 ctx->bstate = BS_STOP;
895c2d04 5666// gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
2423f660 5667 rn = "UserTraceData";
8487327a
TS
5668 /* Stop translation as we may have switched the execution mode */
5669 ctx->bstate = BS_STOP;
2423f660 5670// break;
7a387fff 5671 case 4:
895c2d04 5672// gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
8487327a
TS
5673 /* Stop translation as we may have switched the execution mode */
5674 ctx->bstate = BS_STOP;
2423f660
TS
5675 rn = "TraceBPC";
5676// break;
7a387fff
TS
5677 default:
5678 goto die;
5679 }
8c0fdd85
TS
5680 break;
5681 case 24:
7a387fff
TS
5682 switch (sel) {
5683 case 0:
f1aa6320 5684 /* EJTAG support */
7db13fae 5685 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
2423f660
TS
5686 rn = "DEPC";
5687 break;
7a387fff
TS
5688 default:
5689 goto die;
5690 }
8c0fdd85
TS
5691 break;
5692 case 25:
7a387fff
TS
5693 switch (sel) {
5694 case 0:
895c2d04 5695 gen_helper_mtc0_performance0(cpu_env, arg);
2423f660
TS
5696 rn = "Performance0";
5697 break;
7a387fff 5698 case 1:
d9bea114 5699// gen_helper_mtc0_performance1(arg);
2423f660
TS
5700 rn = "Performance1";
5701// break;
7a387fff 5702 case 2:
d9bea114 5703// gen_helper_mtc0_performance2(arg);
2423f660
TS
5704 rn = "Performance2";
5705// break;
7a387fff 5706 case 3:
d9bea114 5707// gen_helper_mtc0_performance3(arg);
2423f660
TS
5708 rn = "Performance3";
5709// break;
7a387fff 5710 case 4:
d9bea114 5711// gen_helper_mtc0_performance4(arg);
2423f660
TS
5712 rn = "Performance4";
5713// break;
7a387fff 5714 case 5:
d9bea114 5715// gen_helper_mtc0_performance5(arg);
2423f660
TS
5716 rn = "Performance5";
5717// break;
7a387fff 5718 case 6:
d9bea114 5719// gen_helper_mtc0_performance6(arg);
2423f660
TS
5720 rn = "Performance6";
5721// break;
7a387fff 5722 case 7:
d9bea114 5723// gen_helper_mtc0_performance7(arg);
2423f660
TS
5724 rn = "Performance7";
5725// break;
7a387fff
TS
5726 default:
5727 goto die;
5728 }
8c0fdd85
TS
5729 break;
5730 case 26:
2423f660 5731 /* ignored */
8c0fdd85 5732 rn = "ECC";
2423f660 5733 break;
8c0fdd85 5734 case 27:
7a387fff
TS
5735 switch (sel) {
5736 case 0 ... 3:
2423f660
TS
5737 /* ignored */
5738 rn = "CacheErr";
5739 break;
7a387fff
TS
5740 default:
5741 goto die;
5742 }
8c0fdd85
TS
5743 break;
5744 case 28:
5745 switch (sel) {
5746 case 0:
7a387fff
TS
5747 case 2:
5748 case 4:
5749 case 6:
895c2d04 5750 gen_helper_mtc0_taglo(cpu_env, arg);
8c0fdd85
TS
5751 rn = "TagLo";
5752 break;
7a387fff
TS
5753 case 1:
5754 case 3:
5755 case 5:
5756 case 7:
895c2d04 5757 gen_helper_mtc0_datalo(cpu_env, arg);
7a387fff
TS
5758 rn = "DataLo";
5759 break;
8c0fdd85 5760 default:
8c0fdd85
TS
5761 goto die;
5762 }
5763 break;
5764 case 29:
7a387fff
TS
5765 switch (sel) {
5766 case 0:
5767 case 2:
5768 case 4:
5769 case 6:
895c2d04 5770 gen_helper_mtc0_taghi(cpu_env, arg);
7a387fff
TS
5771 rn = "TagHi";
5772 break;
5773 case 1:
5774 case 3:
5775 case 5:
5776 case 7:
895c2d04 5777 gen_helper_mtc0_datahi(cpu_env, arg);
7a387fff
TS
5778 rn = "DataHi";
5779 break;
5780 default:
5781 rn = "invalid sel";
5782 goto die;
5783 }
8c0fdd85
TS
5784 break;
5785 case 30:
7a387fff
TS
5786 switch (sel) {
5787 case 0:
7db13fae 5788 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
2423f660
TS
5789 rn = "ErrorEPC";
5790 break;
7a387fff
TS
5791 default:
5792 goto die;
5793 }
8c0fdd85
TS
5794 break;
5795 case 31:
7a387fff
TS
5796 switch (sel) {
5797 case 0:
f1aa6320 5798 /* EJTAG support */
7db13fae 5799 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
5800 rn = "DESAVE";
5801 break;
e98c0d17
LA
5802 case 2 ... 7:
5803 if (ctx->kscrexist & (1 << sel)) {
5804 tcg_gen_st_tl(arg, cpu_env,
5805 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
5806 rn = "KScratch";
5807 }
5808 break;
7a387fff
TS
5809 default:
5810 goto die;
5811 }
2423f660
TS
5812 /* Stop translation as we may have switched the execution mode */
5813 ctx->bstate = BS_STOP;
8c0fdd85
TS
5814 break;
5815 default:
8c0fdd85
TS
5816 goto die;
5817 }
2abf314d 5818 (void)rn; /* avoid a compiler warning */
d12d51d5 5819 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
bf20dc07 5820 /* For simplicity assume that all writes can cause interrupts. */
2e70f6ef
PB
5821 if (use_icount) {
5822 gen_io_end();
5823 ctx->bstate = BS_STOP;
5824 }
8c0fdd85
TS
5825 return;
5826
5827die:
d12d51d5 5828 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
8c0fdd85
TS
5829 generate_exception(ctx, EXCP_RI);
5830}
5831
d26bc211 5832#if defined(TARGET_MIPS64)
d75c135e 5833static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8
TS
5834{
5835 const char *rn = "invalid";
5836
e189e748 5837 if (sel != 0)
d75c135e 5838 check_insn(ctx, ISA_MIPS64);
e189e748 5839
9c2149c8
TS
5840 switch (reg) {
5841 case 0:
5842 switch (sel) {
5843 case 0:
7db13fae 5844 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
9c2149c8
TS
5845 rn = "Index";
5846 break;
5847 case 1:
d75c135e 5848 check_insn(ctx, ASE_MT);
895c2d04 5849 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
9c2149c8 5850 rn = "MVPControl";
ead9360e 5851 break;
9c2149c8 5852 case 2:
d75c135e 5853 check_insn(ctx, ASE_MT);
895c2d04 5854 gen_helper_mfc0_mvpconf0(arg, cpu_env);
9c2149c8 5855 rn = "MVPConf0";
ead9360e 5856 break;
9c2149c8 5857 case 3:
d75c135e 5858 check_insn(ctx, ASE_MT);
895c2d04 5859 gen_helper_mfc0_mvpconf1(arg, cpu_env);
9c2149c8 5860 rn = "MVPConf1";
ead9360e 5861 break;
9c2149c8
TS
5862 default:
5863 goto die;
5864 }
5865 break;
5866 case 1:
5867 switch (sel) {
5868 case 0:
895c2d04 5869 gen_helper_mfc0_random(arg, cpu_env);
9c2149c8 5870 rn = "Random";
2423f660 5871 break;
9c2149c8 5872 case 1:
d75c135e 5873 check_insn(ctx, ASE_MT);
7db13fae 5874 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
9c2149c8 5875 rn = "VPEControl";
ead9360e 5876 break;
9c2149c8 5877 case 2:
d75c135e 5878 check_insn(ctx, ASE_MT);
7db13fae 5879 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
9c2149c8 5880 rn = "VPEConf0";
ead9360e 5881 break;
9c2149c8 5882 case 3:
d75c135e 5883 check_insn(ctx, ASE_MT);
7db13fae 5884 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
9c2149c8 5885 rn = "VPEConf1";
ead9360e 5886 break;
9c2149c8 5887 case 4:
d75c135e 5888 check_insn(ctx, ASE_MT);
7db13fae 5889 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
9c2149c8 5890 rn = "YQMask";
ead9360e 5891 break;
9c2149c8 5892 case 5:
d75c135e 5893 check_insn(ctx, ASE_MT);
7db13fae 5894 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
9c2149c8 5895 rn = "VPESchedule";
ead9360e 5896 break;
9c2149c8 5897 case 6:
d75c135e 5898 check_insn(ctx, ASE_MT);
7db13fae 5899 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
9c2149c8 5900 rn = "VPEScheFBack";
ead9360e 5901 break;
9c2149c8 5902 case 7:
d75c135e 5903 check_insn(ctx, ASE_MT);
7db13fae 5904 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
9c2149c8 5905 rn = "VPEOpt";
ead9360e 5906 break;
9c2149c8
TS
5907 default:
5908 goto die;
5909 }
5910 break;
5911 case 2:
5912 switch (sel) {
5913 case 0:
7db13fae 5914 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
2423f660
TS
5915 rn = "EntryLo0";
5916 break;
9c2149c8 5917 case 1:
d75c135e 5918 check_insn(ctx, ASE_MT);
895c2d04 5919 gen_helper_mfc0_tcstatus(arg, cpu_env);
2423f660 5920 rn = "TCStatus";
ead9360e 5921 break;
9c2149c8 5922 case 2:
d75c135e 5923 check_insn(ctx, ASE_MT);
895c2d04 5924 gen_helper_mfc0_tcbind(arg, cpu_env);
2423f660 5925 rn = "TCBind";
ead9360e 5926 break;
9c2149c8 5927 case 3:
d75c135e 5928 check_insn(ctx, ASE_MT);
895c2d04 5929 gen_helper_dmfc0_tcrestart(arg, cpu_env);
2423f660 5930 rn = "TCRestart";
ead9360e 5931 break;
9c2149c8 5932 case 4:
d75c135e 5933 check_insn(ctx, ASE_MT);
895c2d04 5934 gen_helper_dmfc0_tchalt(arg, cpu_env);
2423f660 5935 rn = "TCHalt";
ead9360e 5936 break;
9c2149c8 5937 case 5:
d75c135e 5938 check_insn(ctx, ASE_MT);
895c2d04 5939 gen_helper_dmfc0_tccontext(arg, cpu_env);
2423f660 5940 rn = "TCContext";
ead9360e 5941 break;
9c2149c8 5942 case 6:
d75c135e 5943 check_insn(ctx, ASE_MT);
895c2d04 5944 gen_helper_dmfc0_tcschedule(arg, cpu_env);
2423f660 5945 rn = "TCSchedule";
ead9360e 5946 break;
9c2149c8 5947 case 7:
d75c135e 5948 check_insn(ctx, ASE_MT);
895c2d04 5949 gen_helper_dmfc0_tcschefback(arg, cpu_env);
2423f660 5950 rn = "TCScheFBack";
ead9360e 5951 break;
9c2149c8
TS
5952 default:
5953 goto die;
5954 }
5955 break;
5956 case 3:
5957 switch (sel) {
5958 case 0:
7db13fae 5959 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
2423f660
TS
5960 rn = "EntryLo1";
5961 break;
9c2149c8
TS
5962 default:
5963 goto die;
1579a72e 5964 }
9c2149c8
TS
5965 break;
5966 case 4:
5967 switch (sel) {
5968 case 0:
7db13fae 5969 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
2423f660
TS
5970 rn = "Context";
5971 break;
9c2149c8 5972 case 1:
d9bea114 5973// gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
2423f660 5974 rn = "ContextConfig";
d279279e 5975 goto die;
2423f660 5976// break;
d279279e
PJ
5977 case 2:
5978 if (ctx->ulri) {
5979 tcg_gen_ld_tl(arg, cpu_env,
5980 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5981 rn = "UserLocal";
5982 } else {
5983 tcg_gen_movi_tl(arg, 0);
5984 }
5985 break;
9c2149c8
TS
5986 default:
5987 goto die;
876d4b07 5988 }
9c2149c8
TS
5989 break;
5990 case 5:
5991 switch (sel) {
5992 case 0:
7db13fae 5993 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
2423f660
TS
5994 rn = "PageMask";
5995 break;
9c2149c8 5996 case 1:
d75c135e 5997 check_insn(ctx, ISA_MIPS32R2);
7db13fae 5998 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
2423f660
TS
5999 rn = "PageGrain";
6000 break;
9c2149c8
TS
6001 default:
6002 goto die;
876d4b07 6003 }
9c2149c8
TS
6004 break;
6005 case 6:
6006 switch (sel) {
6007 case 0:
7db13fae 6008 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
2423f660
TS
6009 rn = "Wired";
6010 break;
9c2149c8 6011 case 1:
d75c135e 6012 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6013 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
2423f660 6014 rn = "SRSConf0";
ead9360e 6015 break;
9c2149c8 6016 case 2:
d75c135e 6017 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6018 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
2423f660 6019 rn = "SRSConf1";
ead9360e 6020 break;
9c2149c8 6021 case 3:
d75c135e 6022 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6023 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
2423f660 6024 rn = "SRSConf2";
ead9360e 6025 break;
9c2149c8 6026 case 4:
d75c135e 6027 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6028 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
2423f660 6029 rn = "SRSConf3";
ead9360e 6030 break;
9c2149c8 6031 case 5:
d75c135e 6032 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6033 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
2423f660 6034 rn = "SRSConf4";
ead9360e 6035 break;
9c2149c8
TS
6036 default:
6037 goto die;
876d4b07 6038 }
9c2149c8
TS
6039 break;
6040 case 7:
6041 switch (sel) {
6042 case 0:
d75c135e 6043 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6044 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
2423f660
TS
6045 rn = "HWREna";
6046 break;
9c2149c8
TS
6047 default:
6048 goto die;
876d4b07 6049 }
9c2149c8
TS
6050 break;
6051 case 8:
6052 switch (sel) {
6053 case 0:
7db13fae 6054 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
f0b3f3ae 6055 rn = "BadVAddr";
2423f660 6056 break;
9c2149c8
TS
6057 default:
6058 goto die;
876d4b07 6059 }
9c2149c8
TS
6060 break;
6061 case 9:
6062 switch (sel) {
6063 case 0:
2e70f6ef
PB
6064 /* Mark as an IO operation because we read the time. */
6065 if (use_icount)
6066 gen_io_start();
895c2d04 6067 gen_helper_mfc0_count(arg, cpu_env);
2e70f6ef
PB
6068 if (use_icount) {
6069 gen_io_end();
2e70f6ef 6070 }
55807224
EI
6071 /* Break the TB to be able to take timer interrupts immediately
6072 after reading count. */
6073 ctx->bstate = BS_STOP;
2423f660
TS
6074 rn = "Count";
6075 break;
6076 /* 6,7 are implementation dependent */
9c2149c8
TS
6077 default:
6078 goto die;
876d4b07 6079 }
9c2149c8
TS
6080 break;
6081 case 10:
6082 switch (sel) {
6083 case 0:
7db13fae 6084 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
2423f660
TS
6085 rn = "EntryHi";
6086 break;
9c2149c8
TS
6087 default:
6088 goto die;
876d4b07 6089 }
9c2149c8
TS
6090 break;
6091 case 11:
6092 switch (sel) {
6093 case 0:
7db13fae 6094 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
2423f660
TS
6095 rn = "Compare";
6096 break;
876d4b07 6097 /* 6,7 are implementation dependent */
9c2149c8
TS
6098 default:
6099 goto die;
876d4b07 6100 }
9c2149c8
TS
6101 break;
6102 case 12:
6103 switch (sel) {
6104 case 0:
7db13fae 6105 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
2423f660
TS
6106 rn = "Status";
6107 break;
9c2149c8 6108 case 1:
d75c135e 6109 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6110 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
2423f660
TS
6111 rn = "IntCtl";
6112 break;
9c2149c8 6113 case 2:
d75c135e 6114 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6115 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
2423f660
TS
6116 rn = "SRSCtl";
6117 break;
9c2149c8 6118 case 3:
d75c135e 6119 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6120 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
2423f660
TS
6121 rn = "SRSMap";
6122 break;
9c2149c8
TS
6123 default:
6124 goto die;
876d4b07 6125 }
9c2149c8
TS
6126 break;
6127 case 13:
6128 switch (sel) {
6129 case 0:
7db13fae 6130 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
2423f660
TS
6131 rn = "Cause";
6132 break;
9c2149c8
TS
6133 default:
6134 goto die;
876d4b07 6135 }
9c2149c8
TS
6136 break;
6137 case 14:
6138 switch (sel) {
6139 case 0:
7db13fae 6140 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
2423f660
TS
6141 rn = "EPC";
6142 break;
9c2149c8
TS
6143 default:
6144 goto die;
876d4b07 6145 }
9c2149c8
TS
6146 break;
6147 case 15:
6148 switch (sel) {
6149 case 0:
7db13fae 6150 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
2423f660
TS
6151 rn = "PRid";
6152 break;
9c2149c8 6153 case 1:
d75c135e 6154 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6155 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
2423f660
TS
6156 rn = "EBase";
6157 break;
9c2149c8
TS
6158 default:
6159 goto die;
876d4b07 6160 }
9c2149c8
TS
6161 break;
6162 case 16:
6163 switch (sel) {
6164 case 0:
7db13fae 6165 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
9c2149c8
TS
6166 rn = "Config";
6167 break;
6168 case 1:
7db13fae 6169 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
9c2149c8
TS
6170 rn = "Config1";
6171 break;
6172 case 2:
7db13fae 6173 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
9c2149c8
TS
6174 rn = "Config2";
6175 break;
6176 case 3:
7db13fae 6177 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
9c2149c8
TS
6178 rn = "Config3";
6179 break;
6180 /* 6,7 are implementation dependent */
f0b3f3ae 6181 case 6:
7db13fae 6182 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
f0b3f3ae
TS
6183 rn = "Config6";
6184 break;
6185 case 7:
7db13fae 6186 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
f0b3f3ae
TS
6187 rn = "Config7";
6188 break;
9c2149c8
TS
6189 default:
6190 goto die;
6191 }
6192 break;
6193 case 17:
6194 switch (sel) {
6195 case 0:
895c2d04 6196 gen_helper_dmfc0_lladdr(arg, cpu_env);
2423f660
TS
6197 rn = "LLAddr";
6198 break;
9c2149c8
TS
6199 default:
6200 goto die;
6201 }
6202 break;
6203 case 18:
6204 switch (sel) {
fd88b6ab 6205 case 0 ... 7:
895c2d04 6206 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
2423f660
TS
6207 rn = "WatchLo";
6208 break;
9c2149c8
TS
6209 default:
6210 goto die;
6211 }
6212 break;
6213 case 19:
6214 switch (sel) {
fd88b6ab 6215 case 0 ... 7:
895c2d04 6216 gen_helper_1e0i(mfc0_watchhi, arg, sel);
2423f660
TS
6217 rn = "WatchHi";
6218 break;
9c2149c8
TS
6219 default:
6220 goto die;
6221 }
6222 break;
6223 case 20:
6224 switch (sel) {
6225 case 0:
d75c135e 6226 check_insn(ctx, ISA_MIPS3);
7db13fae 6227 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
2423f660
TS
6228 rn = "XContext";
6229 break;
9c2149c8
TS
6230 default:
6231 goto die;
6232 }
6233 break;
6234 case 21:
6235 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6236 switch (sel) {
6237 case 0:
7db13fae 6238 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
2423f660
TS
6239 rn = "Framemask";
6240 break;
9c2149c8
TS
6241 default:
6242 goto die;
6243 }
6244 break;
6245 case 22:
d9bea114 6246 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
6247 rn = "'Diagnostic"; /* implementation dependent */
6248 break;
9c2149c8
TS
6249 case 23:
6250 switch (sel) {
6251 case 0:
895c2d04 6252 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
2423f660
TS
6253 rn = "Debug";
6254 break;
9c2149c8 6255 case 1:
895c2d04 6256// gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
2423f660
TS
6257 rn = "TraceControl";
6258// break;
9c2149c8 6259 case 2:
895c2d04 6260// gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
2423f660
TS
6261 rn = "TraceControl2";
6262// break;
9c2149c8 6263 case 3:
895c2d04 6264// gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
2423f660
TS
6265 rn = "UserTraceData";
6266// break;
9c2149c8 6267 case 4:
895c2d04 6268// gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
2423f660
TS
6269 rn = "TraceBPC";
6270// break;
9c2149c8
TS
6271 default:
6272 goto die;
6273 }
6274 break;
6275 case 24:
6276 switch (sel) {
6277 case 0:
f0b3f3ae 6278 /* EJTAG support */
7db13fae 6279 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
2423f660
TS
6280 rn = "DEPC";
6281 break;
9c2149c8
TS
6282 default:
6283 goto die;
6284 }
6285 break;
6286 case 25:
6287 switch (sel) {
6288 case 0:
7db13fae 6289 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
2423f660 6290 rn = "Performance0";
9c2149c8
TS
6291 break;
6292 case 1:
d9bea114 6293// gen_helper_dmfc0_performance1(arg);
2423f660
TS
6294 rn = "Performance1";
6295// break;
9c2149c8 6296 case 2:
d9bea114 6297// gen_helper_dmfc0_performance2(arg);
2423f660
TS
6298 rn = "Performance2";
6299// break;
9c2149c8 6300 case 3:
d9bea114 6301// gen_helper_dmfc0_performance3(arg);
2423f660
TS
6302 rn = "Performance3";
6303// break;
9c2149c8 6304 case 4:
d9bea114 6305// gen_helper_dmfc0_performance4(arg);
2423f660
TS
6306 rn = "Performance4";
6307// break;
9c2149c8 6308 case 5:
d9bea114 6309// gen_helper_dmfc0_performance5(arg);
2423f660
TS
6310 rn = "Performance5";
6311// break;
9c2149c8 6312 case 6:
d9bea114 6313// gen_helper_dmfc0_performance6(arg);
2423f660
TS
6314 rn = "Performance6";
6315// break;
9c2149c8 6316 case 7:
d9bea114 6317// gen_helper_dmfc0_performance7(arg);
2423f660
TS
6318 rn = "Performance7";
6319// break;
9c2149c8
TS
6320 default:
6321 goto die;
6322 }
6323 break;
6324 case 26:
d9bea114 6325 tcg_gen_movi_tl(arg, 0); /* unimplemented */
da80682b
AJ
6326 rn = "ECC";
6327 break;
9c2149c8
TS
6328 case 27:
6329 switch (sel) {
6330 /* ignored */
6331 case 0 ... 3:
d9bea114 6332 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
6333 rn = "CacheErr";
6334 break;
9c2149c8
TS
6335 default:
6336 goto die;
6337 }
6338 break;
6339 case 28:
6340 switch (sel) {
6341 case 0:
6342 case 2:
6343 case 4:
6344 case 6:
7db13fae 6345 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
9c2149c8
TS
6346 rn = "TagLo";
6347 break;
6348 case 1:
6349 case 3:
6350 case 5:
6351 case 7:
7db13fae 6352 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
9c2149c8
TS
6353 rn = "DataLo";
6354 break;
6355 default:
6356 goto die;
6357 }
6358 break;
6359 case 29:
6360 switch (sel) {
6361 case 0:
6362 case 2:
6363 case 4:
6364 case 6:
7db13fae 6365 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
9c2149c8
TS
6366 rn = "TagHi";
6367 break;
6368 case 1:
6369 case 3:
6370 case 5:
6371 case 7:
7db13fae 6372 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
9c2149c8
TS
6373 rn = "DataHi";
6374 break;
6375 default:
6376 goto die;
6377 }
6378 break;
6379 case 30:
6380 switch (sel) {
6381 case 0:
7db13fae 6382 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
2423f660
TS
6383 rn = "ErrorEPC";
6384 break;
9c2149c8
TS
6385 default:
6386 goto die;
6387 }
6388 break;
6389 case 31:
6390 switch (sel) {
6391 case 0:
f0b3f3ae 6392 /* EJTAG support */
7db13fae 6393 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
6394 rn = "DESAVE";
6395 break;
e98c0d17
LA
6396 case 2 ... 7:
6397 if (ctx->kscrexist & (1 << sel)) {
6398 tcg_gen_ld_tl(arg, cpu_env,
6399 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6400 rn = "KScratch";
6401 } else {
6402 gen_mfc0_unimplemented(ctx, arg);
6403 }
6404 break;
9c2149c8
TS
6405 default:
6406 goto die;
6407 }
6408 break;
6409 default:
876d4b07 6410 goto die;
9c2149c8 6411 }
2abf314d 6412 (void)rn; /* avoid a compiler warning */
d12d51d5 6413 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
6414 return;
6415
6416die:
d12d51d5 6417 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
6418 generate_exception(ctx, EXCP_RI);
6419}
6420
d75c135e 6421static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8
TS
6422{
6423 const char *rn = "invalid";
6424
e189e748 6425 if (sel != 0)
d75c135e 6426 check_insn(ctx, ISA_MIPS64);
e189e748 6427
2e70f6ef
PB
6428 if (use_icount)
6429 gen_io_start();
6430
9c2149c8
TS
6431 switch (reg) {
6432 case 0:
6433 switch (sel) {
6434 case 0:
895c2d04 6435 gen_helper_mtc0_index(cpu_env, arg);
9c2149c8
TS
6436 rn = "Index";
6437 break;
6438 case 1:
d75c135e 6439 check_insn(ctx, ASE_MT);
895c2d04 6440 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
9c2149c8 6441 rn = "MVPControl";
ead9360e 6442 break;
9c2149c8 6443 case 2:
d75c135e 6444 check_insn(ctx, ASE_MT);
ead9360e 6445 /* ignored */
9c2149c8 6446 rn = "MVPConf0";
ead9360e 6447 break;
9c2149c8 6448 case 3:
d75c135e 6449 check_insn(ctx, ASE_MT);
ead9360e 6450 /* ignored */
9c2149c8 6451 rn = "MVPConf1";
ead9360e 6452 break;
9c2149c8
TS
6453 default:
6454 goto die;
6455 }
6456 break;
6457 case 1:
6458 switch (sel) {
6459 case 0:
2423f660 6460 /* ignored */
9c2149c8 6461 rn = "Random";
2423f660 6462 break;
9c2149c8 6463 case 1:
d75c135e 6464 check_insn(ctx, ASE_MT);
895c2d04 6465 gen_helper_mtc0_vpecontrol(cpu_env, arg);
9c2149c8 6466 rn = "VPEControl";
ead9360e 6467 break;
9c2149c8 6468 case 2:
d75c135e 6469 check_insn(ctx, ASE_MT);
895c2d04 6470 gen_helper_mtc0_vpeconf0(cpu_env, arg);
9c2149c8 6471 rn = "VPEConf0";
ead9360e 6472 break;
9c2149c8 6473 case 3:
d75c135e 6474 check_insn(ctx, ASE_MT);
895c2d04 6475 gen_helper_mtc0_vpeconf1(cpu_env, arg);
9c2149c8 6476 rn = "VPEConf1";
ead9360e 6477 break;
9c2149c8 6478 case 4:
d75c135e 6479 check_insn(ctx, ASE_MT);
895c2d04 6480 gen_helper_mtc0_yqmask(cpu_env, arg);
9c2149c8 6481 rn = "YQMask";
ead9360e 6482 break;
9c2149c8 6483 case 5:
d75c135e 6484 check_insn(ctx, ASE_MT);
7db13fae 6485 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
9c2149c8 6486 rn = "VPESchedule";
ead9360e 6487 break;
9c2149c8 6488 case 6:
d75c135e 6489 check_insn(ctx, ASE_MT);
7db13fae 6490 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
9c2149c8 6491 rn = "VPEScheFBack";
ead9360e 6492 break;
9c2149c8 6493 case 7:
d75c135e 6494 check_insn(ctx, ASE_MT);
895c2d04 6495 gen_helper_mtc0_vpeopt(cpu_env, arg);
9c2149c8 6496 rn = "VPEOpt";
ead9360e 6497 break;
9c2149c8
TS
6498 default:
6499 goto die;
6500 }
6501 break;
6502 case 2:
6503 switch (sel) {
6504 case 0:
7207c7f9 6505 gen_helper_dmtc0_entrylo0(cpu_env, arg);
2423f660
TS
6506 rn = "EntryLo0";
6507 break;
9c2149c8 6508 case 1:
d75c135e 6509 check_insn(ctx, ASE_MT);
895c2d04 6510 gen_helper_mtc0_tcstatus(cpu_env, arg);
2423f660 6511 rn = "TCStatus";
ead9360e 6512 break;
9c2149c8 6513 case 2:
d75c135e 6514 check_insn(ctx, ASE_MT);
895c2d04 6515 gen_helper_mtc0_tcbind(cpu_env, arg);
2423f660 6516 rn = "TCBind";
ead9360e 6517 break;
9c2149c8 6518 case 3:
d75c135e 6519 check_insn(ctx, ASE_MT);
895c2d04 6520 gen_helper_mtc0_tcrestart(cpu_env, arg);
2423f660 6521 rn = "TCRestart";
ead9360e 6522 break;
9c2149c8 6523 case 4:
d75c135e 6524 check_insn(ctx, ASE_MT);
895c2d04 6525 gen_helper_mtc0_tchalt(cpu_env, arg);
2423f660 6526 rn = "TCHalt";
ead9360e 6527 break;
9c2149c8 6528 case 5:
d75c135e 6529 check_insn(ctx, ASE_MT);
895c2d04 6530 gen_helper_mtc0_tccontext(cpu_env, arg);
2423f660 6531 rn = "TCContext";
ead9360e 6532 break;
9c2149c8 6533 case 6:
d75c135e 6534 check_insn(ctx, ASE_MT);
895c2d04 6535 gen_helper_mtc0_tcschedule(cpu_env, arg);
2423f660 6536 rn = "TCSchedule";
ead9360e 6537 break;
9c2149c8 6538 case 7:
d75c135e 6539 check_insn(ctx, ASE_MT);
895c2d04 6540 gen_helper_mtc0_tcschefback(cpu_env, arg);
2423f660 6541 rn = "TCScheFBack";
ead9360e 6542 break;
9c2149c8
TS
6543 default:
6544 goto die;
6545 }
6546 break;
6547 case 3:
6548 switch (sel) {
6549 case 0:
7207c7f9 6550 gen_helper_dmtc0_entrylo1(cpu_env, arg);
2423f660
TS
6551 rn = "EntryLo1";
6552 break;
9c2149c8
TS
6553 default:
6554 goto die;
876d4b07 6555 }
9c2149c8
TS
6556 break;
6557 case 4:
6558 switch (sel) {
6559 case 0:
895c2d04 6560 gen_helper_mtc0_context(cpu_env, arg);
2423f660
TS
6561 rn = "Context";
6562 break;
9c2149c8 6563 case 1:
895c2d04 6564// gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
2423f660 6565 rn = "ContextConfig";
d279279e 6566 goto die;
2423f660 6567// break;
d279279e
PJ
6568 case 2:
6569 if (ctx->ulri) {
6570 tcg_gen_st_tl(arg, cpu_env,
6571 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6572 rn = "UserLocal";
6573 }
6574 break;
9c2149c8
TS
6575 default:
6576 goto die;
876d4b07 6577 }
9c2149c8
TS
6578 break;
6579 case 5:
6580 switch (sel) {
6581 case 0:
895c2d04 6582 gen_helper_mtc0_pagemask(cpu_env, arg);
2423f660
TS
6583 rn = "PageMask";
6584 break;
9c2149c8 6585 case 1:
d75c135e 6586 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6587 gen_helper_mtc0_pagegrain(cpu_env, arg);
2423f660
TS
6588 rn = "PageGrain";
6589 break;
9c2149c8
TS
6590 default:
6591 goto die;
876d4b07 6592 }
9c2149c8
TS
6593 break;
6594 case 6:
6595 switch (sel) {
6596 case 0:
895c2d04 6597 gen_helper_mtc0_wired(cpu_env, arg);
2423f660
TS
6598 rn = "Wired";
6599 break;
9c2149c8 6600 case 1:
d75c135e 6601 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6602 gen_helper_mtc0_srsconf0(cpu_env, arg);
2423f660 6603 rn = "SRSConf0";
ead9360e 6604 break;
9c2149c8 6605 case 2:
d75c135e 6606 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6607 gen_helper_mtc0_srsconf1(cpu_env, arg);
2423f660 6608 rn = "SRSConf1";
ead9360e 6609 break;
9c2149c8 6610 case 3:
d75c135e 6611 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6612 gen_helper_mtc0_srsconf2(cpu_env, arg);
2423f660 6613 rn = "SRSConf2";
ead9360e 6614 break;
9c2149c8 6615 case 4:
d75c135e 6616 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6617 gen_helper_mtc0_srsconf3(cpu_env, arg);
2423f660 6618 rn = "SRSConf3";
ead9360e 6619 break;
9c2149c8 6620 case 5:
d75c135e 6621 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6622 gen_helper_mtc0_srsconf4(cpu_env, arg);
2423f660 6623 rn = "SRSConf4";
ead9360e 6624 break;
9c2149c8
TS
6625 default:
6626 goto die;
876d4b07 6627 }
9c2149c8
TS
6628 break;
6629 case 7:
6630 switch (sel) {
6631 case 0:
d75c135e 6632 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6633 gen_helper_mtc0_hwrena(cpu_env, arg);
d279279e 6634 ctx->bstate = BS_STOP;
2423f660
TS
6635 rn = "HWREna";
6636 break;
9c2149c8
TS
6637 default:
6638 goto die;
876d4b07 6639 }
9c2149c8
TS
6640 break;
6641 case 8:
6642 /* ignored */
f0b3f3ae 6643 rn = "BadVAddr";
9c2149c8
TS
6644 break;
6645 case 9:
6646 switch (sel) {
6647 case 0:
895c2d04 6648 gen_helper_mtc0_count(cpu_env, arg);
2423f660
TS
6649 rn = "Count";
6650 break;
876d4b07 6651 /* 6,7 are implementation dependent */
9c2149c8
TS
6652 default:
6653 goto die;
876d4b07
TS
6654 }
6655 /* Stop translation as we may have switched the execution mode */
6656 ctx->bstate = BS_STOP;
9c2149c8
TS
6657 break;
6658 case 10:
6659 switch (sel) {
6660 case 0:
895c2d04 6661 gen_helper_mtc0_entryhi(cpu_env, arg);
2423f660
TS
6662 rn = "EntryHi";
6663 break;
9c2149c8
TS
6664 default:
6665 goto die;
876d4b07 6666 }
9c2149c8
TS
6667 break;
6668 case 11:
6669 switch (sel) {
6670 case 0:
895c2d04 6671 gen_helper_mtc0_compare(cpu_env, arg);
2423f660
TS
6672 rn = "Compare";
6673 break;
876d4b07 6674 /* 6,7 are implementation dependent */
9c2149c8
TS
6675 default:
6676 goto die;
876d4b07 6677 }
de9a95f0
AJ
6678 /* Stop translation as we may have switched the execution mode */
6679 ctx->bstate = BS_STOP;
9c2149c8
TS
6680 break;
6681 case 12:
6682 switch (sel) {
6683 case 0:
867abc7e 6684 save_cpu_state(ctx, 1);
895c2d04 6685 gen_helper_mtc0_status(cpu_env, arg);
8487327a
TS
6686 /* BS_STOP isn't good enough here, hflags may have changed. */
6687 gen_save_pc(ctx->pc + 4);
6688 ctx->bstate = BS_EXCP;
2423f660
TS
6689 rn = "Status";
6690 break;
9c2149c8 6691 case 1:
d75c135e 6692 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6693 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a
TS
6694 /* Stop translation as we may have switched the execution mode */
6695 ctx->bstate = BS_STOP;
2423f660
TS
6696 rn = "IntCtl";
6697 break;
9c2149c8 6698 case 2:
d75c135e 6699 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6700 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a
TS
6701 /* Stop translation as we may have switched the execution mode */
6702 ctx->bstate = BS_STOP;
2423f660
TS
6703 rn = "SRSCtl";
6704 break;
9c2149c8 6705 case 3:
d75c135e 6706 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6707 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a
TS
6708 /* Stop translation as we may have switched the execution mode */
6709 ctx->bstate = BS_STOP;
2423f660
TS
6710 rn = "SRSMap";
6711 break;
6712 default:
9c2149c8 6713 goto die;
876d4b07 6714 }
9c2149c8
TS
6715 break;
6716 case 13:
6717 switch (sel) {
6718 case 0:
867abc7e 6719 save_cpu_state(ctx, 1);
5dc5d9f0
AJ
6720 /* Mark as an IO operation because we may trigger a software
6721 interrupt. */
6722 if (use_icount) {
6723 gen_io_start();
6724 }
895c2d04 6725 gen_helper_mtc0_cause(cpu_env, arg);
5dc5d9f0
AJ
6726 if (use_icount) {
6727 gen_io_end();
6728 }
6729 /* Stop translation as we may have triggered an intetrupt */
6730 ctx->bstate = BS_STOP;
2423f660
TS
6731 rn = "Cause";
6732 break;
9c2149c8
TS
6733 default:
6734 goto die;
876d4b07 6735 }
9c2149c8
TS
6736 break;
6737 case 14:
6738 switch (sel) {
6739 case 0:
7db13fae 6740 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
2423f660
TS
6741 rn = "EPC";
6742 break;
9c2149c8
TS
6743 default:
6744 goto die;
876d4b07 6745 }
9c2149c8
TS
6746 break;
6747 case 15:
6748 switch (sel) {
6749 case 0:
2423f660
TS
6750 /* ignored */
6751 rn = "PRid";
6752 break;
9c2149c8 6753 case 1:
d75c135e 6754 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6755 gen_helper_mtc0_ebase(cpu_env, arg);
2423f660
TS
6756 rn = "EBase";
6757 break;
9c2149c8
TS
6758 default:
6759 goto die;
876d4b07 6760 }
9c2149c8
TS
6761 break;
6762 case 16:
6763 switch (sel) {
6764 case 0:
895c2d04 6765 gen_helper_mtc0_config0(cpu_env, arg);
9c2149c8 6766 rn = "Config";
2423f660
TS
6767 /* Stop translation as we may have switched the execution mode */
6768 ctx->bstate = BS_STOP;
9c2149c8
TS
6769 break;
6770 case 1:
1fc7bf6e 6771 /* ignored, read only */
9c2149c8
TS
6772 rn = "Config1";
6773 break;
6774 case 2:
895c2d04 6775 gen_helper_mtc0_config2(cpu_env, arg);
9c2149c8 6776 rn = "Config2";
2423f660
TS
6777 /* Stop translation as we may have switched the execution mode */
6778 ctx->bstate = BS_STOP;
9c2149c8
TS
6779 break;
6780 case 3:
2423f660 6781 /* ignored */
9c2149c8
TS
6782 rn = "Config3";
6783 break;
6784 /* 6,7 are implementation dependent */
6785 default:
6786 rn = "Invalid config selector";
6787 goto die;
6788 }
9c2149c8
TS
6789 break;
6790 case 17:
6791 switch (sel) {
6792 case 0:
895c2d04 6793 gen_helper_mtc0_lladdr(cpu_env, arg);
2423f660
TS
6794 rn = "LLAddr";
6795 break;
9c2149c8
TS
6796 default:
6797 goto die;
6798 }
6799 break;
6800 case 18:
6801 switch (sel) {
fd88b6ab 6802 case 0 ... 7:
895c2d04 6803 gen_helper_0e1i(mtc0_watchlo, arg, sel);
2423f660
TS
6804 rn = "WatchLo";
6805 break;
9c2149c8
TS
6806 default:
6807 goto die;
6808 }
6809 break;
6810 case 19:
6811 switch (sel) {
fd88b6ab 6812 case 0 ... 7:
895c2d04 6813 gen_helper_0e1i(mtc0_watchhi, arg, sel);
2423f660
TS
6814 rn = "WatchHi";
6815 break;
9c2149c8
TS
6816 default:
6817 goto die;
6818 }
6819 break;
6820 case 20:
6821 switch (sel) {
6822 case 0:
d75c135e 6823 check_insn(ctx, ISA_MIPS3);
895c2d04 6824 gen_helper_mtc0_xcontext(cpu_env, arg);
2423f660
TS
6825 rn = "XContext";
6826 break;
9c2149c8
TS
6827 default:
6828 goto die;
6829 }
6830 break;
6831 case 21:
6832 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6833 switch (sel) {
6834 case 0:
895c2d04 6835 gen_helper_mtc0_framemask(cpu_env, arg);
2423f660
TS
6836 rn = "Framemask";
6837 break;
9c2149c8
TS
6838 default:
6839 goto die;
6840 }
6841 break;
6842 case 22:
6843 /* ignored */
6844 rn = "Diagnostic"; /* implementation dependent */
876d4b07 6845 break;
9c2149c8
TS
6846 case 23:
6847 switch (sel) {
6848 case 0:
895c2d04 6849 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8487327a
TS
6850 /* BS_STOP isn't good enough here, hflags may have changed. */
6851 gen_save_pc(ctx->pc + 4);
6852 ctx->bstate = BS_EXCP;
2423f660
TS
6853 rn = "Debug";
6854 break;
9c2149c8 6855 case 1:
895c2d04 6856// gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
8487327a
TS
6857 /* Stop translation as we may have switched the execution mode */
6858 ctx->bstate = BS_STOP;
2423f660
TS
6859 rn = "TraceControl";
6860// break;
9c2149c8 6861 case 2:
895c2d04 6862// gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
8487327a
TS
6863 /* Stop translation as we may have switched the execution mode */
6864 ctx->bstate = BS_STOP;
2423f660
TS
6865 rn = "TraceControl2";
6866// break;
9c2149c8 6867 case 3:
895c2d04 6868// gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
8487327a
TS
6869 /* Stop translation as we may have switched the execution mode */
6870 ctx->bstate = BS_STOP;
2423f660
TS
6871 rn = "UserTraceData";
6872// break;
9c2149c8 6873 case 4:
895c2d04 6874// gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
8487327a
TS
6875 /* Stop translation as we may have switched the execution mode */
6876 ctx->bstate = BS_STOP;
2423f660
TS
6877 rn = "TraceBPC";
6878// break;
9c2149c8
TS
6879 default:
6880 goto die;
6881 }
9c2149c8
TS
6882 break;
6883 case 24:
6884 switch (sel) {
6885 case 0:
f1aa6320 6886 /* EJTAG support */
7db13fae 6887 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
2423f660
TS
6888 rn = "DEPC";
6889 break;
9c2149c8
TS
6890 default:
6891 goto die;
6892 }
6893 break;
6894 case 25:
6895 switch (sel) {
6896 case 0:
895c2d04 6897 gen_helper_mtc0_performance0(cpu_env, arg);
2423f660
TS
6898 rn = "Performance0";
6899 break;
9c2149c8 6900 case 1:
895c2d04 6901// gen_helper_mtc0_performance1(cpu_env, arg);
2423f660
TS
6902 rn = "Performance1";
6903// break;
9c2149c8 6904 case 2:
895c2d04 6905// gen_helper_mtc0_performance2(cpu_env, arg);
2423f660
TS
6906 rn = "Performance2";
6907// break;
9c2149c8 6908 case 3:
895c2d04 6909// gen_helper_mtc0_performance3(cpu_env, arg);
2423f660
TS
6910 rn = "Performance3";
6911// break;
9c2149c8 6912 case 4:
895c2d04 6913// gen_helper_mtc0_performance4(cpu_env, arg);
2423f660
TS
6914 rn = "Performance4";
6915// break;
9c2149c8 6916 case 5:
895c2d04 6917// gen_helper_mtc0_performance5(cpu_env, arg);
2423f660
TS
6918 rn = "Performance5";
6919// break;
9c2149c8 6920 case 6:
895c2d04 6921// gen_helper_mtc0_performance6(cpu_env, arg);
2423f660
TS
6922 rn = "Performance6";
6923// break;
9c2149c8 6924 case 7:
895c2d04 6925// gen_helper_mtc0_performance7(cpu_env, arg);
2423f660
TS
6926 rn = "Performance7";
6927// break;
9c2149c8
TS
6928 default:
6929 goto die;
6930 }
876d4b07 6931 break;
9c2149c8 6932 case 26:
876d4b07 6933 /* ignored */
9c2149c8 6934 rn = "ECC";
876d4b07 6935 break;
9c2149c8
TS
6936 case 27:
6937 switch (sel) {
6938 case 0 ... 3:
2423f660
TS
6939 /* ignored */
6940 rn = "CacheErr";
6941 break;
9c2149c8
TS
6942 default:
6943 goto die;
6944 }
876d4b07 6945 break;
9c2149c8
TS
6946 case 28:
6947 switch (sel) {
6948 case 0:
6949 case 2:
6950 case 4:
6951 case 6:
895c2d04 6952 gen_helper_mtc0_taglo(cpu_env, arg);
9c2149c8
TS
6953 rn = "TagLo";
6954 break;
6955 case 1:
6956 case 3:
6957 case 5:
6958 case 7:
895c2d04 6959 gen_helper_mtc0_datalo(cpu_env, arg);
9c2149c8
TS
6960 rn = "DataLo";
6961 break;
6962 default:
6963 goto die;
6964 }
6965 break;
6966 case 29:
6967 switch (sel) {
6968 case 0:
6969 case 2:
6970 case 4:
6971 case 6:
895c2d04 6972 gen_helper_mtc0_taghi(cpu_env, arg);
9c2149c8
TS
6973 rn = "TagHi";
6974 break;
6975 case 1:
6976 case 3:
6977 case 5:
6978 case 7:
895c2d04 6979 gen_helper_mtc0_datahi(cpu_env, arg);
9c2149c8
TS
6980 rn = "DataHi";
6981 break;
6982 default:
6983 rn = "invalid sel";
6984 goto die;
6985 }
876d4b07 6986 break;
9c2149c8
TS
6987 case 30:
6988 switch (sel) {
6989 case 0:
7db13fae 6990 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
2423f660
TS
6991 rn = "ErrorEPC";
6992 break;
9c2149c8
TS
6993 default:
6994 goto die;
6995 }
6996 break;
6997 case 31:
6998 switch (sel) {
6999 case 0:
f1aa6320 7000 /* EJTAG support */
7db13fae 7001 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
7002 rn = "DESAVE";
7003 break;
e98c0d17
LA
7004 case 2 ... 7:
7005 if (ctx->kscrexist & (1 << sel)) {
7006 tcg_gen_st_tl(arg, cpu_env,
7007 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7008 rn = "KScratch";
7009 }
7010 break;
9c2149c8
TS
7011 default:
7012 goto die;
7013 }
876d4b07
TS
7014 /* Stop translation as we may have switched the execution mode */
7015 ctx->bstate = BS_STOP;
9c2149c8
TS
7016 break;
7017 default:
876d4b07 7018 goto die;
9c2149c8 7019 }
2abf314d 7020 (void)rn; /* avoid a compiler warning */
d12d51d5 7021 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
bf20dc07 7022 /* For simplicity assume that all writes can cause interrupts. */
2e70f6ef
PB
7023 if (use_icount) {
7024 gen_io_end();
7025 ctx->bstate = BS_STOP;
7026 }
9c2149c8
TS
7027 return;
7028
7029die:
d12d51d5 7030 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
7031 generate_exception(ctx, EXCP_RI);
7032}
d26bc211 7033#endif /* TARGET_MIPS64 */
9c2149c8 7034
7db13fae 7035static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
ead9360e
TS
7036 int u, int sel, int h)
7037{
7038 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 7039 TCGv t0 = tcg_temp_local_new();
ead9360e
TS
7040
7041 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
7042 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7043 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
1a3fd9c3 7044 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
7045 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7046 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
1a3fd9c3 7047 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
7048 else if (u == 0) {
7049 switch (rt) {
5a25ce94
EI
7050 case 1:
7051 switch (sel) {
7052 case 1:
895c2d04 7053 gen_helper_mftc0_vpecontrol(t0, cpu_env);
5a25ce94
EI
7054 break;
7055 case 2:
895c2d04 7056 gen_helper_mftc0_vpeconf0(t0, cpu_env);
5a25ce94
EI
7057 break;
7058 default:
7059 goto die;
7060 break;
7061 }
7062 break;
ead9360e
TS
7063 case 2:
7064 switch (sel) {
7065 case 1:
895c2d04 7066 gen_helper_mftc0_tcstatus(t0, cpu_env);
ead9360e
TS
7067 break;
7068 case 2:
895c2d04 7069 gen_helper_mftc0_tcbind(t0, cpu_env);
ead9360e
TS
7070 break;
7071 case 3:
895c2d04 7072 gen_helper_mftc0_tcrestart(t0, cpu_env);
ead9360e
TS
7073 break;
7074 case 4:
895c2d04 7075 gen_helper_mftc0_tchalt(t0, cpu_env);
ead9360e
TS
7076 break;
7077 case 5:
895c2d04 7078 gen_helper_mftc0_tccontext(t0, cpu_env);
ead9360e
TS
7079 break;
7080 case 6:
895c2d04 7081 gen_helper_mftc0_tcschedule(t0, cpu_env);
ead9360e
TS
7082 break;
7083 case 7:
895c2d04 7084 gen_helper_mftc0_tcschefback(t0, cpu_env);
ead9360e
TS
7085 break;
7086 default:
d75c135e 7087 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
7088 break;
7089 }
7090 break;
7091 case 10:
7092 switch (sel) {
7093 case 0:
895c2d04 7094 gen_helper_mftc0_entryhi(t0, cpu_env);
ead9360e
TS
7095 break;
7096 default:
d75c135e 7097 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
7098 break;
7099 }
7100 case 12:
7101 switch (sel) {
7102 case 0:
895c2d04 7103 gen_helper_mftc0_status(t0, cpu_env);
ead9360e
TS
7104 break;
7105 default:
d75c135e 7106 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
7107 break;
7108 }
5a25ce94
EI
7109 case 13:
7110 switch (sel) {
7111 case 0:
895c2d04 7112 gen_helper_mftc0_cause(t0, cpu_env);
5a25ce94
EI
7113 break;
7114 default:
7115 goto die;
7116 break;
7117 }
7118 break;
7119 case 14:
7120 switch (sel) {
7121 case 0:
895c2d04 7122 gen_helper_mftc0_epc(t0, cpu_env);
5a25ce94
EI
7123 break;
7124 default:
7125 goto die;
7126 break;
7127 }
7128 break;
7129 case 15:
7130 switch (sel) {
7131 case 1:
895c2d04 7132 gen_helper_mftc0_ebase(t0, cpu_env);
5a25ce94
EI
7133 break;
7134 default:
7135 goto die;
7136 break;
7137 }
7138 break;
7139 case 16:
7140 switch (sel) {
7141 case 0 ... 7:
895c2d04 7142 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
5a25ce94
EI
7143 break;
7144 default:
7145 goto die;
7146 break;
7147 }
7148 break;
ead9360e
TS
7149 case 23:
7150 switch (sel) {
7151 case 0:
895c2d04 7152 gen_helper_mftc0_debug(t0, cpu_env);
ead9360e
TS
7153 break;
7154 default:
d75c135e 7155 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
7156 break;
7157 }
7158 break;
7159 default:
d75c135e 7160 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
7161 }
7162 } else switch (sel) {
7163 /* GPR registers. */
7164 case 0:
895c2d04 7165 gen_helper_1e0i(mftgpr, t0, rt);
ead9360e
TS
7166 break;
7167 /* Auxiliary CPU registers */
7168 case 1:
7169 switch (rt) {
7170 case 0:
895c2d04 7171 gen_helper_1e0i(mftlo, t0, 0);
ead9360e
TS
7172 break;
7173 case 1:
895c2d04 7174 gen_helper_1e0i(mfthi, t0, 0);
ead9360e
TS
7175 break;
7176 case 2:
895c2d04 7177 gen_helper_1e0i(mftacx, t0, 0);
ead9360e
TS
7178 break;
7179 case 4:
895c2d04 7180 gen_helper_1e0i(mftlo, t0, 1);
ead9360e
TS
7181 break;
7182 case 5:
895c2d04 7183 gen_helper_1e0i(mfthi, t0, 1);
ead9360e
TS
7184 break;
7185 case 6:
895c2d04 7186 gen_helper_1e0i(mftacx, t0, 1);
ead9360e
TS
7187 break;
7188 case 8:
895c2d04 7189 gen_helper_1e0i(mftlo, t0, 2);
ead9360e
TS
7190 break;
7191 case 9:
895c2d04 7192 gen_helper_1e0i(mfthi, t0, 2);
ead9360e
TS
7193 break;
7194 case 10:
895c2d04 7195 gen_helper_1e0i(mftacx, t0, 2);
ead9360e
TS
7196 break;
7197 case 12:
895c2d04 7198 gen_helper_1e0i(mftlo, t0, 3);
ead9360e
TS
7199 break;
7200 case 13:
895c2d04 7201 gen_helper_1e0i(mfthi, t0, 3);
ead9360e
TS
7202 break;
7203 case 14:
895c2d04 7204 gen_helper_1e0i(mftacx, t0, 3);
ead9360e
TS
7205 break;
7206 case 16:
895c2d04 7207 gen_helper_mftdsp(t0, cpu_env);
ead9360e
TS
7208 break;
7209 default:
7210 goto die;
7211 }
7212 break;
7213 /* Floating point (COP1). */
7214 case 2:
7215 /* XXX: For now we support only a single FPU context. */
7216 if (h == 0) {
a7812ae4 7217 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7218
7219 gen_load_fpr32(fp0, rt);
7220 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 7221 tcg_temp_free_i32(fp0);
ead9360e 7222 } else {
a7812ae4 7223 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 7224
7f6613ce 7225 gen_load_fpr32h(ctx, fp0, rt);
b6d96bed 7226 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 7227 tcg_temp_free_i32(fp0);
ead9360e
TS
7228 }
7229 break;
7230 case 3:
7231 /* XXX: For now we support only a single FPU context. */
895c2d04 7232 gen_helper_1e0i(cfc1, t0, rt);
ead9360e
TS
7233 break;
7234 /* COP2: Not implemented. */
7235 case 4:
7236 case 5:
7237 /* fall through */
7238 default:
7239 goto die;
7240 }
d12d51d5 7241 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
1a3fd9c3
TS
7242 gen_store_gpr(t0, rd);
7243 tcg_temp_free(t0);
ead9360e
TS
7244 return;
7245
7246die:
1a3fd9c3 7247 tcg_temp_free(t0);
d12d51d5 7248 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
ead9360e
TS
7249 generate_exception(ctx, EXCP_RI);
7250}
7251
7db13fae 7252static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
ead9360e
TS
7253 int u, int sel, int h)
7254{
7255 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 7256 TCGv t0 = tcg_temp_local_new();
ead9360e 7257
1a3fd9c3 7258 gen_load_gpr(t0, rt);
ead9360e 7259 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
7260 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7261 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
ead9360e
TS
7262 /* NOP */ ;
7263 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7264 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7265 /* NOP */ ;
7266 else if (u == 0) {
7267 switch (rd) {
5a25ce94
EI
7268 case 1:
7269 switch (sel) {
7270 case 1:
895c2d04 7271 gen_helper_mttc0_vpecontrol(cpu_env, t0);
5a25ce94
EI
7272 break;
7273 case 2:
895c2d04 7274 gen_helper_mttc0_vpeconf0(cpu_env, t0);
5a25ce94
EI
7275 break;
7276 default:
7277 goto die;
7278 break;
7279 }
7280 break;
ead9360e
TS
7281 case 2:
7282 switch (sel) {
7283 case 1:
895c2d04 7284 gen_helper_mttc0_tcstatus(cpu_env, t0);
ead9360e
TS
7285 break;
7286 case 2:
895c2d04 7287 gen_helper_mttc0_tcbind(cpu_env, t0);
ead9360e
TS
7288 break;
7289 case 3:
895c2d04 7290 gen_helper_mttc0_tcrestart(cpu_env, t0);
ead9360e
TS
7291 break;
7292 case 4:
895c2d04 7293 gen_helper_mttc0_tchalt(cpu_env, t0);
ead9360e
TS
7294 break;
7295 case 5:
895c2d04 7296 gen_helper_mttc0_tccontext(cpu_env, t0);
ead9360e
TS
7297 break;
7298 case 6:
895c2d04 7299 gen_helper_mttc0_tcschedule(cpu_env, t0);
ead9360e
TS
7300 break;
7301 case 7:
895c2d04 7302 gen_helper_mttc0_tcschefback(cpu_env, t0);
ead9360e
TS
7303 break;
7304 default:
d75c135e 7305 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
7306 break;
7307 }
7308 break;
7309 case 10:
7310 switch (sel) {
7311 case 0:
895c2d04 7312 gen_helper_mttc0_entryhi(cpu_env, t0);
ead9360e
TS
7313 break;
7314 default:
d75c135e 7315 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
7316 break;
7317 }
7318 case 12:
7319 switch (sel) {
7320 case 0:
895c2d04 7321 gen_helper_mttc0_status(cpu_env, t0);
ead9360e
TS
7322 break;
7323 default:
d75c135e 7324 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
7325 break;
7326 }
5a25ce94
EI
7327 case 13:
7328 switch (sel) {
7329 case 0:
895c2d04 7330 gen_helper_mttc0_cause(cpu_env, t0);
5a25ce94
EI
7331 break;
7332 default:
7333 goto die;
7334 break;
7335 }
7336 break;
7337 case 15:
7338 switch (sel) {
7339 case 1:
895c2d04 7340 gen_helper_mttc0_ebase(cpu_env, t0);
5a25ce94
EI
7341 break;
7342 default:
7343 goto die;
7344 break;
7345 }
7346 break;
ead9360e
TS
7347 case 23:
7348 switch (sel) {
7349 case 0:
895c2d04 7350 gen_helper_mttc0_debug(cpu_env, t0);
ead9360e
TS
7351 break;
7352 default:
d75c135e 7353 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
7354 break;
7355 }
7356 break;
7357 default:
d75c135e 7358 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
7359 }
7360 } else switch (sel) {
7361 /* GPR registers. */
7362 case 0:
895c2d04 7363 gen_helper_0e1i(mttgpr, t0, rd);
ead9360e
TS
7364 break;
7365 /* Auxiliary CPU registers */
7366 case 1:
7367 switch (rd) {
7368 case 0:
895c2d04 7369 gen_helper_0e1i(mttlo, t0, 0);
ead9360e
TS
7370 break;
7371 case 1:
895c2d04 7372 gen_helper_0e1i(mtthi, t0, 0);
ead9360e
TS
7373 break;
7374 case 2:
895c2d04 7375 gen_helper_0e1i(mttacx, t0, 0);
ead9360e
TS
7376 break;
7377 case 4:
895c2d04 7378 gen_helper_0e1i(mttlo, t0, 1);
ead9360e
TS
7379 break;
7380 case 5:
895c2d04 7381 gen_helper_0e1i(mtthi, t0, 1);
ead9360e
TS
7382 break;
7383 case 6:
895c2d04 7384 gen_helper_0e1i(mttacx, t0, 1);
ead9360e
TS
7385 break;
7386 case 8:
895c2d04 7387 gen_helper_0e1i(mttlo, t0, 2);
ead9360e
TS
7388 break;
7389 case 9:
895c2d04 7390 gen_helper_0e1i(mtthi, t0, 2);
ead9360e
TS
7391 break;
7392 case 10:
895c2d04 7393 gen_helper_0e1i(mttacx, t0, 2);
ead9360e
TS
7394 break;
7395 case 12:
895c2d04 7396 gen_helper_0e1i(mttlo, t0, 3);
ead9360e
TS
7397 break;
7398 case 13:
895c2d04 7399 gen_helper_0e1i(mtthi, t0, 3);
ead9360e
TS
7400 break;
7401 case 14:
895c2d04 7402 gen_helper_0e1i(mttacx, t0, 3);
ead9360e
TS
7403 break;
7404 case 16:
895c2d04 7405 gen_helper_mttdsp(cpu_env, t0);
ead9360e
TS
7406 break;
7407 default:
7408 goto die;
7409 }
7410 break;
7411 /* Floating point (COP1). */
7412 case 2:
7413 /* XXX: For now we support only a single FPU context. */
7414 if (h == 0) {
a7812ae4 7415 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7416
7417 tcg_gen_trunc_tl_i32(fp0, t0);
7418 gen_store_fpr32(fp0, rd);
a7812ae4 7419 tcg_temp_free_i32(fp0);
ead9360e 7420 } else {
a7812ae4 7421 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7422
7423 tcg_gen_trunc_tl_i32(fp0, t0);
7f6613ce 7424 gen_store_fpr32h(ctx, fp0, rd);
a7812ae4 7425 tcg_temp_free_i32(fp0);
ead9360e
TS
7426 }
7427 break;
7428 case 3:
7429 /* XXX: For now we support only a single FPU context. */
736d120a
PJ
7430 {
7431 TCGv_i32 fs_tmp = tcg_const_i32(rd);
7432
7433 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
7434 tcg_temp_free_i32(fs_tmp);
7435 }
ead9360e
TS
7436 break;
7437 /* COP2: Not implemented. */
7438 case 4:
7439 case 5:
7440 /* fall through */
7441 default:
7442 goto die;
7443 }
d12d51d5 7444 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
1a3fd9c3 7445 tcg_temp_free(t0);
ead9360e
TS
7446 return;
7447
7448die:
1a3fd9c3 7449 tcg_temp_free(t0);
d12d51d5 7450 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
ead9360e
TS
7451 generate_exception(ctx, EXCP_RI);
7452}
7453
7db13fae 7454static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
6af0bf9c 7455{
287c4b84 7456 const char *opn = "ldst";
6af0bf9c 7457
2e15497c 7458 check_cp0_enabled(ctx);
6af0bf9c
FB
7459 switch (opc) {
7460 case OPC_MFC0:
7461 if (rt == 0) {
ead9360e 7462 /* Treat as NOP. */
6af0bf9c
FB
7463 return;
7464 }
d75c135e 7465 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
6af0bf9c
FB
7466 opn = "mfc0";
7467 break;
7468 case OPC_MTC0:
1a3fd9c3 7469 {
1fc7bf6e 7470 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
7471
7472 gen_load_gpr(t0, rt);
d75c135e 7473 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
1a3fd9c3
TS
7474 tcg_temp_free(t0);
7475 }
6af0bf9c
FB
7476 opn = "mtc0";
7477 break;
d26bc211 7478#if defined(TARGET_MIPS64)
9c2149c8 7479 case OPC_DMFC0:
d75c135e 7480 check_insn(ctx, ISA_MIPS3);
9c2149c8 7481 if (rt == 0) {
ead9360e 7482 /* Treat as NOP. */
9c2149c8
TS
7483 return;
7484 }
d75c135e 7485 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9c2149c8
TS
7486 opn = "dmfc0";
7487 break;
7488 case OPC_DMTC0:
d75c135e 7489 check_insn(ctx, ISA_MIPS3);
1a3fd9c3 7490 {
1fc7bf6e 7491 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
7492
7493 gen_load_gpr(t0, rt);
d75c135e 7494 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
1a3fd9c3
TS
7495 tcg_temp_free(t0);
7496 }
9c2149c8
TS
7497 opn = "dmtc0";
7498 break;
534ce69f 7499#endif
ead9360e 7500 case OPC_MFTR:
d75c135e 7501 check_insn(ctx, ASE_MT);
ead9360e
TS
7502 if (rd == 0) {
7503 /* Treat as NOP. */
7504 return;
7505 }
6c5c1e20 7506 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
ead9360e 7507 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
ead9360e
TS
7508 opn = "mftr";
7509 break;
7510 case OPC_MTTR:
d75c135e 7511 check_insn(ctx, ASE_MT);
6c5c1e20 7512 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
ead9360e
TS
7513 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
7514 opn = "mttr";
7515 break;
6af0bf9c 7516 case OPC_TLBWI:
6af0bf9c 7517 opn = "tlbwi";
c01fccd2 7518 if (!env->tlb->helper_tlbwi)
29929e34 7519 goto die;
895c2d04 7520 gen_helper_tlbwi(cpu_env);
6af0bf9c 7521 break;
9456c2fb
LA
7522 case OPC_TLBINV:
7523 opn = "tlbinv";
7524 if (ctx->ie >= 2) {
7525 if (!env->tlb->helper_tlbinv) {
7526 goto die;
7527 }
7528 gen_helper_tlbinv(cpu_env);
7529 } /* treat as nop if TLBINV not supported */
7530 break;
7531 case OPC_TLBINVF:
7532 opn = "tlbinvf";
7533 if (ctx->ie >= 2) {
7534 if (!env->tlb->helper_tlbinvf) {
7535 goto die;
7536 }
7537 gen_helper_tlbinvf(cpu_env);
7538 } /* treat as nop if TLBINV not supported */
7539 break;
6af0bf9c 7540 case OPC_TLBWR:
6af0bf9c 7541 opn = "tlbwr";
c01fccd2 7542 if (!env->tlb->helper_tlbwr)
29929e34 7543 goto die;
895c2d04 7544 gen_helper_tlbwr(cpu_env);
6af0bf9c
FB
7545 break;
7546 case OPC_TLBP:
6af0bf9c 7547 opn = "tlbp";
c01fccd2 7548 if (!env->tlb->helper_tlbp)
29929e34 7549 goto die;
895c2d04 7550 gen_helper_tlbp(cpu_env);
6af0bf9c
FB
7551 break;
7552 case OPC_TLBR:
6af0bf9c 7553 opn = "tlbr";
c01fccd2 7554 if (!env->tlb->helper_tlbr)
29929e34 7555 goto die;
895c2d04 7556 gen_helper_tlbr(cpu_env);
6af0bf9c 7557 break;
6af0bf9c
FB
7558 case OPC_ERET:
7559 opn = "eret";
d75c135e 7560 check_insn(ctx, ISA_MIPS2);
895c2d04 7561 gen_helper_eret(cpu_env);
6af0bf9c
FB
7562 ctx->bstate = BS_EXCP;
7563 break;
7564 case OPC_DERET:
7565 opn = "deret";
d75c135e 7566 check_insn(ctx, ISA_MIPS32);
6af0bf9c 7567 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
923617a3 7568 MIPS_INVAL(opn);
6af0bf9c
FB
7569 generate_exception(ctx, EXCP_RI);
7570 } else {
895c2d04 7571 gen_helper_deret(cpu_env);
6af0bf9c
FB
7572 ctx->bstate = BS_EXCP;
7573 }
7574 break;
4ad40f36
FB
7575 case OPC_WAIT:
7576 opn = "wait";
d75c135e 7577 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
4ad40f36
FB
7578 /* If we get an exception, we want to restart at next instruction */
7579 ctx->pc += 4;
7580 save_cpu_state(ctx, 1);
7581 ctx->pc -= 4;
895c2d04 7582 gen_helper_wait(cpu_env);
4ad40f36
FB
7583 ctx->bstate = BS_EXCP;
7584 break;
6af0bf9c 7585 default:
29929e34 7586 die:
923617a3 7587 MIPS_INVAL(opn);
6af0bf9c
FB
7588 generate_exception(ctx, EXCP_RI);
7589 return;
7590 }
2abf314d 7591 (void)opn; /* avoid a compiler warning */
6af0bf9c
FB
7592 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
7593}
f1aa6320 7594#endif /* !CONFIG_USER_ONLY */
6af0bf9c 7595
6ea83fed 7596/* CP1 Branches (before delay slot) */
d75c135e
AJ
7597static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
7598 int32_t cc, int32_t offset)
6ea83fed
FB
7599{
7600 target_ulong btarget;
923617a3 7601 const char *opn = "cp1 cond branch";
a7812ae4 7602 TCGv_i32 t0 = tcg_temp_new_i32();
6ea83fed 7603
e189e748 7604 if (cc != 0)
d75c135e 7605 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
e189e748 7606
6ea83fed
FB
7607 btarget = ctx->pc + 4 + offset;
7608
7a387fff
TS
7609 switch (op) {
7610 case OPC_BC1F:
d94536f4
AJ
7611 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7612 tcg_gen_not_i32(t0, t0);
7613 tcg_gen_andi_i32(t0, t0, 1);
7614 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 7615 opn = "bc1f";
6ea83fed 7616 goto not_likely;
7a387fff 7617 case OPC_BC1FL:
d94536f4
AJ
7618 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7619 tcg_gen_not_i32(t0, t0);
7620 tcg_gen_andi_i32(t0, t0, 1);
7621 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 7622 opn = "bc1fl";
6ea83fed 7623 goto likely;
7a387fff 7624 case OPC_BC1T:
d94536f4
AJ
7625 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7626 tcg_gen_andi_i32(t0, t0, 1);
7627 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 7628 opn = "bc1t";
5a5012ec 7629 goto not_likely;
7a387fff 7630 case OPC_BC1TL:
d94536f4
AJ
7631 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7632 tcg_gen_andi_i32(t0, t0, 1);
7633 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 7634 opn = "bc1tl";
6ea83fed
FB
7635 likely:
7636 ctx->hflags |= MIPS_HFLAG_BL;
7637 break;
5a5012ec 7638 case OPC_BC1FANY2:
a16336e4 7639 {
d94536f4
AJ
7640 TCGv_i32 t1 = tcg_temp_new_i32();
7641 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7642 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
d7f66b52 7643 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 7644 tcg_temp_free_i32(t1);
d94536f4
AJ
7645 tcg_gen_andi_i32(t0, t0, 1);
7646 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 7647 }
fd4a04eb 7648 opn = "bc1any2f";
5a5012ec
TS
7649 goto not_likely;
7650 case OPC_BC1TANY2:
a16336e4 7651 {
d94536f4
AJ
7652 TCGv_i32 t1 = tcg_temp_new_i32();
7653 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7654 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
7655 tcg_gen_or_i32(t0, t0, t1);
7656 tcg_temp_free_i32(t1);
7657 tcg_gen_andi_i32(t0, t0, 1);
7658 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 7659 }
fd4a04eb 7660 opn = "bc1any2t";
5a5012ec
TS
7661 goto not_likely;
7662 case OPC_BC1FANY4:
a16336e4 7663 {
d94536f4
AJ
7664 TCGv_i32 t1 = tcg_temp_new_i32();
7665 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7666 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
d7f66b52 7667 tcg_gen_and_i32(t0, t0, t1);
d94536f4 7668 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
d7f66b52 7669 tcg_gen_and_i32(t0, t0, t1);
d94536f4 7670 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
d7f66b52 7671 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 7672 tcg_temp_free_i32(t1);
d94536f4
AJ
7673 tcg_gen_andi_i32(t0, t0, 1);
7674 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 7675 }
fd4a04eb 7676 opn = "bc1any4f";
5a5012ec
TS
7677 goto not_likely;
7678 case OPC_BC1TANY4:
a16336e4 7679 {
d94536f4
AJ
7680 TCGv_i32 t1 = tcg_temp_new_i32();
7681 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7682 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
7683 tcg_gen_or_i32(t0, t0, t1);
7684 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
7685 tcg_gen_or_i32(t0, t0, t1);
7686 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
7687 tcg_gen_or_i32(t0, t0, t1);
7688 tcg_temp_free_i32(t1);
7689 tcg_gen_andi_i32(t0, t0, 1);
7690 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 7691 }
fd4a04eb 7692 opn = "bc1any4t";
5a5012ec
TS
7693 not_likely:
7694 ctx->hflags |= MIPS_HFLAG_BC;
5a5012ec
TS
7695 break;
7696 default:
923617a3 7697 MIPS_INVAL(opn);
e397ee33 7698 generate_exception (ctx, EXCP_RI);
6c5c1e20 7699 goto out;
6ea83fed 7700 }
2abf314d 7701 (void)opn; /* avoid a compiler warning */
923617a3 7702 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
6ea83fed
FB
7703 ctx->hflags, btarget);
7704 ctx->btarget = btarget;
b231c103 7705 ctx->hflags |= MIPS_HFLAG_BDS32;
6c5c1e20 7706 out:
a7812ae4 7707 tcg_temp_free_i32(t0);
6ea83fed
FB
7708}
7709
31837be3
YK
7710/* R6 CP1 Branches */
7711static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
7712 int32_t ft, int32_t offset)
7713{
7714 target_ulong btarget;
7715 const char *opn = "cp1 cond branch";
7716 TCGv_i64 t0 = tcg_temp_new_i64();
7717
7718 if (ctx->hflags & MIPS_HFLAG_BMASK) {
7719#ifdef MIPS_DEBUG_DISAS
7720 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
7721#endif
7722 generate_exception(ctx, EXCP_RI);
7723 goto out;
7724 }
7725
7726 gen_load_fpr64(ctx, t0, ft);
7727 tcg_gen_andi_i64(t0, t0, 1);
7728
7729 btarget = addr_add(ctx, ctx->pc + 4, offset);
7730
7731 switch (op) {
7732 case OPC_BC1EQZ:
7733 tcg_gen_xori_i64(t0, t0, 1);
7734 opn = "bc1eqz";
7735 ctx->hflags |= MIPS_HFLAG_BC;
7736 break;
7737 case OPC_BC1NEZ:
7738 /* t0 already set */
7739 opn = "bc1nez";
7740 ctx->hflags |= MIPS_HFLAG_BC;
7741 break;
7742 default:
7743 MIPS_INVAL(opn);
7744 generate_exception(ctx, EXCP_RI);
7745 goto out;
7746 }
7747
7748 tcg_gen_trunc_i64_tl(bcond, t0);
7749
7750 (void)opn; /* avoid a compiler warning */
7751 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
7752 ctx->hflags, btarget);
7753 ctx->btarget = btarget;
7754
7755out:
7756 tcg_temp_free_i64(t0);
7757}
7758
6af0bf9c 7759/* Coprocessor 1 (FPU) */
5a5012ec 7760
5a5012ec
TS
7761#define FOP(func, fmt) (((fmt) << 21) | (func))
7762
bf4120ad
NF
7763enum fopcode {
7764 OPC_ADD_S = FOP(0, FMT_S),
7765 OPC_SUB_S = FOP(1, FMT_S),
7766 OPC_MUL_S = FOP(2, FMT_S),
7767 OPC_DIV_S = FOP(3, FMT_S),
7768 OPC_SQRT_S = FOP(4, FMT_S),
7769 OPC_ABS_S = FOP(5, FMT_S),
7770 OPC_MOV_S = FOP(6, FMT_S),
7771 OPC_NEG_S = FOP(7, FMT_S),
7772 OPC_ROUND_L_S = FOP(8, FMT_S),
7773 OPC_TRUNC_L_S = FOP(9, FMT_S),
7774 OPC_CEIL_L_S = FOP(10, FMT_S),
7775 OPC_FLOOR_L_S = FOP(11, FMT_S),
7776 OPC_ROUND_W_S = FOP(12, FMT_S),
7777 OPC_TRUNC_W_S = FOP(13, FMT_S),
7778 OPC_CEIL_W_S = FOP(14, FMT_S),
7779 OPC_FLOOR_W_S = FOP(15, FMT_S),
e7f16abb 7780 OPC_SEL_S = FOP(16, FMT_S),
bf4120ad
NF
7781 OPC_MOVCF_S = FOP(17, FMT_S),
7782 OPC_MOVZ_S = FOP(18, FMT_S),
7783 OPC_MOVN_S = FOP(19, FMT_S),
e7f16abb 7784 OPC_SELEQZ_S = FOP(20, FMT_S),
bf4120ad
NF
7785 OPC_RECIP_S = FOP(21, FMT_S),
7786 OPC_RSQRT_S = FOP(22, FMT_S),
e7f16abb
LA
7787 OPC_SELNEZ_S = FOP(23, FMT_S),
7788 OPC_MADDF_S = FOP(24, FMT_S),
7789 OPC_MSUBF_S = FOP(25, FMT_S),
7790 OPC_RINT_S = FOP(26, FMT_S),
7791 OPC_CLASS_S = FOP(27, FMT_S),
7792 OPC_MIN_S = FOP(28, FMT_S),
bf4120ad 7793 OPC_RECIP2_S = FOP(28, FMT_S),
e7f16abb 7794 OPC_MINA_S = FOP(29, FMT_S),
bf4120ad 7795 OPC_RECIP1_S = FOP(29, FMT_S),
e7f16abb 7796 OPC_MAX_S = FOP(30, FMT_S),
bf4120ad 7797 OPC_RSQRT1_S = FOP(30, FMT_S),
e7f16abb 7798 OPC_MAXA_S = FOP(31, FMT_S),
bf4120ad
NF
7799 OPC_RSQRT2_S = FOP(31, FMT_S),
7800 OPC_CVT_D_S = FOP(33, FMT_S),
7801 OPC_CVT_W_S = FOP(36, FMT_S),
7802 OPC_CVT_L_S = FOP(37, FMT_S),
7803 OPC_CVT_PS_S = FOP(38, FMT_S),
7804 OPC_CMP_F_S = FOP (48, FMT_S),
7805 OPC_CMP_UN_S = FOP (49, FMT_S),
7806 OPC_CMP_EQ_S = FOP (50, FMT_S),
7807 OPC_CMP_UEQ_S = FOP (51, FMT_S),
7808 OPC_CMP_OLT_S = FOP (52, FMT_S),
7809 OPC_CMP_ULT_S = FOP (53, FMT_S),
7810 OPC_CMP_OLE_S = FOP (54, FMT_S),
7811 OPC_CMP_ULE_S = FOP (55, FMT_S),
7812 OPC_CMP_SF_S = FOP (56, FMT_S),
7813 OPC_CMP_NGLE_S = FOP (57, FMT_S),
7814 OPC_CMP_SEQ_S = FOP (58, FMT_S),
7815 OPC_CMP_NGL_S = FOP (59, FMT_S),
7816 OPC_CMP_LT_S = FOP (60, FMT_S),
7817 OPC_CMP_NGE_S = FOP (61, FMT_S),
7818 OPC_CMP_LE_S = FOP (62, FMT_S),
7819 OPC_CMP_NGT_S = FOP (63, FMT_S),
7820
7821 OPC_ADD_D = FOP(0, FMT_D),
7822 OPC_SUB_D = FOP(1, FMT_D),
7823 OPC_MUL_D = FOP(2, FMT_D),
7824 OPC_DIV_D = FOP(3, FMT_D),
7825 OPC_SQRT_D = FOP(4, FMT_D),
7826 OPC_ABS_D = FOP(5, FMT_D),
7827 OPC_MOV_D = FOP(6, FMT_D),
7828 OPC_NEG_D = FOP(7, FMT_D),
7829 OPC_ROUND_L_D = FOP(8, FMT_D),
7830 OPC_TRUNC_L_D = FOP(9, FMT_D),
7831 OPC_CEIL_L_D = FOP(10, FMT_D),
7832 OPC_FLOOR_L_D = FOP(11, FMT_D),
7833 OPC_ROUND_W_D = FOP(12, FMT_D),
7834 OPC_TRUNC_W_D = FOP(13, FMT_D),
7835 OPC_CEIL_W_D = FOP(14, FMT_D),
7836 OPC_FLOOR_W_D = FOP(15, FMT_D),
e7f16abb 7837 OPC_SEL_D = FOP(16, FMT_D),
bf4120ad
NF
7838 OPC_MOVCF_D = FOP(17, FMT_D),
7839 OPC_MOVZ_D = FOP(18, FMT_D),
7840 OPC_MOVN_D = FOP(19, FMT_D),
e7f16abb 7841 OPC_SELEQZ_D = FOP(20, FMT_D),
bf4120ad
NF
7842 OPC_RECIP_D = FOP(21, FMT_D),
7843 OPC_RSQRT_D = FOP(22, FMT_D),
e7f16abb
LA
7844 OPC_SELNEZ_D = FOP(23, FMT_D),
7845 OPC_MADDF_D = FOP(24, FMT_D),
7846 OPC_MSUBF_D = FOP(25, FMT_D),
7847 OPC_RINT_D = FOP(26, FMT_D),
7848 OPC_CLASS_D = FOP(27, FMT_D),
7849 OPC_MIN_D = FOP(28, FMT_D),
bf4120ad 7850 OPC_RECIP2_D = FOP(28, FMT_D),
e7f16abb 7851 OPC_MINA_D = FOP(29, FMT_D),
bf4120ad 7852 OPC_RECIP1_D = FOP(29, FMT_D),
e7f16abb 7853 OPC_MAX_D = FOP(30, FMT_D),
bf4120ad 7854 OPC_RSQRT1_D = FOP(30, FMT_D),
e7f16abb 7855 OPC_MAXA_D = FOP(31, FMT_D),
bf4120ad
NF
7856 OPC_RSQRT2_D = FOP(31, FMT_D),
7857 OPC_CVT_S_D = FOP(32, FMT_D),
7858 OPC_CVT_W_D = FOP(36, FMT_D),
7859 OPC_CVT_L_D = FOP(37, FMT_D),
7860 OPC_CMP_F_D = FOP (48, FMT_D),
7861 OPC_CMP_UN_D = FOP (49, FMT_D),
7862 OPC_CMP_EQ_D = FOP (50, FMT_D),
7863 OPC_CMP_UEQ_D = FOP (51, FMT_D),
7864 OPC_CMP_OLT_D = FOP (52, FMT_D),
7865 OPC_CMP_ULT_D = FOP (53, FMT_D),
7866 OPC_CMP_OLE_D = FOP (54, FMT_D),
7867 OPC_CMP_ULE_D = FOP (55, FMT_D),
7868 OPC_CMP_SF_D = FOP (56, FMT_D),
7869 OPC_CMP_NGLE_D = FOP (57, FMT_D),
7870 OPC_CMP_SEQ_D = FOP (58, FMT_D),
7871 OPC_CMP_NGL_D = FOP (59, FMT_D),
7872 OPC_CMP_LT_D = FOP (60, FMT_D),
7873 OPC_CMP_NGE_D = FOP (61, FMT_D),
7874 OPC_CMP_LE_D = FOP (62, FMT_D),
7875 OPC_CMP_NGT_D = FOP (63, FMT_D),
7876
7877 OPC_CVT_S_W = FOP(32, FMT_W),
7878 OPC_CVT_D_W = FOP(33, FMT_W),
7879 OPC_CVT_S_L = FOP(32, FMT_L),
7880 OPC_CVT_D_L = FOP(33, FMT_L),
7881 OPC_CVT_PS_PW = FOP(38, FMT_W),
7882
7883 OPC_ADD_PS = FOP(0, FMT_PS),
7884 OPC_SUB_PS = FOP(1, FMT_PS),
7885 OPC_MUL_PS = FOP(2, FMT_PS),
7886 OPC_DIV_PS = FOP(3, FMT_PS),
7887 OPC_ABS_PS = FOP(5, FMT_PS),
7888 OPC_MOV_PS = FOP(6, FMT_PS),
7889 OPC_NEG_PS = FOP(7, FMT_PS),
7890 OPC_MOVCF_PS = FOP(17, FMT_PS),
7891 OPC_MOVZ_PS = FOP(18, FMT_PS),
7892 OPC_MOVN_PS = FOP(19, FMT_PS),
7893 OPC_ADDR_PS = FOP(24, FMT_PS),
7894 OPC_MULR_PS = FOP(26, FMT_PS),
7895 OPC_RECIP2_PS = FOP(28, FMT_PS),
7896 OPC_RECIP1_PS = FOP(29, FMT_PS),
7897 OPC_RSQRT1_PS = FOP(30, FMT_PS),
7898 OPC_RSQRT2_PS = FOP(31, FMT_PS),
7899
7900 OPC_CVT_S_PU = FOP(32, FMT_PS),
7901 OPC_CVT_PW_PS = FOP(36, FMT_PS),
7902 OPC_CVT_S_PL = FOP(40, FMT_PS),
7903 OPC_PLL_PS = FOP(44, FMT_PS),
7904 OPC_PLU_PS = FOP(45, FMT_PS),
7905 OPC_PUL_PS = FOP(46, FMT_PS),
7906 OPC_PUU_PS = FOP(47, FMT_PS),
7907 OPC_CMP_F_PS = FOP (48, FMT_PS),
7908 OPC_CMP_UN_PS = FOP (49, FMT_PS),
7909 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
7910 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
7911 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
7912 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
7913 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
7914 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
7915 OPC_CMP_SF_PS = FOP (56, FMT_PS),
7916 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
7917 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
7918 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
7919 OPC_CMP_LT_PS = FOP (60, FMT_PS),
7920 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
7921 OPC_CMP_LE_PS = FOP (62, FMT_PS),
7922 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
7923};
7924
3f493883
YK
7925enum r6_f_cmp_op {
7926 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
7927 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
7928 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
7929 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
7930 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
7931 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
7932 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
7933 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
7934 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
7935 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
7936 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
7937 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
7938 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
7939 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
7940 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
7941 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
7942 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
7943 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
7944 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
7945 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
7946 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
7947 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
7948
7949 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
7950 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
7951 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
7952 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
7953 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
7954 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
7955 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
7956 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
7957 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
7958 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
7959 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
7960 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
7961 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
7962 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
7963 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
7964 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
7965 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
7966 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
7967 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
7968 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
7969 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
7970 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
7971};
7a387fff 7972static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6ea83fed 7973{
923617a3 7974 const char *opn = "cp1 move";
72c3a3ee 7975 TCGv t0 = tcg_temp_new();
6ea83fed
FB
7976
7977 switch (opc) {
7978 case OPC_MFC1:
b6d96bed 7979 {
a7812ae4 7980 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7981
7982 gen_load_fpr32(fp0, fs);
7983 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 7984 tcg_temp_free_i32(fp0);
6958549d 7985 }
6c5c1e20 7986 gen_store_gpr(t0, rt);
6ea83fed
FB
7987 opn = "mfc1";
7988 break;
7989 case OPC_MTC1:
6c5c1e20 7990 gen_load_gpr(t0, rt);
b6d96bed 7991 {
a7812ae4 7992 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7993
7994 tcg_gen_trunc_tl_i32(fp0, t0);
7995 gen_store_fpr32(fp0, fs);
a7812ae4 7996 tcg_temp_free_i32(fp0);
6958549d 7997 }
6ea83fed
FB
7998 opn = "mtc1";
7999 break;
8000 case OPC_CFC1:
895c2d04 8001 gen_helper_1e0i(cfc1, t0, fs);
6c5c1e20 8002 gen_store_gpr(t0, rt);
6ea83fed
FB
8003 opn = "cfc1";
8004 break;
8005 case OPC_CTC1:
6c5c1e20 8006 gen_load_gpr(t0, rt);
736d120a
PJ
8007 {
8008 TCGv_i32 fs_tmp = tcg_const_i32(fs);
8009
8010 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8011 tcg_temp_free_i32(fs_tmp);
8012 }
6ea83fed
FB
8013 opn = "ctc1";
8014 break;
72c3a3ee 8015#if defined(TARGET_MIPS64)
9c2149c8 8016 case OPC_DMFC1:
72c3a3ee 8017 gen_load_fpr64(ctx, t0, fs);
6c5c1e20 8018 gen_store_gpr(t0, rt);
5a5012ec
TS
8019 opn = "dmfc1";
8020 break;
9c2149c8 8021 case OPC_DMTC1:
6c5c1e20 8022 gen_load_gpr(t0, rt);
72c3a3ee 8023 gen_store_fpr64(ctx, t0, fs);
5a5012ec
TS
8024 opn = "dmtc1";
8025 break;
72c3a3ee 8026#endif
5a5012ec 8027 case OPC_MFHC1:
b6d96bed 8028 {
a7812ae4 8029 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 8030
7f6613ce 8031 gen_load_fpr32h(ctx, fp0, fs);
b6d96bed 8032 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 8033 tcg_temp_free_i32(fp0);
6958549d 8034 }
6c5c1e20 8035 gen_store_gpr(t0, rt);
5a5012ec
TS
8036 opn = "mfhc1";
8037 break;
8038 case OPC_MTHC1:
6c5c1e20 8039 gen_load_gpr(t0, rt);
b6d96bed 8040 {
a7812ae4 8041 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
8042
8043 tcg_gen_trunc_tl_i32(fp0, t0);
7f6613ce 8044 gen_store_fpr32h(ctx, fp0, fs);
a7812ae4 8045 tcg_temp_free_i32(fp0);
6958549d 8046 }
5a5012ec
TS
8047 opn = "mthc1";
8048 break;
6ea83fed 8049 default:
923617a3 8050 MIPS_INVAL(opn);
e397ee33 8051 generate_exception (ctx, EXCP_RI);
6c5c1e20 8052 goto out;
6ea83fed 8053 }
2abf314d 8054 (void)opn; /* avoid a compiler warning */
6ea83fed 8055 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
6c5c1e20
TS
8056
8057 out:
8058 tcg_temp_free(t0);
6ea83fed
FB
8059}
8060
5a5012ec
TS
8061static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
8062{
af58f9ca 8063 int l1;
e214b9bb 8064 TCGCond cond;
af58f9ca
AJ
8065 TCGv_i32 t0;
8066
8067 if (rd == 0) {
8068 /* Treat as NOP. */
8069 return;
8070 }
6ea83fed 8071
e214b9bb 8072 if (tf)
e214b9bb 8073 cond = TCG_COND_EQ;
27848470
TS
8074 else
8075 cond = TCG_COND_NE;
8076
af58f9ca
AJ
8077 l1 = gen_new_label();
8078 t0 = tcg_temp_new_i32();
fa31af0e 8079 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
af58f9ca 8080 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 8081 tcg_temp_free_i32(t0);
af58f9ca
AJ
8082 if (rs == 0) {
8083 tcg_gen_movi_tl(cpu_gpr[rd], 0);
8084 } else {
8085 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
8086 }
e214b9bb 8087 gen_set_label(l1);
5a5012ec
TS
8088}
8089
b6d96bed 8090static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
a16336e4 8091{
a16336e4 8092 int cond;
cbc37b28 8093 TCGv_i32 t0 = tcg_temp_new_i32();
a16336e4
TS
8094 int l1 = gen_new_label();
8095
a16336e4
TS
8096 if (tf)
8097 cond = TCG_COND_EQ;
8098 else
8099 cond = TCG_COND_NE;
8100
fa31af0e 8101 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28
AJ
8102 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8103 gen_load_fpr32(t0, fs);
8104 gen_store_fpr32(t0, fd);
a16336e4 8105 gen_set_label(l1);
cbc37b28 8106 tcg_temp_free_i32(t0);
5a5012ec 8107}
a16336e4 8108
b6d96bed 8109static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
a16336e4 8110{
a16336e4 8111 int cond;
cbc37b28
AJ
8112 TCGv_i32 t0 = tcg_temp_new_i32();
8113 TCGv_i64 fp0;
a16336e4
TS
8114 int l1 = gen_new_label();
8115
a16336e4
TS
8116 if (tf)
8117 cond = TCG_COND_EQ;
8118 else
8119 cond = TCG_COND_NE;
8120
fa31af0e 8121 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 8122 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 8123 tcg_temp_free_i32(t0);
11f94258 8124 fp0 = tcg_temp_new_i64();
9bf3eb2c 8125 gen_load_fpr64(ctx, fp0, fs);
9bf3eb2c 8126 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8127 tcg_temp_free_i64(fp0);
cbc37b28 8128 gen_set_label(l1);
a16336e4
TS
8129}
8130
7f6613ce
PJ
8131static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
8132 int cc, int tf)
a16336e4
TS
8133{
8134 int cond;
cbc37b28 8135 TCGv_i32 t0 = tcg_temp_new_i32();
a16336e4
TS
8136 int l1 = gen_new_label();
8137 int l2 = gen_new_label();
8138
8139 if (tf)
8140 cond = TCG_COND_EQ;
8141 else
8142 cond = TCG_COND_NE;
8143
fa31af0e 8144 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28
AJ
8145 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8146 gen_load_fpr32(t0, fs);
8147 gen_store_fpr32(t0, fd);
a16336e4 8148 gen_set_label(l1);
9bf3eb2c 8149
fa31af0e 8150 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
cbc37b28 8151 tcg_gen_brcondi_i32(cond, t0, 0, l2);
7f6613ce
PJ
8152 gen_load_fpr32h(ctx, t0, fs);
8153 gen_store_fpr32h(ctx, t0, fd);
52a0e9eb 8154 tcg_temp_free_i32(t0);
a16336e4 8155 gen_set_label(l2);
a16336e4
TS
8156}
8157
e7f16abb
LA
8158static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8159 int fs)
8160{
8161 TCGv_i32 t1 = tcg_const_i32(0);
8162 TCGv_i32 fp0 = tcg_temp_new_i32();
8163 TCGv_i32 fp1 = tcg_temp_new_i32();
8164 TCGv_i32 fp2 = tcg_temp_new_i32();
8165 gen_load_fpr32(fp0, fd);
8166 gen_load_fpr32(fp1, ft);
8167 gen_load_fpr32(fp2, fs);
8168
8169 switch (op1) {
8170 case OPC_SEL_S:
8171 tcg_gen_andi_i32(fp0, fp0, 1);
8172 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8173 break;
8174 case OPC_SELEQZ_S:
8175 tcg_gen_andi_i32(fp1, fp1, 1);
8176 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8177 break;
8178 case OPC_SELNEZ_S:
8179 tcg_gen_andi_i32(fp1, fp1, 1);
8180 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8181 break;
8182 default:
8183 MIPS_INVAL("gen_sel_s");
8184 generate_exception (ctx, EXCP_RI);
8185 break;
8186 }
8187
8188 gen_store_fpr32(fp0, fd);
8189 tcg_temp_free_i32(fp2);
8190 tcg_temp_free_i32(fp1);
8191 tcg_temp_free_i32(fp0);
8192 tcg_temp_free_i32(t1);
8193}
8194
8195static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8196 int fs)
8197{
8198 TCGv_i64 t1 = tcg_const_i64(0);
8199 TCGv_i64 fp0 = tcg_temp_new_i64();
8200 TCGv_i64 fp1 = tcg_temp_new_i64();
8201 TCGv_i64 fp2 = tcg_temp_new_i64();
8202 gen_load_fpr64(ctx, fp0, fd);
8203 gen_load_fpr64(ctx, fp1, ft);
8204 gen_load_fpr64(ctx, fp2, fs);
8205
8206 switch (op1) {
8207 case OPC_SEL_D:
8208 tcg_gen_andi_i64(fp0, fp0, 1);
8209 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8210 break;
8211 case OPC_SELEQZ_D:
8212 tcg_gen_andi_i64(fp1, fp1, 1);
8213 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8214 break;
8215 case OPC_SELNEZ_D:
8216 tcg_gen_andi_i64(fp1, fp1, 1);
8217 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8218 break;
8219 default:
8220 MIPS_INVAL("gen_sel_d");
8221 generate_exception (ctx, EXCP_RI);
8222 break;
8223 }
8224
8225 gen_store_fpr64(ctx, fp0, fd);
8226 tcg_temp_free_i64(fp2);
8227 tcg_temp_free_i64(fp1);
8228 tcg_temp_free_i64(fp0);
8229 tcg_temp_free_i64(t1);
8230}
6ea83fed 8231
bf4120ad 8232static void gen_farith (DisasContext *ctx, enum fopcode op1,
5e755519 8233 int ft, int fs, int fd, int cc)
6ea83fed 8234{
923617a3 8235 const char *opn = "farith";
6ea83fed
FB
8236 const char *condnames[] = {
8237 "c.f",
8238 "c.un",
8239 "c.eq",
8240 "c.ueq",
8241 "c.olt",
8242 "c.ult",
8243 "c.ole",
8244 "c.ule",
8245 "c.sf",
8246 "c.ngle",
8247 "c.seq",
8248 "c.ngl",
8249 "c.lt",
8250 "c.nge",
8251 "c.le",
8252 "c.ngt",
8253 };
5a1e8ffb
TS
8254 const char *condnames_abs[] = {
8255 "cabs.f",
8256 "cabs.un",
8257 "cabs.eq",
8258 "cabs.ueq",
8259 "cabs.olt",
8260 "cabs.ult",
8261 "cabs.ole",
8262 "cabs.ule",
8263 "cabs.sf",
8264 "cabs.ngle",
8265 "cabs.seq",
8266 "cabs.ngl",
8267 "cabs.lt",
8268 "cabs.nge",
8269 "cabs.le",
8270 "cabs.ngt",
8271 };
8272 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
7a387fff
TS
8273 uint32_t func = ctx->opcode & 0x3f;
8274
bf4120ad
NF
8275 switch (op1) {
8276 case OPC_ADD_S:
b6d96bed 8277 {
a7812ae4
PB
8278 TCGv_i32 fp0 = tcg_temp_new_i32();
8279 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
8280
8281 gen_load_fpr32(fp0, fs);
8282 gen_load_fpr32(fp1, ft);
895c2d04 8283 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
a7812ae4 8284 tcg_temp_free_i32(fp1);
b6d96bed 8285 gen_store_fpr32(fp0, fd);
a7812ae4 8286 tcg_temp_free_i32(fp0);
b6d96bed 8287 }
5a5012ec 8288 opn = "add.s";
5a1e8ffb 8289 optype = BINOP;
5a5012ec 8290 break;
bf4120ad 8291 case OPC_SUB_S:
b6d96bed 8292 {
a7812ae4
PB
8293 TCGv_i32 fp0 = tcg_temp_new_i32();
8294 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
8295
8296 gen_load_fpr32(fp0, fs);
8297 gen_load_fpr32(fp1, ft);
895c2d04 8298 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
a7812ae4 8299 tcg_temp_free_i32(fp1);
b6d96bed 8300 gen_store_fpr32(fp0, fd);
a7812ae4 8301 tcg_temp_free_i32(fp0);
b6d96bed 8302 }
5a5012ec 8303 opn = "sub.s";
5a1e8ffb 8304 optype = BINOP;
5a5012ec 8305 break;
bf4120ad 8306 case OPC_MUL_S:
b6d96bed 8307 {
a7812ae4
PB
8308 TCGv_i32 fp0 = tcg_temp_new_i32();
8309 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
8310
8311 gen_load_fpr32(fp0, fs);
8312 gen_load_fpr32(fp1, ft);
895c2d04 8313 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
a7812ae4 8314 tcg_temp_free_i32(fp1);
b6d96bed 8315 gen_store_fpr32(fp0, fd);
a7812ae4 8316 tcg_temp_free_i32(fp0);
b6d96bed 8317 }
5a5012ec 8318 opn = "mul.s";
5a1e8ffb 8319 optype = BINOP;
5a5012ec 8320 break;
bf4120ad 8321 case OPC_DIV_S:
b6d96bed 8322 {
a7812ae4
PB
8323 TCGv_i32 fp0 = tcg_temp_new_i32();
8324 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
8325
8326 gen_load_fpr32(fp0, fs);
8327 gen_load_fpr32(fp1, ft);
895c2d04 8328 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
a7812ae4 8329 tcg_temp_free_i32(fp1);
b6d96bed 8330 gen_store_fpr32(fp0, fd);
a7812ae4 8331 tcg_temp_free_i32(fp0);
b6d96bed 8332 }
5a5012ec 8333 opn = "div.s";
5a1e8ffb 8334 optype = BINOP;
5a5012ec 8335 break;
bf4120ad 8336 case OPC_SQRT_S:
b6d96bed 8337 {
a7812ae4 8338 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
8339
8340 gen_load_fpr32(fp0, fs);
895c2d04 8341 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
b6d96bed 8342 gen_store_fpr32(fp0, fd);
a7812ae4 8343 tcg_temp_free_i32(fp0);
b6d96bed 8344 }
5a5012ec
TS
8345 opn = "sqrt.s";
8346 break;
bf4120ad 8347 case OPC_ABS_S:
b6d96bed 8348 {
a7812ae4 8349 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
8350
8351 gen_load_fpr32(fp0, fs);
a7812ae4 8352 gen_helper_float_abs_s(fp0, fp0);
b6d96bed 8353 gen_store_fpr32(fp0, fd);
a7812ae4 8354 tcg_temp_free_i32(fp0);
b6d96bed 8355 }
5a5012ec
TS
8356 opn = "abs.s";
8357 break;
bf4120ad 8358 case OPC_MOV_S:
b6d96bed 8359 {
a7812ae4 8360 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
8361
8362 gen_load_fpr32(fp0, fs);
8363 gen_store_fpr32(fp0, fd);
a7812ae4 8364 tcg_temp_free_i32(fp0);
b6d96bed 8365 }
5a5012ec
TS
8366 opn = "mov.s";
8367 break;
bf4120ad 8368 case OPC_NEG_S:
b6d96bed 8369 {
a7812ae4 8370 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
8371
8372 gen_load_fpr32(fp0, fs);
a7812ae4 8373 gen_helper_float_chs_s(fp0, fp0);
b6d96bed 8374 gen_store_fpr32(fp0, fd);
a7812ae4 8375 tcg_temp_free_i32(fp0);
b6d96bed 8376 }
5a5012ec
TS
8377 opn = "neg.s";
8378 break;
bf4120ad 8379 case OPC_ROUND_L_S:
5e755519 8380 check_cp1_64bitmode(ctx);
b6d96bed 8381 {
a7812ae4
PB
8382 TCGv_i32 fp32 = tcg_temp_new_i32();
8383 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
8384
8385 gen_load_fpr32(fp32, fs);
895c2d04 8386 gen_helper_float_roundl_s(fp64, cpu_env, fp32);
a7812ae4 8387 tcg_temp_free_i32(fp32);
b6d96bed 8388 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 8389 tcg_temp_free_i64(fp64);
b6d96bed 8390 }
5a5012ec
TS
8391 opn = "round.l.s";
8392 break;
bf4120ad 8393 case OPC_TRUNC_L_S:
5e755519 8394 check_cp1_64bitmode(ctx);
b6d96bed 8395 {
a7812ae4
PB
8396 TCGv_i32 fp32 = tcg_temp_new_i32();
8397 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
8398
8399 gen_load_fpr32(fp32, fs);
895c2d04 8400 gen_helper_float_truncl_s(fp64, cpu_env, fp32);
a7812ae4 8401 tcg_temp_free_i32(fp32);
b6d96bed 8402 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 8403 tcg_temp_free_i64(fp64);
b6d96bed 8404 }
5a5012ec
TS
8405 opn = "trunc.l.s";
8406 break;
bf4120ad 8407 case OPC_CEIL_L_S:
5e755519 8408 check_cp1_64bitmode(ctx);
b6d96bed 8409 {
a7812ae4
PB
8410 TCGv_i32 fp32 = tcg_temp_new_i32();
8411 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
8412
8413 gen_load_fpr32(fp32, fs);
895c2d04 8414 gen_helper_float_ceill_s(fp64, cpu_env, fp32);
a7812ae4 8415 tcg_temp_free_i32(fp32);
b6d96bed 8416 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 8417 tcg_temp_free_i64(fp64);
b6d96bed 8418 }
5a5012ec
TS
8419 opn = "ceil.l.s";
8420 break;
bf4120ad 8421 case OPC_FLOOR_L_S:
5e755519 8422 check_cp1_64bitmode(ctx);
b6d96bed 8423 {
a7812ae4
PB
8424 TCGv_i32 fp32 = tcg_temp_new_i32();
8425 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
8426
8427 gen_load_fpr32(fp32, fs);
895c2d04 8428 gen_helper_float_floorl_s(fp64, cpu_env, fp32);
a7812ae4 8429 tcg_temp_free_i32(fp32);
b6d96bed 8430 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 8431 tcg_temp_free_i64(fp64);
b6d96bed 8432 }
5a5012ec
TS
8433 opn = "floor.l.s";
8434 break;
bf4120ad 8435 case OPC_ROUND_W_S:
b6d96bed 8436 {
a7812ae4 8437 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
8438
8439 gen_load_fpr32(fp0, fs);
895c2d04 8440 gen_helper_float_roundw_s(fp0, cpu_env, fp0);
b6d96bed 8441 gen_store_fpr32(fp0, fd);
a7812ae4 8442 tcg_temp_free_i32(fp0);
b6d96bed 8443 }
5a5012ec
TS
8444 opn = "round.w.s";
8445 break;
bf4120ad 8446 case OPC_TRUNC_W_S:
b6d96bed 8447 {
a7812ae4 8448 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
8449
8450 gen_load_fpr32(fp0, fs);
895c2d04 8451 gen_helper_float_truncw_s(fp0, cpu_env, fp0);
b6d96bed 8452 gen_store_fpr32(fp0, fd);
a7812ae4 8453 tcg_temp_free_i32(fp0);
b6d96bed 8454 }
5a5012ec
TS
8455 opn = "trunc.w.s";
8456 break;
bf4120ad 8457 case OPC_CEIL_W_S:
b6d96bed 8458 {
a7812ae4 8459 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
8460
8461 gen_load_fpr32(fp0, fs);
895c2d04 8462 gen_helper_float_ceilw_s(fp0, cpu_env, fp0);
b6d96bed 8463 gen_store_fpr32(fp0, fd);
a7812ae4 8464 tcg_temp_free_i32(fp0);
b6d96bed 8465 }
5a5012ec
TS
8466 opn = "ceil.w.s";
8467 break;
bf4120ad 8468 case OPC_FLOOR_W_S:
b6d96bed 8469 {
a7812ae4 8470 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
8471
8472 gen_load_fpr32(fp0, fs);
895c2d04 8473 gen_helper_float_floorw_s(fp0, cpu_env, fp0);
b6d96bed 8474 gen_store_fpr32(fp0, fd);
a7812ae4 8475 tcg_temp_free_i32(fp0);
b6d96bed 8476 }
5a5012ec
TS
8477 opn = "floor.w.s";
8478 break;
e7f16abb
LA
8479 case OPC_SEL_S:
8480 check_insn(ctx, ISA_MIPS32R6);
8481 gen_sel_s(ctx, op1, fd, ft, fs);
8482 opn = "sel.s";
8483 break;
8484 case OPC_SELEQZ_S:
8485 check_insn(ctx, ISA_MIPS32R6);
8486 gen_sel_s(ctx, op1, fd, ft, fs);
8487 opn = "seleqz.s";
8488 break;
8489 case OPC_SELNEZ_S:
8490 check_insn(ctx, ISA_MIPS32R6);
8491 gen_sel_s(ctx, op1, fd, ft, fs);
8492 opn = "selnez.s";
8493 break;
bf4120ad 8494 case OPC_MOVCF_S:
fecd2646 8495 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6d96bed 8496 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec
TS
8497 opn = "movcf.s";
8498 break;
bf4120ad 8499 case OPC_MOVZ_S:
fecd2646 8500 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4
TS
8501 {
8502 int l1 = gen_new_label();
c9297f4d 8503 TCGv_i32 fp0;
a16336e4 8504
c9297f4d
AJ
8505 if (ft != 0) {
8506 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
8507 }
8508 fp0 = tcg_temp_new_i32();
b6d96bed
TS
8509 gen_load_fpr32(fp0, fs);
8510 gen_store_fpr32(fp0, fd);
a7812ae4 8511 tcg_temp_free_i32(fp0);
a16336e4
TS
8512 gen_set_label(l1);
8513 }
5a5012ec
TS
8514 opn = "movz.s";
8515 break;
bf4120ad 8516 case OPC_MOVN_S:
fecd2646 8517 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4
TS
8518 {
8519 int l1 = gen_new_label();
c9297f4d
AJ
8520 TCGv_i32 fp0;
8521
8522 if (ft != 0) {
8523 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
8524 fp0 = tcg_temp_new_i32();
8525 gen_load_fpr32(fp0, fs);
8526 gen_store_fpr32(fp0, fd);
8527 tcg_temp_free_i32(fp0);
8528 gen_set_label(l1);
8529 }
a16336e4 8530 }
5a5012ec
TS
8531 opn = "movn.s";
8532 break;
bf4120ad 8533 case OPC_RECIP_S:
b8aa4598 8534 check_cop1x(ctx);
b6d96bed 8535 {
a7812ae4 8536 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
8537
8538 gen_load_fpr32(fp0, fs);
895c2d04 8539 gen_helper_float_recip_s(fp0, cpu_env, fp0);
b6d96bed 8540 gen_store_fpr32(fp0, fd);
a7812ae4 8541 tcg_temp_free_i32(fp0);
b6d96bed 8542 }
57fa1fb3
TS
8543 opn = "recip.s";
8544 break;
bf4120ad 8545 case OPC_RSQRT_S:
b8aa4598 8546 check_cop1x(ctx);
b6d96bed 8547 {
a7812ae4 8548 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
8549
8550 gen_load_fpr32(fp0, fs);
895c2d04 8551 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
b6d96bed 8552 gen_store_fpr32(fp0, fd);
a7812ae4 8553 tcg_temp_free_i32(fp0);
b6d96bed 8554 }
57fa1fb3
TS
8555 opn = "rsqrt.s";
8556 break;
e7f16abb
LA
8557 case OPC_MADDF_S:
8558 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 8559 {
a7812ae4
PB
8560 TCGv_i32 fp0 = tcg_temp_new_i32();
8561 TCGv_i32 fp1 = tcg_temp_new_i32();
e7f16abb 8562 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 8563 gen_load_fpr32(fp0, fs);
d22d7289 8564 gen_load_fpr32(fp1, ft);
e7f16abb
LA
8565 gen_load_fpr32(fp2, fd);
8566 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
8567 gen_store_fpr32(fp2, fd);
8568 tcg_temp_free_i32(fp2);
a7812ae4 8569 tcg_temp_free_i32(fp1);
a7812ae4 8570 tcg_temp_free_i32(fp0);
e7f16abb 8571 opn = "maddf.s";
b6d96bed 8572 }
57fa1fb3 8573 break;
e7f16abb
LA
8574 case OPC_MSUBF_S:
8575 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 8576 {
a7812ae4 8577 TCGv_i32 fp0 = tcg_temp_new_i32();
e7f16abb
LA
8578 TCGv_i32 fp1 = tcg_temp_new_i32();
8579 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 8580 gen_load_fpr32(fp0, fs);
e7f16abb
LA
8581 gen_load_fpr32(fp1, ft);
8582 gen_load_fpr32(fp2, fd);
8583 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
8584 gen_store_fpr32(fp2, fd);
8585 tcg_temp_free_i32(fp2);
8586 tcg_temp_free_i32(fp1);
a7812ae4 8587 tcg_temp_free_i32(fp0);
e7f16abb 8588 opn = "msubf.s";
b6d96bed 8589 }
57fa1fb3 8590 break;
e7f16abb
LA
8591 case OPC_RINT_S:
8592 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 8593 {
a7812ae4 8594 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 8595 gen_load_fpr32(fp0, fs);
e7f16abb 8596 gen_helper_float_rint_s(fp0, cpu_env, fp0);
b6d96bed 8597 gen_store_fpr32(fp0, fd);
a7812ae4 8598 tcg_temp_free_i32(fp0);
e7f16abb 8599 opn = "rint.s";
b6d96bed 8600 }
57fa1fb3 8601 break;
e7f16abb
LA
8602 case OPC_CLASS_S:
8603 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 8604 {
e7f16abb
LA
8605 TCGv_i32 fp0 = tcg_temp_new_i32();
8606 gen_load_fpr32(fp0, fs);
8607 gen_helper_float_class_s(fp0, fp0);
8608 gen_store_fpr32(fp0, fd);
8609 tcg_temp_free_i32(fp0);
8610 opn = "class.s";
8611 }
8612 break;
8613 case OPC_MIN_S: /* OPC_RECIP2_S */
8614 if (ctx->insn_flags & ISA_MIPS32R6) {
8615 /* OPC_MIN_S */
a7812ae4
PB
8616 TCGv_i32 fp0 = tcg_temp_new_i32();
8617 TCGv_i32 fp1 = tcg_temp_new_i32();
e7f16abb
LA
8618 TCGv_i32 fp2 = tcg_temp_new_i32();
8619 gen_load_fpr32(fp0, fs);
8620 gen_load_fpr32(fp1, ft);
8621 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
8622 gen_store_fpr32(fp2, fd);
8623 tcg_temp_free_i32(fp2);
8624 tcg_temp_free_i32(fp1);
8625 tcg_temp_free_i32(fp0);
8626 opn = "min.s";
8627 } else {
8628 /* OPC_RECIP2_S */
8629 check_cp1_64bitmode(ctx);
8630 {
8631 TCGv_i32 fp0 = tcg_temp_new_i32();
8632 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 8633
e7f16abb
LA
8634 gen_load_fpr32(fp0, fs);
8635 gen_load_fpr32(fp1, ft);
8636 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
8637 tcg_temp_free_i32(fp1);
8638 gen_store_fpr32(fp0, fd);
8639 tcg_temp_free_i32(fp0);
8640 }
8641 opn = "recip2.s";
8642 }
8643 break;
8644 case OPC_MINA_S: /* OPC_RECIP1_S */
8645 if (ctx->insn_flags & ISA_MIPS32R6) {
8646 /* OPC_MINA_S */
8647 TCGv_i32 fp0 = tcg_temp_new_i32();
8648 TCGv_i32 fp1 = tcg_temp_new_i32();
8649 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
8650 gen_load_fpr32(fp0, fs);
8651 gen_load_fpr32(fp1, ft);
e7f16abb
LA
8652 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
8653 gen_store_fpr32(fp2, fd);
8654 tcg_temp_free_i32(fp2);
8655 tcg_temp_free_i32(fp1);
8656 tcg_temp_free_i32(fp0);
8657 opn = "mina.s";
8658 } else {
8659 /* OPC_RECIP1_S */
8660 check_cp1_64bitmode(ctx);
8661 {
8662 TCGv_i32 fp0 = tcg_temp_new_i32();
8663
8664 gen_load_fpr32(fp0, fs);
8665 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
8666 gen_store_fpr32(fp0, fd);
8667 tcg_temp_free_i32(fp0);
8668 }
8669 opn = "recip1.s";
8670 }
8671 break;
8672 case OPC_MAX_S: /* OPC_RSQRT1_S */
8673 if (ctx->insn_flags & ISA_MIPS32R6) {
8674 /* OPC_MAX_S */
8675 TCGv_i32 fp0 = tcg_temp_new_i32();
8676 TCGv_i32 fp1 = tcg_temp_new_i32();
8677 gen_load_fpr32(fp0, fs);
8678 gen_load_fpr32(fp1, ft);
8679 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
8680 gen_store_fpr32(fp1, fd);
8681 tcg_temp_free_i32(fp1);
8682 tcg_temp_free_i32(fp0);
8683 opn = "max.s";
8684 } else {
8685 /* OPC_RSQRT1_S */
8686 check_cp1_64bitmode(ctx);
8687 {
8688 TCGv_i32 fp0 = tcg_temp_new_i32();
8689
8690 gen_load_fpr32(fp0, fs);
8691 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
8692 gen_store_fpr32(fp0, fd);
8693 tcg_temp_free_i32(fp0);
8694 }
8695 opn = "rsqrt1.s";
8696 }
8697 break;
8698 case OPC_MAXA_S: /* OPC_RSQRT2_S */
8699 if (ctx->insn_flags & ISA_MIPS32R6) {
8700 /* OPC_MAXA_S */
8701 TCGv_i32 fp0 = tcg_temp_new_i32();
8702 TCGv_i32 fp1 = tcg_temp_new_i32();
8703 gen_load_fpr32(fp0, fs);
8704 gen_load_fpr32(fp1, ft);
8705 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
8706 gen_store_fpr32(fp1, fd);
a7812ae4 8707 tcg_temp_free_i32(fp1);
a7812ae4 8708 tcg_temp_free_i32(fp0);
e7f16abb
LA
8709 opn = "maxa.s";
8710 } else {
8711 /* OPC_RSQRT2_S */
8712 check_cp1_64bitmode(ctx);
8713 {
8714 TCGv_i32 fp0 = tcg_temp_new_i32();
8715 TCGv_i32 fp1 = tcg_temp_new_i32();
8716
8717 gen_load_fpr32(fp0, fs);
8718 gen_load_fpr32(fp1, ft);
8719 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
8720 tcg_temp_free_i32(fp1);
8721 gen_store_fpr32(fp0, fd);
8722 tcg_temp_free_i32(fp0);
8723 }
8724 opn = "rsqrt2.s";
b6d96bed 8725 }
57fa1fb3 8726 break;
bf4120ad 8727 case OPC_CVT_D_S:
5e755519 8728 check_cp1_registers(ctx, fd);
b6d96bed 8729 {
a7812ae4
PB
8730 TCGv_i32 fp32 = tcg_temp_new_i32();
8731 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
8732
8733 gen_load_fpr32(fp32, fs);
895c2d04 8734 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
a7812ae4 8735 tcg_temp_free_i32(fp32);
b6d96bed 8736 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 8737 tcg_temp_free_i64(fp64);
b6d96bed 8738 }
5a5012ec
TS
8739 opn = "cvt.d.s";
8740 break;
bf4120ad 8741 case OPC_CVT_W_S:
b6d96bed 8742 {
a7812ae4 8743 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
8744
8745 gen_load_fpr32(fp0, fs);
895c2d04 8746 gen_helper_float_cvtw_s(fp0, cpu_env, fp0);
b6d96bed 8747 gen_store_fpr32(fp0, fd);
a7812ae4 8748 tcg_temp_free_i32(fp0);
b6d96bed 8749 }
5a5012ec
TS
8750 opn = "cvt.w.s";
8751 break;
bf4120ad 8752 case OPC_CVT_L_S:
5e755519 8753 check_cp1_64bitmode(ctx);
b6d96bed 8754 {
a7812ae4
PB
8755 TCGv_i32 fp32 = tcg_temp_new_i32();
8756 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
8757
8758 gen_load_fpr32(fp32, fs);
895c2d04 8759 gen_helper_float_cvtl_s(fp64, cpu_env, fp32);
a7812ae4 8760 tcg_temp_free_i32(fp32);
b6d96bed 8761 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 8762 tcg_temp_free_i64(fp64);
b6d96bed 8763 }
5a5012ec
TS
8764 opn = "cvt.l.s";
8765 break;
bf4120ad 8766 case OPC_CVT_PS_S:
fecd2646 8767 check_insn_opc_removed(ctx, ISA_MIPS32R6);
5e755519 8768 check_cp1_64bitmode(ctx);
b6d96bed 8769 {
a7812ae4
PB
8770 TCGv_i64 fp64 = tcg_temp_new_i64();
8771 TCGv_i32 fp32_0 = tcg_temp_new_i32();
8772 TCGv_i32 fp32_1 = tcg_temp_new_i32();
b6d96bed
TS
8773
8774 gen_load_fpr32(fp32_0, fs);
8775 gen_load_fpr32(fp32_1, ft);
13d24f49 8776 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
a7812ae4
PB
8777 tcg_temp_free_i32(fp32_1);
8778 tcg_temp_free_i32(fp32_0);
36aa55dc 8779 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 8780 tcg_temp_free_i64(fp64);
b6d96bed 8781 }
5a5012ec
TS
8782 opn = "cvt.ps.s";
8783 break;
bf4120ad
NF
8784 case OPC_CMP_F_S:
8785 case OPC_CMP_UN_S:
8786 case OPC_CMP_EQ_S:
8787 case OPC_CMP_UEQ_S:
8788 case OPC_CMP_OLT_S:
8789 case OPC_CMP_ULT_S:
8790 case OPC_CMP_OLE_S:
8791 case OPC_CMP_ULE_S:
8792 case OPC_CMP_SF_S:
8793 case OPC_CMP_NGLE_S:
8794 case OPC_CMP_SEQ_S:
8795 case OPC_CMP_NGL_S:
8796 case OPC_CMP_LT_S:
8797 case OPC_CMP_NGE_S:
8798 case OPC_CMP_LE_S:
8799 case OPC_CMP_NGT_S:
fecd2646 8800 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8153667c
NF
8801 if (ctx->opcode & (1 << 6)) {
8802 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
8803 opn = condnames_abs[func-48];
8804 } else {
8805 gen_cmp_s(ctx, func-48, ft, fs, cc);
8806 opn = condnames[func-48];
5a1e8ffb 8807 }
5a5012ec 8808 break;
bf4120ad 8809 case OPC_ADD_D:
5e755519 8810 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 8811 {
a7812ae4
PB
8812 TCGv_i64 fp0 = tcg_temp_new_i64();
8813 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
8814
8815 gen_load_fpr64(ctx, fp0, fs);
8816 gen_load_fpr64(ctx, fp1, ft);
895c2d04 8817 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
a7812ae4 8818 tcg_temp_free_i64(fp1);
b6d96bed 8819 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8820 tcg_temp_free_i64(fp0);
b6d96bed 8821 }
6ea83fed 8822 opn = "add.d";
5a1e8ffb 8823 optype = BINOP;
6ea83fed 8824 break;
bf4120ad 8825 case OPC_SUB_D:
5e755519 8826 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 8827 {
a7812ae4
PB
8828 TCGv_i64 fp0 = tcg_temp_new_i64();
8829 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
8830
8831 gen_load_fpr64(ctx, fp0, fs);
8832 gen_load_fpr64(ctx, fp1, ft);
895c2d04 8833 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
a7812ae4 8834 tcg_temp_free_i64(fp1);
b6d96bed 8835 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8836 tcg_temp_free_i64(fp0);
b6d96bed 8837 }
6ea83fed 8838 opn = "sub.d";
5a1e8ffb 8839 optype = BINOP;
6ea83fed 8840 break;
bf4120ad 8841 case OPC_MUL_D:
5e755519 8842 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 8843 {
a7812ae4
PB
8844 TCGv_i64 fp0 = tcg_temp_new_i64();
8845 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
8846
8847 gen_load_fpr64(ctx, fp0, fs);
8848 gen_load_fpr64(ctx, fp1, ft);
895c2d04 8849 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
a7812ae4 8850 tcg_temp_free_i64(fp1);
b6d96bed 8851 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8852 tcg_temp_free_i64(fp0);
b6d96bed 8853 }
6ea83fed 8854 opn = "mul.d";
5a1e8ffb 8855 optype = BINOP;
6ea83fed 8856 break;
bf4120ad 8857 case OPC_DIV_D:
5e755519 8858 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 8859 {
a7812ae4
PB
8860 TCGv_i64 fp0 = tcg_temp_new_i64();
8861 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
8862
8863 gen_load_fpr64(ctx, fp0, fs);
8864 gen_load_fpr64(ctx, fp1, ft);
895c2d04 8865 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
a7812ae4 8866 tcg_temp_free_i64(fp1);
b6d96bed 8867 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8868 tcg_temp_free_i64(fp0);
b6d96bed 8869 }
6ea83fed 8870 opn = "div.d";
5a1e8ffb 8871 optype = BINOP;
6ea83fed 8872 break;
bf4120ad 8873 case OPC_SQRT_D:
5e755519 8874 check_cp1_registers(ctx, fs | fd);
b6d96bed 8875 {
a7812ae4 8876 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8877
8878 gen_load_fpr64(ctx, fp0, fs);
895c2d04 8879 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
b6d96bed 8880 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8881 tcg_temp_free_i64(fp0);
b6d96bed 8882 }
6ea83fed
FB
8883 opn = "sqrt.d";
8884 break;
bf4120ad 8885 case OPC_ABS_D:
5e755519 8886 check_cp1_registers(ctx, fs | fd);
b6d96bed 8887 {
a7812ae4 8888 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8889
8890 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 8891 gen_helper_float_abs_d(fp0, fp0);
b6d96bed 8892 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8893 tcg_temp_free_i64(fp0);
b6d96bed 8894 }
6ea83fed
FB
8895 opn = "abs.d";
8896 break;
bf4120ad 8897 case OPC_MOV_D:
5e755519 8898 check_cp1_registers(ctx, fs | fd);
b6d96bed 8899 {
a7812ae4 8900 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8901
8902 gen_load_fpr64(ctx, fp0, fs);
8903 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8904 tcg_temp_free_i64(fp0);
b6d96bed 8905 }
6ea83fed
FB
8906 opn = "mov.d";
8907 break;
bf4120ad 8908 case OPC_NEG_D:
5e755519 8909 check_cp1_registers(ctx, fs | fd);
b6d96bed 8910 {
a7812ae4 8911 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8912
8913 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 8914 gen_helper_float_chs_d(fp0, fp0);
b6d96bed 8915 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8916 tcg_temp_free_i64(fp0);
b6d96bed 8917 }
6ea83fed
FB
8918 opn = "neg.d";
8919 break;
bf4120ad 8920 case OPC_ROUND_L_D:
5e755519 8921 check_cp1_64bitmode(ctx);
b6d96bed 8922 {
a7812ae4 8923 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8924
8925 gen_load_fpr64(ctx, fp0, fs);
895c2d04 8926 gen_helper_float_roundl_d(fp0, cpu_env, fp0);
b6d96bed 8927 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8928 tcg_temp_free_i64(fp0);
b6d96bed 8929 }
5a5012ec
TS
8930 opn = "round.l.d";
8931 break;
bf4120ad 8932 case OPC_TRUNC_L_D:
5e755519 8933 check_cp1_64bitmode(ctx);
b6d96bed 8934 {
a7812ae4 8935 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8936
8937 gen_load_fpr64(ctx, fp0, fs);
895c2d04 8938 gen_helper_float_truncl_d(fp0, cpu_env, fp0);
b6d96bed 8939 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8940 tcg_temp_free_i64(fp0);
b6d96bed 8941 }
5a5012ec
TS
8942 opn = "trunc.l.d";
8943 break;
bf4120ad 8944 case OPC_CEIL_L_D:
5e755519 8945 check_cp1_64bitmode(ctx);
b6d96bed 8946 {
a7812ae4 8947 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8948
8949 gen_load_fpr64(ctx, fp0, fs);
895c2d04 8950 gen_helper_float_ceill_d(fp0, cpu_env, fp0);
b6d96bed 8951 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8952 tcg_temp_free_i64(fp0);
b6d96bed 8953 }
5a5012ec
TS
8954 opn = "ceil.l.d";
8955 break;
bf4120ad 8956 case OPC_FLOOR_L_D:
5e755519 8957 check_cp1_64bitmode(ctx);
b6d96bed 8958 {
a7812ae4 8959 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8960
8961 gen_load_fpr64(ctx, fp0, fs);
895c2d04 8962 gen_helper_float_floorl_d(fp0, cpu_env, fp0);
b6d96bed 8963 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8964 tcg_temp_free_i64(fp0);
b6d96bed 8965 }
5a5012ec
TS
8966 opn = "floor.l.d";
8967 break;
bf4120ad 8968 case OPC_ROUND_W_D:
5e755519 8969 check_cp1_registers(ctx, fs);
b6d96bed 8970 {
a7812ae4
PB
8971 TCGv_i32 fp32 = tcg_temp_new_i32();
8972 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
8973
8974 gen_load_fpr64(ctx, fp64, fs);
895c2d04 8975 gen_helper_float_roundw_d(fp32, cpu_env, fp64);
a7812ae4 8976 tcg_temp_free_i64(fp64);
b6d96bed 8977 gen_store_fpr32(fp32, fd);
a7812ae4 8978 tcg_temp_free_i32(fp32);
b6d96bed 8979 }
6ea83fed
FB
8980 opn = "round.w.d";
8981 break;
bf4120ad 8982 case OPC_TRUNC_W_D:
5e755519 8983 check_cp1_registers(ctx, fs);
b6d96bed 8984 {
a7812ae4
PB
8985 TCGv_i32 fp32 = tcg_temp_new_i32();
8986 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
8987
8988 gen_load_fpr64(ctx, fp64, fs);
895c2d04 8989 gen_helper_float_truncw_d(fp32, cpu_env, fp64);
a7812ae4 8990 tcg_temp_free_i64(fp64);
b6d96bed 8991 gen_store_fpr32(fp32, fd);
a7812ae4 8992 tcg_temp_free_i32(fp32);
b6d96bed 8993 }
6ea83fed
FB
8994 opn = "trunc.w.d";
8995 break;
bf4120ad 8996 case OPC_CEIL_W_D:
5e755519 8997 check_cp1_registers(ctx, fs);
b6d96bed 8998 {
a7812ae4
PB
8999 TCGv_i32 fp32 = tcg_temp_new_i32();
9000 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
9001
9002 gen_load_fpr64(ctx, fp64, fs);
895c2d04 9003 gen_helper_float_ceilw_d(fp32, cpu_env, fp64);
a7812ae4 9004 tcg_temp_free_i64(fp64);
b6d96bed 9005 gen_store_fpr32(fp32, fd);
a7812ae4 9006 tcg_temp_free_i32(fp32);
b6d96bed 9007 }
6ea83fed
FB
9008 opn = "ceil.w.d";
9009 break;
bf4120ad 9010 case OPC_FLOOR_W_D:
5e755519 9011 check_cp1_registers(ctx, fs);
b6d96bed 9012 {
a7812ae4
PB
9013 TCGv_i32 fp32 = tcg_temp_new_i32();
9014 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
9015
9016 gen_load_fpr64(ctx, fp64, fs);
895c2d04 9017 gen_helper_float_floorw_d(fp32, cpu_env, fp64);
a7812ae4 9018 tcg_temp_free_i64(fp64);
b6d96bed 9019 gen_store_fpr32(fp32, fd);
a7812ae4 9020 tcg_temp_free_i32(fp32);
b6d96bed 9021 }
7a387fff 9022 opn = "floor.w.d";
6ea83fed 9023 break;
e7f16abb
LA
9024 case OPC_SEL_D:
9025 check_insn(ctx, ISA_MIPS32R6);
9026 gen_sel_d(ctx, op1, fd, ft, fs);
9027 opn = "sel.d";
9028 break;
9029 case OPC_SELEQZ_D:
9030 check_insn(ctx, ISA_MIPS32R6);
9031 gen_sel_d(ctx, op1, fd, ft, fs);
9032 opn = "seleqz.d";
9033 break;
9034 case OPC_SELNEZ_D:
9035 check_insn(ctx, ISA_MIPS32R6);
9036 gen_sel_d(ctx, op1, fd, ft, fs);
9037 opn = "selnez.d";
9038 break;
bf4120ad 9039 case OPC_MOVCF_D:
fecd2646 9040 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6d96bed 9041 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 9042 opn = "movcf.d";
dd016883 9043 break;
bf4120ad 9044 case OPC_MOVZ_D:
fecd2646 9045 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4
TS
9046 {
9047 int l1 = gen_new_label();
c9297f4d 9048 TCGv_i64 fp0;
a16336e4 9049
c9297f4d
AJ
9050 if (ft != 0) {
9051 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9052 }
9053 fp0 = tcg_temp_new_i64();
b6d96bed
TS
9054 gen_load_fpr64(ctx, fp0, fs);
9055 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9056 tcg_temp_free_i64(fp0);
a16336e4
TS
9057 gen_set_label(l1);
9058 }
5a5012ec
TS
9059 opn = "movz.d";
9060 break;
bf4120ad 9061 case OPC_MOVN_D:
fecd2646 9062 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4
TS
9063 {
9064 int l1 = gen_new_label();
c9297f4d
AJ
9065 TCGv_i64 fp0;
9066
9067 if (ft != 0) {
9068 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9069 fp0 = tcg_temp_new_i64();
9070 gen_load_fpr64(ctx, fp0, fs);
9071 gen_store_fpr64(ctx, fp0, fd);
9072 tcg_temp_free_i64(fp0);
9073 gen_set_label(l1);
9074 }
a16336e4 9075 }
5a5012ec 9076 opn = "movn.d";
6ea83fed 9077 break;
bf4120ad 9078 case OPC_RECIP_D:
b8aa4598 9079 check_cp1_64bitmode(ctx);
b6d96bed 9080 {
a7812ae4 9081 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
9082
9083 gen_load_fpr64(ctx, fp0, fs);
895c2d04 9084 gen_helper_float_recip_d(fp0, cpu_env, fp0);
b6d96bed 9085 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9086 tcg_temp_free_i64(fp0);
b6d96bed 9087 }
57fa1fb3
TS
9088 opn = "recip.d";
9089 break;
bf4120ad 9090 case OPC_RSQRT_D:
b8aa4598 9091 check_cp1_64bitmode(ctx);
b6d96bed 9092 {
a7812ae4 9093 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
9094
9095 gen_load_fpr64(ctx, fp0, fs);
895c2d04 9096 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
b6d96bed 9097 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9098 tcg_temp_free_i64(fp0);
b6d96bed 9099 }
57fa1fb3
TS
9100 opn = "rsqrt.d";
9101 break;
e7f16abb
LA
9102 case OPC_MADDF_D:
9103 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 9104 {
a7812ae4
PB
9105 TCGv_i64 fp0 = tcg_temp_new_i64();
9106 TCGv_i64 fp1 = tcg_temp_new_i64();
e7f16abb 9107 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
9108 gen_load_fpr64(ctx, fp0, fs);
9109 gen_load_fpr64(ctx, fp1, ft);
e7f16abb
LA
9110 gen_load_fpr64(ctx, fp2, fd);
9111 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
9112 gen_store_fpr64(ctx, fp2, fd);
9113 tcg_temp_free_i64(fp2);
a7812ae4 9114 tcg_temp_free_i64(fp1);
a7812ae4 9115 tcg_temp_free_i64(fp0);
e7f16abb 9116 opn = "maddf.d";
b6d96bed 9117 }
57fa1fb3 9118 break;
e7f16abb
LA
9119 case OPC_MSUBF_D:
9120 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 9121 {
a7812ae4 9122 TCGv_i64 fp0 = tcg_temp_new_i64();
e7f16abb
LA
9123 TCGv_i64 fp1 = tcg_temp_new_i64();
9124 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed 9125 gen_load_fpr64(ctx, fp0, fs);
e7f16abb
LA
9126 gen_load_fpr64(ctx, fp1, ft);
9127 gen_load_fpr64(ctx, fp2, fd);
9128 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
9129 gen_store_fpr64(ctx, fp2, fd);
9130 tcg_temp_free_i64(fp2);
9131 tcg_temp_free_i64(fp1);
a7812ae4 9132 tcg_temp_free_i64(fp0);
e7f16abb 9133 opn = "msubf.d";
b6d96bed 9134 }
57fa1fb3 9135 break;
e7f16abb
LA
9136 case OPC_RINT_D:
9137 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 9138 {
a7812ae4 9139 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 9140 gen_load_fpr64(ctx, fp0, fs);
e7f16abb 9141 gen_helper_float_rint_d(fp0, cpu_env, fp0);
b6d96bed 9142 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9143 tcg_temp_free_i64(fp0);
e7f16abb 9144 opn = "rint.d";
b6d96bed 9145 }
57fa1fb3 9146 break;
e7f16abb
LA
9147 case OPC_CLASS_D:
9148 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 9149 {
e7f16abb
LA
9150 TCGv_i64 fp0 = tcg_temp_new_i64();
9151 gen_load_fpr64(ctx, fp0, fs);
9152 gen_helper_float_class_d(fp0, fp0);
9153 gen_store_fpr64(ctx, fp0, fd);
9154 tcg_temp_free_i64(fp0);
9155 opn = "class.d";
9156 }
9157 break;
9158 case OPC_MIN_D: /* OPC_RECIP2_D */
9159 if (ctx->insn_flags & ISA_MIPS32R6) {
9160 /* OPC_MIN_D */
a7812ae4
PB
9161 TCGv_i64 fp0 = tcg_temp_new_i64();
9162 TCGv_i64 fp1 = tcg_temp_new_i64();
e7f16abb
LA
9163 gen_load_fpr64(ctx, fp0, fs);
9164 gen_load_fpr64(ctx, fp1, ft);
9165 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
9166 gen_store_fpr64(ctx, fp1, fd);
9167 tcg_temp_free_i64(fp1);
9168 tcg_temp_free_i64(fp0);
9169 opn = "min.d";
9170 } else {
9171 /* OPC_RECIP2_D */
9172 check_cp1_64bitmode(ctx);
9173 {
9174 TCGv_i64 fp0 = tcg_temp_new_i64();
9175 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed 9176
e7f16abb
LA
9177 gen_load_fpr64(ctx, fp0, fs);
9178 gen_load_fpr64(ctx, fp1, ft);
9179 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
9180 tcg_temp_free_i64(fp1);
9181 gen_store_fpr64(ctx, fp0, fd);
9182 tcg_temp_free_i64(fp0);
9183 }
9184 opn = "recip2.d";
9185 }
9186 break;
9187 case OPC_MINA_D: /* OPC_RECIP1_D */
9188 if (ctx->insn_flags & ISA_MIPS32R6) {
9189 /* OPC_MINA_D */
9190 TCGv_i64 fp0 = tcg_temp_new_i64();
9191 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
9192 gen_load_fpr64(ctx, fp0, fs);
9193 gen_load_fpr64(ctx, fp1, ft);
e7f16abb
LA
9194 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
9195 gen_store_fpr64(ctx, fp1, fd);
9196 tcg_temp_free_i64(fp1);
9197 tcg_temp_free_i64(fp0);
9198 opn = "mina.d";
9199 } else {
9200 /* OPC_RECIP1_D */
9201 check_cp1_64bitmode(ctx);
9202 {
9203 TCGv_i64 fp0 = tcg_temp_new_i64();
9204
9205 gen_load_fpr64(ctx, fp0, fs);
9206 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
9207 gen_store_fpr64(ctx, fp0, fd);
9208 tcg_temp_free_i64(fp0);
9209 }
9210 opn = "recip1.d";
9211 }
9212 break;
9213 case OPC_MAX_D: /* OPC_RSQRT1_D */
9214 if (ctx->insn_flags & ISA_MIPS32R6) {
9215 /* OPC_MAX_D */
9216 TCGv_i64 fp0 = tcg_temp_new_i64();
9217 TCGv_i64 fp1 = tcg_temp_new_i64();
9218 gen_load_fpr64(ctx, fp0, fs);
9219 gen_load_fpr64(ctx, fp1, ft);
9220 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
9221 gen_store_fpr64(ctx, fp1, fd);
a7812ae4 9222 tcg_temp_free_i64(fp1);
a7812ae4 9223 tcg_temp_free_i64(fp0);
e7f16abb
LA
9224 opn = "max.d";
9225 } else {
9226 /* OPC_RSQRT1_D */
9227 check_cp1_64bitmode(ctx);
9228 {
9229 TCGv_i64 fp0 = tcg_temp_new_i64();
9230
9231 gen_load_fpr64(ctx, fp0, fs);
9232 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
9233 gen_store_fpr64(ctx, fp0, fd);
9234 tcg_temp_free_i64(fp0);
9235 }
9236 opn = "rsqrt1.d";
9237 }
9238 break;
9239 case OPC_MAXA_D: /* OPC_RSQRT2_D */
9240 if (ctx->insn_flags & ISA_MIPS32R6) {
9241 /* OPC_MAXA_D */
9242 TCGv_i64 fp0 = tcg_temp_new_i64();
9243 TCGv_i64 fp1 = tcg_temp_new_i64();
9244 gen_load_fpr64(ctx, fp0, fs);
9245 gen_load_fpr64(ctx, fp1, ft);
9246 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
9247 gen_store_fpr64(ctx, fp1, fd);
9248 tcg_temp_free_i64(fp1);
9249 tcg_temp_free_i64(fp0);
9250 opn = "maxa.d";
9251 } else {
9252 /* OPC_RSQRT2_D */
9253 check_cp1_64bitmode(ctx);
9254 {
9255 TCGv_i64 fp0 = tcg_temp_new_i64();
9256 TCGv_i64 fp1 = tcg_temp_new_i64();
9257
9258 gen_load_fpr64(ctx, fp0, fs);
9259 gen_load_fpr64(ctx, fp1, ft);
9260 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
9261 tcg_temp_free_i64(fp1);
9262 gen_store_fpr64(ctx, fp0, fd);
9263 tcg_temp_free_i64(fp0);
9264 }
9265 opn = "rsqrt2.d";
b6d96bed 9266 }
57fa1fb3 9267 break;
bf4120ad
NF
9268 case OPC_CMP_F_D:
9269 case OPC_CMP_UN_D:
9270 case OPC_CMP_EQ_D:
9271 case OPC_CMP_UEQ_D:
9272 case OPC_CMP_OLT_D:
9273 case OPC_CMP_ULT_D:
9274 case OPC_CMP_OLE_D:
9275 case OPC_CMP_ULE_D:
9276 case OPC_CMP_SF_D:
9277 case OPC_CMP_NGLE_D:
9278 case OPC_CMP_SEQ_D:
9279 case OPC_CMP_NGL_D:
9280 case OPC_CMP_LT_D:
9281 case OPC_CMP_NGE_D:
9282 case OPC_CMP_LE_D:
9283 case OPC_CMP_NGT_D:
fecd2646 9284 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8153667c
NF
9285 if (ctx->opcode & (1 << 6)) {
9286 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
9287 opn = condnames_abs[func-48];
9288 } else {
9289 gen_cmp_d(ctx, func-48, ft, fs, cc);
9290 opn = condnames[func-48];
5a1e8ffb 9291 }
6ea83fed 9292 break;
bf4120ad 9293 case OPC_CVT_S_D:
5e755519 9294 check_cp1_registers(ctx, fs);
b6d96bed 9295 {
a7812ae4
PB
9296 TCGv_i32 fp32 = tcg_temp_new_i32();
9297 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
9298
9299 gen_load_fpr64(ctx, fp64, fs);
895c2d04 9300 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
a7812ae4 9301 tcg_temp_free_i64(fp64);
b6d96bed 9302 gen_store_fpr32(fp32, fd);
a7812ae4 9303 tcg_temp_free_i32(fp32);
b6d96bed 9304 }
5a5012ec
TS
9305 opn = "cvt.s.d";
9306 break;
bf4120ad 9307 case OPC_CVT_W_D:
5e755519 9308 check_cp1_registers(ctx, fs);
b6d96bed 9309 {
a7812ae4
PB
9310 TCGv_i32 fp32 = tcg_temp_new_i32();
9311 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
9312
9313 gen_load_fpr64(ctx, fp64, fs);
895c2d04 9314 gen_helper_float_cvtw_d(fp32, cpu_env, fp64);
a7812ae4 9315 tcg_temp_free_i64(fp64);
b6d96bed 9316 gen_store_fpr32(fp32, fd);
a7812ae4 9317 tcg_temp_free_i32(fp32);
b6d96bed 9318 }
5a5012ec
TS
9319 opn = "cvt.w.d";
9320 break;
bf4120ad 9321 case OPC_CVT_L_D:
5e755519 9322 check_cp1_64bitmode(ctx);
b6d96bed 9323 {
a7812ae4 9324 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
9325
9326 gen_load_fpr64(ctx, fp0, fs);
895c2d04 9327 gen_helper_float_cvtl_d(fp0, cpu_env, fp0);
b6d96bed 9328 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9329 tcg_temp_free_i64(fp0);
b6d96bed 9330 }
5a5012ec
TS
9331 opn = "cvt.l.d";
9332 break;
bf4120ad 9333 case OPC_CVT_S_W:
b6d96bed 9334 {
a7812ae4 9335 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
9336
9337 gen_load_fpr32(fp0, fs);
895c2d04 9338 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
b6d96bed 9339 gen_store_fpr32(fp0, fd);
a7812ae4 9340 tcg_temp_free_i32(fp0);
b6d96bed 9341 }
5a5012ec 9342 opn = "cvt.s.w";
6ea83fed 9343 break;
bf4120ad 9344 case OPC_CVT_D_W:
5e755519 9345 check_cp1_registers(ctx, fd);
b6d96bed 9346 {
a7812ae4
PB
9347 TCGv_i32 fp32 = tcg_temp_new_i32();
9348 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
9349
9350 gen_load_fpr32(fp32, fs);
895c2d04 9351 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
a7812ae4 9352 tcg_temp_free_i32(fp32);
b6d96bed 9353 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 9354 tcg_temp_free_i64(fp64);
b6d96bed 9355 }
5a5012ec
TS
9356 opn = "cvt.d.w";
9357 break;
bf4120ad 9358 case OPC_CVT_S_L:
5e755519 9359 check_cp1_64bitmode(ctx);
b6d96bed 9360 {
a7812ae4
PB
9361 TCGv_i32 fp32 = tcg_temp_new_i32();
9362 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
9363
9364 gen_load_fpr64(ctx, fp64, fs);
895c2d04 9365 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
a7812ae4 9366 tcg_temp_free_i64(fp64);
b6d96bed 9367 gen_store_fpr32(fp32, fd);
a7812ae4 9368 tcg_temp_free_i32(fp32);
b6d96bed 9369 }
5a5012ec
TS
9370 opn = "cvt.s.l";
9371 break;
bf4120ad 9372 case OPC_CVT_D_L:
5e755519 9373 check_cp1_64bitmode(ctx);
b6d96bed 9374 {
a7812ae4 9375 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
9376
9377 gen_load_fpr64(ctx, fp0, fs);
895c2d04 9378 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
b6d96bed 9379 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9380 tcg_temp_free_i64(fp0);
b6d96bed 9381 }
5a5012ec
TS
9382 opn = "cvt.d.l";
9383 break;
bf4120ad 9384 case OPC_CVT_PS_PW:
fecd2646 9385 check_insn_opc_removed(ctx, ISA_MIPS32R6);
5e755519 9386 check_cp1_64bitmode(ctx);
b6d96bed 9387 {
a7812ae4 9388 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
9389
9390 gen_load_fpr64(ctx, fp0, fs);
895c2d04 9391 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
b6d96bed 9392 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9393 tcg_temp_free_i64(fp0);
b6d96bed 9394 }
5a5012ec
TS
9395 opn = "cvt.ps.pw";
9396 break;
bf4120ad 9397 case OPC_ADD_PS:
5e755519 9398 check_cp1_64bitmode(ctx);
b6d96bed 9399 {
a7812ae4
PB
9400 TCGv_i64 fp0 = tcg_temp_new_i64();
9401 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
9402
9403 gen_load_fpr64(ctx, fp0, fs);
9404 gen_load_fpr64(ctx, fp1, ft);
895c2d04 9405 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 9406 tcg_temp_free_i64(fp1);
b6d96bed 9407 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9408 tcg_temp_free_i64(fp0);
b6d96bed 9409 }
5a5012ec 9410 opn = "add.ps";
6ea83fed 9411 break;
bf4120ad 9412 case OPC_SUB_PS:
5e755519 9413 check_cp1_64bitmode(ctx);
b6d96bed 9414 {
a7812ae4
PB
9415 TCGv_i64 fp0 = tcg_temp_new_i64();
9416 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
9417
9418 gen_load_fpr64(ctx, fp0, fs);
9419 gen_load_fpr64(ctx, fp1, ft);
895c2d04 9420 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 9421 tcg_temp_free_i64(fp1);
b6d96bed 9422 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9423 tcg_temp_free_i64(fp0);
b6d96bed 9424 }
5a5012ec 9425 opn = "sub.ps";
6ea83fed 9426 break;
bf4120ad 9427 case OPC_MUL_PS:
5e755519 9428 check_cp1_64bitmode(ctx);
b6d96bed 9429 {
a7812ae4
PB
9430 TCGv_i64 fp0 = tcg_temp_new_i64();
9431 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
9432
9433 gen_load_fpr64(ctx, fp0, fs);
9434 gen_load_fpr64(ctx, fp1, ft);
895c2d04 9435 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 9436 tcg_temp_free_i64(fp1);
b6d96bed 9437 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9438 tcg_temp_free_i64(fp0);
b6d96bed 9439 }
5a5012ec 9440 opn = "mul.ps";
6ea83fed 9441 break;
bf4120ad 9442 case OPC_ABS_PS:
5e755519 9443 check_cp1_64bitmode(ctx);
b6d96bed 9444 {
a7812ae4 9445 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
9446
9447 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 9448 gen_helper_float_abs_ps(fp0, fp0);
b6d96bed 9449 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9450 tcg_temp_free_i64(fp0);
b6d96bed 9451 }
5a5012ec 9452 opn = "abs.ps";
6ea83fed 9453 break;
bf4120ad 9454 case OPC_MOV_PS:
5e755519 9455 check_cp1_64bitmode(ctx);
b6d96bed 9456 {
a7812ae4 9457 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
9458
9459 gen_load_fpr64(ctx, fp0, fs);
9460 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9461 tcg_temp_free_i64(fp0);
b6d96bed 9462 }
5a5012ec 9463 opn = "mov.ps";
6ea83fed 9464 break;
bf4120ad 9465 case OPC_NEG_PS:
5e755519 9466 check_cp1_64bitmode(ctx);
b6d96bed 9467 {
a7812ae4 9468 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
9469
9470 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 9471 gen_helper_float_chs_ps(fp0, fp0);
b6d96bed 9472 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9473 tcg_temp_free_i64(fp0);
b6d96bed 9474 }
5a5012ec 9475 opn = "neg.ps";
6ea83fed 9476 break;
bf4120ad 9477 case OPC_MOVCF_PS:
5e755519 9478 check_cp1_64bitmode(ctx);
7f6613ce 9479 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 9480 opn = "movcf.ps";
6ea83fed 9481 break;
bf4120ad 9482 case OPC_MOVZ_PS:
5e755519 9483 check_cp1_64bitmode(ctx);
a16336e4
TS
9484 {
9485 int l1 = gen_new_label();
30a3848b 9486 TCGv_i64 fp0;
a16336e4 9487
c9297f4d
AJ
9488 if (ft != 0)
9489 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9490 fp0 = tcg_temp_new_i64();
9491 gen_load_fpr64(ctx, fp0, fs);
9492 gen_store_fpr64(ctx, fp0, fd);
9493 tcg_temp_free_i64(fp0);
a16336e4
TS
9494 gen_set_label(l1);
9495 }
5a5012ec 9496 opn = "movz.ps";
6ea83fed 9497 break;
bf4120ad 9498 case OPC_MOVN_PS:
5e755519 9499 check_cp1_64bitmode(ctx);
a16336e4
TS
9500 {
9501 int l1 = gen_new_label();
30a3848b 9502 TCGv_i64 fp0;
c9297f4d
AJ
9503
9504 if (ft != 0) {
9505 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9506 fp0 = tcg_temp_new_i64();
9507 gen_load_fpr64(ctx, fp0, fs);
9508 gen_store_fpr64(ctx, fp0, fd);
9509 tcg_temp_free_i64(fp0);
9510 gen_set_label(l1);
9511 }
a16336e4 9512 }
5a5012ec 9513 opn = "movn.ps";
6ea83fed 9514 break;
bf4120ad 9515 case OPC_ADDR_PS:
5e755519 9516 check_cp1_64bitmode(ctx);
b6d96bed 9517 {
a7812ae4
PB
9518 TCGv_i64 fp0 = tcg_temp_new_i64();
9519 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
9520
9521 gen_load_fpr64(ctx, fp0, ft);
9522 gen_load_fpr64(ctx, fp1, fs);
895c2d04 9523 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 9524 tcg_temp_free_i64(fp1);
b6d96bed 9525 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9526 tcg_temp_free_i64(fp0);
b6d96bed 9527 }
fbcc6828
TS
9528 opn = "addr.ps";
9529 break;
bf4120ad 9530 case OPC_MULR_PS:
5e755519 9531 check_cp1_64bitmode(ctx);
b6d96bed 9532 {
a7812ae4
PB
9533 TCGv_i64 fp0 = tcg_temp_new_i64();
9534 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
9535
9536 gen_load_fpr64(ctx, fp0, ft);
9537 gen_load_fpr64(ctx, fp1, fs);
895c2d04 9538 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 9539 tcg_temp_free_i64(fp1);
b6d96bed 9540 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9541 tcg_temp_free_i64(fp0);
b6d96bed 9542 }
57fa1fb3
TS
9543 opn = "mulr.ps";
9544 break;
bf4120ad 9545 case OPC_RECIP2_PS:
5e755519 9546 check_cp1_64bitmode(ctx);
b6d96bed 9547 {
a7812ae4
PB
9548 TCGv_i64 fp0 = tcg_temp_new_i64();
9549 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
9550
9551 gen_load_fpr64(ctx, fp0, fs);
d22d7289 9552 gen_load_fpr64(ctx, fp1, ft);
895c2d04 9553 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 9554 tcg_temp_free_i64(fp1);
b6d96bed 9555 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9556 tcg_temp_free_i64(fp0);
b6d96bed 9557 }
57fa1fb3
TS
9558 opn = "recip2.ps";
9559 break;
bf4120ad 9560 case OPC_RECIP1_PS:
5e755519 9561 check_cp1_64bitmode(ctx);
b6d96bed 9562 {
a7812ae4 9563 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
9564
9565 gen_load_fpr64(ctx, fp0, fs);
895c2d04 9566 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
b6d96bed 9567 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9568 tcg_temp_free_i64(fp0);
b6d96bed 9569 }
57fa1fb3
TS
9570 opn = "recip1.ps";
9571 break;
bf4120ad 9572 case OPC_RSQRT1_PS:
5e755519 9573 check_cp1_64bitmode(ctx);
b6d96bed 9574 {
a7812ae4 9575 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
9576
9577 gen_load_fpr64(ctx, fp0, fs);
895c2d04 9578 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
b6d96bed 9579 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9580 tcg_temp_free_i64(fp0);
b6d96bed 9581 }
57fa1fb3
TS
9582 opn = "rsqrt1.ps";
9583 break;
bf4120ad 9584 case OPC_RSQRT2_PS:
5e755519 9585 check_cp1_64bitmode(ctx);
b6d96bed 9586 {
a7812ae4
PB
9587 TCGv_i64 fp0 = tcg_temp_new_i64();
9588 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
9589
9590 gen_load_fpr64(ctx, fp0, fs);
9591 gen_load_fpr64(ctx, fp1, ft);
895c2d04 9592 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 9593 tcg_temp_free_i64(fp1);
b6d96bed 9594 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9595 tcg_temp_free_i64(fp0);
b6d96bed 9596 }
57fa1fb3
TS
9597 opn = "rsqrt2.ps";
9598 break;
bf4120ad 9599 case OPC_CVT_S_PU:
5e755519 9600 check_cp1_64bitmode(ctx);
b6d96bed 9601 {
a7812ae4 9602 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9603
7f6613ce 9604 gen_load_fpr32h(ctx, fp0, fs);
895c2d04 9605 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
b6d96bed 9606 gen_store_fpr32(fp0, fd);
a7812ae4 9607 tcg_temp_free_i32(fp0);
b6d96bed 9608 }
5a5012ec 9609 opn = "cvt.s.pu";
dd016883 9610 break;
bf4120ad 9611 case OPC_CVT_PW_PS:
5e755519 9612 check_cp1_64bitmode(ctx);
b6d96bed 9613 {
a7812ae4 9614 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
9615
9616 gen_load_fpr64(ctx, fp0, fs);
895c2d04 9617 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
b6d96bed 9618 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9619 tcg_temp_free_i64(fp0);
b6d96bed 9620 }
5a5012ec 9621 opn = "cvt.pw.ps";
6ea83fed 9622 break;
bf4120ad 9623 case OPC_CVT_S_PL:
5e755519 9624 check_cp1_64bitmode(ctx);
b6d96bed 9625 {
a7812ae4 9626 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
9627
9628 gen_load_fpr32(fp0, fs);
895c2d04 9629 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
b6d96bed 9630 gen_store_fpr32(fp0, fd);
a7812ae4 9631 tcg_temp_free_i32(fp0);
b6d96bed 9632 }
5a5012ec 9633 opn = "cvt.s.pl";
6ea83fed 9634 break;
bf4120ad 9635 case OPC_PLL_PS:
5e755519 9636 check_cp1_64bitmode(ctx);
b6d96bed 9637 {
a7812ae4
PB
9638 TCGv_i32 fp0 = tcg_temp_new_i32();
9639 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
9640
9641 gen_load_fpr32(fp0, fs);
9642 gen_load_fpr32(fp1, ft);
7f6613ce 9643 gen_store_fpr32h(ctx, fp0, fd);
b6d96bed 9644 gen_store_fpr32(fp1, fd);
a7812ae4
PB
9645 tcg_temp_free_i32(fp0);
9646 tcg_temp_free_i32(fp1);
b6d96bed 9647 }
5a5012ec 9648 opn = "pll.ps";
6ea83fed 9649 break;
bf4120ad 9650 case OPC_PLU_PS:
5e755519 9651 check_cp1_64bitmode(ctx);
b6d96bed 9652 {
a7812ae4
PB
9653 TCGv_i32 fp0 = tcg_temp_new_i32();
9654 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
9655
9656 gen_load_fpr32(fp0, fs);
7f6613ce 9657 gen_load_fpr32h(ctx, fp1, ft);
b6d96bed 9658 gen_store_fpr32(fp1, fd);
7f6613ce 9659 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
9660 tcg_temp_free_i32(fp0);
9661 tcg_temp_free_i32(fp1);
b6d96bed 9662 }
5a5012ec
TS
9663 opn = "plu.ps";
9664 break;
bf4120ad 9665 case OPC_PUL_PS:
5e755519 9666 check_cp1_64bitmode(ctx);
b6d96bed 9667 {
a7812ae4
PB
9668 TCGv_i32 fp0 = tcg_temp_new_i32();
9669 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 9670
7f6613ce 9671 gen_load_fpr32h(ctx, fp0, fs);
b6d96bed
TS
9672 gen_load_fpr32(fp1, ft);
9673 gen_store_fpr32(fp1, fd);
7f6613ce 9674 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
9675 tcg_temp_free_i32(fp0);
9676 tcg_temp_free_i32(fp1);
b6d96bed 9677 }
5a5012ec
TS
9678 opn = "pul.ps";
9679 break;
bf4120ad 9680 case OPC_PUU_PS:
5e755519 9681 check_cp1_64bitmode(ctx);
b6d96bed 9682 {
a7812ae4
PB
9683 TCGv_i32 fp0 = tcg_temp_new_i32();
9684 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 9685
7f6613ce
PJ
9686 gen_load_fpr32h(ctx, fp0, fs);
9687 gen_load_fpr32h(ctx, fp1, ft);
b6d96bed 9688 gen_store_fpr32(fp1, fd);
7f6613ce 9689 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
9690 tcg_temp_free_i32(fp0);
9691 tcg_temp_free_i32(fp1);
b6d96bed 9692 }
5a5012ec
TS
9693 opn = "puu.ps";
9694 break;
bf4120ad
NF
9695 case OPC_CMP_F_PS:
9696 case OPC_CMP_UN_PS:
9697 case OPC_CMP_EQ_PS:
9698 case OPC_CMP_UEQ_PS:
9699 case OPC_CMP_OLT_PS:
9700 case OPC_CMP_ULT_PS:
9701 case OPC_CMP_OLE_PS:
9702 case OPC_CMP_ULE_PS:
9703 case OPC_CMP_SF_PS:
9704 case OPC_CMP_NGLE_PS:
9705 case OPC_CMP_SEQ_PS:
9706 case OPC_CMP_NGL_PS:
9707 case OPC_CMP_LT_PS:
9708 case OPC_CMP_NGE_PS:
9709 case OPC_CMP_LE_PS:
9710 case OPC_CMP_NGT_PS:
8153667c
NF
9711 if (ctx->opcode & (1 << 6)) {
9712 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
9713 opn = condnames_abs[func-48];
9714 } else {
9715 gen_cmp_ps(ctx, func-48, ft, fs, cc);
9716 opn = condnames[func-48];
5a1e8ffb 9717 }
6ea83fed 9718 break;
5a5012ec 9719 default:
923617a3 9720 MIPS_INVAL(opn);
e397ee33 9721 generate_exception (ctx, EXCP_RI);
6ea83fed
FB
9722 return;
9723 }
2abf314d 9724 (void)opn; /* avoid a compiler warning */
5a1e8ffb
TS
9725 switch (optype) {
9726 case BINOP:
6ea83fed 9727 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
5a1e8ffb
TS
9728 break;
9729 case CMPOP:
9730 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
9731 break;
9732 default:
6ea83fed 9733 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
5a1e8ffb
TS
9734 break;
9735 }
6ea83fed 9736}
6af0bf9c 9737
5a5012ec 9738/* Coprocessor 3 (FPU) */
5e755519
TS
9739static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
9740 int fd, int fs, int base, int index)
7a387fff 9741{
923617a3 9742 const char *opn = "extended float load/store";
93b12ccc 9743 int store = 0;
4e2474d6 9744 TCGv t0 = tcg_temp_new();
7a387fff 9745
93b12ccc 9746 if (base == 0) {
6c5c1e20 9747 gen_load_gpr(t0, index);
93b12ccc 9748 } else if (index == 0) {
6c5c1e20 9749 gen_load_gpr(t0, base);
93b12ccc 9750 } else {
05168674 9751 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
93b12ccc 9752 }
5a5012ec 9753 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 9754 memory access. */
5a5012ec
TS
9755 switch (opc) {
9756 case OPC_LWXC1:
8c0ab41f 9757 check_cop1x(ctx);
b6d96bed 9758 {
a7812ae4 9759 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9760
5f68f5ae 9761 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
585c88d5 9762 tcg_gen_trunc_tl_i32(fp0, t0);
b6d96bed 9763 gen_store_fpr32(fp0, fd);
a7812ae4 9764 tcg_temp_free_i32(fp0);
b6d96bed 9765 }
5a5012ec
TS
9766 opn = "lwxc1";
9767 break;
9768 case OPC_LDXC1:
8c0ab41f
AJ
9769 check_cop1x(ctx);
9770 check_cp1_registers(ctx, fd);
b6d96bed 9771 {
a7812ae4 9772 TCGv_i64 fp0 = tcg_temp_new_i64();
5f68f5ae 9773 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
b6d96bed 9774 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9775 tcg_temp_free_i64(fp0);
b6d96bed 9776 }
5a5012ec
TS
9777 opn = "ldxc1";
9778 break;
9779 case OPC_LUXC1:
8c0ab41f 9780 check_cp1_64bitmode(ctx);
6c5c1e20 9781 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 9782 {
a7812ae4 9783 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 9784
5f68f5ae 9785 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
b6d96bed 9786 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9787 tcg_temp_free_i64(fp0);
b6d96bed 9788 }
5a5012ec
TS
9789 opn = "luxc1";
9790 break;
9791 case OPC_SWXC1:
8c0ab41f 9792 check_cop1x(ctx);
b6d96bed 9793 {
a7812ae4 9794 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9795 gen_load_fpr32(fp0, fs);
5f68f5ae 9796 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
a7812ae4 9797 tcg_temp_free_i32(fp0);
b6d96bed 9798 }
5a5012ec 9799 opn = "swxc1";
93b12ccc 9800 store = 1;
5a5012ec
TS
9801 break;
9802 case OPC_SDXC1:
8c0ab41f
AJ
9803 check_cop1x(ctx);
9804 check_cp1_registers(ctx, fs);
b6d96bed 9805 {
a7812ae4 9806 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 9807 gen_load_fpr64(ctx, fp0, fs);
5f68f5ae 9808 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
a7812ae4 9809 tcg_temp_free_i64(fp0);
b6d96bed 9810 }
5a5012ec 9811 opn = "sdxc1";
93b12ccc 9812 store = 1;
5a5012ec
TS
9813 break;
9814 case OPC_SUXC1:
8c0ab41f 9815 check_cp1_64bitmode(ctx);
6c5c1e20 9816 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 9817 {
a7812ae4 9818 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 9819 gen_load_fpr64(ctx, fp0, fs);
5f68f5ae 9820 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
a7812ae4 9821 tcg_temp_free_i64(fp0);
b6d96bed 9822 }
5a5012ec 9823 opn = "suxc1";
93b12ccc 9824 store = 1;
5a5012ec 9825 break;
5a5012ec 9826 }
6c5c1e20 9827 tcg_temp_free(t0);
2abf314d 9828 (void)opn; (void)store; /* avoid compiler warnings */
93b12ccc
TS
9829 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
9830 regnames[index], regnames[base]);
5a5012ec
TS
9831}
9832
5e755519
TS
9833static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
9834 int fd, int fr, int fs, int ft)
5a5012ec 9835{
923617a3 9836 const char *opn = "flt3_arith";
5a5012ec 9837
5a5012ec
TS
9838 switch (opc) {
9839 case OPC_ALNV_PS:
b8aa4598 9840 check_cp1_64bitmode(ctx);
a16336e4 9841 {
a7812ae4 9842 TCGv t0 = tcg_temp_local_new();
c905fdac
AJ
9843 TCGv_i32 fp = tcg_temp_new_i32();
9844 TCGv_i32 fph = tcg_temp_new_i32();
a16336e4
TS
9845 int l1 = gen_new_label();
9846 int l2 = gen_new_label();
9847
6c5c1e20
TS
9848 gen_load_gpr(t0, fr);
9849 tcg_gen_andi_tl(t0, t0, 0x7);
6c5c1e20
TS
9850
9851 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
c905fdac 9852 gen_load_fpr32(fp, fs);
7f6613ce 9853 gen_load_fpr32h(ctx, fph, fs);
c905fdac 9854 gen_store_fpr32(fp, fd);
7f6613ce 9855 gen_store_fpr32h(ctx, fph, fd);
a16336e4
TS
9856 tcg_gen_br(l2);
9857 gen_set_label(l1);
6c5c1e20
TS
9858 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
9859 tcg_temp_free(t0);
a16336e4 9860#ifdef TARGET_WORDS_BIGENDIAN
c905fdac 9861 gen_load_fpr32(fp, fs);
7f6613ce
PJ
9862 gen_load_fpr32h(ctx, fph, ft);
9863 gen_store_fpr32h(ctx, fp, fd);
c905fdac 9864 gen_store_fpr32(fph, fd);
a16336e4 9865#else
7f6613ce 9866 gen_load_fpr32h(ctx, fph, fs);
c905fdac
AJ
9867 gen_load_fpr32(fp, ft);
9868 gen_store_fpr32(fph, fd);
7f6613ce 9869 gen_store_fpr32h(ctx, fp, fd);
a16336e4
TS
9870#endif
9871 gen_set_label(l2);
c905fdac
AJ
9872 tcg_temp_free_i32(fp);
9873 tcg_temp_free_i32(fph);
a16336e4 9874 }
5a5012ec
TS
9875 opn = "alnv.ps";
9876 break;
9877 case OPC_MADD_S:
b8aa4598 9878 check_cop1x(ctx);
b6d96bed 9879 {
a7812ae4
PB
9880 TCGv_i32 fp0 = tcg_temp_new_i32();
9881 TCGv_i32 fp1 = tcg_temp_new_i32();
9882 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
9883
9884 gen_load_fpr32(fp0, fs);
9885 gen_load_fpr32(fp1, ft);
9886 gen_load_fpr32(fp2, fr);
b3d6cd44 9887 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
9888 tcg_temp_free_i32(fp0);
9889 tcg_temp_free_i32(fp1);
b6d96bed 9890 gen_store_fpr32(fp2, fd);
a7812ae4 9891 tcg_temp_free_i32(fp2);
b6d96bed 9892 }
5a5012ec
TS
9893 opn = "madd.s";
9894 break;
9895 case OPC_MADD_D:
b8aa4598
TS
9896 check_cop1x(ctx);
9897 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 9898 {
a7812ae4
PB
9899 TCGv_i64 fp0 = tcg_temp_new_i64();
9900 TCGv_i64 fp1 = tcg_temp_new_i64();
9901 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
9902
9903 gen_load_fpr64(ctx, fp0, fs);
9904 gen_load_fpr64(ctx, fp1, ft);
9905 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 9906 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
9907 tcg_temp_free_i64(fp0);
9908 tcg_temp_free_i64(fp1);
b6d96bed 9909 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 9910 tcg_temp_free_i64(fp2);
b6d96bed 9911 }
5a5012ec
TS
9912 opn = "madd.d";
9913 break;
9914 case OPC_MADD_PS:
b8aa4598 9915 check_cp1_64bitmode(ctx);
b6d96bed 9916 {
a7812ae4
PB
9917 TCGv_i64 fp0 = tcg_temp_new_i64();
9918 TCGv_i64 fp1 = tcg_temp_new_i64();
9919 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
9920
9921 gen_load_fpr64(ctx, fp0, fs);
9922 gen_load_fpr64(ctx, fp1, ft);
9923 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 9924 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
9925 tcg_temp_free_i64(fp0);
9926 tcg_temp_free_i64(fp1);
b6d96bed 9927 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 9928 tcg_temp_free_i64(fp2);
b6d96bed 9929 }
5a5012ec
TS
9930 opn = "madd.ps";
9931 break;
9932 case OPC_MSUB_S:
b8aa4598 9933 check_cop1x(ctx);
b6d96bed 9934 {
a7812ae4
PB
9935 TCGv_i32 fp0 = tcg_temp_new_i32();
9936 TCGv_i32 fp1 = tcg_temp_new_i32();
9937 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
9938
9939 gen_load_fpr32(fp0, fs);
9940 gen_load_fpr32(fp1, ft);
9941 gen_load_fpr32(fp2, fr);
b3d6cd44 9942 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
9943 tcg_temp_free_i32(fp0);
9944 tcg_temp_free_i32(fp1);
b6d96bed 9945 gen_store_fpr32(fp2, fd);
a7812ae4 9946 tcg_temp_free_i32(fp2);
b6d96bed 9947 }
5a5012ec
TS
9948 opn = "msub.s";
9949 break;
9950 case OPC_MSUB_D:
b8aa4598
TS
9951 check_cop1x(ctx);
9952 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 9953 {
a7812ae4
PB
9954 TCGv_i64 fp0 = tcg_temp_new_i64();
9955 TCGv_i64 fp1 = tcg_temp_new_i64();
9956 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
9957
9958 gen_load_fpr64(ctx, fp0, fs);
9959 gen_load_fpr64(ctx, fp1, ft);
9960 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 9961 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
9962 tcg_temp_free_i64(fp0);
9963 tcg_temp_free_i64(fp1);
b6d96bed 9964 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 9965 tcg_temp_free_i64(fp2);
b6d96bed 9966 }
5a5012ec
TS
9967 opn = "msub.d";
9968 break;
9969 case OPC_MSUB_PS:
b8aa4598 9970 check_cp1_64bitmode(ctx);
b6d96bed 9971 {
a7812ae4
PB
9972 TCGv_i64 fp0 = tcg_temp_new_i64();
9973 TCGv_i64 fp1 = tcg_temp_new_i64();
9974 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
9975
9976 gen_load_fpr64(ctx, fp0, fs);
9977 gen_load_fpr64(ctx, fp1, ft);
9978 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 9979 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
9980 tcg_temp_free_i64(fp0);
9981 tcg_temp_free_i64(fp1);
b6d96bed 9982 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 9983 tcg_temp_free_i64(fp2);
b6d96bed 9984 }
5a5012ec
TS
9985 opn = "msub.ps";
9986 break;
9987 case OPC_NMADD_S:
b8aa4598 9988 check_cop1x(ctx);
b6d96bed 9989 {
a7812ae4
PB
9990 TCGv_i32 fp0 = tcg_temp_new_i32();
9991 TCGv_i32 fp1 = tcg_temp_new_i32();
9992 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
9993
9994 gen_load_fpr32(fp0, fs);
9995 gen_load_fpr32(fp1, ft);
9996 gen_load_fpr32(fp2, fr);
b3d6cd44 9997 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
9998 tcg_temp_free_i32(fp0);
9999 tcg_temp_free_i32(fp1);
b6d96bed 10000 gen_store_fpr32(fp2, fd);
a7812ae4 10001 tcg_temp_free_i32(fp2);
b6d96bed 10002 }
5a5012ec
TS
10003 opn = "nmadd.s";
10004 break;
10005 case OPC_NMADD_D:
b8aa4598
TS
10006 check_cop1x(ctx);
10007 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 10008 {
a7812ae4
PB
10009 TCGv_i64 fp0 = tcg_temp_new_i64();
10010 TCGv_i64 fp1 = tcg_temp_new_i64();
10011 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
10012
10013 gen_load_fpr64(ctx, fp0, fs);
10014 gen_load_fpr64(ctx, fp1, ft);
10015 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 10016 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
10017 tcg_temp_free_i64(fp0);
10018 tcg_temp_free_i64(fp1);
b6d96bed 10019 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 10020 tcg_temp_free_i64(fp2);
b6d96bed 10021 }
5a5012ec
TS
10022 opn = "nmadd.d";
10023 break;
10024 case OPC_NMADD_PS:
b8aa4598 10025 check_cp1_64bitmode(ctx);
b6d96bed 10026 {
a7812ae4
PB
10027 TCGv_i64 fp0 = tcg_temp_new_i64();
10028 TCGv_i64 fp1 = tcg_temp_new_i64();
10029 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
10030
10031 gen_load_fpr64(ctx, fp0, fs);
10032 gen_load_fpr64(ctx, fp1, ft);
10033 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 10034 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
10035 tcg_temp_free_i64(fp0);
10036 tcg_temp_free_i64(fp1);
b6d96bed 10037 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 10038 tcg_temp_free_i64(fp2);
b6d96bed 10039 }
5a5012ec
TS
10040 opn = "nmadd.ps";
10041 break;
10042 case OPC_NMSUB_S:
b8aa4598 10043 check_cop1x(ctx);
b6d96bed 10044 {
a7812ae4
PB
10045 TCGv_i32 fp0 = tcg_temp_new_i32();
10046 TCGv_i32 fp1 = tcg_temp_new_i32();
10047 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
10048
10049 gen_load_fpr32(fp0, fs);
10050 gen_load_fpr32(fp1, ft);
10051 gen_load_fpr32(fp2, fr);
b3d6cd44 10052 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
10053 tcg_temp_free_i32(fp0);
10054 tcg_temp_free_i32(fp1);
b6d96bed 10055 gen_store_fpr32(fp2, fd);
a7812ae4 10056 tcg_temp_free_i32(fp2);
b6d96bed 10057 }
5a5012ec
TS
10058 opn = "nmsub.s";
10059 break;
10060 case OPC_NMSUB_D:
b8aa4598
TS
10061 check_cop1x(ctx);
10062 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 10063 {
a7812ae4
PB
10064 TCGv_i64 fp0 = tcg_temp_new_i64();
10065 TCGv_i64 fp1 = tcg_temp_new_i64();
10066 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
10067
10068 gen_load_fpr64(ctx, fp0, fs);
10069 gen_load_fpr64(ctx, fp1, ft);
10070 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 10071 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
10072 tcg_temp_free_i64(fp0);
10073 tcg_temp_free_i64(fp1);
b6d96bed 10074 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 10075 tcg_temp_free_i64(fp2);
b6d96bed 10076 }
5a5012ec
TS
10077 opn = "nmsub.d";
10078 break;
10079 case OPC_NMSUB_PS:
b8aa4598 10080 check_cp1_64bitmode(ctx);
b6d96bed 10081 {
a7812ae4
PB
10082 TCGv_i64 fp0 = tcg_temp_new_i64();
10083 TCGv_i64 fp1 = tcg_temp_new_i64();
10084 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
10085
10086 gen_load_fpr64(ctx, fp0, fs);
10087 gen_load_fpr64(ctx, fp1, ft);
10088 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 10089 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
10090 tcg_temp_free_i64(fp0);
10091 tcg_temp_free_i64(fp1);
b6d96bed 10092 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 10093 tcg_temp_free_i64(fp2);
b6d96bed 10094 }
5a5012ec
TS
10095 opn = "nmsub.ps";
10096 break;
923617a3
TS
10097 default:
10098 MIPS_INVAL(opn);
5a5012ec
TS
10099 generate_exception (ctx, EXCP_RI);
10100 return;
10101 }
2abf314d 10102 (void)opn; /* avoid a compiler warning */
5a5012ec
TS
10103 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
10104 fregnames[fs], fregnames[ft]);
7a387fff
TS
10105}
10106
d75c135e 10107static void gen_rdhwr(DisasContext *ctx, int rt, int rd)
26ebe468
NF
10108{
10109 TCGv t0;
10110
b3167288
RH
10111#if !defined(CONFIG_USER_ONLY)
10112 /* The Linux kernel will emulate rdhwr if it's not supported natively.
10113 Therefore only check the ISA in system mode. */
d75c135e 10114 check_insn(ctx, ISA_MIPS32R2);
b3167288 10115#endif
26ebe468
NF
10116 t0 = tcg_temp_new();
10117
10118 switch (rd) {
10119 case 0:
10120 save_cpu_state(ctx, 1);
895c2d04 10121 gen_helper_rdhwr_cpunum(t0, cpu_env);
26ebe468
NF
10122 gen_store_gpr(t0, rt);
10123 break;
10124 case 1:
10125 save_cpu_state(ctx, 1);
895c2d04 10126 gen_helper_rdhwr_synci_step(t0, cpu_env);
26ebe468
NF
10127 gen_store_gpr(t0, rt);
10128 break;
10129 case 2:
10130 save_cpu_state(ctx, 1);
895c2d04 10131 gen_helper_rdhwr_cc(t0, cpu_env);
26ebe468
NF
10132 gen_store_gpr(t0, rt);
10133 break;
10134 case 3:
10135 save_cpu_state(ctx, 1);
895c2d04 10136 gen_helper_rdhwr_ccres(t0, cpu_env);
26ebe468
NF
10137 gen_store_gpr(t0, rt);
10138 break;
10139 case 29:
10140#if defined(CONFIG_USER_ONLY)
d279279e
PJ
10141 tcg_gen_ld_tl(t0, cpu_env,
10142 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
26ebe468
NF
10143 gen_store_gpr(t0, rt);
10144 break;
10145#else
d279279e
PJ
10146 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
10147 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
10148 tcg_gen_ld_tl(t0, cpu_env,
10149 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10150 gen_store_gpr(t0, rt);
10151 } else {
10152 generate_exception(ctx, EXCP_RI);
10153 }
10154 break;
26ebe468
NF
10155#endif
10156 default: /* Invalid */
10157 MIPS_INVAL("rdhwr");
10158 generate_exception(ctx, EXCP_RI);
10159 break;
10160 }
10161 tcg_temp_free(t0);
10162}
10163
31837be3 10164static void gen_branch(DisasContext *ctx, int insn_bytes)
c9602061
NF
10165{
10166 if (ctx->hflags & MIPS_HFLAG_BMASK) {
364d4831 10167 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
c9602061
NF
10168 /* Branches completion */
10169 ctx->hflags &= ~MIPS_HFLAG_BMASK;
10170 ctx->bstate = BS_BRANCH;
10171 save_cpu_state(ctx, 0);
10172 /* FIXME: Need to clear can_do_io. */
364d4831 10173 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
c9602061
NF
10174 case MIPS_HFLAG_B:
10175 /* unconditional branch */
10176 MIPS_DEBUG("unconditional branch");
364d4831
NF
10177 if (proc_hflags & MIPS_HFLAG_BX) {
10178 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
10179 }
c9602061
NF
10180 gen_goto_tb(ctx, 0, ctx->btarget);
10181 break;
10182 case MIPS_HFLAG_BL:
10183 /* blikely taken case */
10184 MIPS_DEBUG("blikely branch taken");
10185 gen_goto_tb(ctx, 0, ctx->btarget);
10186 break;
10187 case MIPS_HFLAG_BC:
10188 /* Conditional branch */
10189 MIPS_DEBUG("conditional branch");
10190 {
10191 int l1 = gen_new_label();
10192
10193 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
10194 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
10195 gen_set_label(l1);
10196 gen_goto_tb(ctx, 0, ctx->btarget);
10197 }
10198 break;
10199 case MIPS_HFLAG_BR:
10200 /* unconditional branch to register */
10201 MIPS_DEBUG("branch to register");
d75c135e 10202 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
364d4831
NF
10203 TCGv t0 = tcg_temp_new();
10204 TCGv_i32 t1 = tcg_temp_new_i32();
10205
10206 tcg_gen_andi_tl(t0, btarget, 0x1);
10207 tcg_gen_trunc_tl_i32(t1, t0);
10208 tcg_temp_free(t0);
10209 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
10210 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
10211 tcg_gen_or_i32(hflags, hflags, t1);
10212 tcg_temp_free_i32(t1);
10213
10214 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
10215 } else {
10216 tcg_gen_mov_tl(cpu_PC, btarget);
10217 }
c9602061
NF
10218 if (ctx->singlestep_enabled) {
10219 save_cpu_state(ctx, 0);
895c2d04 10220 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
c9602061
NF
10221 }
10222 tcg_gen_exit_tb(0);
10223 break;
10224 default:
10225 MIPS_DEBUG("unknown branch");
10226 break;
10227 }
10228 }
10229}
10230
7a387fff 10231/* ISA extensions (ASEs) */
6af0bf9c 10232/* MIPS16 extension to MIPS32 */
6ea219d0
NF
10233
10234/* MIPS16 major opcodes */
10235enum {
10236 M16_OPC_ADDIUSP = 0x00,
10237 M16_OPC_ADDIUPC = 0x01,
10238 M16_OPC_B = 0x02,
10239 M16_OPC_JAL = 0x03,
10240 M16_OPC_BEQZ = 0x04,
10241 M16_OPC_BNEQZ = 0x05,
10242 M16_OPC_SHIFT = 0x06,
10243 M16_OPC_LD = 0x07,
10244 M16_OPC_RRIA = 0x08,
10245 M16_OPC_ADDIU8 = 0x09,
10246 M16_OPC_SLTI = 0x0a,
10247 M16_OPC_SLTIU = 0x0b,
10248 M16_OPC_I8 = 0x0c,
10249 M16_OPC_LI = 0x0d,
10250 M16_OPC_CMPI = 0x0e,
10251 M16_OPC_SD = 0x0f,
10252 M16_OPC_LB = 0x10,
10253 M16_OPC_LH = 0x11,
10254 M16_OPC_LWSP = 0x12,
10255 M16_OPC_LW = 0x13,
10256 M16_OPC_LBU = 0x14,
10257 M16_OPC_LHU = 0x15,
10258 M16_OPC_LWPC = 0x16,
10259 M16_OPC_LWU = 0x17,
10260 M16_OPC_SB = 0x18,
10261 M16_OPC_SH = 0x19,
10262 M16_OPC_SWSP = 0x1a,
10263 M16_OPC_SW = 0x1b,
10264 M16_OPC_RRR = 0x1c,
10265 M16_OPC_RR = 0x1d,
10266 M16_OPC_EXTEND = 0x1e,
10267 M16_OPC_I64 = 0x1f
10268};
10269
10270/* I8 funct field */
10271enum {
10272 I8_BTEQZ = 0x0,
10273 I8_BTNEZ = 0x1,
10274 I8_SWRASP = 0x2,
10275 I8_ADJSP = 0x3,
10276 I8_SVRS = 0x4,
10277 I8_MOV32R = 0x5,
10278 I8_MOVR32 = 0x7
10279};
10280
10281/* RRR f field */
10282enum {
10283 RRR_DADDU = 0x0,
10284 RRR_ADDU = 0x1,
10285 RRR_DSUBU = 0x2,
10286 RRR_SUBU = 0x3
10287};
10288
10289/* RR funct field */
10290enum {
10291 RR_JR = 0x00,
10292 RR_SDBBP = 0x01,
10293 RR_SLT = 0x02,
10294 RR_SLTU = 0x03,
10295 RR_SLLV = 0x04,
10296 RR_BREAK = 0x05,
10297 RR_SRLV = 0x06,
10298 RR_SRAV = 0x07,
10299 RR_DSRL = 0x08,
10300 RR_CMP = 0x0a,
10301 RR_NEG = 0x0b,
10302 RR_AND = 0x0c,
10303 RR_OR = 0x0d,
10304 RR_XOR = 0x0e,
10305 RR_NOT = 0x0f,
10306 RR_MFHI = 0x10,
10307 RR_CNVT = 0x11,
10308 RR_MFLO = 0x12,
10309 RR_DSRA = 0x13,
10310 RR_DSLLV = 0x14,
10311 RR_DSRLV = 0x16,
10312 RR_DSRAV = 0x17,
10313 RR_MULT = 0x18,
10314 RR_MULTU = 0x19,
10315 RR_DIV = 0x1a,
10316 RR_DIVU = 0x1b,
10317 RR_DMULT = 0x1c,
10318 RR_DMULTU = 0x1d,
10319 RR_DDIV = 0x1e,
10320 RR_DDIVU = 0x1f
10321};
10322
10323/* I64 funct field */
10324enum {
10325 I64_LDSP = 0x0,
10326 I64_SDSP = 0x1,
10327 I64_SDRASP = 0x2,
10328 I64_DADJSP = 0x3,
10329 I64_LDPC = 0x4,
364d4831 10330 I64_DADDIU5 = 0x5,
6ea219d0
NF
10331 I64_DADDIUPC = 0x6,
10332 I64_DADDIUSP = 0x7
10333};
10334
10335/* RR ry field for CNVT */
10336enum {
10337 RR_RY_CNVT_ZEB = 0x0,
10338 RR_RY_CNVT_ZEH = 0x1,
10339 RR_RY_CNVT_ZEW = 0x2,
10340 RR_RY_CNVT_SEB = 0x4,
10341 RR_RY_CNVT_SEH = 0x5,
10342 RR_RY_CNVT_SEW = 0x6,
10343};
10344
364d4831
NF
10345static int xlat (int r)
10346{
10347 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
10348
10349 return map[r];
10350}
10351
10352static void gen_mips16_save (DisasContext *ctx,
10353 int xsregs, int aregs,
10354 int do_ra, int do_s0, int do_s1,
10355 int framesize)
10356{
10357 TCGv t0 = tcg_temp_new();
10358 TCGv t1 = tcg_temp_new();
10359 int args, astatic;
10360
10361 switch (aregs) {
10362 case 0:
10363 case 1:
10364 case 2:
10365 case 3:
10366 case 11:
10367 args = 0;
10368 break;
10369 case 4:
10370 case 5:
10371 case 6:
10372 case 7:
10373 args = 1;
10374 break;
10375 case 8:
10376 case 9:
10377 case 10:
10378 args = 2;
10379 break;
10380 case 12:
10381 case 13:
10382 args = 3;
10383 break;
10384 case 14:
10385 args = 4;
10386 break;
10387 default:
10388 generate_exception(ctx, EXCP_RI);
10389 return;
10390 }
10391
10392 switch (args) {
10393 case 4:
10394 gen_base_offset_addr(ctx, t0, 29, 12);
10395 gen_load_gpr(t1, 7);
5f68f5ae 10396 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
10397 /* Fall through */
10398 case 3:
10399 gen_base_offset_addr(ctx, t0, 29, 8);
10400 gen_load_gpr(t1, 6);
5f68f5ae 10401 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
10402 /* Fall through */
10403 case 2:
10404 gen_base_offset_addr(ctx, t0, 29, 4);
10405 gen_load_gpr(t1, 5);
5f68f5ae 10406 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
10407 /* Fall through */
10408 case 1:
10409 gen_base_offset_addr(ctx, t0, 29, 0);
10410 gen_load_gpr(t1, 4);
5f68f5ae 10411 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
10412 }
10413
10414 gen_load_gpr(t0, 29);
10415
5f68f5ae
AJ
10416#define DECR_AND_STORE(reg) do { \
10417 tcg_gen_subi_tl(t0, t0, 4); \
10418 gen_load_gpr(t1, reg); \
10419 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
364d4831
NF
10420 } while (0)
10421
10422 if (do_ra) {
10423 DECR_AND_STORE(31);
10424 }
10425
10426 switch (xsregs) {
10427 case 7:
10428 DECR_AND_STORE(30);
10429 /* Fall through */
10430 case 6:
10431 DECR_AND_STORE(23);
10432 /* Fall through */
10433 case 5:
10434 DECR_AND_STORE(22);
10435 /* Fall through */
10436 case 4:
10437 DECR_AND_STORE(21);
10438 /* Fall through */
10439 case 3:
10440 DECR_AND_STORE(20);
10441 /* Fall through */
10442 case 2:
10443 DECR_AND_STORE(19);
10444 /* Fall through */
10445 case 1:
10446 DECR_AND_STORE(18);
10447 }
10448
10449 if (do_s1) {
10450 DECR_AND_STORE(17);
10451 }
10452 if (do_s0) {
10453 DECR_AND_STORE(16);
10454 }
10455
10456 switch (aregs) {
10457 case 0:
10458 case 4:
10459 case 8:
10460 case 12:
10461 case 14:
10462 astatic = 0;
10463 break;
10464 case 1:
10465 case 5:
10466 case 9:
10467 case 13:
10468 astatic = 1;
10469 break;
10470 case 2:
10471 case 6:
10472 case 10:
10473 astatic = 2;
10474 break;
10475 case 3:
10476 case 7:
10477 astatic = 3;
10478 break;
10479 case 11:
10480 astatic = 4;
10481 break;
10482 default:
10483 generate_exception(ctx, EXCP_RI);
10484 return;
10485 }
10486
10487 if (astatic > 0) {
10488 DECR_AND_STORE(7);
10489 if (astatic > 1) {
10490 DECR_AND_STORE(6);
10491 if (astatic > 2) {
10492 DECR_AND_STORE(5);
10493 if (astatic > 3) {
10494 DECR_AND_STORE(4);
10495 }
10496 }
10497 }
10498 }
10499#undef DECR_AND_STORE
10500
10501 tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
10502 tcg_temp_free(t0);
10503 tcg_temp_free(t1);
10504}
10505
10506static void gen_mips16_restore (DisasContext *ctx,
10507 int xsregs, int aregs,
10508 int do_ra, int do_s0, int do_s1,
10509 int framesize)
10510{
10511 int astatic;
10512 TCGv t0 = tcg_temp_new();
10513 TCGv t1 = tcg_temp_new();
10514
10515 tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
10516
5f68f5ae
AJ
10517#define DECR_AND_LOAD(reg) do { \
10518 tcg_gen_subi_tl(t0, t0, 4); \
10519 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
10520 gen_store_gpr(t1, reg); \
364d4831
NF
10521 } while (0)
10522
10523 if (do_ra) {
10524 DECR_AND_LOAD(31);
10525 }
10526
10527 switch (xsregs) {
10528 case 7:
10529 DECR_AND_LOAD(30);
10530 /* Fall through */
10531 case 6:
10532 DECR_AND_LOAD(23);
10533 /* Fall through */
10534 case 5:
10535 DECR_AND_LOAD(22);
10536 /* Fall through */
10537 case 4:
10538 DECR_AND_LOAD(21);
10539 /* Fall through */
10540 case 3:
10541 DECR_AND_LOAD(20);
10542 /* Fall through */
10543 case 2:
10544 DECR_AND_LOAD(19);
10545 /* Fall through */
10546 case 1:
10547 DECR_AND_LOAD(18);
10548 }
10549
10550 if (do_s1) {
10551 DECR_AND_LOAD(17);
10552 }
10553 if (do_s0) {
10554 DECR_AND_LOAD(16);
10555 }
10556
10557 switch (aregs) {
10558 case 0:
10559 case 4:
10560 case 8:
10561 case 12:
10562 case 14:
10563 astatic = 0;
10564 break;
10565 case 1:
10566 case 5:
10567 case 9:
10568 case 13:
10569 astatic = 1;
10570 break;
10571 case 2:
10572 case 6:
10573 case 10:
10574 astatic = 2;
10575 break;
10576 case 3:
10577 case 7:
10578 astatic = 3;
10579 break;
10580 case 11:
10581 astatic = 4;
10582 break;
10583 default:
10584 generate_exception(ctx, EXCP_RI);
10585 return;
10586 }
10587
10588 if (astatic > 0) {
10589 DECR_AND_LOAD(7);
10590 if (astatic > 1) {
10591 DECR_AND_LOAD(6);
10592 if (astatic > 2) {
10593 DECR_AND_LOAD(5);
10594 if (astatic > 3) {
10595 DECR_AND_LOAD(4);
10596 }
10597 }
10598 }
10599 }
10600#undef DECR_AND_LOAD
10601
10602 tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
10603 tcg_temp_free(t0);
10604 tcg_temp_free(t1);
10605}
10606
10607static void gen_addiupc (DisasContext *ctx, int rx, int imm,
10608 int is_64_bit, int extended)
10609{
10610 TCGv t0;
10611
10612 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
10613 generate_exception(ctx, EXCP_RI);
10614 return;
10615 }
10616
10617 t0 = tcg_temp_new();
10618
10619 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
10620 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
10621 if (!is_64_bit) {
10622 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
10623 }
10624
10625 tcg_temp_free(t0);
10626}
10627
10628#if defined(TARGET_MIPS64)
d75c135e 10629static void decode_i64_mips16 (DisasContext *ctx,
364d4831
NF
10630 int ry, int funct, int16_t offset,
10631 int extended)
10632{
10633 switch (funct) {
10634 case I64_LDSP:
10635 check_mips_64(ctx);
10636 offset = extended ? offset : offset << 3;
d75c135e 10637 gen_ld(ctx, OPC_LD, ry, 29, offset);
364d4831
NF
10638 break;
10639 case I64_SDSP:
10640 check_mips_64(ctx);
10641 offset = extended ? offset : offset << 3;
5c13fdfd 10642 gen_st(ctx, OPC_SD, ry, 29, offset);
364d4831
NF
10643 break;
10644 case I64_SDRASP:
10645 check_mips_64(ctx);
10646 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
5c13fdfd 10647 gen_st(ctx, OPC_SD, 31, 29, offset);
364d4831
NF
10648 break;
10649 case I64_DADJSP:
10650 check_mips_64(ctx);
10651 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
d75c135e 10652 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
364d4831
NF
10653 break;
10654 case I64_LDPC:
10655 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
10656 generate_exception(ctx, EXCP_RI);
10657 } else {
10658 offset = extended ? offset : offset << 3;
d75c135e 10659 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
364d4831
NF
10660 }
10661 break;
10662 case I64_DADDIU5:
10663 check_mips_64(ctx);
10664 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
d75c135e 10665 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
364d4831
NF
10666 break;
10667 case I64_DADDIUPC:
10668 check_mips_64(ctx);
10669 offset = extended ? offset : offset << 2;
10670 gen_addiupc(ctx, ry, offset, 1, extended);
10671 break;
10672 case I64_DADDIUSP:
10673 check_mips_64(ctx);
10674 offset = extended ? offset : offset << 2;
d75c135e 10675 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
364d4831
NF
10676 break;
10677 }
10678}
10679#endif
10680
240ce26a 10681static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
364d4831 10682{
895c2d04 10683 int extend = cpu_lduw_code(env, ctx->pc + 2);
364d4831
NF
10684 int op, rx, ry, funct, sa;
10685 int16_t imm, offset;
10686
10687 ctx->opcode = (ctx->opcode << 16) | extend;
10688 op = (ctx->opcode >> 11) & 0x1f;
10689 sa = (ctx->opcode >> 22) & 0x1f;
10690 funct = (ctx->opcode >> 8) & 0x7;
10691 rx = xlat((ctx->opcode >> 8) & 0x7);
10692 ry = xlat((ctx->opcode >> 5) & 0x7);
10693 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
10694 | ((ctx->opcode >> 21) & 0x3f) << 5
10695 | (ctx->opcode & 0x1f));
10696
10697 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
10698 counterparts. */
10699 switch (op) {
10700 case M16_OPC_ADDIUSP:
d75c135e 10701 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
364d4831
NF
10702 break;
10703 case M16_OPC_ADDIUPC:
10704 gen_addiupc(ctx, rx, imm, 0, 1);
10705 break;
10706 case M16_OPC_B:
b231c103 10707 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
364d4831
NF
10708 /* No delay slot, so just process as a normal instruction */
10709 break;
10710 case M16_OPC_BEQZ:
b231c103 10711 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
364d4831
NF
10712 /* No delay slot, so just process as a normal instruction */
10713 break;
10714 case M16_OPC_BNEQZ:
b231c103 10715 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
364d4831
NF
10716 /* No delay slot, so just process as a normal instruction */
10717 break;
10718 case M16_OPC_SHIFT:
10719 switch (ctx->opcode & 0x3) {
10720 case 0x0:
d75c135e 10721 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
364d4831
NF
10722 break;
10723 case 0x1:
10724#if defined(TARGET_MIPS64)
10725 check_mips_64(ctx);
d75c135e 10726 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
364d4831
NF
10727#else
10728 generate_exception(ctx, EXCP_RI);
10729#endif
10730 break;
10731 case 0x2:
d75c135e 10732 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
364d4831
NF
10733 break;
10734 case 0x3:
d75c135e 10735 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
364d4831
NF
10736 break;
10737 }
10738 break;
10739#if defined(TARGET_MIPS64)
10740 case M16_OPC_LD:
10741 check_mips_64(ctx);
d75c135e 10742 gen_ld(ctx, OPC_LD, ry, rx, offset);
364d4831
NF
10743 break;
10744#endif
10745 case M16_OPC_RRIA:
10746 imm = ctx->opcode & 0xf;
10747 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
10748 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
10749 imm = (int16_t) (imm << 1) >> 1;
10750 if ((ctx->opcode >> 4) & 0x1) {
10751#if defined(TARGET_MIPS64)
10752 check_mips_64(ctx);
d75c135e 10753 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
364d4831
NF
10754#else
10755 generate_exception(ctx, EXCP_RI);
10756#endif
10757 } else {
d75c135e 10758 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
364d4831
NF
10759 }
10760 break;
10761 case M16_OPC_ADDIU8:
d75c135e 10762 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
364d4831
NF
10763 break;
10764 case M16_OPC_SLTI:
d75c135e 10765 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
10766 break;
10767 case M16_OPC_SLTIU:
d75c135e 10768 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
10769 break;
10770 case M16_OPC_I8:
10771 switch (funct) {
10772 case I8_BTEQZ:
b231c103 10773 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
364d4831
NF
10774 break;
10775 case I8_BTNEZ:
b231c103 10776 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
364d4831
NF
10777 break;
10778 case I8_SWRASP:
5c13fdfd 10779 gen_st(ctx, OPC_SW, 31, 29, imm);
364d4831
NF
10780 break;
10781 case I8_ADJSP:
d75c135e 10782 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
364d4831
NF
10783 break;
10784 case I8_SVRS:
10785 {
10786 int xsregs = (ctx->opcode >> 24) & 0x7;
10787 int aregs = (ctx->opcode >> 16) & 0xf;
10788 int do_ra = (ctx->opcode >> 6) & 0x1;
10789 int do_s0 = (ctx->opcode >> 5) & 0x1;
10790 int do_s1 = (ctx->opcode >> 4) & 0x1;
10791 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
10792 | (ctx->opcode & 0xf)) << 3;
10793
10794 if (ctx->opcode & (1 << 7)) {
10795 gen_mips16_save(ctx, xsregs, aregs,
10796 do_ra, do_s0, do_s1,
10797 framesize);
10798 } else {
10799 gen_mips16_restore(ctx, xsregs, aregs,
10800 do_ra, do_s0, do_s1,
10801 framesize);
10802 }
10803 }
10804 break;
10805 default:
10806 generate_exception(ctx, EXCP_RI);
10807 break;
10808 }
10809 break;
10810 case M16_OPC_LI:
10811 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
10812 break;
10813 case M16_OPC_CMPI:
10814 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
10815 break;
10816#if defined(TARGET_MIPS64)
10817 case M16_OPC_SD:
5c13fdfd 10818 gen_st(ctx, OPC_SD, ry, rx, offset);
364d4831
NF
10819 break;
10820#endif
10821 case M16_OPC_LB:
d75c135e 10822 gen_ld(ctx, OPC_LB, ry, rx, offset);
364d4831
NF
10823 break;
10824 case M16_OPC_LH:
d75c135e 10825 gen_ld(ctx, OPC_LH, ry, rx, offset);
364d4831
NF
10826 break;
10827 case M16_OPC_LWSP:
d75c135e 10828 gen_ld(ctx, OPC_LW, rx, 29, offset);
364d4831
NF
10829 break;
10830 case M16_OPC_LW:
d75c135e 10831 gen_ld(ctx, OPC_LW, ry, rx, offset);
364d4831
NF
10832 break;
10833 case M16_OPC_LBU:
d75c135e 10834 gen_ld(ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
10835 break;
10836 case M16_OPC_LHU:
d75c135e 10837 gen_ld(ctx, OPC_LHU, ry, rx, offset);
364d4831
NF
10838 break;
10839 case M16_OPC_LWPC:
d75c135e 10840 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
364d4831
NF
10841 break;
10842#if defined(TARGET_MIPS64)
10843 case M16_OPC_LWU:
d75c135e 10844 gen_ld(ctx, OPC_LWU, ry, rx, offset);
364d4831
NF
10845 break;
10846#endif
10847 case M16_OPC_SB:
5c13fdfd 10848 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
10849 break;
10850 case M16_OPC_SH:
5c13fdfd 10851 gen_st(ctx, OPC_SH, ry, rx, offset);
364d4831
NF
10852 break;
10853 case M16_OPC_SWSP:
5c13fdfd 10854 gen_st(ctx, OPC_SW, rx, 29, offset);
364d4831
NF
10855 break;
10856 case M16_OPC_SW:
5c13fdfd 10857 gen_st(ctx, OPC_SW, ry, rx, offset);
364d4831
NF
10858 break;
10859#if defined(TARGET_MIPS64)
10860 case M16_OPC_I64:
d75c135e 10861 decode_i64_mips16(ctx, ry, funct, offset, 1);
364d4831
NF
10862 break;
10863#endif
10864 default:
10865 generate_exception(ctx, EXCP_RI);
10866 break;
10867 }
10868
10869 return 4;
10870}
10871
240ce26a 10872static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
364d4831
NF
10873{
10874 int rx, ry;
10875 int sa;
10876 int op, cnvt_op, op1, offset;
10877 int funct;
10878 int n_bytes;
10879
10880 op = (ctx->opcode >> 11) & 0x1f;
10881 sa = (ctx->opcode >> 2) & 0x7;
10882 sa = sa == 0 ? 8 : sa;
10883 rx = xlat((ctx->opcode >> 8) & 0x7);
10884 cnvt_op = (ctx->opcode >> 5) & 0x7;
10885 ry = xlat((ctx->opcode >> 5) & 0x7);
10886 op1 = offset = ctx->opcode & 0x1f;
10887
10888 n_bytes = 2;
10889
10890 switch (op) {
10891 case M16_OPC_ADDIUSP:
10892 {
10893 int16_t imm = ((uint8_t) ctx->opcode) << 2;
10894
d75c135e 10895 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
364d4831
NF
10896 }
10897 break;
10898 case M16_OPC_ADDIUPC:
10899 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
10900 break;
10901 case M16_OPC_B:
10902 offset = (ctx->opcode & 0x7ff) << 1;
10903 offset = (int16_t)(offset << 4) >> 4;
b231c103 10904 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
364d4831
NF
10905 /* No delay slot, so just process as a normal instruction */
10906 break;
10907 case M16_OPC_JAL:
895c2d04 10908 offset = cpu_lduw_code(env, ctx->pc + 2);
364d4831
NF
10909 offset = (((ctx->opcode & 0x1f) << 21)
10910 | ((ctx->opcode >> 5) & 0x1f) << 16
10911 | offset) << 2;
b231c103
YK
10912 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
10913 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
364d4831 10914 n_bytes = 4;
364d4831
NF
10915 break;
10916 case M16_OPC_BEQZ:
b231c103
YK
10917 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
10918 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
10919 /* No delay slot, so just process as a normal instruction */
10920 break;
10921 case M16_OPC_BNEQZ:
b231c103
YK
10922 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
10923 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
10924 /* No delay slot, so just process as a normal instruction */
10925 break;
10926 case M16_OPC_SHIFT:
10927 switch (ctx->opcode & 0x3) {
10928 case 0x0:
d75c135e 10929 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
364d4831
NF
10930 break;
10931 case 0x1:
10932#if defined(TARGET_MIPS64)
10933 check_mips_64(ctx);
d75c135e 10934 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
364d4831
NF
10935#else
10936 generate_exception(ctx, EXCP_RI);
10937#endif
10938 break;
10939 case 0x2:
d75c135e 10940 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
364d4831
NF
10941 break;
10942 case 0x3:
d75c135e 10943 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
364d4831
NF
10944 break;
10945 }
10946 break;
10947#if defined(TARGET_MIPS64)
10948 case M16_OPC_LD:
10949 check_mips_64(ctx);
d75c135e 10950 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
364d4831
NF
10951 break;
10952#endif
10953 case M16_OPC_RRIA:
10954 {
10955 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
10956
10957 if ((ctx->opcode >> 4) & 1) {
10958#if defined(TARGET_MIPS64)
10959 check_mips_64(ctx);
d75c135e 10960 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
364d4831
NF
10961#else
10962 generate_exception(ctx, EXCP_RI);
10963#endif
10964 } else {
d75c135e 10965 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
364d4831
NF
10966 }
10967 }
10968 break;
10969 case M16_OPC_ADDIU8:
10970 {
10971 int16_t imm = (int8_t) ctx->opcode;
10972
d75c135e 10973 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
364d4831
NF
10974 }
10975 break;
10976 case M16_OPC_SLTI:
10977 {
10978 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 10979 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
10980 }
10981 break;
10982 case M16_OPC_SLTIU:
10983 {
10984 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 10985 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
10986 }
10987 break;
10988 case M16_OPC_I8:
10989 {
10990 int reg32;
10991
10992 funct = (ctx->opcode >> 8) & 0x7;
10993 switch (funct) {
10994 case I8_BTEQZ:
10995 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
b231c103 10996 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
10997 break;
10998 case I8_BTNEZ:
10999 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
b231c103 11000 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
11001 break;
11002 case I8_SWRASP:
5c13fdfd 11003 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
364d4831
NF
11004 break;
11005 case I8_ADJSP:
d75c135e 11006 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
364d4831
NF
11007 ((int8_t)ctx->opcode) << 3);
11008 break;
11009 case I8_SVRS:
11010 {
11011 int do_ra = ctx->opcode & (1 << 6);
11012 int do_s0 = ctx->opcode & (1 << 5);
11013 int do_s1 = ctx->opcode & (1 << 4);
11014 int framesize = ctx->opcode & 0xf;
11015
11016 if (framesize == 0) {
11017 framesize = 128;
11018 } else {
11019 framesize = framesize << 3;
11020 }
11021
11022 if (ctx->opcode & (1 << 7)) {
11023 gen_mips16_save(ctx, 0, 0,
11024 do_ra, do_s0, do_s1, framesize);
11025 } else {
11026 gen_mips16_restore(ctx, 0, 0,
11027 do_ra, do_s0, do_s1, framesize);
11028 }
11029 }
11030 break;
11031 case I8_MOV32R:
11032 {
11033 int rz = xlat(ctx->opcode & 0x7);
11034
11035 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
11036 ((ctx->opcode >> 5) & 0x7);
d75c135e 11037 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
364d4831
NF
11038 }
11039 break;
11040 case I8_MOVR32:
11041 reg32 = ctx->opcode & 0x1f;
d75c135e 11042 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
364d4831
NF
11043 break;
11044 default:
11045 generate_exception(ctx, EXCP_RI);
11046 break;
11047 }
11048 }
11049 break;
11050 case M16_OPC_LI:
11051 {
11052 int16_t imm = (uint8_t) ctx->opcode;
11053
d75c135e 11054 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
364d4831
NF
11055 }
11056 break;
11057 case M16_OPC_CMPI:
11058 {
11059 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 11060 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
364d4831
NF
11061 }
11062 break;
11063#if defined(TARGET_MIPS64)
11064 case M16_OPC_SD:
11065 check_mips_64(ctx);
5c13fdfd 11066 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
364d4831
NF
11067 break;
11068#endif
11069 case M16_OPC_LB:
d75c135e 11070 gen_ld(ctx, OPC_LB, ry, rx, offset);
364d4831
NF
11071 break;
11072 case M16_OPC_LH:
d75c135e 11073 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
364d4831
NF
11074 break;
11075 case M16_OPC_LWSP:
d75c135e 11076 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
11077 break;
11078 case M16_OPC_LW:
d75c135e 11079 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
364d4831
NF
11080 break;
11081 case M16_OPC_LBU:
d75c135e 11082 gen_ld(ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
11083 break;
11084 case M16_OPC_LHU:
d75c135e 11085 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
364d4831
NF
11086 break;
11087 case M16_OPC_LWPC:
d75c135e 11088 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
11089 break;
11090#if defined (TARGET_MIPS64)
11091 case M16_OPC_LWU:
11092 check_mips_64(ctx);
d75c135e 11093 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
364d4831
NF
11094 break;
11095#endif
11096 case M16_OPC_SB:
5c13fdfd 11097 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
11098 break;
11099 case M16_OPC_SH:
5c13fdfd 11100 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
364d4831
NF
11101 break;
11102 case M16_OPC_SWSP:
5c13fdfd 11103 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
11104 break;
11105 case M16_OPC_SW:
5c13fdfd 11106 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
364d4831
NF
11107 break;
11108 case M16_OPC_RRR:
11109 {
11110 int rz = xlat((ctx->opcode >> 2) & 0x7);
11111 int mips32_op;
11112
11113 switch (ctx->opcode & 0x3) {
11114 case RRR_ADDU:
11115 mips32_op = OPC_ADDU;
11116 break;
11117 case RRR_SUBU:
11118 mips32_op = OPC_SUBU;
11119 break;
11120#if defined(TARGET_MIPS64)
11121 case RRR_DADDU:
11122 mips32_op = OPC_DADDU;
11123 check_mips_64(ctx);
11124 break;
11125 case RRR_DSUBU:
11126 mips32_op = OPC_DSUBU;
11127 check_mips_64(ctx);
11128 break;
11129#endif
11130 default:
11131 generate_exception(ctx, EXCP_RI);
11132 goto done;
11133 }
11134
d75c135e 11135 gen_arith(ctx, mips32_op, rz, rx, ry);
364d4831
NF
11136 done:
11137 ;
11138 }
11139 break;
11140 case M16_OPC_RR:
11141 switch (op1) {
11142 case RR_JR:
11143 {
11144 int nd = (ctx->opcode >> 7) & 0x1;
11145 int link = (ctx->opcode >> 6) & 0x1;
11146 int ra = (ctx->opcode >> 5) & 0x1;
11147
11148 if (link) {
b231c103 11149 op = OPC_JALR;
364d4831
NF
11150 } else {
11151 op = OPC_JR;
11152 }
11153
b231c103
YK
11154 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
11155 (nd ? 0 : 2));
364d4831
NF
11156 }
11157 break;
11158 case RR_SDBBP:
11159 /* XXX: not clear which exception should be raised
11160 * when in debug mode...
11161 */
d75c135e 11162 check_insn(ctx, ISA_MIPS32);
364d4831
NF
11163 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11164 generate_exception(ctx, EXCP_DBp);
11165 } else {
11166 generate_exception(ctx, EXCP_DBp);
11167 }
11168 break;
11169 case RR_SLT:
d75c135e 11170 gen_slt(ctx, OPC_SLT, 24, rx, ry);
364d4831
NF
11171 break;
11172 case RR_SLTU:
d75c135e 11173 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
364d4831
NF
11174 break;
11175 case RR_BREAK:
11176 generate_exception(ctx, EXCP_BREAK);
11177 break;
11178 case RR_SLLV:
d75c135e 11179 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
364d4831
NF
11180 break;
11181 case RR_SRLV:
d75c135e 11182 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
364d4831
NF
11183 break;
11184 case RR_SRAV:
d75c135e 11185 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
364d4831
NF
11186 break;
11187#if defined (TARGET_MIPS64)
11188 case RR_DSRL:
11189 check_mips_64(ctx);
d75c135e 11190 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
364d4831
NF
11191 break;
11192#endif
11193 case RR_CMP:
d75c135e 11194 gen_logic(ctx, OPC_XOR, 24, rx, ry);
364d4831
NF
11195 break;
11196 case RR_NEG:
d75c135e 11197 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
364d4831
NF
11198 break;
11199 case RR_AND:
d75c135e 11200 gen_logic(ctx, OPC_AND, rx, rx, ry);
364d4831
NF
11201 break;
11202 case RR_OR:
d75c135e 11203 gen_logic(ctx, OPC_OR, rx, rx, ry);
364d4831
NF
11204 break;
11205 case RR_XOR:
d75c135e 11206 gen_logic(ctx, OPC_XOR, rx, rx, ry);
364d4831
NF
11207 break;
11208 case RR_NOT:
d75c135e 11209 gen_logic(ctx, OPC_NOR, rx, ry, 0);
364d4831
NF
11210 break;
11211 case RR_MFHI:
26135ead 11212 gen_HILO(ctx, OPC_MFHI, 0, rx);
364d4831
NF
11213 break;
11214 case RR_CNVT:
11215 switch (cnvt_op) {
11216 case RR_RY_CNVT_ZEB:
11217 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11218 break;
11219 case RR_RY_CNVT_ZEH:
11220 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11221 break;
11222 case RR_RY_CNVT_SEB:
11223 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11224 break;
11225 case RR_RY_CNVT_SEH:
11226 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11227 break;
11228#if defined (TARGET_MIPS64)
11229 case RR_RY_CNVT_ZEW:
11230 check_mips_64(ctx);
11231 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11232 break;
11233 case RR_RY_CNVT_SEW:
11234 check_mips_64(ctx);
11235 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11236 break;
11237#endif
11238 default:
11239 generate_exception(ctx, EXCP_RI);
11240 break;
11241 }
11242 break;
11243 case RR_MFLO:
26135ead 11244 gen_HILO(ctx, OPC_MFLO, 0, rx);
364d4831
NF
11245 break;
11246#if defined (TARGET_MIPS64)
11247 case RR_DSRA:
11248 check_mips_64(ctx);
d75c135e 11249 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
364d4831
NF
11250 break;
11251 case RR_DSLLV:
11252 check_mips_64(ctx);
d75c135e 11253 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
364d4831
NF
11254 break;
11255 case RR_DSRLV:
11256 check_mips_64(ctx);
d75c135e 11257 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
364d4831
NF
11258 break;
11259 case RR_DSRAV:
11260 check_mips_64(ctx);
d75c135e 11261 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
364d4831
NF
11262 break;
11263#endif
11264 case RR_MULT:
26135ead 11265 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
364d4831
NF
11266 break;
11267 case RR_MULTU:
26135ead 11268 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
364d4831
NF
11269 break;
11270 case RR_DIV:
26135ead 11271 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
364d4831
NF
11272 break;
11273 case RR_DIVU:
26135ead 11274 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
364d4831
NF
11275 break;
11276#if defined (TARGET_MIPS64)
11277 case RR_DMULT:
11278 check_mips_64(ctx);
26135ead 11279 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
364d4831
NF
11280 break;
11281 case RR_DMULTU:
11282 check_mips_64(ctx);
26135ead 11283 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
364d4831
NF
11284 break;
11285 case RR_DDIV:
11286 check_mips_64(ctx);
26135ead 11287 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
364d4831
NF
11288 break;
11289 case RR_DDIVU:
11290 check_mips_64(ctx);
26135ead 11291 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
364d4831
NF
11292 break;
11293#endif
11294 default:
11295 generate_exception(ctx, EXCP_RI);
11296 break;
11297 }
11298 break;
11299 case M16_OPC_EXTEND:
240ce26a 11300 decode_extended_mips16_opc(env, ctx);
364d4831
NF
11301 n_bytes = 4;
11302 break;
11303#if defined(TARGET_MIPS64)
11304 case M16_OPC_I64:
11305 funct = (ctx->opcode >> 8) & 0x7;
d75c135e 11306 decode_i64_mips16(ctx, ry, funct, offset, 0);
364d4831
NF
11307 break;
11308#endif
11309 default:
11310 generate_exception(ctx, EXCP_RI);
11311 break;
11312 }
11313
11314 return n_bytes;
11315}
11316
211da992 11317/* microMIPS extension to MIPS32/MIPS64 */
6af0bf9c 11318
211da992
CWR
11319/*
11320 * microMIPS32/microMIPS64 major opcodes
11321 *
11322 * 1. MIPS Architecture for Programmers Volume II-B:
11323 * The microMIPS32 Instruction Set (Revision 3.05)
11324 *
11325 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
11326 *
11327 * 2. MIPS Architecture For Programmers Volume II-A:
11328 * The MIPS64 Instruction Set (Revision 3.51)
11329 */
6af0bf9c 11330
3c824109
NF
11331enum {
11332 POOL32A = 0x00,
11333 POOL16A = 0x01,
11334 LBU16 = 0x02,
11335 MOVE16 = 0x03,
11336 ADDI32 = 0x04,
11337 LBU32 = 0x05,
11338 SB32 = 0x06,
11339 LB32 = 0x07,
11340
11341 POOL32B = 0x08,
11342 POOL16B = 0x09,
11343 LHU16 = 0x0a,
11344 ANDI16 = 0x0b,
11345 ADDIU32 = 0x0c,
11346 LHU32 = 0x0d,
11347 SH32 = 0x0e,
11348 LH32 = 0x0f,
11349
11350 POOL32I = 0x10,
11351 POOL16C = 0x11,
11352 LWSP16 = 0x12,
11353 POOL16D = 0x13,
11354 ORI32 = 0x14,
11355 POOL32F = 0x15,
211da992
CWR
11356 POOL32S = 0x16, /* MIPS64 */
11357 DADDIU32 = 0x17, /* MIPS64 */
3c824109 11358
211da992 11359 /* 0x1f is reserved */
3c824109
NF
11360 POOL32C = 0x18,
11361 LWGP16 = 0x19,
11362 LW16 = 0x1a,
11363 POOL16E = 0x1b,
11364 XORI32 = 0x1c,
11365 JALS32 = 0x1d,
11366 ADDIUPC = 0x1e,
3c824109
NF
11367
11368 /* 0x20 is reserved */
11369 RES_20 = 0x20,
11370 POOL16F = 0x21,
11371 SB16 = 0x22,
11372 BEQZ16 = 0x23,
11373 SLTI32 = 0x24,
11374 BEQ32 = 0x25,
11375 SWC132 = 0x26,
11376 LWC132 = 0x27,
11377
11378 /* 0x28 and 0x29 are reserved */
11379 RES_28 = 0x28,
11380 RES_29 = 0x29,
11381 SH16 = 0x2a,
11382 BNEZ16 = 0x2b,
11383 SLTIU32 = 0x2c,
11384 BNE32 = 0x2d,
11385 SDC132 = 0x2e,
11386 LDC132 = 0x2f,
11387
11388 /* 0x30 and 0x31 are reserved */
11389 RES_30 = 0x30,
11390 RES_31 = 0x31,
11391 SWSP16 = 0x32,
11392 B16 = 0x33,
11393 ANDI32 = 0x34,
11394 J32 = 0x35,
211da992
CWR
11395 SD32 = 0x36, /* MIPS64 */
11396 LD32 = 0x37, /* MIPS64 */
3c824109
NF
11397
11398 /* 0x38 and 0x39 are reserved */
11399 RES_38 = 0x38,
11400 RES_39 = 0x39,
11401 SW16 = 0x3a,
11402 LI16 = 0x3b,
11403 JALX32 = 0x3c,
11404 JAL32 = 0x3d,
11405 SW32 = 0x3e,
11406 LW32 = 0x3f
11407};
11408
11409/* POOL32A encoding of minor opcode field */
11410
11411enum {
11412 /* These opcodes are distinguished only by bits 9..6; those bits are
11413 * what are recorded below. */
11414 SLL32 = 0x0,
11415 SRL32 = 0x1,
11416 SRA = 0x2,
11417 ROTR = 0x3,
11418
11419 SLLV = 0x0,
11420 SRLV = 0x1,
11421 SRAV = 0x2,
11422 ROTRV = 0x3,
11423 ADD = 0x4,
11424 ADDU32 = 0x5,
11425 SUB = 0x6,
11426 SUBU32 = 0x7,
11427 MUL = 0x8,
11428 AND = 0x9,
11429 OR32 = 0xa,
11430 NOR = 0xb,
11431 XOR32 = 0xc,
11432 SLT = 0xd,
11433 SLTU = 0xe,
11434
11435 MOVN = 0x0,
11436 MOVZ = 0x1,
11437 LWXS = 0x4,
11438
11439 /* The following can be distinguished by their lower 6 bits. */
11440 INS = 0x0c,
11441 EXT = 0x2c,
11442 POOL32AXF = 0x3c
11443};
11444
11445/* POOL32AXF encoding of minor opcode field extension */
11446
d132c79f
CWR
11447/*
11448 * 1. MIPS Architecture for Programmers Volume II-B:
11449 * The microMIPS32 Instruction Set (Revision 3.05)
11450 *
11451 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
11452 *
11453 * 2. MIPS Architecture for Programmers VolumeIV-e:
11454 * The MIPS DSP Application-Specific Extension
11455 * to the microMIPS32 Architecture (Revision 2.34)
11456 *
11457 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
11458 */
11459
3c824109
NF
11460enum {
11461 /* bits 11..6 */
11462 TEQ = 0x00,
11463 TGE = 0x08,
11464 TGEU = 0x10,
11465 TLT = 0x20,
11466 TLTU = 0x28,
11467 TNE = 0x30,
11468
11469 MFC0 = 0x03,
11470 MTC0 = 0x0b,
11471
d132c79f
CWR
11472 /* begin of microMIPS32 DSP */
11473
3c824109
NF
11474 /* bits 13..12 for 0x01 */
11475 MFHI_ACC = 0x0,
11476 MFLO_ACC = 0x1,
11477 MTHI_ACC = 0x2,
11478 MTLO_ACC = 0x3,
11479
11480 /* bits 13..12 for 0x2a */
11481 MADD_ACC = 0x0,
11482 MADDU_ACC = 0x1,
11483 MSUB_ACC = 0x2,
11484 MSUBU_ACC = 0x3,
11485
11486 /* bits 13..12 for 0x32 */
11487 MULT_ACC = 0x0,
6801038b 11488 MULTU_ACC = 0x1,
3c824109 11489
d132c79f
CWR
11490 /* end of microMIPS32 DSP */
11491
3c824109
NF
11492 /* bits 15..12 for 0x2c */
11493 SEB = 0x2,
11494 SEH = 0x3,
11495 CLO = 0x4,
11496 CLZ = 0x5,
11497 RDHWR = 0x6,
11498 WSBH = 0x7,
11499 MULT = 0x8,
11500 MULTU = 0x9,
11501 DIV = 0xa,
11502 DIVU = 0xb,
11503 MADD = 0xc,
11504 MADDU = 0xd,
11505 MSUB = 0xe,
11506 MSUBU = 0xf,
11507
11508 /* bits 15..12 for 0x34 */
11509 MFC2 = 0x4,
11510 MTC2 = 0x5,
11511 MFHC2 = 0x8,
11512 MTHC2 = 0x9,
11513 CFC2 = 0xc,
11514 CTC2 = 0xd,
11515
11516 /* bits 15..12 for 0x3c */
11517 JALR = 0x0,
11518 JR = 0x0, /* alias */
11519 JALR_HB = 0x1,
11520 JALRS = 0x4,
11521 JALRS_HB = 0x5,
11522
11523 /* bits 15..12 for 0x05 */
11524 RDPGPR = 0xe,
11525 WRPGPR = 0xf,
11526
11527 /* bits 15..12 for 0x0d */
11528 TLBP = 0x0,
11529 TLBR = 0x1,
11530 TLBWI = 0x2,
11531 TLBWR = 0x3,
11532 WAIT = 0x9,
11533 IRET = 0xd,
11534 DERET = 0xe,
11535 ERET = 0xf,
11536
11537 /* bits 15..12 for 0x15 */
11538 DMT = 0x0,
11539 DVPE = 0x1,
11540 EMT = 0x2,
11541 EVPE = 0x3,
11542
11543 /* bits 15..12 for 0x1d */
11544 DI = 0x4,
11545 EI = 0x5,
11546
11547 /* bits 15..12 for 0x2d */
11548 SYNC = 0x6,
11549 SYSCALL = 0x8,
11550 SDBBP = 0xd,
11551
11552 /* bits 15..12 for 0x35 */
11553 MFHI32 = 0x0,
11554 MFLO32 = 0x1,
11555 MTHI32 = 0x2,
11556 MTLO32 = 0x3,
11557};
11558
11559/* POOL32B encoding of minor opcode field (bits 15..12) */
11560
11561enum {
11562 LWC2 = 0x0,
11563 LWP = 0x1,
11564 LDP = 0x4,
11565 LWM32 = 0x5,
11566 CACHE = 0x6,
11567 LDM = 0x7,
11568 SWC2 = 0x8,
11569 SWP = 0x9,
11570 SDP = 0xc,
11571 SWM32 = 0xd,
11572 SDM = 0xf
11573};
11574
11575/* POOL32C encoding of minor opcode field (bits 15..12) */
11576
11577enum {
11578 LWL = 0x0,
11579 SWL = 0x8,
11580 LWR = 0x1,
11581 SWR = 0x9,
11582 PREF = 0x2,
11583 /* 0xa is reserved */
11584 LL = 0x3,
11585 SC = 0xb,
11586 LDL = 0x4,
11587 SDL = 0xc,
11588 LDR = 0x5,
11589 SDR = 0xd,
11590 /* 0x6 is reserved */
11591 LWU = 0xe,
11592 LLD = 0x7,
11593 SCD = 0xf
11594};
11595
11596/* POOL32F encoding of minor opcode field (bits 5..0) */
11597
11598enum {
11599 /* These are the bit 7..6 values */
11600 ADD_FMT = 0x0,
11601 MOVN_FMT = 0x0,
11602
11603 SUB_FMT = 0x1,
11604 MOVZ_FMT = 0x1,
11605
11606 MUL_FMT = 0x2,
11607
11608 DIV_FMT = 0x3,
11609
11610 /* These are the bit 8..6 values */
11611 RSQRT2_FMT = 0x0,
11612 MOVF_FMT = 0x0,
11613
11614 LWXC1 = 0x1,
11615 MOVT_FMT = 0x1,
11616
11617 PLL_PS = 0x2,
11618 SWXC1 = 0x2,
11619
11620 PLU_PS = 0x3,
11621 LDXC1 = 0x3,
11622
11623 PUL_PS = 0x4,
11624 SDXC1 = 0x4,
11625 RECIP2_FMT = 0x4,
11626
11627 PUU_PS = 0x5,
11628 LUXC1 = 0x5,
11629
11630 CVT_PS_S = 0x6,
11631 SUXC1 = 0x6,
11632 ADDR_PS = 0x6,
11633 PREFX = 0x6,
11634
11635 MULR_PS = 0x7,
11636
11637 MADD_S = 0x01,
11638 MADD_D = 0x09,
11639 MADD_PS = 0x11,
11640 ALNV_PS = 0x19,
11641 MSUB_S = 0x21,
11642 MSUB_D = 0x29,
11643 MSUB_PS = 0x31,
11644
11645 NMADD_S = 0x02,
11646 NMADD_D = 0x0a,
11647 NMADD_PS = 0x12,
11648 NMSUB_S = 0x22,
11649 NMSUB_D = 0x2a,
11650 NMSUB_PS = 0x32,
11651
11652 POOL32FXF = 0x3b,
11653
11654 CABS_COND_FMT = 0x1c, /* MIPS3D */
11655 C_COND_FMT = 0x3c
11656};
11657
11658/* POOL32Fxf encoding of minor opcode extension field */
11659
11660enum {
11661 CVT_L = 0x04,
11662 RSQRT_FMT = 0x08,
11663 FLOOR_L = 0x0c,
11664 CVT_PW_PS = 0x1c,
11665 CVT_W = 0x24,
11666 SQRT_FMT = 0x28,
11667 FLOOR_W = 0x2c,
11668 CVT_PS_PW = 0x3c,
11669 CFC1 = 0x40,
11670 RECIP_FMT = 0x48,
11671 CEIL_L = 0x4c,
11672 CTC1 = 0x60,
11673 CEIL_W = 0x6c,
11674 MFC1 = 0x80,
11675 CVT_S_PL = 0x84,
11676 TRUNC_L = 0x8c,
11677 MTC1 = 0xa0,
11678 CVT_S_PU = 0xa4,
11679 TRUNC_W = 0xac,
11680 MFHC1 = 0xc0,
11681 ROUND_L = 0xcc,
11682 MTHC1 = 0xe0,
11683 ROUND_W = 0xec,
11684
11685 MOV_FMT = 0x01,
11686 MOVF = 0x05,
11687 ABS_FMT = 0x0d,
11688 RSQRT1_FMT = 0x1d,
11689 MOVT = 0x25,
11690 NEG_FMT = 0x2d,
11691 CVT_D = 0x4d,
11692 RECIP1_FMT = 0x5d,
11693 CVT_S = 0x6d
11694};
11695
11696/* POOL32I encoding of minor opcode field (bits 25..21) */
11697
11698enum {
11699 BLTZ = 0x00,
11700 BLTZAL = 0x01,
11701 BGEZ = 0x02,
11702 BGEZAL = 0x03,
11703 BLEZ = 0x04,
11704 BNEZC = 0x05,
11705 BGTZ = 0x06,
11706 BEQZC = 0x07,
11707 TLTI = 0x08,
11708 TGEI = 0x09,
11709 TLTIU = 0x0a,
11710 TGEIU = 0x0b,
11711 TNEI = 0x0c,
11712 LUI = 0x0d,
11713 TEQI = 0x0e,
11714 SYNCI = 0x10,
11715 BLTZALS = 0x11,
11716 BGEZALS = 0x13,
11717 BC2F = 0x14,
11718 BC2T = 0x15,
11719 BPOSGE64 = 0x1a,
11720 BPOSGE32 = 0x1b,
11721 /* These overlap and are distinguished by bit16 of the instruction */
11722 BC1F = 0x1c,
11723 BC1T = 0x1d,
11724 BC1ANY2F = 0x1c,
11725 BC1ANY2T = 0x1d,
11726 BC1ANY4F = 0x1e,
11727 BC1ANY4T = 0x1f
11728};
11729
11730/* POOL16A encoding of minor opcode field */
11731
11732enum {
11733 ADDU16 = 0x0,
11734 SUBU16 = 0x1
11735};
11736
11737/* POOL16B encoding of minor opcode field */
11738
11739enum {
11740 SLL16 = 0x0,
11741 SRL16 = 0x1
11742};
11743
11744/* POOL16C encoding of minor opcode field */
11745
11746enum {
11747 NOT16 = 0x00,
11748 XOR16 = 0x04,
11749 AND16 = 0x08,
11750 OR16 = 0x0c,
11751 LWM16 = 0x10,
11752 SWM16 = 0x14,
11753 JR16 = 0x18,
11754 JRC16 = 0x1a,
11755 JALR16 = 0x1c,
11756 JALR16S = 0x1e,
11757 MFHI16 = 0x20,
11758 MFLO16 = 0x24,
11759 BREAK16 = 0x28,
11760 SDBBP16 = 0x2c,
11761 JRADDIUSP = 0x30
11762};
11763
11764/* POOL16D encoding of minor opcode field */
11765
11766enum {
11767 ADDIUS5 = 0x0,
11768 ADDIUSP = 0x1
11769};
11770
11771/* POOL16E encoding of minor opcode field */
11772
11773enum {
11774 ADDIUR2 = 0x0,
11775 ADDIUR1SP = 0x1
11776};
11777
11778static int mmreg (int r)
11779{
11780 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
11781
11782 return map[r];
11783}
11784
11785/* Used for 16-bit store instructions. */
11786static int mmreg2 (int r)
11787{
11788 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
11789
11790 return map[r];
11791}
11792
11793#define uMIPS_RD(op) ((op >> 7) & 0x7)
11794#define uMIPS_RS(op) ((op >> 4) & 0x7)
11795#define uMIPS_RS2(op) uMIPS_RS(op)
11796#define uMIPS_RS1(op) ((op >> 1) & 0x7)
11797#define uMIPS_RD5(op) ((op >> 5) & 0x1f)
11798#define uMIPS_RS5(op) (op & 0x1f)
11799
11800/* Signed immediate */
11801#define SIMM(op, start, width) \
11802 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
11803 << (32-width)) \
11804 >> (32-width))
11805/* Zero-extended immediate */
11806#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
11807
d75c135e 11808static void gen_addiur1sp(DisasContext *ctx)
3c824109
NF
11809{
11810 int rd = mmreg(uMIPS_RD(ctx->opcode));
11811
d75c135e 11812 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
3c824109
NF
11813}
11814
d75c135e 11815static void gen_addiur2(DisasContext *ctx)
3c824109
NF
11816{
11817 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
11818 int rd = mmreg(uMIPS_RD(ctx->opcode));
11819 int rs = mmreg(uMIPS_RS(ctx->opcode));
11820
d75c135e 11821 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
3c824109
NF
11822}
11823
d75c135e 11824static void gen_addiusp(DisasContext *ctx)
3c824109
NF
11825{
11826 int encoded = ZIMM(ctx->opcode, 1, 9);
11827 int decoded;
11828
11829 if (encoded <= 1) {
11830 decoded = 256 + encoded;
11831 } else if (encoded <= 255) {
11832 decoded = encoded;
11833 } else if (encoded <= 509) {
11834 decoded = encoded - 512;
11835 } else {
11836 decoded = encoded - 768;
11837 }
11838
d75c135e 11839 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
3c824109
NF
11840}
11841
d75c135e 11842static void gen_addius5(DisasContext *ctx)
3c824109
NF
11843{
11844 int imm = SIMM(ctx->opcode, 1, 4);
11845 int rd = (ctx->opcode >> 5) & 0x1f;
11846
d75c135e 11847 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
3c824109
NF
11848}
11849
d75c135e 11850static void gen_andi16(DisasContext *ctx)
3c824109
NF
11851{
11852 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
11853 31, 32, 63, 64, 255, 32768, 65535 };
11854 int rd = mmreg(uMIPS_RD(ctx->opcode));
11855 int rs = mmreg(uMIPS_RS(ctx->opcode));
11856 int encoded = ZIMM(ctx->opcode, 0, 4);
11857
d75c135e 11858 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
3c824109
NF
11859}
11860
11861static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
11862 int base, int16_t offset)
11863{
e1050a76 11864 const char *opn = "ldst_multiple";
3c824109
NF
11865 TCGv t0, t1;
11866 TCGv_i32 t2;
11867
11868 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11869 generate_exception(ctx, EXCP_RI);
11870 return;
11871 }
11872
11873 t0 = tcg_temp_new();
11874
11875 gen_base_offset_addr(ctx, t0, base, offset);
11876
11877 t1 = tcg_const_tl(reglist);
11878 t2 = tcg_const_i32(ctx->mem_idx);
6af0bf9c 11879
3c824109
NF
11880 save_cpu_state(ctx, 1);
11881 switch (opc) {
11882 case LWM32:
895c2d04 11883 gen_helper_lwm(cpu_env, t0, t1, t2);
e1050a76 11884 opn = "lwm";
3c824109
NF
11885 break;
11886 case SWM32:
895c2d04 11887 gen_helper_swm(cpu_env, t0, t1, t2);
e1050a76 11888 opn = "swm";
3c824109
NF
11889 break;
11890#ifdef TARGET_MIPS64
11891 case LDM:
895c2d04 11892 gen_helper_ldm(cpu_env, t0, t1, t2);
e1050a76 11893 opn = "ldm";
3c824109
NF
11894 break;
11895 case SDM:
895c2d04 11896 gen_helper_sdm(cpu_env, t0, t1, t2);
e1050a76 11897 opn = "sdm";
3c824109 11898 break;
6af0bf9c 11899#endif
3c824109 11900 }
e1050a76 11901 (void)opn;
3c824109
NF
11902 MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
11903 tcg_temp_free(t0);
33087598 11904 tcg_temp_free(t1);
3c824109
NF
11905 tcg_temp_free_i32(t2);
11906}
6af0bf9c 11907
3c824109 11908
240ce26a 11909static void gen_pool16c_insn(DisasContext *ctx)
6af0bf9c 11910{
3c824109
NF
11911 int rd = mmreg((ctx->opcode >> 3) & 0x7);
11912 int rs = mmreg(ctx->opcode & 0x7);
6af0bf9c 11913
3c824109
NF
11914 switch (((ctx->opcode) >> 4) & 0x3f) {
11915 case NOT16 + 0:
11916 case NOT16 + 1:
11917 case NOT16 + 2:
11918 case NOT16 + 3:
d75c135e 11919 gen_logic(ctx, OPC_NOR, rd, rs, 0);
3c824109
NF
11920 break;
11921 case XOR16 + 0:
11922 case XOR16 + 1:
11923 case XOR16 + 2:
11924 case XOR16 + 3:
d75c135e 11925 gen_logic(ctx, OPC_XOR, rd, rd, rs);
3c824109
NF
11926 break;
11927 case AND16 + 0:
11928 case AND16 + 1:
11929 case AND16 + 2:
11930 case AND16 + 3:
d75c135e 11931 gen_logic(ctx, OPC_AND, rd, rd, rs);
3c824109
NF
11932 break;
11933 case OR16 + 0:
11934 case OR16 + 1:
11935 case OR16 + 2:
11936 case OR16 + 3:
d75c135e 11937 gen_logic(ctx, OPC_OR, rd, rd, rs);
3c824109
NF
11938 break;
11939 case LWM16 + 0:
11940 case LWM16 + 1:
11941 case LWM16 + 2:
11942 case LWM16 + 3:
11943 {
11944 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
11945 int offset = ZIMM(ctx->opcode, 0, 4);
11946
11947 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
11948 29, offset << 2);
11949 }
11950 break;
11951 case SWM16 + 0:
11952 case SWM16 + 1:
11953 case SWM16 + 2:
11954 case SWM16 + 3:
11955 {
11956 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
11957 int offset = ZIMM(ctx->opcode, 0, 4);
11958
11959 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
11960 29, offset << 2);
11961 }
11962 break;
11963 case JR16 + 0:
11964 case JR16 + 1:
11965 {
11966 int reg = ctx->opcode & 0x1f;
11967
b231c103 11968 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
3c824109 11969 }
3c824109
NF
11970 break;
11971 case JRC16 + 0:
11972 case JRC16 + 1:
11973 {
11974 int reg = ctx->opcode & 0x1f;
b231c103 11975 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
3c824109
NF
11976 /* Let normal delay slot handling in our caller take us
11977 to the branch target. */
11978 }
11979 break;
11980 case JALR16 + 0:
11981 case JALR16 + 1:
b231c103
YK
11982 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
11983 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
11984 break;
3c824109
NF
11985 case JALR16S + 0:
11986 case JALR16S + 1:
b231c103
YK
11987 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
11988 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
11989 break;
11990 case MFHI16 + 0:
11991 case MFHI16 + 1:
26135ead 11992 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
3c824109
NF
11993 break;
11994 case MFLO16 + 0:
11995 case MFLO16 + 1:
26135ead 11996 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
3c824109
NF
11997 break;
11998 case BREAK16:
11999 generate_exception(ctx, EXCP_BREAK);
12000 break;
12001 case SDBBP16:
12002 /* XXX: not clear which exception should be raised
12003 * when in debug mode...
12004 */
d75c135e 12005 check_insn(ctx, ISA_MIPS32);
3c824109
NF
12006 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
12007 generate_exception(ctx, EXCP_DBp);
12008 } else {
12009 generate_exception(ctx, EXCP_DBp);
12010 }
12011 break;
12012 case JRADDIUSP + 0:
12013 case JRADDIUSP + 1:
12014 {
12015 int imm = ZIMM(ctx->opcode, 0, 5);
b231c103 12016 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
d75c135e 12017 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
3c824109
NF
12018 /* Let normal delay slot handling in our caller take us
12019 to the branch target. */
12020 }
12021 break;
12022 default:
12023 generate_exception(ctx, EXCP_RI);
12024 break;
12025 }
12026}
12027
12028static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
12029{
12030 TCGv t0 = tcg_temp_new();
12031 TCGv t1 = tcg_temp_new();
12032
12033 gen_load_gpr(t0, base);
12034
12035 if (index != 0) {
12036 gen_load_gpr(t1, index);
12037 tcg_gen_shli_tl(t1, t1, 2);
12038 gen_op_addr_add(ctx, t0, t1, t0);
12039 }
12040
5f68f5ae 12041 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109
NF
12042 gen_store_gpr(t1, rd);
12043
12044 tcg_temp_free(t0);
12045 tcg_temp_free(t1);
12046}
12047
12048static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
12049 int base, int16_t offset)
12050{
12051 const char *opn = "ldst_pair";
12052 TCGv t0, t1;
12053
36c6711b 12054 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
3c824109 12055 generate_exception(ctx, EXCP_RI);
d796321b
FB
12056 return;
12057 }
12058
3c824109
NF
12059 t0 = tcg_temp_new();
12060 t1 = tcg_temp_new();
8e9ade68 12061
3c824109
NF
12062 gen_base_offset_addr(ctx, t0, base, offset);
12063
12064 switch (opc) {
12065 case LWP:
36c6711b
EJ
12066 if (rd == base) {
12067 generate_exception(ctx, EXCP_RI);
12068 return;
12069 }
5f68f5ae 12070 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109
NF
12071 gen_store_gpr(t1, rd);
12072 tcg_gen_movi_tl(t1, 4);
12073 gen_op_addr_add(ctx, t0, t0, t1);
5f68f5ae 12074 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109
NF
12075 gen_store_gpr(t1, rd+1);
12076 opn = "lwp";
12077 break;
12078 case SWP:
3c824109 12079 gen_load_gpr(t1, rd);
5f68f5ae 12080 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
3c824109
NF
12081 tcg_gen_movi_tl(t1, 4);
12082 gen_op_addr_add(ctx, t0, t0, t1);
12083 gen_load_gpr(t1, rd+1);
5f68f5ae 12084 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
3c824109
NF
12085 opn = "swp";
12086 break;
12087#ifdef TARGET_MIPS64
12088 case LDP:
36c6711b
EJ
12089 if (rd == base) {
12090 generate_exception(ctx, EXCP_RI);
12091 return;
12092 }
5f68f5ae 12093 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
12094 gen_store_gpr(t1, rd);
12095 tcg_gen_movi_tl(t1, 8);
12096 gen_op_addr_add(ctx, t0, t0, t1);
5f68f5ae 12097 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
12098 gen_store_gpr(t1, rd+1);
12099 opn = "ldp";
12100 break;
12101 case SDP:
3c824109 12102 gen_load_gpr(t1, rd);
5f68f5ae 12103 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
12104 tcg_gen_movi_tl(t1, 8);
12105 gen_op_addr_add(ctx, t0, t0, t1);
12106 gen_load_gpr(t1, rd+1);
5f68f5ae 12107 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
12108 opn = "sdp";
12109 break;
12110#endif
6af0bf9c 12111 }
2abf314d 12112 (void)opn; /* avoid a compiler warning */
3c824109
NF
12113 MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
12114 tcg_temp_free(t0);
12115 tcg_temp_free(t1);
12116}
618b0fe9 12117
240ce26a 12118static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
3c824109
NF
12119{
12120 int extension = (ctx->opcode >> 6) & 0x3f;
12121 int minor = (ctx->opcode >> 12) & 0xf;
12122 uint32_t mips32_op;
12123
12124 switch (extension) {
12125 case TEQ:
12126 mips32_op = OPC_TEQ;
12127 goto do_trap;
12128 case TGE:
12129 mips32_op = OPC_TGE;
12130 goto do_trap;
12131 case TGEU:
12132 mips32_op = OPC_TGEU;
12133 goto do_trap;
12134 case TLT:
12135 mips32_op = OPC_TLT;
12136 goto do_trap;
12137 case TLTU:
12138 mips32_op = OPC_TLTU;
12139 goto do_trap;
12140 case TNE:
12141 mips32_op = OPC_TNE;
12142 do_trap:
12143 gen_trap(ctx, mips32_op, rs, rt, -1);
12144 break;
12145#ifndef CONFIG_USER_ONLY
12146 case MFC0:
12147 case MFC0 + 32:
2e15497c 12148 check_cp0_enabled(ctx);
3c824109
NF
12149 if (rt == 0) {
12150 /* Treat as NOP. */
12151 break;
12152 }
d75c135e 12153 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
3c824109
NF
12154 break;
12155 case MTC0:
12156 case MTC0 + 32:
2e15497c 12157 check_cp0_enabled(ctx);
3c824109
NF
12158 {
12159 TCGv t0 = tcg_temp_new();
618b0fe9 12160
3c824109 12161 gen_load_gpr(t0, rt);
d75c135e 12162 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
3c824109
NF
12163 tcg_temp_free(t0);
12164 }
12165 break;
12166#endif
a1fc6246
LA
12167 case 0x2a:
12168 switch (minor & 3) {
12169 case MADD_ACC:
12170 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
12171 break;
12172 case MADDU_ACC:
12173 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
12174 break;
12175 case MSUB_ACC:
12176 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
12177 break;
12178 case MSUBU_ACC:
12179 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
12180 break;
12181 default:
12182 goto pool32axf_invalid;
12183 }
12184 break;
12185 case 0x32:
12186 switch (minor & 3) {
12187 case MULT_ACC:
12188 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
12189 break;
12190 case MULTU_ACC:
12191 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
12192 break;
12193 default:
12194 goto pool32axf_invalid;
12195 }
12196 break;
3c824109
NF
12197 case 0x2c:
12198 switch (minor) {
12199 case SEB:
12200 gen_bshfl(ctx, OPC_SEB, rs, rt);
12201 break;
12202 case SEH:
12203 gen_bshfl(ctx, OPC_SEH, rs, rt);
12204 break;
12205 case CLO:
12206 mips32_op = OPC_CLO;
12207 goto do_cl;
12208 case CLZ:
12209 mips32_op = OPC_CLZ;
12210 do_cl:
d75c135e 12211 check_insn(ctx, ISA_MIPS32);
3c824109
NF
12212 gen_cl(ctx, mips32_op, rt, rs);
12213 break;
12214 case RDHWR:
d75c135e 12215 gen_rdhwr(ctx, rt, rs);
3c824109
NF
12216 break;
12217 case WSBH:
12218 gen_bshfl(ctx, OPC_WSBH, rs, rt);
12219 break;
12220 case MULT:
12221 mips32_op = OPC_MULT;
26135ead 12222 goto do_mul;
3c824109
NF
12223 case MULTU:
12224 mips32_op = OPC_MULTU;
26135ead 12225 goto do_mul;
3c824109
NF
12226 case DIV:
12227 mips32_op = OPC_DIV;
26135ead 12228 goto do_div;
3c824109
NF
12229 case DIVU:
12230 mips32_op = OPC_DIVU;
26135ead
RS
12231 goto do_div;
12232 do_div:
12233 check_insn(ctx, ISA_MIPS32);
12234 gen_muldiv(ctx, mips32_op, 0, rs, rt);
12235 break;
3c824109
NF
12236 case MADD:
12237 mips32_op = OPC_MADD;
26135ead 12238 goto do_mul;
3c824109
NF
12239 case MADDU:
12240 mips32_op = OPC_MADDU;
26135ead 12241 goto do_mul;
3c824109
NF
12242 case MSUB:
12243 mips32_op = OPC_MSUB;
26135ead 12244 goto do_mul;
3c824109
NF
12245 case MSUBU:
12246 mips32_op = OPC_MSUBU;
26135ead 12247 do_mul:
d75c135e 12248 check_insn(ctx, ISA_MIPS32);
a1fc6246 12249 gen_muldiv(ctx, mips32_op, 0, rs, rt);
3c824109
NF
12250 break;
12251 default:
12252 goto pool32axf_invalid;
12253 }
12254 break;
12255 case 0x34:
12256 switch (minor) {
12257 case MFC2:
12258 case MTC2:
12259 case MFHC2:
12260 case MTHC2:
12261 case CFC2:
12262 case CTC2:
12263 generate_exception_err(ctx, EXCP_CpU, 2);
12264 break;
12265 default:
12266 goto pool32axf_invalid;
12267 }
12268 break;
12269 case 0x3c:
12270 switch (minor) {
12271 case JALR:
12272 case JALR_HB:
b231c103
YK
12273 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
12274 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
12275 break;
12276 case JALRS:
12277 case JALRS_HB:
b231c103
YK
12278 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
12279 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
12280 break;
12281 default:
12282 goto pool32axf_invalid;
12283 }
12284 break;
12285 case 0x05:
12286 switch (minor) {
12287 case RDPGPR:
2e15497c 12288 check_cp0_enabled(ctx);
d75c135e 12289 check_insn(ctx, ISA_MIPS32R2);
3c824109
NF
12290 gen_load_srsgpr(rt, rs);
12291 break;
12292 case WRPGPR:
2e15497c 12293 check_cp0_enabled(ctx);
d75c135e 12294 check_insn(ctx, ISA_MIPS32R2);
3c824109
NF
12295 gen_store_srsgpr(rt, rs);
12296 break;
12297 default:
12298 goto pool32axf_invalid;
12299 }
12300 break;
12301#ifndef CONFIG_USER_ONLY
12302 case 0x0d:
12303 switch (minor) {
12304 case TLBP:
12305 mips32_op = OPC_TLBP;
12306 goto do_cp0;
12307 case TLBR:
12308 mips32_op = OPC_TLBR;
12309 goto do_cp0;
12310 case TLBWI:
12311 mips32_op = OPC_TLBWI;
12312 goto do_cp0;
12313 case TLBWR:
12314 mips32_op = OPC_TLBWR;
12315 goto do_cp0;
12316 case WAIT:
12317 mips32_op = OPC_WAIT;
12318 goto do_cp0;
12319 case DERET:
12320 mips32_op = OPC_DERET;
12321 goto do_cp0;
12322 case ERET:
12323 mips32_op = OPC_ERET;
12324 do_cp0:
12325 gen_cp0(env, ctx, mips32_op, rt, rs);
12326 break;
12327 default:
12328 goto pool32axf_invalid;
12329 }
12330 break;
12331 case 0x1d:
12332 switch (minor) {
12333 case DI:
2e15497c 12334 check_cp0_enabled(ctx);
3c824109
NF
12335 {
12336 TCGv t0 = tcg_temp_new();
12337
12338 save_cpu_state(ctx, 1);
895c2d04 12339 gen_helper_di(t0, cpu_env);
3c824109
NF
12340 gen_store_gpr(t0, rs);
12341 /* Stop translation as we may have switched the execution mode */
12342 ctx->bstate = BS_STOP;
12343 tcg_temp_free(t0);
12344 }
12345 break;
12346 case EI:
2e15497c 12347 check_cp0_enabled(ctx);
3c824109
NF
12348 {
12349 TCGv t0 = tcg_temp_new();
12350
12351 save_cpu_state(ctx, 1);
895c2d04 12352 gen_helper_ei(t0, cpu_env);
3c824109
NF
12353 gen_store_gpr(t0, rs);
12354 /* Stop translation as we may have switched the execution mode */
12355 ctx->bstate = BS_STOP;
12356 tcg_temp_free(t0);
12357 }
12358 break;
12359 default:
12360 goto pool32axf_invalid;
12361 }
12362 break;
12363#endif
12364 case 0x2d:
12365 switch (minor) {
12366 case SYNC:
12367 /* NOP */
12368 break;
12369 case SYSCALL:
12370 generate_exception(ctx, EXCP_SYSCALL);
12371 ctx->bstate = BS_STOP;
12372 break;
12373 case SDBBP:
d75c135e 12374 check_insn(ctx, ISA_MIPS32);
3c824109
NF
12375 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
12376 generate_exception(ctx, EXCP_DBp);
12377 } else {
12378 generate_exception(ctx, EXCP_DBp);
12379 }
12380 break;
12381 default:
12382 goto pool32axf_invalid;
12383 }
12384 break;
a1fc6246 12385 case 0x01:
26135ead 12386 switch (minor & 3) {
a1fc6246 12387 case MFHI_ACC:
26135ead 12388 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
3c824109 12389 break;
a1fc6246 12390 case MFLO_ACC:
26135ead 12391 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
3c824109 12392 break;
a1fc6246 12393 case MTHI_ACC:
26135ead 12394 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
3c824109 12395 break;
a1fc6246 12396 case MTLO_ACC:
26135ead 12397 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
3c824109
NF
12398 break;
12399 default:
12400 goto pool32axf_invalid;
12401 }
12402 break;
a1fc6246
LA
12403 case 0x35:
12404 switch (minor) {
12405 case MFHI32:
12406 gen_HILO(ctx, OPC_MFHI, 0, rs);
12407 break;
12408 case MFLO32:
12409 gen_HILO(ctx, OPC_MFLO, 0, rs);
12410 break;
12411 case MTHI32:
12412 gen_HILO(ctx, OPC_MTHI, 0, rs);
12413 break;
12414 case MTLO32:
12415 gen_HILO(ctx, OPC_MTLO, 0, rs);
12416 break;
12417 default:
12418 goto pool32axf_invalid;
12419 }
12420 break;
3c824109
NF
12421 default:
12422 pool32axf_invalid:
12423 MIPS_INVAL("pool32axf");
12424 generate_exception(ctx, EXCP_RI);
12425 break;
12426 }
12427}
12428
12429/* Values for microMIPS fmt field. Variable-width, depending on which
12430 formats the instruction supports. */
12431
12432enum {
12433 FMT_SD_S = 0,
12434 FMT_SD_D = 1,
12435
12436 FMT_SDPS_S = 0,
12437 FMT_SDPS_D = 1,
12438 FMT_SDPS_PS = 2,
12439
12440 FMT_SWL_S = 0,
12441 FMT_SWL_W = 1,
12442 FMT_SWL_L = 2,
12443
12444 FMT_DWL_D = 0,
12445 FMT_DWL_W = 1,
12446 FMT_DWL_L = 2
12447};
12448
d75c135e 12449static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
3c824109
NF
12450{
12451 int extension = (ctx->opcode >> 6) & 0x3ff;
12452 uint32_t mips32_op;
12453
12454#define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
12455#define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
12456#define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
12457
12458 switch (extension) {
12459 case FLOAT_1BIT_FMT(CFC1, 0):
12460 mips32_op = OPC_CFC1;
12461 goto do_cp1;
12462 case FLOAT_1BIT_FMT(CTC1, 0):
12463 mips32_op = OPC_CTC1;
12464 goto do_cp1;
12465 case FLOAT_1BIT_FMT(MFC1, 0):
12466 mips32_op = OPC_MFC1;
12467 goto do_cp1;
12468 case FLOAT_1BIT_FMT(MTC1, 0):
12469 mips32_op = OPC_MTC1;
12470 goto do_cp1;
12471 case FLOAT_1BIT_FMT(MFHC1, 0):
12472 mips32_op = OPC_MFHC1;
12473 goto do_cp1;
12474 case FLOAT_1BIT_FMT(MTHC1, 0):
12475 mips32_op = OPC_MTHC1;
12476 do_cp1:
12477 gen_cp1(ctx, mips32_op, rt, rs);
12478 break;
12479
12480 /* Reciprocal square root */
12481 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
12482 mips32_op = OPC_RSQRT_S;
12483 goto do_unaryfp;
12484 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
12485 mips32_op = OPC_RSQRT_D;
12486 goto do_unaryfp;
12487
12488 /* Square root */
12489 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
12490 mips32_op = OPC_SQRT_S;
12491 goto do_unaryfp;
12492 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
12493 mips32_op = OPC_SQRT_D;
12494 goto do_unaryfp;
12495
12496 /* Reciprocal */
12497 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
12498 mips32_op = OPC_RECIP_S;
12499 goto do_unaryfp;
12500 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
12501 mips32_op = OPC_RECIP_D;
12502 goto do_unaryfp;
12503
12504 /* Floor */
12505 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
12506 mips32_op = OPC_FLOOR_L_S;
12507 goto do_unaryfp;
12508 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
12509 mips32_op = OPC_FLOOR_L_D;
12510 goto do_unaryfp;
12511 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
12512 mips32_op = OPC_FLOOR_W_S;
12513 goto do_unaryfp;
12514 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
12515 mips32_op = OPC_FLOOR_W_D;
12516 goto do_unaryfp;
12517
12518 /* Ceiling */
12519 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
12520 mips32_op = OPC_CEIL_L_S;
12521 goto do_unaryfp;
12522 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
12523 mips32_op = OPC_CEIL_L_D;
12524 goto do_unaryfp;
12525 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
12526 mips32_op = OPC_CEIL_W_S;
12527 goto do_unaryfp;
12528 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
12529 mips32_op = OPC_CEIL_W_D;
12530 goto do_unaryfp;
12531
12532 /* Truncation */
12533 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
12534 mips32_op = OPC_TRUNC_L_S;
12535 goto do_unaryfp;
12536 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
12537 mips32_op = OPC_TRUNC_L_D;
12538 goto do_unaryfp;
12539 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
12540 mips32_op = OPC_TRUNC_W_S;
12541 goto do_unaryfp;
12542 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
12543 mips32_op = OPC_TRUNC_W_D;
12544 goto do_unaryfp;
12545
12546 /* Round */
12547 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
12548 mips32_op = OPC_ROUND_L_S;
12549 goto do_unaryfp;
12550 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
12551 mips32_op = OPC_ROUND_L_D;
12552 goto do_unaryfp;
12553 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
12554 mips32_op = OPC_ROUND_W_S;
12555 goto do_unaryfp;
12556 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
12557 mips32_op = OPC_ROUND_W_D;
12558 goto do_unaryfp;
12559
12560 /* Integer to floating-point conversion */
12561 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
12562 mips32_op = OPC_CVT_L_S;
12563 goto do_unaryfp;
12564 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
12565 mips32_op = OPC_CVT_L_D;
12566 goto do_unaryfp;
12567 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
12568 mips32_op = OPC_CVT_W_S;
12569 goto do_unaryfp;
12570 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
12571 mips32_op = OPC_CVT_W_D;
12572 goto do_unaryfp;
12573
12574 /* Paired-foo conversions */
12575 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
12576 mips32_op = OPC_CVT_S_PL;
12577 goto do_unaryfp;
12578 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
12579 mips32_op = OPC_CVT_S_PU;
12580 goto do_unaryfp;
12581 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
12582 mips32_op = OPC_CVT_PW_PS;
12583 goto do_unaryfp;
12584 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
12585 mips32_op = OPC_CVT_PS_PW;
12586 goto do_unaryfp;
12587
12588 /* Floating-point moves */
12589 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
12590 mips32_op = OPC_MOV_S;
12591 goto do_unaryfp;
12592 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
12593 mips32_op = OPC_MOV_D;
12594 goto do_unaryfp;
12595 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
12596 mips32_op = OPC_MOV_PS;
12597 goto do_unaryfp;
12598
12599 /* Absolute value */
12600 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
12601 mips32_op = OPC_ABS_S;
12602 goto do_unaryfp;
12603 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
12604 mips32_op = OPC_ABS_D;
12605 goto do_unaryfp;
12606 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
12607 mips32_op = OPC_ABS_PS;
12608 goto do_unaryfp;
12609
12610 /* Negation */
12611 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
12612 mips32_op = OPC_NEG_S;
12613 goto do_unaryfp;
12614 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
12615 mips32_op = OPC_NEG_D;
12616 goto do_unaryfp;
12617 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
12618 mips32_op = OPC_NEG_PS;
12619 goto do_unaryfp;
12620
12621 /* Reciprocal square root step */
12622 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
12623 mips32_op = OPC_RSQRT1_S;
12624 goto do_unaryfp;
12625 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
12626 mips32_op = OPC_RSQRT1_D;
12627 goto do_unaryfp;
12628 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
12629 mips32_op = OPC_RSQRT1_PS;
12630 goto do_unaryfp;
12631
12632 /* Reciprocal step */
12633 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
12634 mips32_op = OPC_RECIP1_S;
12635 goto do_unaryfp;
12636 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
12637 mips32_op = OPC_RECIP1_S;
12638 goto do_unaryfp;
12639 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
12640 mips32_op = OPC_RECIP1_PS;
12641 goto do_unaryfp;
12642
12643 /* Conversions from double */
12644 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
12645 mips32_op = OPC_CVT_D_S;
12646 goto do_unaryfp;
12647 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
12648 mips32_op = OPC_CVT_D_W;
12649 goto do_unaryfp;
12650 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
12651 mips32_op = OPC_CVT_D_L;
12652 goto do_unaryfp;
12653
12654 /* Conversions from single */
12655 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
12656 mips32_op = OPC_CVT_S_D;
12657 goto do_unaryfp;
12658 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
12659 mips32_op = OPC_CVT_S_W;
12660 goto do_unaryfp;
12661 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
12662 mips32_op = OPC_CVT_S_L;
12663 do_unaryfp:
12664 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
12665 break;
12666
12667 /* Conditional moves on floating-point codes */
12668 case COND_FLOAT_MOV(MOVT, 0):
12669 case COND_FLOAT_MOV(MOVT, 1):
12670 case COND_FLOAT_MOV(MOVT, 2):
12671 case COND_FLOAT_MOV(MOVT, 3):
12672 case COND_FLOAT_MOV(MOVT, 4):
12673 case COND_FLOAT_MOV(MOVT, 5):
12674 case COND_FLOAT_MOV(MOVT, 6):
12675 case COND_FLOAT_MOV(MOVT, 7):
12676 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
12677 break;
12678 case COND_FLOAT_MOV(MOVF, 0):
12679 case COND_FLOAT_MOV(MOVF, 1):
12680 case COND_FLOAT_MOV(MOVF, 2):
12681 case COND_FLOAT_MOV(MOVF, 3):
12682 case COND_FLOAT_MOV(MOVF, 4):
12683 case COND_FLOAT_MOV(MOVF, 5):
12684 case COND_FLOAT_MOV(MOVF, 6):
12685 case COND_FLOAT_MOV(MOVF, 7):
12686 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
12687 break;
12688 default:
12689 MIPS_INVAL("pool32fxf");
12690 generate_exception(ctx, EXCP_RI);
12691 break;
12692 }
12693}
12694
7db13fae 12695static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
240ce26a 12696 uint16_t insn_hw1)
3c824109
NF
12697{
12698 int32_t offset;
12699 uint16_t insn;
12700 int rt, rs, rd, rr;
12701 int16_t imm;
12702 uint32_t op, minor, mips32_op;
12703 uint32_t cond, fmt, cc;
12704
895c2d04 12705 insn = cpu_lduw_code(env, ctx->pc + 2);
3c824109
NF
12706 ctx->opcode = (ctx->opcode << 16) | insn;
12707
12708 rt = (ctx->opcode >> 21) & 0x1f;
12709 rs = (ctx->opcode >> 16) & 0x1f;
12710 rd = (ctx->opcode >> 11) & 0x1f;
12711 rr = (ctx->opcode >> 6) & 0x1f;
12712 imm = (int16_t) ctx->opcode;
12713
12714 op = (ctx->opcode >> 26) & 0x3f;
12715 switch (op) {
12716 case POOL32A:
12717 minor = ctx->opcode & 0x3f;
12718 switch (minor) {
12719 case 0x00:
12720 minor = (ctx->opcode >> 6) & 0xf;
12721 switch (minor) {
12722 case SLL32:
12723 mips32_op = OPC_SLL;
12724 goto do_shifti;
12725 case SRA:
12726 mips32_op = OPC_SRA;
12727 goto do_shifti;
12728 case SRL32:
12729 mips32_op = OPC_SRL;
12730 goto do_shifti;
12731 case ROTR:
12732 mips32_op = OPC_ROTR;
12733 do_shifti:
d75c135e 12734 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
3c824109
NF
12735 break;
12736 default:
12737 goto pool32a_invalid;
12738 }
12739 break;
12740 case 0x10:
12741 minor = (ctx->opcode >> 6) & 0xf;
12742 switch (minor) {
12743 /* Arithmetic */
12744 case ADD:
12745 mips32_op = OPC_ADD;
12746 goto do_arith;
12747 case ADDU32:
12748 mips32_op = OPC_ADDU;
12749 goto do_arith;
12750 case SUB:
12751 mips32_op = OPC_SUB;
12752 goto do_arith;
12753 case SUBU32:
12754 mips32_op = OPC_SUBU;
12755 goto do_arith;
12756 case MUL:
12757 mips32_op = OPC_MUL;
12758 do_arith:
d75c135e 12759 gen_arith(ctx, mips32_op, rd, rs, rt);
3c824109
NF
12760 break;
12761 /* Shifts */
12762 case SLLV:
12763 mips32_op = OPC_SLLV;
12764 goto do_shift;
12765 case SRLV:
12766 mips32_op = OPC_SRLV;
12767 goto do_shift;
12768 case SRAV:
12769 mips32_op = OPC_SRAV;
12770 goto do_shift;
12771 case ROTRV:
12772 mips32_op = OPC_ROTRV;
12773 do_shift:
d75c135e 12774 gen_shift(ctx, mips32_op, rd, rs, rt);
3c824109
NF
12775 break;
12776 /* Logical operations */
12777 case AND:
12778 mips32_op = OPC_AND;
12779 goto do_logic;
12780 case OR32:
12781 mips32_op = OPC_OR;
12782 goto do_logic;
12783 case NOR:
12784 mips32_op = OPC_NOR;
12785 goto do_logic;
12786 case XOR32:
12787 mips32_op = OPC_XOR;
12788 do_logic:
d75c135e 12789 gen_logic(ctx, mips32_op, rd, rs, rt);
3c824109
NF
12790 break;
12791 /* Set less than */
12792 case SLT:
12793 mips32_op = OPC_SLT;
12794 goto do_slt;
12795 case SLTU:
12796 mips32_op = OPC_SLTU;
12797 do_slt:
d75c135e 12798 gen_slt(ctx, mips32_op, rd, rs, rt);
3c824109
NF
12799 break;
12800 default:
12801 goto pool32a_invalid;
12802 }
12803 break;
12804 case 0x18:
12805 minor = (ctx->opcode >> 6) & 0xf;
12806 switch (minor) {
12807 /* Conditional moves */
12808 case MOVN:
12809 mips32_op = OPC_MOVN;
12810 goto do_cmov;
12811 case MOVZ:
12812 mips32_op = OPC_MOVZ;
12813 do_cmov:
d75c135e 12814 gen_cond_move(ctx, mips32_op, rd, rs, rt);
3c824109
NF
12815 break;
12816 case LWXS:
12817 gen_ldxs(ctx, rs, rt, rd);
12818 break;
12819 default:
12820 goto pool32a_invalid;
12821 }
12822 break;
12823 case INS:
12824 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
12825 return;
12826 case EXT:
12827 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
12828 return;
12829 case POOL32AXF:
240ce26a 12830 gen_pool32axf(env, ctx, rt, rs);
3c824109
NF
12831 break;
12832 case 0x07:
12833 generate_exception(ctx, EXCP_BREAK);
12834 break;
12835 default:
12836 pool32a_invalid:
12837 MIPS_INVAL("pool32a");
12838 generate_exception(ctx, EXCP_RI);
12839 break;
12840 }
12841 break;
12842 case POOL32B:
12843 minor = (ctx->opcode >> 12) & 0xf;
12844 switch (minor) {
12845 case CACHE:
2e15497c 12846 check_cp0_enabled(ctx);
3c824109
NF
12847 /* Treat as no-op. */
12848 break;
12849 case LWC2:
12850 case SWC2:
12851 /* COP2: Not implemented. */
12852 generate_exception_err(ctx, EXCP_CpU, 2);
12853 break;
12854 case LWP:
12855 case SWP:
12856#ifdef TARGET_MIPS64
12857 case LDP:
12858 case SDP:
12859#endif
12860 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
12861 break;
12862 case LWM32:
12863 case SWM32:
12864#ifdef TARGET_MIPS64
12865 case LDM:
12866 case SDM:
12867#endif
12868 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
12869 break;
12870 default:
12871 MIPS_INVAL("pool32b");
12872 generate_exception(ctx, EXCP_RI);
12873 break;
12874 }
12875 break;
12876 case POOL32F:
5ab5c041 12877 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3c824109
NF
12878 minor = ctx->opcode & 0x3f;
12879 check_cp1_enabled(ctx);
12880 switch (minor) {
12881 case ALNV_PS:
12882 mips32_op = OPC_ALNV_PS;
12883 goto do_madd;
12884 case MADD_S:
12885 mips32_op = OPC_MADD_S;
12886 goto do_madd;
12887 case MADD_D:
12888 mips32_op = OPC_MADD_D;
12889 goto do_madd;
12890 case MADD_PS:
12891 mips32_op = OPC_MADD_PS;
12892 goto do_madd;
12893 case MSUB_S:
12894 mips32_op = OPC_MSUB_S;
12895 goto do_madd;
12896 case MSUB_D:
12897 mips32_op = OPC_MSUB_D;
12898 goto do_madd;
12899 case MSUB_PS:
12900 mips32_op = OPC_MSUB_PS;
12901 goto do_madd;
12902 case NMADD_S:
12903 mips32_op = OPC_NMADD_S;
12904 goto do_madd;
12905 case NMADD_D:
12906 mips32_op = OPC_NMADD_D;
12907 goto do_madd;
12908 case NMADD_PS:
12909 mips32_op = OPC_NMADD_PS;
12910 goto do_madd;
12911 case NMSUB_S:
12912 mips32_op = OPC_NMSUB_S;
12913 goto do_madd;
12914 case NMSUB_D:
12915 mips32_op = OPC_NMSUB_D;
12916 goto do_madd;
12917 case NMSUB_PS:
12918 mips32_op = OPC_NMSUB_PS;
12919 do_madd:
12920 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
12921 break;
12922 case CABS_COND_FMT:
12923 cond = (ctx->opcode >> 6) & 0xf;
12924 cc = (ctx->opcode >> 13) & 0x7;
12925 fmt = (ctx->opcode >> 10) & 0x3;
12926 switch (fmt) {
12927 case 0x0:
12928 gen_cmpabs_s(ctx, cond, rt, rs, cc);
12929 break;
12930 case 0x1:
12931 gen_cmpabs_d(ctx, cond, rt, rs, cc);
12932 break;
12933 case 0x2:
12934 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
12935 break;
12936 default:
12937 goto pool32f_invalid;
12938 }
12939 break;
12940 case C_COND_FMT:
12941 cond = (ctx->opcode >> 6) & 0xf;
12942 cc = (ctx->opcode >> 13) & 0x7;
12943 fmt = (ctx->opcode >> 10) & 0x3;
12944 switch (fmt) {
12945 case 0x0:
12946 gen_cmp_s(ctx, cond, rt, rs, cc);
12947 break;
12948 case 0x1:
12949 gen_cmp_d(ctx, cond, rt, rs, cc);
12950 break;
12951 case 0x2:
12952 gen_cmp_ps(ctx, cond, rt, rs, cc);
12953 break;
12954 default:
12955 goto pool32f_invalid;
12956 }
12957 break;
12958 case POOL32FXF:
d75c135e 12959 gen_pool32fxf(ctx, rt, rs);
3c824109
NF
12960 break;
12961 case 0x00:
12962 /* PLL foo */
12963 switch ((ctx->opcode >> 6) & 0x7) {
12964 case PLL_PS:
12965 mips32_op = OPC_PLL_PS;
12966 goto do_ps;
12967 case PLU_PS:
12968 mips32_op = OPC_PLU_PS;
12969 goto do_ps;
12970 case PUL_PS:
12971 mips32_op = OPC_PUL_PS;
12972 goto do_ps;
12973 case PUU_PS:
12974 mips32_op = OPC_PUU_PS;
12975 goto do_ps;
12976 case CVT_PS_S:
12977 mips32_op = OPC_CVT_PS_S;
12978 do_ps:
12979 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
12980 break;
12981 default:
12982 goto pool32f_invalid;
12983 }
12984 break;
12985 case 0x08:
12986 /* [LS][WDU]XC1 */
12987 switch ((ctx->opcode >> 6) & 0x7) {
12988 case LWXC1:
12989 mips32_op = OPC_LWXC1;
12990 goto do_ldst_cp1;
12991 case SWXC1:
12992 mips32_op = OPC_SWXC1;
12993 goto do_ldst_cp1;
12994 case LDXC1:
12995 mips32_op = OPC_LDXC1;
12996 goto do_ldst_cp1;
12997 case SDXC1:
12998 mips32_op = OPC_SDXC1;
12999 goto do_ldst_cp1;
13000 case LUXC1:
13001 mips32_op = OPC_LUXC1;
13002 goto do_ldst_cp1;
13003 case SUXC1:
13004 mips32_op = OPC_SUXC1;
13005 do_ldst_cp1:
13006 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
13007 break;
13008 default:
13009 goto pool32f_invalid;
13010 }
13011 break;
13012 case 0x18:
13013 /* 3D insns */
13014 fmt = (ctx->opcode >> 9) & 0x3;
13015 switch ((ctx->opcode >> 6) & 0x7) {
13016 case RSQRT2_FMT:
13017 switch (fmt) {
13018 case FMT_SDPS_S:
13019 mips32_op = OPC_RSQRT2_S;
13020 goto do_3d;
13021 case FMT_SDPS_D:
13022 mips32_op = OPC_RSQRT2_D;
13023 goto do_3d;
13024 case FMT_SDPS_PS:
13025 mips32_op = OPC_RSQRT2_PS;
13026 goto do_3d;
13027 default:
13028 goto pool32f_invalid;
13029 }
13030 break;
13031 case RECIP2_FMT:
13032 switch (fmt) {
13033 case FMT_SDPS_S:
13034 mips32_op = OPC_RECIP2_S;
13035 goto do_3d;
13036 case FMT_SDPS_D:
13037 mips32_op = OPC_RECIP2_D;
13038 goto do_3d;
13039 case FMT_SDPS_PS:
13040 mips32_op = OPC_RECIP2_PS;
13041 goto do_3d;
13042 default:
13043 goto pool32f_invalid;
13044 }
13045 break;
13046 case ADDR_PS:
13047 mips32_op = OPC_ADDR_PS;
13048 goto do_3d;
13049 case MULR_PS:
13050 mips32_op = OPC_MULR_PS;
13051 do_3d:
13052 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
13053 break;
13054 default:
13055 goto pool32f_invalid;
13056 }
13057 break;
13058 case 0x20:
13059 /* MOV[FT].fmt and PREFX */
13060 cc = (ctx->opcode >> 13) & 0x7;
13061 fmt = (ctx->opcode >> 9) & 0x3;
13062 switch ((ctx->opcode >> 6) & 0x7) {
13063 case MOVF_FMT:
13064 switch (fmt) {
13065 case FMT_SDPS_S:
13066 gen_movcf_s(rs, rt, cc, 0);
13067 break;
13068 case FMT_SDPS_D:
13069 gen_movcf_d(ctx, rs, rt, cc, 0);
13070 break;
13071 case FMT_SDPS_PS:
7f6613ce 13072 gen_movcf_ps(ctx, rs, rt, cc, 0);
3c824109
NF
13073 break;
13074 default:
13075 goto pool32f_invalid;
13076 }
13077 break;
13078 case MOVT_FMT:
13079 switch (fmt) {
13080 case FMT_SDPS_S:
13081 gen_movcf_s(rs, rt, cc, 1);
13082 break;
13083 case FMT_SDPS_D:
13084 gen_movcf_d(ctx, rs, rt, cc, 1);
13085 break;
13086 case FMT_SDPS_PS:
7f6613ce 13087 gen_movcf_ps(ctx, rs, rt, cc, 1);
3c824109
NF
13088 break;
13089 default:
13090 goto pool32f_invalid;
13091 }
13092 break;
13093 case PREFX:
13094 break;
13095 default:
13096 goto pool32f_invalid;
13097 }
13098 break;
13099#define FINSN_3ARG_SDPS(prfx) \
13100 switch ((ctx->opcode >> 8) & 0x3) { \
13101 case FMT_SDPS_S: \
13102 mips32_op = OPC_##prfx##_S; \
13103 goto do_fpop; \
13104 case FMT_SDPS_D: \
13105 mips32_op = OPC_##prfx##_D; \
13106 goto do_fpop; \
13107 case FMT_SDPS_PS: \
13108 mips32_op = OPC_##prfx##_PS; \
13109 goto do_fpop; \
13110 default: \
13111 goto pool32f_invalid; \
13112 }
13113 case 0x30:
13114 /* regular FP ops */
13115 switch ((ctx->opcode >> 6) & 0x3) {
13116 case ADD_FMT:
13117 FINSN_3ARG_SDPS(ADD);
13118 break;
13119 case SUB_FMT:
13120 FINSN_3ARG_SDPS(SUB);
13121 break;
13122 case MUL_FMT:
13123 FINSN_3ARG_SDPS(MUL);
13124 break;
13125 case DIV_FMT:
13126 fmt = (ctx->opcode >> 8) & 0x3;
13127 if (fmt == 1) {
13128 mips32_op = OPC_DIV_D;
13129 } else if (fmt == 0) {
13130 mips32_op = OPC_DIV_S;
13131 } else {
13132 goto pool32f_invalid;
13133 }
13134 goto do_fpop;
13135 default:
13136 goto pool32f_invalid;
13137 }
13138 break;
13139 case 0x38:
13140 /* cmovs */
13141 switch ((ctx->opcode >> 6) & 0x3) {
13142 case MOVN_FMT:
13143 FINSN_3ARG_SDPS(MOVN);
13144 break;
13145 case MOVZ_FMT:
13146 FINSN_3ARG_SDPS(MOVZ);
13147 break;
13148 default:
13149 goto pool32f_invalid;
13150 }
13151 break;
13152 do_fpop:
13153 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
13154 break;
13155 default:
13156 pool32f_invalid:
13157 MIPS_INVAL("pool32f");
13158 generate_exception(ctx, EXCP_RI);
13159 break;
13160 }
13161 } else {
13162 generate_exception_err(ctx, EXCP_CpU, 1);
13163 }
13164 break;
13165 case POOL32I:
13166 minor = (ctx->opcode >> 21) & 0x1f;
13167 switch (minor) {
13168 case BLTZ:
b231c103
YK
13169 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
13170 break;
3c824109 13171 case BLTZAL:
b231c103
YK
13172 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
13173 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13174 break;
3c824109 13175 case BLTZALS:
b231c103
YK
13176 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
13177 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13178 break;
3c824109 13179 case BGEZ:
b231c103
YK
13180 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
13181 break;
3c824109 13182 case BGEZAL:
b231c103
YK
13183 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
13184 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13185 break;
3c824109 13186 case BGEZALS:
b231c103
YK
13187 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
13188 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13189 break;
3c824109 13190 case BLEZ:
b231c103
YK
13191 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
13192 break;
3c824109 13193 case BGTZ:
b231c103 13194 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
3c824109
NF
13195 break;
13196
13197 /* Traps */
13198 case TLTI:
13199 mips32_op = OPC_TLTI;
13200 goto do_trapi;
13201 case TGEI:
13202 mips32_op = OPC_TGEI;
13203 goto do_trapi;
13204 case TLTIU:
13205 mips32_op = OPC_TLTIU;
13206 goto do_trapi;
13207 case TGEIU:
13208 mips32_op = OPC_TGEIU;
13209 goto do_trapi;
13210 case TNEI:
13211 mips32_op = OPC_TNEI;
13212 goto do_trapi;
13213 case TEQI:
13214 mips32_op = OPC_TEQI;
13215 do_trapi:
13216 gen_trap(ctx, mips32_op, rs, -1, imm);
13217 break;
13218
13219 case BNEZC:
13220 case BEQZC:
13221 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
b231c103 13222 4, rs, 0, imm << 1, 0);
3c824109
NF
13223 /* Compact branches don't have a delay slot, so just let
13224 the normal delay slot handling take us to the branch
13225 target. */
13226 break;
13227 case LUI:
d75c135e 13228 gen_logic_imm(ctx, OPC_LUI, rs, -1, imm);
3c824109
NF
13229 break;
13230 case SYNCI:
a83bddd6
DZ
13231 /* Break the TB to be able to sync copied instructions
13232 immediately */
13233 ctx->bstate = BS_STOP;
3c824109
NF
13234 break;
13235 case BC2F:
13236 case BC2T:
13237 /* COP2: Not implemented. */
13238 generate_exception_err(ctx, EXCP_CpU, 2);
13239 break;
13240 case BC1F:
13241 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
13242 goto do_cp1branch;
13243 case BC1T:
13244 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
13245 goto do_cp1branch;
13246 case BC1ANY4F:
13247 mips32_op = OPC_BC1FANY4;
13248 goto do_cp1mips3d;
13249 case BC1ANY4T:
13250 mips32_op = OPC_BC1TANY4;
13251 do_cp1mips3d:
13252 check_cop1x(ctx);
d75c135e 13253 check_insn(ctx, ASE_MIPS3D);
3c824109
NF
13254 /* Fall through */
13255 do_cp1branch:
d75c135e 13256 gen_compute_branch1(ctx, mips32_op,
3c824109 13257 (ctx->opcode >> 18) & 0x7, imm << 1);
3c824109
NF
13258 break;
13259 case BPOSGE64:
13260 case BPOSGE32:
13261 /* MIPS DSP: not implemented */
13262 /* Fall through */
13263 default:
13264 MIPS_INVAL("pool32i");
13265 generate_exception(ctx, EXCP_RI);
13266 break;
13267 }
13268 break;
13269 case POOL32C:
13270 minor = (ctx->opcode >> 12) & 0xf;
13271 switch (minor) {
13272 case LWL:
13273 mips32_op = OPC_LWL;
5c13fdfd 13274 goto do_ld_lr;
3c824109
NF
13275 case SWL:
13276 mips32_op = OPC_SWL;
5c13fdfd 13277 goto do_st_lr;
3c824109
NF
13278 case LWR:
13279 mips32_op = OPC_LWR;
5c13fdfd 13280 goto do_ld_lr;
3c824109
NF
13281 case SWR:
13282 mips32_op = OPC_SWR;
5c13fdfd 13283 goto do_st_lr;
3c824109
NF
13284#if defined(TARGET_MIPS64)
13285 case LDL:
13286 mips32_op = OPC_LDL;
5c13fdfd 13287 goto do_ld_lr;
3c824109
NF
13288 case SDL:
13289 mips32_op = OPC_SDL;
5c13fdfd 13290 goto do_st_lr;
3c824109
NF
13291 case LDR:
13292 mips32_op = OPC_LDR;
5c13fdfd 13293 goto do_ld_lr;
3c824109
NF
13294 case SDR:
13295 mips32_op = OPC_SDR;
5c13fdfd 13296 goto do_st_lr;
3c824109
NF
13297 case LWU:
13298 mips32_op = OPC_LWU;
5c13fdfd 13299 goto do_ld_lr;
3c824109
NF
13300 case LLD:
13301 mips32_op = OPC_LLD;
5c13fdfd 13302 goto do_ld_lr;
3c824109
NF
13303#endif
13304 case LL:
13305 mips32_op = OPC_LL;
5c13fdfd
AJ
13306 goto do_ld_lr;
13307 do_ld_lr:
d75c135e 13308 gen_ld(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
5c13fdfd
AJ
13309 break;
13310 do_st_lr:
13311 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
3c824109
NF
13312 break;
13313 case SC:
13314 gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
13315 break;
13316#if defined(TARGET_MIPS64)
13317 case SCD:
13318 gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
13319 break;
13320#endif
13321 case PREF:
13322 /* Treat as no-op */
13323 break;
13324 default:
13325 MIPS_INVAL("pool32c");
13326 generate_exception(ctx, EXCP_RI);
13327 break;
13328 }
13329 break;
13330 case ADDI32:
13331 mips32_op = OPC_ADDI;
13332 goto do_addi;
13333 case ADDIU32:
13334 mips32_op = OPC_ADDIU;
13335 do_addi:
d75c135e 13336 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
13337 break;
13338
13339 /* Logical operations */
13340 case ORI32:
13341 mips32_op = OPC_ORI;
13342 goto do_logici;
13343 case XORI32:
13344 mips32_op = OPC_XORI;
13345 goto do_logici;
13346 case ANDI32:
13347 mips32_op = OPC_ANDI;
13348 do_logici:
d75c135e 13349 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
13350 break;
13351
13352 /* Set less than immediate */
13353 case SLTI32:
13354 mips32_op = OPC_SLTI;
13355 goto do_slti;
13356 case SLTIU32:
13357 mips32_op = OPC_SLTIU;
13358 do_slti:
d75c135e 13359 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
13360 break;
13361 case JALX32:
13362 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103
YK
13363 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
13364 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
13365 break;
13366 case JALS32:
13367 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
b231c103
YK
13368 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
13369 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
13370 break;
13371 case BEQ32:
b231c103 13372 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
3c824109
NF
13373 break;
13374 case BNE32:
b231c103 13375 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
3c824109
NF
13376 break;
13377 case J32:
13378 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
b231c103 13379 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
3c824109
NF
13380 break;
13381 case JAL32:
13382 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
b231c103
YK
13383 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
13384 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
13385 break;
13386 /* Floating point (COP1) */
13387 case LWC132:
13388 mips32_op = OPC_LWC1;
13389 goto do_cop1;
13390 case LDC132:
13391 mips32_op = OPC_LDC1;
13392 goto do_cop1;
13393 case SWC132:
13394 mips32_op = OPC_SWC1;
13395 goto do_cop1;
13396 case SDC132:
13397 mips32_op = OPC_SDC1;
13398 do_cop1:
5ab5c041 13399 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
3c824109
NF
13400 break;
13401 case ADDIUPC:
13402 {
13403 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
13404 int offset = SIMM(ctx->opcode, 0, 23) << 2;
13405
13406 gen_addiupc(ctx, reg, offset, 0, 0);
13407 }
13408 break;
13409 /* Loads and stores */
13410 case LB32:
13411 mips32_op = OPC_LB;
5c13fdfd 13412 goto do_ld;
3c824109
NF
13413 case LBU32:
13414 mips32_op = OPC_LBU;
5c13fdfd 13415 goto do_ld;
3c824109
NF
13416 case LH32:
13417 mips32_op = OPC_LH;
5c13fdfd 13418 goto do_ld;
3c824109
NF
13419 case LHU32:
13420 mips32_op = OPC_LHU;
5c13fdfd 13421 goto do_ld;
3c824109
NF
13422 case LW32:
13423 mips32_op = OPC_LW;
5c13fdfd 13424 goto do_ld;
3c824109
NF
13425#ifdef TARGET_MIPS64
13426 case LD32:
13427 mips32_op = OPC_LD;
5c13fdfd 13428 goto do_ld;
3c824109
NF
13429 case SD32:
13430 mips32_op = OPC_SD;
5c13fdfd 13431 goto do_st;
3c824109
NF
13432#endif
13433 case SB32:
13434 mips32_op = OPC_SB;
5c13fdfd 13435 goto do_st;
3c824109
NF
13436 case SH32:
13437 mips32_op = OPC_SH;
5c13fdfd 13438 goto do_st;
3c824109
NF
13439 case SW32:
13440 mips32_op = OPC_SW;
5c13fdfd
AJ
13441 goto do_st;
13442 do_ld:
d75c135e 13443 gen_ld(ctx, mips32_op, rt, rs, imm);
5c13fdfd
AJ
13444 break;
13445 do_st:
13446 gen_st(ctx, mips32_op, rt, rs, imm);
3c824109
NF
13447 break;
13448 default:
13449 generate_exception(ctx, EXCP_RI);
13450 break;
13451 }
13452}
13453
240ce26a 13454static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
13455{
13456 uint32_t op;
13457
13458 /* make sure instructions are on a halfword boundary */
13459 if (ctx->pc & 0x1) {
13460 env->CP0_BadVAddr = ctx->pc;
13461 generate_exception(ctx, EXCP_AdEL);
13462 ctx->bstate = BS_STOP;
13463 return 2;
13464 }
13465
13466 op = (ctx->opcode >> 10) & 0x3f;
13467 /* Enforce properly-sized instructions in a delay slot */
b231c103
YK
13468 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
13469 switch (op & 0x7) { /* MSB-3..MSB-5 */
13470 case 0:
13471 /* POOL32A, POOL32B, POOL32I, POOL32C */
13472 case 4:
13473 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
13474 case 5:
13475 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
13476 case 6:
13477 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
13478 case 7:
13479 /* LB32, LH32, LWC132, LDC132, LW32 */
13480 if (ctx->hflags & MIPS_HFLAG_BDS16) {
3c824109
NF
13481 generate_exception(ctx, EXCP_RI);
13482 /* Just stop translation; the user is confused. */
13483 ctx->bstate = BS_STOP;
13484 return 2;
13485 }
13486 break;
b231c103
YK
13487 case 1:
13488 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
13489 case 2:
13490 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
13491 case 3:
13492 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
13493 if (ctx->hflags & MIPS_HFLAG_BDS32) {
3c824109
NF
13494 generate_exception(ctx, EXCP_RI);
13495 /* Just stop translation; the user is confused. */
13496 ctx->bstate = BS_STOP;
13497 return 2;
13498 }
13499 break;
3c824109
NF
13500 }
13501 }
b231c103 13502
3c824109
NF
13503 switch (op) {
13504 case POOL16A:
13505 {
13506 int rd = mmreg(uMIPS_RD(ctx->opcode));
13507 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
13508 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
13509 uint32_t opc = 0;
13510
13511 switch (ctx->opcode & 0x1) {
13512 case ADDU16:
13513 opc = OPC_ADDU;
13514 break;
13515 case SUBU16:
13516 opc = OPC_SUBU;
13517 break;
13518 }
13519
d75c135e 13520 gen_arith(ctx, opc, rd, rs1, rs2);
3c824109
NF
13521 }
13522 break;
13523 case POOL16B:
13524 {
13525 int rd = mmreg(uMIPS_RD(ctx->opcode));
13526 int rs = mmreg(uMIPS_RS(ctx->opcode));
13527 int amount = (ctx->opcode >> 1) & 0x7;
13528 uint32_t opc = 0;
13529 amount = amount == 0 ? 8 : amount;
13530
13531 switch (ctx->opcode & 0x1) {
13532 case SLL16:
13533 opc = OPC_SLL;
13534 break;
13535 case SRL16:
13536 opc = OPC_SRL;
13537 break;
13538 }
13539
d75c135e 13540 gen_shift_imm(ctx, opc, rd, rs, amount);
3c824109
NF
13541 }
13542 break;
13543 case POOL16C:
240ce26a 13544 gen_pool16c_insn(ctx);
3c824109
NF
13545 break;
13546 case LWGP16:
13547 {
13548 int rd = mmreg(uMIPS_RD(ctx->opcode));
13549 int rb = 28; /* GP */
13550 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
13551
d75c135e 13552 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
13553 }
13554 break;
13555 case POOL16F:
13556 if (ctx->opcode & 1) {
13557 generate_exception(ctx, EXCP_RI);
13558 } else {
13559 /* MOVEP */
13560 int enc_dest = uMIPS_RD(ctx->opcode);
13561 int enc_rt = uMIPS_RS2(ctx->opcode);
13562 int enc_rs = uMIPS_RS1(ctx->opcode);
13563 int rd, rs, re, rt;
13564 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
13565 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
13566 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
13567
13568 rd = rd_enc[enc_dest];
13569 re = re_enc[enc_dest];
13570 rs = rs_rt_enc[enc_rs];
13571 rt = rs_rt_enc[enc_rt];
13572
d75c135e
AJ
13573 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, 0);
13574 gen_arith_imm(ctx, OPC_ADDIU, re, rt, 0);
3c824109
NF
13575 }
13576 break;
13577 case LBU16:
13578 {
13579 int rd = mmreg(uMIPS_RD(ctx->opcode));
13580 int rb = mmreg(uMIPS_RS(ctx->opcode));
13581 int16_t offset = ZIMM(ctx->opcode, 0, 4);
13582 offset = (offset == 0xf ? -1 : offset);
13583
d75c135e 13584 gen_ld(ctx, OPC_LBU, rd, rb, offset);
3c824109
NF
13585 }
13586 break;
13587 case LHU16:
13588 {
13589 int rd = mmreg(uMIPS_RD(ctx->opcode));
13590 int rb = mmreg(uMIPS_RS(ctx->opcode));
13591 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
13592
d75c135e 13593 gen_ld(ctx, OPC_LHU, rd, rb, offset);
3c824109
NF
13594 }
13595 break;
13596 case LWSP16:
13597 {
13598 int rd = (ctx->opcode >> 5) & 0x1f;
13599 int rb = 29; /* SP */
13600 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
13601
d75c135e 13602 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
13603 }
13604 break;
13605 case LW16:
13606 {
13607 int rd = mmreg(uMIPS_RD(ctx->opcode));
13608 int rb = mmreg(uMIPS_RS(ctx->opcode));
13609 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
13610
d75c135e 13611 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
13612 }
13613 break;
13614 case SB16:
13615 {
13616 int rd = mmreg2(uMIPS_RD(ctx->opcode));
13617 int rb = mmreg(uMIPS_RS(ctx->opcode));
13618 int16_t offset = ZIMM(ctx->opcode, 0, 4);
13619
5c13fdfd 13620 gen_st(ctx, OPC_SB, rd, rb, offset);
3c824109
NF
13621 }
13622 break;
13623 case SH16:
13624 {
13625 int rd = mmreg2(uMIPS_RD(ctx->opcode));
13626 int rb = mmreg(uMIPS_RS(ctx->opcode));
13627 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
13628
5c13fdfd 13629 gen_st(ctx, OPC_SH, rd, rb, offset);
3c824109
NF
13630 }
13631 break;
13632 case SWSP16:
13633 {
13634 int rd = (ctx->opcode >> 5) & 0x1f;
13635 int rb = 29; /* SP */
13636 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
13637
5c13fdfd 13638 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
13639 }
13640 break;
13641 case SW16:
13642 {
13643 int rd = mmreg2(uMIPS_RD(ctx->opcode));
13644 int rb = mmreg(uMIPS_RS(ctx->opcode));
13645 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
13646
5c13fdfd 13647 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
13648 }
13649 break;
13650 case MOVE16:
13651 {
13652 int rd = uMIPS_RD5(ctx->opcode);
13653 int rs = uMIPS_RS5(ctx->opcode);
13654
d75c135e 13655 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, 0);
3c824109
NF
13656 }
13657 break;
13658 case ANDI16:
d75c135e 13659 gen_andi16(ctx);
3c824109
NF
13660 break;
13661 case POOL16D:
13662 switch (ctx->opcode & 0x1) {
13663 case ADDIUS5:
d75c135e 13664 gen_addius5(ctx);
3c824109
NF
13665 break;
13666 case ADDIUSP:
d75c135e 13667 gen_addiusp(ctx);
3c824109
NF
13668 break;
13669 }
13670 break;
13671 case POOL16E:
13672 switch (ctx->opcode & 0x1) {
13673 case ADDIUR2:
d75c135e 13674 gen_addiur2(ctx);
3c824109
NF
13675 break;
13676 case ADDIUR1SP:
d75c135e 13677 gen_addiur1sp(ctx);
3c824109
NF
13678 break;
13679 }
13680 break;
13681 case B16:
13682 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
b231c103 13683 SIMM(ctx->opcode, 0, 10) << 1, 4);
3c824109
NF
13684 break;
13685 case BNEZ16:
13686 case BEQZ16:
13687 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
13688 mmreg(uMIPS_RD(ctx->opcode)),
b231c103 13689 0, SIMM(ctx->opcode, 0, 7) << 1, 4);
3c824109
NF
13690 break;
13691 case LI16:
13692 {
13693 int reg = mmreg(uMIPS_RD(ctx->opcode));
13694 int imm = ZIMM(ctx->opcode, 0, 7);
13695
13696 imm = (imm == 0x7f ? -1 : imm);
13697 tcg_gen_movi_tl(cpu_gpr[reg], imm);
13698 }
13699 break;
13700 case RES_20:
13701 case RES_28:
13702 case RES_29:
13703 case RES_30:
13704 case RES_31:
13705 case RES_38:
13706 case RES_39:
13707 generate_exception(ctx, EXCP_RI);
13708 break;
13709 default:
240ce26a 13710 decode_micromips32_opc (env, ctx, op);
3c824109
NF
13711 return 4;
13712 }
13713
13714 return 2;
13715}
13716
13717/* SmartMIPS extension to MIPS32 */
13718
13719#if defined(TARGET_MIPS64)
13720
13721/* MDMX extension to MIPS64 */
13722
13723#endif
13724
9b1a1d68 13725/* MIPSDSP functions. */
d75c135e 13726static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
9b1a1d68
JL
13727 int rd, int base, int offset)
13728{
13729 const char *opn = "ldx";
13730 TCGv t0;
13731
9b1a1d68
JL
13732 check_dsp(ctx);
13733 t0 = tcg_temp_new();
13734
13735 if (base == 0) {
13736 gen_load_gpr(t0, offset);
13737 } else if (offset == 0) {
13738 gen_load_gpr(t0, base);
13739 } else {
13740 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
13741 }
13742
9b1a1d68
JL
13743 switch (opc) {
13744 case OPC_LBUX:
5f68f5ae 13745 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
9b1a1d68
JL
13746 gen_store_gpr(t0, rd);
13747 opn = "lbux";
13748 break;
13749 case OPC_LHX:
5f68f5ae 13750 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
9b1a1d68
JL
13751 gen_store_gpr(t0, rd);
13752 opn = "lhx";
13753 break;
13754 case OPC_LWX:
5f68f5ae 13755 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
9b1a1d68
JL
13756 gen_store_gpr(t0, rd);
13757 opn = "lwx";
13758 break;
13759#if defined(TARGET_MIPS64)
13760 case OPC_LDX:
5f68f5ae 13761 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
9b1a1d68
JL
13762 gen_store_gpr(t0, rd);
13763 opn = "ldx";
13764 break;
13765#endif
13766 }
13767 (void)opn; /* avoid a compiler warning */
13768 MIPS_DEBUG("%s %s, %s(%s)", opn,
13769 regnames[rd], regnames[offset], regnames[base]);
13770 tcg_temp_free(t0);
13771}
13772
461c08df
JL
13773static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
13774 int ret, int v1, int v2)
13775{
13776 const char *opn = "mipsdsp arith";
13777 TCGv v1_t;
13778 TCGv v2_t;
13779
13780 if (ret == 0) {
13781 /* Treat as NOP. */
13782 MIPS_DEBUG("NOP");
13783 return;
13784 }
13785
13786 v1_t = tcg_temp_new();
13787 v2_t = tcg_temp_new();
13788
13789 gen_load_gpr(v1_t, v1);
13790 gen_load_gpr(v2_t, v2);
13791
13792 switch (op1) {
13793 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
13794 case OPC_MULT_G_2E:
13795 check_dspr2(ctx);
13796 switch (op2) {
13797 case OPC_ADDUH_QB:
13798 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
13799 break;
13800 case OPC_ADDUH_R_QB:
13801 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
13802 break;
13803 case OPC_ADDQH_PH:
13804 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
13805 break;
13806 case OPC_ADDQH_R_PH:
13807 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
13808 break;
13809 case OPC_ADDQH_W:
13810 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
13811 break;
13812 case OPC_ADDQH_R_W:
13813 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
13814 break;
13815 case OPC_SUBUH_QB:
13816 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
13817 break;
13818 case OPC_SUBUH_R_QB:
13819 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
13820 break;
13821 case OPC_SUBQH_PH:
13822 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
13823 break;
13824 case OPC_SUBQH_R_PH:
13825 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
13826 break;
13827 case OPC_SUBQH_W:
13828 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
13829 break;
13830 case OPC_SUBQH_R_W:
13831 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
13832 break;
13833 }
13834 break;
13835 case OPC_ABSQ_S_PH_DSP:
13836 switch (op2) {
13837 case OPC_ABSQ_S_QB:
13838 check_dspr2(ctx);
13839 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
13840 break;
13841 case OPC_ABSQ_S_PH:
13842 check_dsp(ctx);
13843 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
13844 break;
13845 case OPC_ABSQ_S_W:
13846 check_dsp(ctx);
13847 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
13848 break;
13849 case OPC_PRECEQ_W_PHL:
13850 check_dsp(ctx);
13851 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
13852 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
13853 break;
13854 case OPC_PRECEQ_W_PHR:
13855 check_dsp(ctx);
13856 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
13857 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
13858 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
13859 break;
13860 case OPC_PRECEQU_PH_QBL:
13861 check_dsp(ctx);
13862 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
13863 break;
13864 case OPC_PRECEQU_PH_QBR:
13865 check_dsp(ctx);
13866 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
13867 break;
13868 case OPC_PRECEQU_PH_QBLA:
13869 check_dsp(ctx);
13870 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
13871 break;
13872 case OPC_PRECEQU_PH_QBRA:
13873 check_dsp(ctx);
13874 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
13875 break;
13876 case OPC_PRECEU_PH_QBL:
13877 check_dsp(ctx);
13878 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
13879 break;
13880 case OPC_PRECEU_PH_QBR:
13881 check_dsp(ctx);
13882 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
13883 break;
13884 case OPC_PRECEU_PH_QBLA:
13885 check_dsp(ctx);
13886 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
13887 break;
13888 case OPC_PRECEU_PH_QBRA:
13889 check_dsp(ctx);
13890 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
13891 break;
13892 }
13893 break;
13894 case OPC_ADDU_QB_DSP:
13895 switch (op2) {
13896 case OPC_ADDQ_PH:
13897 check_dsp(ctx);
13898 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13899 break;
13900 case OPC_ADDQ_S_PH:
13901 check_dsp(ctx);
13902 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13903 break;
13904 case OPC_ADDQ_S_W:
13905 check_dsp(ctx);
13906 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13907 break;
13908 case OPC_ADDU_QB:
13909 check_dsp(ctx);
13910 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13911 break;
13912 case OPC_ADDU_S_QB:
13913 check_dsp(ctx);
13914 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13915 break;
13916 case OPC_ADDU_PH:
13917 check_dspr2(ctx);
13918 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13919 break;
13920 case OPC_ADDU_S_PH:
13921 check_dspr2(ctx);
13922 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13923 break;
13924 case OPC_SUBQ_PH:
13925 check_dsp(ctx);
13926 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13927 break;
13928 case OPC_SUBQ_S_PH:
13929 check_dsp(ctx);
13930 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13931 break;
13932 case OPC_SUBQ_S_W:
13933 check_dsp(ctx);
13934 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13935 break;
13936 case OPC_SUBU_QB:
13937 check_dsp(ctx);
13938 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13939 break;
13940 case OPC_SUBU_S_QB:
13941 check_dsp(ctx);
13942 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13943 break;
13944 case OPC_SUBU_PH:
13945 check_dspr2(ctx);
13946 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13947 break;
13948 case OPC_SUBU_S_PH:
13949 check_dspr2(ctx);
13950 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13951 break;
13952 case OPC_ADDSC:
13953 check_dsp(ctx);
13954 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13955 break;
13956 case OPC_ADDWC:
13957 check_dsp(ctx);
13958 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13959 break;
13960 case OPC_MODSUB:
13961 check_dsp(ctx);
13962 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
13963 break;
13964 case OPC_RADDU_W_QB:
13965 check_dsp(ctx);
13966 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
13967 break;
13968 }
13969 break;
13970 case OPC_CMPU_EQ_QB_DSP:
13971 switch (op2) {
13972 case OPC_PRECR_QB_PH:
13973 check_dspr2(ctx);
13974 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
13975 break;
13976 case OPC_PRECRQ_QB_PH:
13977 check_dsp(ctx);
13978 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
13979 break;
13980 case OPC_PRECR_SRA_PH_W:
13981 check_dspr2(ctx);
13982 {
13983 TCGv_i32 sa_t = tcg_const_i32(v2);
13984 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
13985 cpu_gpr[ret]);
13986 tcg_temp_free_i32(sa_t);
13987 break;
13988 }
13989 case OPC_PRECR_SRA_R_PH_W:
13990 check_dspr2(ctx);
13991 {
13992 TCGv_i32 sa_t = tcg_const_i32(v2);
13993 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
13994 cpu_gpr[ret]);
13995 tcg_temp_free_i32(sa_t);
13996 break;
13997 }
13998 case OPC_PRECRQ_PH_W:
13999 check_dsp(ctx);
14000 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
14001 break;
14002 case OPC_PRECRQ_RS_PH_W:
14003 check_dsp(ctx);
14004 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14005 break;
14006 case OPC_PRECRQU_S_QB_PH:
14007 check_dsp(ctx);
14008 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14009 break;
14010 }
14011 break;
14012#ifdef TARGET_MIPS64
14013 case OPC_ABSQ_S_QH_DSP:
14014 switch (op2) {
14015 case OPC_PRECEQ_L_PWL:
14016 check_dsp(ctx);
14017 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
14018 break;
14019 case OPC_PRECEQ_L_PWR:
14020 check_dsp(ctx);
14021 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
14022 break;
14023 case OPC_PRECEQ_PW_QHL:
14024 check_dsp(ctx);
14025 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
14026 break;
14027 case OPC_PRECEQ_PW_QHR:
14028 check_dsp(ctx);
14029 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
14030 break;
14031 case OPC_PRECEQ_PW_QHLA:
14032 check_dsp(ctx);
14033 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
14034 break;
14035 case OPC_PRECEQ_PW_QHRA:
14036 check_dsp(ctx);
14037 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
14038 break;
14039 case OPC_PRECEQU_QH_OBL:
14040 check_dsp(ctx);
14041 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
14042 break;
14043 case OPC_PRECEQU_QH_OBR:
14044 check_dsp(ctx);
14045 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
14046 break;
14047 case OPC_PRECEQU_QH_OBLA:
14048 check_dsp(ctx);
14049 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
14050 break;
14051 case OPC_PRECEQU_QH_OBRA:
14052 check_dsp(ctx);
14053 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
14054 break;
14055 case OPC_PRECEU_QH_OBL:
14056 check_dsp(ctx);
14057 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
14058 break;
14059 case OPC_PRECEU_QH_OBR:
14060 check_dsp(ctx);
14061 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
14062 break;
14063 case OPC_PRECEU_QH_OBLA:
14064 check_dsp(ctx);
14065 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
14066 break;
14067 case OPC_PRECEU_QH_OBRA:
14068 check_dsp(ctx);
14069 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
14070 break;
14071 case OPC_ABSQ_S_OB:
14072 check_dspr2(ctx);
14073 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
14074 break;
14075 case OPC_ABSQ_S_PW:
14076 check_dsp(ctx);
14077 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
14078 break;
14079 case OPC_ABSQ_S_QH:
14080 check_dsp(ctx);
14081 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
14082 break;
14083 }
14084 break;
14085 case OPC_ADDU_OB_DSP:
14086 switch (op2) {
14087 case OPC_RADDU_L_OB:
14088 check_dsp(ctx);
14089 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
14090 break;
14091 case OPC_SUBQ_PW:
14092 check_dsp(ctx);
14093 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14094 break;
14095 case OPC_SUBQ_S_PW:
14096 check_dsp(ctx);
14097 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14098 break;
14099 case OPC_SUBQ_QH:
14100 check_dsp(ctx);
14101 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14102 break;
14103 case OPC_SUBQ_S_QH:
14104 check_dsp(ctx);
14105 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14106 break;
14107 case OPC_SUBU_OB:
14108 check_dsp(ctx);
14109 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14110 break;
14111 case OPC_SUBU_S_OB:
14112 check_dsp(ctx);
14113 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14114 break;
14115 case OPC_SUBU_QH:
14116 check_dspr2(ctx);
14117 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14118 break;
14119 case OPC_SUBU_S_QH:
14120 check_dspr2(ctx);
14121 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14122 break;
14123 case OPC_SUBUH_OB:
14124 check_dspr2(ctx);
14125 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
14126 break;
14127 case OPC_SUBUH_R_OB:
14128 check_dspr2(ctx);
14129 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
14130 break;
14131 case OPC_ADDQ_PW:
14132 check_dsp(ctx);
14133 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14134 break;
14135 case OPC_ADDQ_S_PW:
14136 check_dsp(ctx);
14137 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14138 break;
14139 case OPC_ADDQ_QH:
14140 check_dsp(ctx);
14141 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14142 break;
14143 case OPC_ADDQ_S_QH:
14144 check_dsp(ctx);
14145 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14146 break;
14147 case OPC_ADDU_OB:
14148 check_dsp(ctx);
14149 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14150 break;
14151 case OPC_ADDU_S_OB:
14152 check_dsp(ctx);
14153 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14154 break;
14155 case OPC_ADDU_QH:
14156 check_dspr2(ctx);
14157 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14158 break;
14159 case OPC_ADDU_S_QH:
14160 check_dspr2(ctx);
14161 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14162 break;
14163 case OPC_ADDUH_OB:
14164 check_dspr2(ctx);
14165 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
14166 break;
14167 case OPC_ADDUH_R_OB:
14168 check_dspr2(ctx);
14169 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
14170 break;
14171 }
14172 break;
14173 case OPC_CMPU_EQ_OB_DSP:
14174 switch (op2) {
14175 case OPC_PRECR_OB_QH:
14176 check_dspr2(ctx);
14177 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
14178 break;
14179 case OPC_PRECR_SRA_QH_PW:
14180 check_dspr2(ctx);
14181 {
14182 TCGv_i32 ret_t = tcg_const_i32(ret);
14183 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
14184 tcg_temp_free_i32(ret_t);
14185 break;
14186 }
14187 case OPC_PRECR_SRA_R_QH_PW:
14188 check_dspr2(ctx);
14189 {
14190 TCGv_i32 sa_v = tcg_const_i32(ret);
14191 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
14192 tcg_temp_free_i32(sa_v);
14193 break;
14194 }
14195 case OPC_PRECRQ_OB_QH:
14196 check_dsp(ctx);
14197 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
14198 break;
14199 case OPC_PRECRQ_PW_L:
14200 check_dsp(ctx);
14201 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
14202 break;
14203 case OPC_PRECRQ_QH_PW:
14204 check_dsp(ctx);
14205 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
14206 break;
14207 case OPC_PRECRQ_RS_QH_PW:
14208 check_dsp(ctx);
14209 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14210 break;
14211 case OPC_PRECRQU_S_OB_QH:
14212 check_dsp(ctx);
14213 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14214 break;
14215 }
14216 break;
14217#endif
14218 }
14219
14220 tcg_temp_free(v1_t);
14221 tcg_temp_free(v2_t);
14222
14223 (void)opn; /* avoid a compiler warning */
14224 MIPS_DEBUG("%s", opn);
14225}
9b1a1d68 14226
77c5fa8b
JL
14227static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
14228 int ret, int v1, int v2)
14229{
14230 uint32_t op2;
14231 const char *opn = "mipsdsp shift";
14232 TCGv t0;
14233 TCGv v1_t;
14234 TCGv v2_t;
14235
14236 if (ret == 0) {
14237 /* Treat as NOP. */
14238 MIPS_DEBUG("NOP");
14239 return;
14240 }
14241
14242 t0 = tcg_temp_new();
14243 v1_t = tcg_temp_new();
14244 v2_t = tcg_temp_new();
14245
14246 tcg_gen_movi_tl(t0, v1);
14247 gen_load_gpr(v1_t, v1);
14248 gen_load_gpr(v2_t, v2);
14249
14250 switch (opc) {
14251 case OPC_SHLL_QB_DSP:
14252 {
14253 op2 = MASK_SHLL_QB(ctx->opcode);
14254 switch (op2) {
14255 case OPC_SHLL_QB:
14256 check_dsp(ctx);
14257 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
14258 break;
14259 case OPC_SHLLV_QB:
14260 check_dsp(ctx);
14261 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14262 break;
14263 case OPC_SHLL_PH:
14264 check_dsp(ctx);
14265 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
14266 break;
14267 case OPC_SHLLV_PH:
14268 check_dsp(ctx);
14269 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14270 break;
14271 case OPC_SHLL_S_PH:
14272 check_dsp(ctx);
14273 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
14274 break;
14275 case OPC_SHLLV_S_PH:
14276 check_dsp(ctx);
14277 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14278 break;
14279 case OPC_SHLL_S_W:
14280 check_dsp(ctx);
14281 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
14282 break;
14283 case OPC_SHLLV_S_W:
14284 check_dsp(ctx);
14285 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14286 break;
14287 case OPC_SHRL_QB:
14288 check_dsp(ctx);
14289 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
14290 break;
14291 case OPC_SHRLV_QB:
14292 check_dsp(ctx);
14293 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
14294 break;
14295 case OPC_SHRL_PH:
14296 check_dspr2(ctx);
14297 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
14298 break;
14299 case OPC_SHRLV_PH:
14300 check_dspr2(ctx);
14301 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
14302 break;
14303 case OPC_SHRA_QB:
14304 check_dspr2(ctx);
14305 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
14306 break;
14307 case OPC_SHRA_R_QB:
14308 check_dspr2(ctx);
14309 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
14310 break;
14311 case OPC_SHRAV_QB:
14312 check_dspr2(ctx);
14313 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
14314 break;
14315 case OPC_SHRAV_R_QB:
14316 check_dspr2(ctx);
14317 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
14318 break;
14319 case OPC_SHRA_PH:
14320 check_dsp(ctx);
14321 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
14322 break;
14323 case OPC_SHRA_R_PH:
14324 check_dsp(ctx);
14325 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
14326 break;
14327 case OPC_SHRAV_PH:
14328 check_dsp(ctx);
14329 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
14330 break;
14331 case OPC_SHRAV_R_PH:
14332 check_dsp(ctx);
14333 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
14334 break;
14335 case OPC_SHRA_R_W:
14336 check_dsp(ctx);
14337 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
14338 break;
14339 case OPC_SHRAV_R_W:
14340 check_dsp(ctx);
14341 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
14342 break;
14343 default: /* Invalid */
14344 MIPS_INVAL("MASK SHLL.QB");
14345 generate_exception(ctx, EXCP_RI);
14346 break;
14347 }
14348 break;
14349 }
14350#ifdef TARGET_MIPS64
14351 case OPC_SHLL_OB_DSP:
14352 op2 = MASK_SHLL_OB(ctx->opcode);
14353 switch (op2) {
14354 case OPC_SHLL_PW:
14355 check_dsp(ctx);
14356 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
14357 break;
14358 case OPC_SHLLV_PW:
14359 check_dsp(ctx);
14360 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
14361 break;
14362 case OPC_SHLL_S_PW:
14363 check_dsp(ctx);
14364 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
14365 break;
14366 case OPC_SHLLV_S_PW:
14367 check_dsp(ctx);
14368 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
14369 break;
14370 case OPC_SHLL_OB:
14371 check_dsp(ctx);
14372 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
14373 break;
14374 case OPC_SHLLV_OB:
14375 check_dsp(ctx);
14376 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
14377 break;
14378 case OPC_SHLL_QH:
14379 check_dsp(ctx);
14380 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
14381 break;
14382 case OPC_SHLLV_QH:
14383 check_dsp(ctx);
14384 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
14385 break;
14386 case OPC_SHLL_S_QH:
14387 check_dsp(ctx);
14388 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
14389 break;
14390 case OPC_SHLLV_S_QH:
14391 check_dsp(ctx);
14392 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
14393 break;
14394 case OPC_SHRA_OB:
14395 check_dspr2(ctx);
14396 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
14397 break;
14398 case OPC_SHRAV_OB:
14399 check_dspr2(ctx);
14400 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
14401 break;
14402 case OPC_SHRA_R_OB:
14403 check_dspr2(ctx);
14404 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
14405 break;
14406 case OPC_SHRAV_R_OB:
14407 check_dspr2(ctx);
14408 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
14409 break;
14410 case OPC_SHRA_PW:
14411 check_dsp(ctx);
14412 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
14413 break;
14414 case OPC_SHRAV_PW:
14415 check_dsp(ctx);
14416 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
14417 break;
14418 case OPC_SHRA_R_PW:
14419 check_dsp(ctx);
14420 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
14421 break;
14422 case OPC_SHRAV_R_PW:
14423 check_dsp(ctx);
14424 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
14425 break;
14426 case OPC_SHRA_QH:
14427 check_dsp(ctx);
14428 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
14429 break;
14430 case OPC_SHRAV_QH:
14431 check_dsp(ctx);
14432 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
14433 break;
14434 case OPC_SHRA_R_QH:
14435 check_dsp(ctx);
14436 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
14437 break;
14438 case OPC_SHRAV_R_QH:
14439 check_dsp(ctx);
14440 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
14441 break;
14442 case OPC_SHRL_OB:
14443 check_dsp(ctx);
14444 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
14445 break;
14446 case OPC_SHRLV_OB:
14447 check_dsp(ctx);
14448 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
14449 break;
14450 case OPC_SHRL_QH:
14451 check_dspr2(ctx);
14452 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
14453 break;
14454 case OPC_SHRLV_QH:
14455 check_dspr2(ctx);
14456 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
14457 break;
14458 default: /* Invalid */
14459 MIPS_INVAL("MASK SHLL.OB");
14460 generate_exception(ctx, EXCP_RI);
14461 break;
14462 }
14463 break;
14464#endif
14465 }
14466
14467 tcg_temp_free(t0);
14468 tcg_temp_free(v1_t);
14469 tcg_temp_free(v2_t);
14470 (void)opn; /* avoid a compiler warning */
14471 MIPS_DEBUG("%s", opn);
14472}
14473
a22260ae
JL
14474static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
14475 int ret, int v1, int v2, int check_ret)
14476{
14477 const char *opn = "mipsdsp multiply";
14478 TCGv_i32 t0;
14479 TCGv v1_t;
14480 TCGv v2_t;
14481
14482 if ((ret == 0) && (check_ret == 1)) {
14483 /* Treat as NOP. */
14484 MIPS_DEBUG("NOP");
14485 return;
14486 }
14487
14488 t0 = tcg_temp_new_i32();
14489 v1_t = tcg_temp_new();
14490 v2_t = tcg_temp_new();
14491
14492 tcg_gen_movi_i32(t0, ret);
14493 gen_load_gpr(v1_t, v1);
14494 gen_load_gpr(v2_t, v2);
14495
14496 switch (op1) {
14497 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
14498 * the same mask and op1. */
14499 case OPC_MULT_G_2E:
639eadb9 14500 check_dspr2(ctx);
a22260ae
JL
14501 switch (op2) {
14502 case OPC_MUL_PH:
14503 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14504 break;
14505 case OPC_MUL_S_PH:
14506 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14507 break;
14508 case OPC_MULQ_S_W:
14509 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14510 break;
14511 case OPC_MULQ_RS_W:
14512 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14513 break;
14514 }
14515 break;
14516 case OPC_DPA_W_PH_DSP:
14517 switch (op2) {
14518 case OPC_DPAU_H_QBL:
14519 check_dsp(ctx);
14520 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
14521 break;
14522 case OPC_DPAU_H_QBR:
14523 check_dsp(ctx);
14524 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
14525 break;
14526 case OPC_DPSU_H_QBL:
14527 check_dsp(ctx);
14528 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
14529 break;
14530 case OPC_DPSU_H_QBR:
14531 check_dsp(ctx);
14532 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
14533 break;
14534 case OPC_DPA_W_PH:
14535 check_dspr2(ctx);
14536 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
14537 break;
14538 case OPC_DPAX_W_PH:
14539 check_dspr2(ctx);
14540 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
14541 break;
14542 case OPC_DPAQ_S_W_PH:
14543 check_dsp(ctx);
14544 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
14545 break;
14546 case OPC_DPAQX_S_W_PH:
14547 check_dspr2(ctx);
14548 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
14549 break;
14550 case OPC_DPAQX_SA_W_PH:
14551 check_dspr2(ctx);
14552 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
14553 break;
14554 case OPC_DPS_W_PH:
14555 check_dspr2(ctx);
14556 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
14557 break;
14558 case OPC_DPSX_W_PH:
14559 check_dspr2(ctx);
14560 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
14561 break;
14562 case OPC_DPSQ_S_W_PH:
14563 check_dsp(ctx);
14564 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
14565 break;
14566 case OPC_DPSQX_S_W_PH:
14567 check_dspr2(ctx);
14568 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
14569 break;
14570 case OPC_DPSQX_SA_W_PH:
14571 check_dspr2(ctx);
14572 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
14573 break;
14574 case OPC_MULSAQ_S_W_PH:
14575 check_dsp(ctx);
14576 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
14577 break;
14578 case OPC_DPAQ_SA_L_W:
14579 check_dsp(ctx);
14580 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
14581 break;
14582 case OPC_DPSQ_SA_L_W:
14583 check_dsp(ctx);
14584 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
14585 break;
14586 case OPC_MAQ_S_W_PHL:
14587 check_dsp(ctx);
14588 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
14589 break;
14590 case OPC_MAQ_S_W_PHR:
14591 check_dsp(ctx);
14592 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
14593 break;
14594 case OPC_MAQ_SA_W_PHL:
14595 check_dsp(ctx);
14596 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
14597 break;
14598 case OPC_MAQ_SA_W_PHR:
14599 check_dsp(ctx);
14600 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
14601 break;
14602 case OPC_MULSA_W_PH:
14603 check_dspr2(ctx);
14604 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
14605 break;
14606 }
14607 break;
14608#ifdef TARGET_MIPS64
14609 case OPC_DPAQ_W_QH_DSP:
14610 {
14611 int ac = ret & 0x03;
14612 tcg_gen_movi_i32(t0, ac);
14613
14614 switch (op2) {
14615 case OPC_DMADD:
14616 check_dsp(ctx);
14617 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
14618 break;
14619 case OPC_DMADDU:
14620 check_dsp(ctx);
14621 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
14622 break;
14623 case OPC_DMSUB:
14624 check_dsp(ctx);
14625 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
14626 break;
14627 case OPC_DMSUBU:
14628 check_dsp(ctx);
14629 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
14630 break;
14631 case OPC_DPA_W_QH:
14632 check_dspr2(ctx);
14633 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
14634 break;
14635 case OPC_DPAQ_S_W_QH:
14636 check_dsp(ctx);
14637 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
14638 break;
14639 case OPC_DPAQ_SA_L_PW:
14640 check_dsp(ctx);
14641 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
14642 break;
14643 case OPC_DPAU_H_OBL:
14644 check_dsp(ctx);
14645 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
14646 break;
14647 case OPC_DPAU_H_OBR:
14648 check_dsp(ctx);
14649 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
14650 break;
14651 case OPC_DPS_W_QH:
14652 check_dspr2(ctx);
14653 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
14654 break;
14655 case OPC_DPSQ_S_W_QH:
14656 check_dsp(ctx);
14657 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
14658 break;
14659 case OPC_DPSQ_SA_L_PW:
14660 check_dsp(ctx);
14661 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
14662 break;
14663 case OPC_DPSU_H_OBL:
14664 check_dsp(ctx);
14665 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
14666 break;
14667 case OPC_DPSU_H_OBR:
14668 check_dsp(ctx);
14669 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
14670 break;
14671 case OPC_MAQ_S_L_PWL:
14672 check_dsp(ctx);
14673 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
14674 break;
14675 case OPC_MAQ_S_L_PWR:
14676 check_dsp(ctx);
14677 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
14678 break;
14679 case OPC_MAQ_S_W_QHLL:
14680 check_dsp(ctx);
14681 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
14682 break;
14683 case OPC_MAQ_SA_W_QHLL:
14684 check_dsp(ctx);
14685 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
14686 break;
14687 case OPC_MAQ_S_W_QHLR:
14688 check_dsp(ctx);
14689 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
14690 break;
14691 case OPC_MAQ_SA_W_QHLR:
14692 check_dsp(ctx);
14693 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
14694 break;
14695 case OPC_MAQ_S_W_QHRL:
14696 check_dsp(ctx);
14697 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
14698 break;
14699 case OPC_MAQ_SA_W_QHRL:
14700 check_dsp(ctx);
14701 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
14702 break;
14703 case OPC_MAQ_S_W_QHRR:
14704 check_dsp(ctx);
14705 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
14706 break;
14707 case OPC_MAQ_SA_W_QHRR:
14708 check_dsp(ctx);
14709 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
14710 break;
14711 case OPC_MULSAQ_S_L_PW:
14712 check_dsp(ctx);
14713 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
14714 break;
14715 case OPC_MULSAQ_S_W_QH:
14716 check_dsp(ctx);
14717 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
14718 break;
14719 }
14720 }
14721 break;
14722#endif
14723 case OPC_ADDU_QB_DSP:
14724 switch (op2) {
14725 case OPC_MULEU_S_PH_QBL:
14726 check_dsp(ctx);
14727 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14728 break;
14729 case OPC_MULEU_S_PH_QBR:
14730 check_dsp(ctx);
14731 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14732 break;
14733 case OPC_MULQ_RS_PH:
14734 check_dsp(ctx);
14735 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14736 break;
14737 case OPC_MULEQ_S_W_PHL:
14738 check_dsp(ctx);
14739 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14740 break;
14741 case OPC_MULEQ_S_W_PHR:
14742 check_dsp(ctx);
14743 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14744 break;
14745 case OPC_MULQ_S_PH:
14746 check_dspr2(ctx);
14747 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14748 break;
14749 }
14750 break;
14751#ifdef TARGET_MIPS64
14752 case OPC_ADDU_OB_DSP:
14753 switch (op2) {
14754 case OPC_MULEQ_S_PW_QHL:
14755 check_dsp(ctx);
14756 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14757 break;
14758 case OPC_MULEQ_S_PW_QHR:
14759 check_dsp(ctx);
14760 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14761 break;
14762 case OPC_MULEU_S_QH_OBL:
14763 check_dsp(ctx);
14764 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14765 break;
14766 case OPC_MULEU_S_QH_OBR:
14767 check_dsp(ctx);
14768 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14769 break;
14770 case OPC_MULQ_RS_QH:
14771 check_dsp(ctx);
14772 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14773 break;
14774 }
14775 break;
14776#endif
14777 }
14778
14779 tcg_temp_free_i32(t0);
14780 tcg_temp_free(v1_t);
14781 tcg_temp_free(v2_t);
14782
14783 (void)opn; /* avoid a compiler warning */
14784 MIPS_DEBUG("%s", opn);
14785
14786}
14787
d75c135e 14788static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
1cb6686c
JL
14789 int ret, int val)
14790{
14791 const char *opn = "mipsdsp Bit/ Manipulation";
14792 int16_t imm;
14793 TCGv t0;
14794 TCGv val_t;
14795
14796 if (ret == 0) {
14797 /* Treat as NOP. */
14798 MIPS_DEBUG("NOP");
14799 return;
14800 }
14801
14802 t0 = tcg_temp_new();
14803 val_t = tcg_temp_new();
14804 gen_load_gpr(val_t, val);
14805
14806 switch (op1) {
14807 case OPC_ABSQ_S_PH_DSP:
14808 switch (op2) {
14809 case OPC_BITREV:
14810 check_dsp(ctx);
14811 gen_helper_bitrev(cpu_gpr[ret], val_t);
14812 break;
14813 case OPC_REPL_QB:
14814 check_dsp(ctx);
14815 {
14816 target_long result;
14817 imm = (ctx->opcode >> 16) & 0xFF;
14818 result = (uint32_t)imm << 24 |
14819 (uint32_t)imm << 16 |
14820 (uint32_t)imm << 8 |
14821 (uint32_t)imm;
14822 result = (int32_t)result;
14823 tcg_gen_movi_tl(cpu_gpr[ret], result);
14824 }
14825 break;
14826 case OPC_REPLV_QB:
14827 check_dsp(ctx);
14828 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
14829 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
14830 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14831 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
14832 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14833 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
14834 break;
14835 case OPC_REPL_PH:
14836 check_dsp(ctx);
14837 {
14838 imm = (ctx->opcode >> 16) & 0x03FF;
c4aaba92 14839 imm = (int16_t)(imm << 6) >> 6;
1cb6686c
JL
14840 tcg_gen_movi_tl(cpu_gpr[ret], \
14841 (target_long)((int32_t)imm << 16 | \
c4aaba92 14842 (uint16_t)imm));
1cb6686c
JL
14843 }
14844 break;
14845 case OPC_REPLV_PH:
14846 check_dsp(ctx);
14847 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
14848 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
14849 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14850 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
14851 break;
14852 }
14853 break;
14854#ifdef TARGET_MIPS64
14855 case OPC_ABSQ_S_QH_DSP:
14856 switch (op2) {
14857 case OPC_REPL_OB:
14858 check_dsp(ctx);
14859 {
14860 target_long temp;
14861
14862 imm = (ctx->opcode >> 16) & 0xFF;
14863 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
14864 temp = (temp << 16) | temp;
14865 temp = (temp << 32) | temp;
14866 tcg_gen_movi_tl(cpu_gpr[ret], temp);
14867 break;
14868 }
14869 case OPC_REPL_PW:
14870 check_dsp(ctx);
14871 {
14872 target_long temp;
14873
14874 imm = (ctx->opcode >> 16) & 0x03FF;
14875 imm = (int16_t)(imm << 6) >> 6;
14876 temp = ((target_long)imm << 32) \
14877 | ((target_long)imm & 0xFFFFFFFF);
14878 tcg_gen_movi_tl(cpu_gpr[ret], temp);
14879 break;
14880 }
14881 case OPC_REPL_QH:
14882 check_dsp(ctx);
14883 {
14884 target_long temp;
14885
14886 imm = (ctx->opcode >> 16) & 0x03FF;
14887 imm = (int16_t)(imm << 6) >> 6;
14888
14889 temp = ((uint64_t)(uint16_t)imm << 48) |
14890 ((uint64_t)(uint16_t)imm << 32) |
14891 ((uint64_t)(uint16_t)imm << 16) |
14892 (uint64_t)(uint16_t)imm;
14893 tcg_gen_movi_tl(cpu_gpr[ret], temp);
14894 break;
14895 }
14896 case OPC_REPLV_OB:
14897 check_dsp(ctx);
14898 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
14899 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
14900 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14901 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
14902 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14903 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
14904 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14905 break;
14906 case OPC_REPLV_PW:
14907 check_dsp(ctx);
14908 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
14909 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
14910 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14911 break;
14912 case OPC_REPLV_QH:
14913 check_dsp(ctx);
14914 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
14915 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
14916 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14917 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
14918 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14919 break;
14920 }
14921 break;
14922#endif
14923 }
14924 tcg_temp_free(t0);
14925 tcg_temp_free(val_t);
14926
14927 (void)opn; /* avoid a compiler warning */
14928 MIPS_DEBUG("%s", opn);
14929}
14930
26690560
JL
14931static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
14932 uint32_t op1, uint32_t op2,
14933 int ret, int v1, int v2, int check_ret)
14934{
14935 const char *opn = "mipsdsp add compare pick";
26690560
JL
14936 TCGv t1;
14937 TCGv v1_t;
14938 TCGv v2_t;
14939
14940 if ((ret == 0) && (check_ret == 1)) {
14941 /* Treat as NOP. */
14942 MIPS_DEBUG("NOP");
14943 return;
14944 }
14945
26690560
JL
14946 t1 = tcg_temp_new();
14947 v1_t = tcg_temp_new();
14948 v2_t = tcg_temp_new();
14949
14950 gen_load_gpr(v1_t, v1);
14951 gen_load_gpr(v2_t, v2);
14952
14953 switch (op1) {
26690560
JL
14954 case OPC_CMPU_EQ_QB_DSP:
14955 switch (op2) {
14956 case OPC_CMPU_EQ_QB:
14957 check_dsp(ctx);
14958 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
14959 break;
14960 case OPC_CMPU_LT_QB:
14961 check_dsp(ctx);
14962 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
14963 break;
14964 case OPC_CMPU_LE_QB:
14965 check_dsp(ctx);
14966 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
14967 break;
14968 case OPC_CMPGU_EQ_QB:
14969 check_dsp(ctx);
14970 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
14971 break;
14972 case OPC_CMPGU_LT_QB:
14973 check_dsp(ctx);
14974 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
14975 break;
14976 case OPC_CMPGU_LE_QB:
14977 check_dsp(ctx);
14978 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
14979 break;
14980 case OPC_CMPGDU_EQ_QB:
14981 check_dspr2(ctx);
14982 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
14983 tcg_gen_mov_tl(cpu_gpr[ret], t1);
14984 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
14985 tcg_gen_shli_tl(t1, t1, 24);
14986 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
14987 break;
14988 case OPC_CMPGDU_LT_QB:
14989 check_dspr2(ctx);
14990 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
14991 tcg_gen_mov_tl(cpu_gpr[ret], t1);
14992 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
14993 tcg_gen_shli_tl(t1, t1, 24);
14994 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
14995 break;
14996 case OPC_CMPGDU_LE_QB:
14997 check_dspr2(ctx);
14998 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
14999 tcg_gen_mov_tl(cpu_gpr[ret], t1);
15000 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
15001 tcg_gen_shli_tl(t1, t1, 24);
15002 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
15003 break;
15004 case OPC_CMP_EQ_PH:
15005 check_dsp(ctx);
15006 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
15007 break;
15008 case OPC_CMP_LT_PH:
15009 check_dsp(ctx);
15010 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
15011 break;
15012 case OPC_CMP_LE_PH:
15013 check_dsp(ctx);
15014 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
15015 break;
15016 case OPC_PICK_QB:
15017 check_dsp(ctx);
15018 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15019 break;
15020 case OPC_PICK_PH:
15021 check_dsp(ctx);
15022 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15023 break;
15024 case OPC_PACKRL_PH:
15025 check_dsp(ctx);
15026 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
15027 break;
15028 }
15029 break;
15030#ifdef TARGET_MIPS64
15031 case OPC_CMPU_EQ_OB_DSP:
15032 switch (op2) {
15033 case OPC_CMP_EQ_PW:
15034 check_dsp(ctx);
15035 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
15036 break;
15037 case OPC_CMP_LT_PW:
15038 check_dsp(ctx);
15039 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
15040 break;
15041 case OPC_CMP_LE_PW:
15042 check_dsp(ctx);
15043 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
15044 break;
15045 case OPC_CMP_EQ_QH:
15046 check_dsp(ctx);
15047 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
15048 break;
15049 case OPC_CMP_LT_QH:
15050 check_dsp(ctx);
15051 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
15052 break;
15053 case OPC_CMP_LE_QH:
15054 check_dsp(ctx);
15055 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
15056 break;
15057 case OPC_CMPGDU_EQ_OB:
15058 check_dspr2(ctx);
15059 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15060 break;
15061 case OPC_CMPGDU_LT_OB:
15062 check_dspr2(ctx);
15063 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15064 break;
15065 case OPC_CMPGDU_LE_OB:
15066 check_dspr2(ctx);
15067 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15068 break;
15069 case OPC_CMPGU_EQ_OB:
15070 check_dsp(ctx);
15071 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
15072 break;
15073 case OPC_CMPGU_LT_OB:
15074 check_dsp(ctx);
15075 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
15076 break;
15077 case OPC_CMPGU_LE_OB:
15078 check_dsp(ctx);
15079 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
15080 break;
15081 case OPC_CMPU_EQ_OB:
15082 check_dsp(ctx);
15083 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
15084 break;
15085 case OPC_CMPU_LT_OB:
15086 check_dsp(ctx);
15087 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
15088 break;
15089 case OPC_CMPU_LE_OB:
15090 check_dsp(ctx);
15091 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
15092 break;
15093 case OPC_PACKRL_PW:
15094 check_dsp(ctx);
15095 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
15096 break;
15097 case OPC_PICK_OB:
15098 check_dsp(ctx);
15099 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15100 break;
15101 case OPC_PICK_PW:
15102 check_dsp(ctx);
15103 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15104 break;
15105 case OPC_PICK_QH:
15106 check_dsp(ctx);
15107 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15108 break;
15109 }
15110 break;
df6126a7
AJ
15111#endif
15112 }
15113
15114 tcg_temp_free(t1);
15115 tcg_temp_free(v1_t);
15116 tcg_temp_free(v2_t);
15117
15118 (void)opn; /* avoid a compiler warning */
15119 MIPS_DEBUG("%s", opn);
15120}
15121
15122static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
15123 uint32_t op1, int rt, int rs, int sa)
15124{
15125 const char *opn = "mipsdsp append/dappend";
15126 TCGv t0;
15127
15128 check_dspr2(ctx);
15129
15130 if (rt == 0) {
15131 /* Treat as NOP. */
15132 MIPS_DEBUG("NOP");
15133 return;
15134 }
15135
15136 t0 = tcg_temp_new();
15137 gen_load_gpr(t0, rs);
15138
15139 switch (op1) {
15140 case OPC_APPEND_DSP:
15141 switch (MASK_APPEND(ctx->opcode)) {
15142 case OPC_APPEND:
15143 if (sa != 0) {
15144 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
15145 }
15146 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
15147 break;
15148 case OPC_PREPEND:
15149 if (sa != 0) {
15150 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
15151 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
15152 tcg_gen_shli_tl(t0, t0, 32 - sa);
15153 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
15154 }
15155 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
15156 break;
15157 case OPC_BALIGN:
15158 sa &= 3;
15159 if (sa != 0 && sa != 2) {
15160 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
15161 tcg_gen_ext32u_tl(t0, t0);
15162 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
15163 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
15164 }
15165 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
15166 break;
15167 default: /* Invalid */
15168 MIPS_INVAL("MASK APPEND");
15169 generate_exception(ctx, EXCP_RI);
15170 break;
15171 }
15172 break;
15173#ifdef TARGET_MIPS64
26690560 15174 case OPC_DAPPEND_DSP:
df6126a7 15175 switch (MASK_DAPPEND(ctx->opcode)) {
26690560 15176 case OPC_DAPPEND:
df6126a7
AJ
15177 if (sa != 0) {
15178 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
15179 }
26690560
JL
15180 break;
15181 case OPC_PREPENDD:
df6126a7
AJ
15182 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
15183 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
15184 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
26690560
JL
15185 break;
15186 case OPC_PREPENDW:
df6126a7
AJ
15187 if (sa != 0) {
15188 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
15189 tcg_gen_shli_tl(t0, t0, 64 - sa);
15190 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
15191 }
26690560
JL
15192 break;
15193 case OPC_DBALIGN:
df6126a7
AJ
15194 sa &= 7;
15195 if (sa != 0 && sa != 2 && sa != 4) {
15196 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
15197 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
15198 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
15199 }
26690560
JL
15200 break;
15201 default: /* Invalid */
15202 MIPS_INVAL("MASK DAPPEND");
15203 generate_exception(ctx, EXCP_RI);
15204 break;
15205 }
15206 break;
15207#endif
15208 }
df6126a7 15209 tcg_temp_free(t0);
26690560
JL
15210 (void)opn; /* avoid a compiler warning */
15211 MIPS_DEBUG("%s", opn);
15212}
15213
b53371ed
JL
15214static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
15215 int ret, int v1, int v2, int check_ret)
15216
15217{
15218 const char *opn = "mipsdsp accumulator";
15219 TCGv t0;
15220 TCGv t1;
15221 TCGv v1_t;
15222 TCGv v2_t;
15223 int16_t imm;
15224
15225 if ((ret == 0) && (check_ret == 1)) {
15226 /* Treat as NOP. */
15227 MIPS_DEBUG("NOP");
15228 return;
15229 }
15230
15231 t0 = tcg_temp_new();
15232 t1 = tcg_temp_new();
15233 v1_t = tcg_temp_new();
15234 v2_t = tcg_temp_new();
15235
15236 gen_load_gpr(v1_t, v1);
15237 gen_load_gpr(v2_t, v2);
15238
15239 switch (op1) {
15240 case OPC_EXTR_W_DSP:
15241 check_dsp(ctx);
15242 switch (op2) {
15243 case OPC_EXTR_W:
15244 tcg_gen_movi_tl(t0, v2);
15245 tcg_gen_movi_tl(t1, v1);
15246 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
15247 break;
15248 case OPC_EXTR_R_W:
15249 tcg_gen_movi_tl(t0, v2);
15250 tcg_gen_movi_tl(t1, v1);
15251 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
15252 break;
15253 case OPC_EXTR_RS_W:
15254 tcg_gen_movi_tl(t0, v2);
15255 tcg_gen_movi_tl(t1, v1);
15256 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
15257 break;
15258 case OPC_EXTR_S_H:
15259 tcg_gen_movi_tl(t0, v2);
15260 tcg_gen_movi_tl(t1, v1);
15261 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
15262 break;
15263 case OPC_EXTRV_S_H:
15264 tcg_gen_movi_tl(t0, v2);
15265 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
15266 break;
15267 case OPC_EXTRV_W:
15268 tcg_gen_movi_tl(t0, v2);
15269 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15270 break;
15271 case OPC_EXTRV_R_W:
15272 tcg_gen_movi_tl(t0, v2);
15273 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15274 break;
15275 case OPC_EXTRV_RS_W:
15276 tcg_gen_movi_tl(t0, v2);
15277 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15278 break;
15279 case OPC_EXTP:
15280 tcg_gen_movi_tl(t0, v2);
15281 tcg_gen_movi_tl(t1, v1);
15282 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
15283 break;
15284 case OPC_EXTPV:
15285 tcg_gen_movi_tl(t0, v2);
15286 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
15287 break;
15288 case OPC_EXTPDP:
15289 tcg_gen_movi_tl(t0, v2);
15290 tcg_gen_movi_tl(t1, v1);
15291 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
15292 break;
15293 case OPC_EXTPDPV:
15294 tcg_gen_movi_tl(t0, v2);
15295 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
15296 break;
15297 case OPC_SHILO:
15298 imm = (ctx->opcode >> 20) & 0x3F;
15299 tcg_gen_movi_tl(t0, ret);
15300 tcg_gen_movi_tl(t1, imm);
15301 gen_helper_shilo(t0, t1, cpu_env);
15302 break;
15303 case OPC_SHILOV:
15304 tcg_gen_movi_tl(t0, ret);
15305 gen_helper_shilo(t0, v1_t, cpu_env);
15306 break;
15307 case OPC_MTHLIP:
15308 tcg_gen_movi_tl(t0, ret);
15309 gen_helper_mthlip(t0, v1_t, cpu_env);
15310 break;
15311 case OPC_WRDSP:
15312 imm = (ctx->opcode >> 11) & 0x3FF;
15313 tcg_gen_movi_tl(t0, imm);
15314 gen_helper_wrdsp(v1_t, t0, cpu_env);
15315 break;
15316 case OPC_RDDSP:
15317 imm = (ctx->opcode >> 16) & 0x03FF;
15318 tcg_gen_movi_tl(t0, imm);
15319 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
15320 break;
15321 }
15322 break;
15323#ifdef TARGET_MIPS64
15324 case OPC_DEXTR_W_DSP:
15325 check_dsp(ctx);
15326 switch (op2) {
15327 case OPC_DMTHLIP:
15328 tcg_gen_movi_tl(t0, ret);
15329 gen_helper_dmthlip(v1_t, t0, cpu_env);
15330 break;
15331 case OPC_DSHILO:
15332 {
15333 int shift = (ctx->opcode >> 19) & 0x7F;
15334 int ac = (ctx->opcode >> 11) & 0x03;
15335 tcg_gen_movi_tl(t0, shift);
15336 tcg_gen_movi_tl(t1, ac);
15337 gen_helper_dshilo(t0, t1, cpu_env);
15338 break;
15339 }
15340 case OPC_DSHILOV:
15341 {
15342 int ac = (ctx->opcode >> 11) & 0x03;
15343 tcg_gen_movi_tl(t0, ac);
15344 gen_helper_dshilo(v1_t, t0, cpu_env);
15345 break;
15346 }
15347 case OPC_DEXTP:
15348 tcg_gen_movi_tl(t0, v2);
15349 tcg_gen_movi_tl(t1, v1);
15350
15351 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
15352 break;
15353 case OPC_DEXTPV:
15354 tcg_gen_movi_tl(t0, v2);
15355 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
15356 break;
15357 case OPC_DEXTPDP:
15358 tcg_gen_movi_tl(t0, v2);
15359 tcg_gen_movi_tl(t1, v1);
15360 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
15361 break;
15362 case OPC_DEXTPDPV:
15363 tcg_gen_movi_tl(t0, v2);
15364 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
15365 break;
15366 case OPC_DEXTR_L:
15367 tcg_gen_movi_tl(t0, v2);
15368 tcg_gen_movi_tl(t1, v1);
15369 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
15370 break;
15371 case OPC_DEXTR_R_L:
15372 tcg_gen_movi_tl(t0, v2);
15373 tcg_gen_movi_tl(t1, v1);
15374 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
15375 break;
15376 case OPC_DEXTR_RS_L:
15377 tcg_gen_movi_tl(t0, v2);
15378 tcg_gen_movi_tl(t1, v1);
15379 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
15380 break;
15381 case OPC_DEXTR_W:
15382 tcg_gen_movi_tl(t0, v2);
15383 tcg_gen_movi_tl(t1, v1);
15384 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
15385 break;
15386 case OPC_DEXTR_R_W:
15387 tcg_gen_movi_tl(t0, v2);
15388 tcg_gen_movi_tl(t1, v1);
15389 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
15390 break;
15391 case OPC_DEXTR_RS_W:
15392 tcg_gen_movi_tl(t0, v2);
15393 tcg_gen_movi_tl(t1, v1);
15394 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
15395 break;
15396 case OPC_DEXTR_S_H:
15397 tcg_gen_movi_tl(t0, v2);
15398 tcg_gen_movi_tl(t1, v1);
15399 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
15400 break;
15401 case OPC_DEXTRV_S_H:
15402 tcg_gen_movi_tl(t0, v2);
15403 tcg_gen_movi_tl(t1, v1);
15404 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
15405 break;
15406 case OPC_DEXTRV_L:
15407 tcg_gen_movi_tl(t0, v2);
15408 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
15409 break;
15410 case OPC_DEXTRV_R_L:
15411 tcg_gen_movi_tl(t0, v2);
15412 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
15413 break;
15414 case OPC_DEXTRV_RS_L:
15415 tcg_gen_movi_tl(t0, v2);
15416 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
15417 break;
15418 case OPC_DEXTRV_W:
15419 tcg_gen_movi_tl(t0, v2);
15420 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15421 break;
15422 case OPC_DEXTRV_R_W:
15423 tcg_gen_movi_tl(t0, v2);
15424 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15425 break;
15426 case OPC_DEXTRV_RS_W:
15427 tcg_gen_movi_tl(t0, v2);
15428 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15429 break;
15430 }
15431 break;
15432#endif
15433 }
15434
15435 tcg_temp_free(t0);
15436 tcg_temp_free(t1);
15437 tcg_temp_free(v1_t);
15438 tcg_temp_free(v2_t);
15439
15440 (void)opn; /* avoid a compiler warning */
15441 MIPS_DEBUG("%s", opn);
15442}
15443
9b1a1d68
JL
15444/* End MIPSDSP functions. */
15445
31837be3
YK
15446/* Compact Branches */
15447static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
15448 int rs, int rt, int32_t offset)
15449{
15450 int bcond_compute = 0;
15451 TCGv t0 = tcg_temp_new();
15452 TCGv t1 = tcg_temp_new();
15453
15454 if (ctx->hflags & MIPS_HFLAG_BMASK) {
15455#ifdef MIPS_DEBUG_DISAS
15456 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
15457#endif
15458 generate_exception(ctx, EXCP_RI);
15459 goto out;
15460 }
15461
15462 /* Load needed operands and calculate btarget */
15463 switch (opc) {
15464 /* compact branch */
15465 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
15466 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
15467 gen_load_gpr(t0, rs);
15468 gen_load_gpr(t1, rt);
15469 bcond_compute = 1;
15470 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
15471 if (rs <= rt && rs == 0) {
15472 /* OPC_BEQZALC, OPC_BNEZALC */
15473 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
15474 }
15475 break;
15476 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
15477 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
15478 gen_load_gpr(t0, rs);
15479 gen_load_gpr(t1, rt);
15480 bcond_compute = 1;
15481 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
15482 break;
15483 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
15484 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
15485 if (rs == 0 || rs == rt) {
15486 /* OPC_BLEZALC, OPC_BGEZALC */
15487 /* OPC_BGTZALC, OPC_BLTZALC */
15488 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
15489 }
15490 gen_load_gpr(t0, rs);
15491 gen_load_gpr(t1, rt);
15492 bcond_compute = 1;
15493 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
15494 break;
15495 case OPC_BC:
15496 case OPC_BALC:
15497 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
15498 break;
15499 case OPC_BEQZC:
15500 case OPC_BNEZC:
15501 if (rs != 0) {
15502 /* OPC_BEQZC, OPC_BNEZC */
15503 gen_load_gpr(t0, rs);
15504 bcond_compute = 1;
15505 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
15506 } else {
15507 /* OPC_JIC, OPC_JIALC */
15508 TCGv tbase = tcg_temp_new();
15509 TCGv toffset = tcg_temp_new();
15510
15511 gen_load_gpr(tbase, rt);
15512 tcg_gen_movi_tl(toffset, offset);
15513 gen_op_addr_add(ctx, btarget, tbase, toffset);
15514 tcg_temp_free(tbase);
15515 tcg_temp_free(toffset);
15516 }
15517 break;
15518 default:
15519 MIPS_INVAL("Compact branch/jump");
15520 generate_exception(ctx, EXCP_RI);
15521 goto out;
15522 }
15523
15524 if (bcond_compute == 0) {
15525 /* Uncoditional compact branch */
15526 switch (opc) {
15527 case OPC_JIALC:
15528 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
15529 /* Fallthrough */
15530 case OPC_JIC:
15531 ctx->hflags |= MIPS_HFLAG_BR;
15532 break;
15533 case OPC_BALC:
15534 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
15535 /* Fallthrough */
15536 case OPC_BC:
15537 ctx->hflags |= MIPS_HFLAG_B;
15538 break;
15539 default:
15540 MIPS_INVAL("Compact branch/jump");
15541 generate_exception(ctx, EXCP_RI);
15542 goto out;
15543 }
15544
15545 /* Generating branch here as compact branches don't have delay slot */
15546 gen_branch(ctx, 4);
15547 } else {
15548 /* Conditional compact branch */
15549 int l1 = gen_new_label();
15550 save_cpu_state(ctx, 0);
15551
15552 switch (opc) {
15553 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
15554 if (rs == 0 && rt != 0) {
15555 /* OPC_BLEZALC */
15556 tcg_gen_brcondi_tl(TCG_COND_LE, t1, 0, l1);
15557 } else if (rs != 0 && rt != 0 && rs == rt) {
15558 /* OPC_BGEZALC */
15559 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
15560 } else {
15561 /* OPC_BGEUC */
15562 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
15563 }
15564 break;
15565 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
15566 if (rs == 0 && rt != 0) {
15567 /* OPC_BGTZALC */
15568 tcg_gen_brcondi_tl(TCG_COND_GT, t1, 0, l1);
15569 } else if (rs != 0 && rt != 0 && rs == rt) {
15570 /* OPC_BLTZALC */
15571 tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
15572 } else {
15573 /* OPC_BLTUC */
15574 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
15575 }
15576 break;
15577 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
15578 if (rs == 0 && rt != 0) {
15579 /* OPC_BLEZC */
15580 tcg_gen_brcondi_tl(TCG_COND_LE, t1, 0, l1);
15581 } else if (rs != 0 && rt != 0 && rs == rt) {
15582 /* OPC_BGEZC */
15583 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
15584 } else {
15585 /* OPC_BGEC */
15586 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
15587 }
15588 break;
15589 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
15590 if (rs == 0 && rt != 0) {
15591 /* OPC_BGTZC */
15592 tcg_gen_brcondi_tl(TCG_COND_GT, t1, 0, l1);
15593 } else if (rs != 0 && rt != 0 && rs == rt) {
15594 /* OPC_BLTZC */
15595 tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
15596 } else {
15597 /* OPC_BLTC */
15598 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
15599 }
15600 break;
15601 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
15602 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
15603 if (rs >= rt) {
15604 /* OPC_BOVC, OPC_BNVC */
15605 TCGv t2 = tcg_temp_new();
15606 TCGv t3 = tcg_temp_new();
15607 TCGv t4 = tcg_temp_new();
15608 TCGv input_overflow = tcg_temp_new();
15609
15610 gen_load_gpr(t0, rs);
15611 gen_load_gpr(t1, rt);
15612 tcg_gen_ext32s_tl(t2, t0);
15613 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
15614 tcg_gen_ext32s_tl(t3, t1);
15615 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
15616 tcg_gen_or_tl(input_overflow, input_overflow, t4);
15617
15618 tcg_gen_add_tl(t4, t2, t3);
15619 tcg_gen_ext32s_tl(t4, t4);
15620 tcg_gen_xor_tl(t2, t2, t3);
15621 tcg_gen_xor_tl(t3, t4, t3);
15622 tcg_gen_andc_tl(t2, t3, t2);
15623 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
15624 tcg_gen_or_tl(t4, t4, input_overflow);
15625 if (opc == OPC_BOVC) {
15626 /* OPC_BOVC */
15627 tcg_gen_brcondi_tl(TCG_COND_NE, t4, 0, l1);
15628 } else {
15629 /* OPC_BNVC */
15630 tcg_gen_brcondi_tl(TCG_COND_EQ, t4, 0, l1);
15631 }
15632 tcg_temp_free(input_overflow);
15633 tcg_temp_free(t4);
15634 tcg_temp_free(t3);
15635 tcg_temp_free(t2);
15636 } else if (rs < rt && rs == 0) {
15637 /* OPC_BEQZALC, OPC_BNEZALC */
15638 if (opc == OPC_BEQZALC) {
15639 /* OPC_BEQZALC */
15640 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
15641 } else {
15642 /* OPC_BNEZALC */
15643 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
15644 }
15645 } else {
15646 /* OPC_BEQC, OPC_BNEC */
15647 if (opc == OPC_BEQC) {
15648 /* OPC_BEQC */
15649 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
15650 } else {
15651 /* OPC_BNEC */
15652 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
15653 }
15654 }
15655 break;
15656 case OPC_BEQZC:
15657 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
15658 break;
15659 case OPC_BNEZC:
15660 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
15661 break;
15662 default:
15663 MIPS_INVAL("Compact conditional branch/jump");
15664 generate_exception(ctx, EXCP_RI);
15665 goto out;
15666 }
15667
15668 /* Generating branch here as compact branches don't have delay slot */
15669 /* TODO: implement forbidden slot */
15670 gen_goto_tb(ctx, 1, ctx->pc + 4);
15671 gen_set_label(l1);
15672 gen_goto_tb(ctx, 0, ctx->btarget);
15673 MIPS_DEBUG("Compact conditional branch");
15674 ctx->bstate = BS_BRANCH;
15675 }
15676
15677out:
15678 tcg_temp_free(t0);
15679 tcg_temp_free(t1);
15680}
15681
10dc65db
LA
15682static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
15683{
4267d3e6 15684 int rs, rt, rd, sa;
b42ee5e1 15685 uint32_t op1, op2;
10dc65db
LA
15686
15687 rs = (ctx->opcode >> 21) & 0x1f;
15688 rt = (ctx->opcode >> 16) & 0x1f;
15689 rd = (ctx->opcode >> 11) & 0x1f;
4267d3e6 15690 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
15691
15692 op1 = MASK_SPECIAL(ctx->opcode);
15693 switch (op1) {
d4ea6acd
LA
15694 case OPC_LSA:
15695 if (rd != 0) {
15696 int imm2 = extract32(ctx->opcode, 6, 3);
15697 TCGv t0 = tcg_temp_new();
15698 TCGv t1 = tcg_temp_new();
15699 gen_load_gpr(t0, rs);
15700 gen_load_gpr(t1, rt);
15701 tcg_gen_shli_tl(t0, t0, imm2 + 1);
15702 tcg_gen_add_tl(t0, t0, t1);
15703 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
15704 tcg_temp_free(t1);
15705 tcg_temp_free(t0);
15706 }
15707 break;
b42ee5e1
LA
15708 case OPC_MULT ... OPC_DIVU:
15709 op2 = MASK_R6_MULDIV(ctx->opcode);
15710 switch (op2) {
15711 case R6_OPC_MUL:
15712 case R6_OPC_MUH:
15713 case R6_OPC_MULU:
15714 case R6_OPC_MUHU:
15715 case R6_OPC_DIV:
15716 case R6_OPC_MOD:
15717 case R6_OPC_DIVU:
15718 case R6_OPC_MODU:
15719 gen_r6_muldiv(ctx, op2, rd, rs, rt);
15720 break;
15721 default:
15722 MIPS_INVAL("special_r6 muldiv");
15723 generate_exception(ctx, EXCP_RI);
15724 break;
15725 }
15726 break;
10dc65db
LA
15727 case OPC_SELEQZ:
15728 case OPC_SELNEZ:
15729 gen_cond_move(ctx, op1, rd, rs, rt);
15730 break;
4267d3e6
LA
15731 case R6_OPC_CLO:
15732 case R6_OPC_CLZ:
15733 if (rt == 0 && sa == 1) {
15734 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
15735 We need additionally to check other fields */
15736 gen_cl(ctx, op1, rd, rs);
15737 } else {
15738 generate_exception(ctx, EXCP_RI);
15739 }
15740 break;
15741 case R6_OPC_SDBBP:
15742 generate_exception(ctx, EXCP_DBp);
15743 break;
b42ee5e1 15744#if defined(TARGET_MIPS64)
d4ea6acd
LA
15745 case OPC_DLSA:
15746 check_mips_64(ctx);
15747 if (rd != 0) {
15748 int imm2 = extract32(ctx->opcode, 6, 3);
15749 TCGv t0 = tcg_temp_new();
15750 TCGv t1 = tcg_temp_new();
15751 gen_load_gpr(t0, rs);
15752 gen_load_gpr(t1, rt);
15753 tcg_gen_shli_tl(t0, t0, imm2 + 1);
15754 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
15755 tcg_temp_free(t1);
15756 tcg_temp_free(t0);
15757 }
15758 break;
4267d3e6
LA
15759 case R6_OPC_DCLO:
15760 case R6_OPC_DCLZ:
15761 if (rt == 0 && sa == 1) {
15762 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
15763 We need additionally to check other fields */
15764 check_mips_64(ctx);
15765 gen_cl(ctx, op1, rd, rs);
15766 } else {
15767 generate_exception(ctx, EXCP_RI);
15768 }
15769 break;
b42ee5e1
LA
15770 case OPC_DMULT ... OPC_DDIVU:
15771 op2 = MASK_R6_MULDIV(ctx->opcode);
15772 switch (op2) {
15773 case R6_OPC_DMUL:
15774 case R6_OPC_DMUH:
15775 case R6_OPC_DMULU:
15776 case R6_OPC_DMUHU:
15777 case R6_OPC_DDIV:
15778 case R6_OPC_DMOD:
15779 case R6_OPC_DDIVU:
15780 case R6_OPC_DMODU:
15781 check_mips_64(ctx);
15782 gen_r6_muldiv(ctx, op2, rd, rs, rt);
15783 break;
15784 default:
15785 MIPS_INVAL("special_r6 muldiv");
15786 generate_exception(ctx, EXCP_RI);
15787 break;
15788 }
15789 break;
15790#endif
10dc65db
LA
15791 default: /* Invalid */
15792 MIPS_INVAL("special_r6");
15793 generate_exception(ctx, EXCP_RI);
15794 break;
15795 }
15796}
15797
15798static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
15799{
b42ee5e1 15800 int rs, rt, rd, sa;
10dc65db
LA
15801 uint32_t op1;
15802
15803 rs = (ctx->opcode >> 21) & 0x1f;
15804 rt = (ctx->opcode >> 16) & 0x1f;
15805 rd = (ctx->opcode >> 11) & 0x1f;
b42ee5e1 15806 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
15807
15808 op1 = MASK_SPECIAL(ctx->opcode);
15809 switch (op1) {
15810 case OPC_MOVN: /* Conditional move */
15811 case OPC_MOVZ:
15812 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
15813 INSN_LOONGSON2E | INSN_LOONGSON2F);
15814 gen_cond_move(ctx, op1, rd, rs, rt);
15815 break;
15816 case OPC_MFHI: /* Move from HI/LO */
15817 case OPC_MFLO:
15818 gen_HILO(ctx, op1, rs & 3, rd);
15819 break;
15820 case OPC_MTHI:
15821 case OPC_MTLO: /* Move to HI/LO */
15822 gen_HILO(ctx, op1, rd & 3, rs);
15823 break;
15824 case OPC_MOVCI:
15825 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
15826 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
15827 check_cp1_enabled(ctx);
15828 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
15829 (ctx->opcode >> 16) & 1);
15830 } else {
15831 generate_exception_err(ctx, EXCP_CpU, 1);
15832 }
15833 break;
b42ee5e1
LA
15834 case OPC_MULT:
15835 case OPC_MULTU:
15836 if (sa) {
15837 check_insn(ctx, INSN_VR54XX);
15838 op1 = MASK_MUL_VR54XX(ctx->opcode);
15839 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
15840 } else {
15841 gen_muldiv(ctx, op1, rd & 3, rs, rt);
15842 }
15843 break;
15844 case OPC_DIV:
15845 case OPC_DIVU:
15846 gen_muldiv(ctx, op1, 0, rs, rt);
15847 break;
15848#if defined(TARGET_MIPS64)
15849 case OPC_DMULT ... OPC_DDIVU:
15850 check_insn(ctx, ISA_MIPS3);
15851 check_mips_64(ctx);
15852 gen_muldiv(ctx, op1, 0, rs, rt);
15853 break;
15854#endif
0aefa333 15855 case OPC_JR:
b231c103 15856 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
0aefa333 15857 break;
4267d3e6
LA
15858 case OPC_SPIM:
15859#ifdef MIPS_STRICT_STANDARD
15860 MIPS_INVAL("SPIM");
15861 generate_exception(ctx, EXCP_RI);
15862#else
15863 /* Implemented as RI exception for now. */
15864 MIPS_INVAL("spim (unofficial)");
15865 generate_exception(ctx, EXCP_RI);
15866#endif
15867 break;
10dc65db
LA
15868 default: /* Invalid */
15869 MIPS_INVAL("special_legacy");
15870 generate_exception(ctx, EXCP_RI);
15871 break;
15872 }
15873}
15874
099e5b4d 15875static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
3c824109 15876{
3c824109 15877 int rs, rt, rd, sa;
099e5b4d 15878 uint32_t op1;
3c824109 15879
3c824109
NF
15880 rs = (ctx->opcode >> 21) & 0x1f;
15881 rt = (ctx->opcode >> 16) & 0x1f;
15882 rd = (ctx->opcode >> 11) & 0x1f;
15883 sa = (ctx->opcode >> 6) & 0x1f;
099e5b4d
LA
15884
15885 op1 = MASK_SPECIAL(ctx->opcode);
15886 switch (op1) {
15887 case OPC_SLL: /* Shift with immediate */
15888 case OPC_SRA:
15889 gen_shift_imm(ctx, op1, rd, rt, sa);
15890 break;
15891 case OPC_SRL:
15892 switch ((ctx->opcode >> 21) & 0x1f) {
15893 case 1:
15894 /* rotr is decoded as srl on non-R2 CPUs */
15895 if (ctx->insn_flags & ISA_MIPS32R2) {
15896 op1 = OPC_ROTR;
ea63e2c3 15897 }
099e5b4d
LA
15898 /* Fallthrough */
15899 case 0:
15900 gen_shift_imm(ctx, op1, rd, rt, sa);
ea63e2c3 15901 break;
099e5b4d
LA
15902 default:
15903 generate_exception(ctx, EXCP_RI);
ea63e2c3 15904 break;
099e5b4d
LA
15905 }
15906 break;
099e5b4d
LA
15907 case OPC_ADD ... OPC_SUBU:
15908 gen_arith(ctx, op1, rd, rs, rt);
15909 break;
15910 case OPC_SLLV: /* Shifts */
15911 case OPC_SRAV:
15912 gen_shift(ctx, op1, rd, rs, rt);
15913 break;
15914 case OPC_SRLV:
15915 switch ((ctx->opcode >> 6) & 0x1f) {
15916 case 1:
15917 /* rotrv is decoded as srlv on non-R2 CPUs */
15918 if (ctx->insn_flags & ISA_MIPS32R2) {
15919 op1 = OPC_ROTRV;
26135ead 15920 }
099e5b4d
LA
15921 /* Fallthrough */
15922 case 0:
15923 gen_shift(ctx, op1, rd, rs, rt);
26135ead 15924 break;
099e5b4d
LA
15925 default:
15926 generate_exception(ctx, EXCP_RI);
6af0bf9c 15927 break;
099e5b4d
LA
15928 }
15929 break;
15930 case OPC_SLT: /* Set on less than */
15931 case OPC_SLTU:
15932 gen_slt(ctx, op1, rd, rs, rt);
15933 break;
15934 case OPC_AND: /* Logic*/
15935 case OPC_OR:
15936 case OPC_NOR:
15937 case OPC_XOR:
15938 gen_logic(ctx, op1, rd, rs, rt);
15939 break;
0aefa333 15940 case OPC_JALR:
b231c103 15941 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
099e5b4d
LA
15942 break;
15943 case OPC_TGE ... OPC_TEQ: /* Traps */
15944 case OPC_TNE:
15945 gen_trap(ctx, op1, rs, rt, -1);
15946 break;
d4ea6acd
LA
15947 case OPC_LSA: /* OPC_PMON */
15948 if (ctx->insn_flags & ISA_MIPS32R6) {
15949 decode_opc_special_r6(env, ctx);
15950 } else {
15951 /* Pmon entry point, also R4010 selsl */
b48cfdff 15952#ifdef MIPS_STRICT_STANDARD
d4ea6acd
LA
15953 MIPS_INVAL("PMON / selsl");
15954 generate_exception(ctx, EXCP_RI);
b48cfdff 15955#else
d4ea6acd 15956 gen_helper_0e0i(pmon, sa);
b48cfdff 15957#endif
d4ea6acd 15958 }
099e5b4d
LA
15959 break;
15960 case OPC_SYSCALL:
15961 generate_exception(ctx, EXCP_SYSCALL);
15962 ctx->bstate = BS_STOP;
15963 break;
15964 case OPC_BREAK:
15965 generate_exception(ctx, EXCP_BREAK);
15966 break;
099e5b4d
LA
15967 case OPC_SYNC:
15968 /* Treat as NOP. */
15969 break;
4ad40f36 15970
d26bc211 15971#if defined(TARGET_MIPS64)
099e5b4d
LA
15972 /* MIPS64 specific opcodes */
15973 case OPC_DSLL:
15974 case OPC_DSRA:
15975 case OPC_DSLL32:
15976 case OPC_DSRA32:
15977 check_insn(ctx, ISA_MIPS3);
15978 check_mips_64(ctx);
15979 gen_shift_imm(ctx, op1, rd, rt, sa);
15980 break;
15981 case OPC_DSRL:
15982 switch ((ctx->opcode >> 21) & 0x1f) {
15983 case 1:
15984 /* drotr is decoded as dsrl on non-R2 CPUs */
15985 if (ctx->insn_flags & ISA_MIPS32R2) {
15986 op1 = OPC_DROTR;
ea63e2c3 15987 }
099e5b4d
LA
15988 /* Fallthrough */
15989 case 0:
d75c135e 15990 check_insn(ctx, ISA_MIPS3);
e189e748 15991 check_mips_64(ctx);
099e5b4d 15992 gen_shift_imm(ctx, op1, rd, rt, sa);
7a387fff 15993 break;
099e5b4d
LA
15994 default:
15995 generate_exception(ctx, EXCP_RI);
460f00c4 15996 break;
099e5b4d
LA
15997 }
15998 break;
15999 case OPC_DSRL32:
16000 switch ((ctx->opcode >> 21) & 0x1f) {
16001 case 1:
16002 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
16003 if (ctx->insn_flags & ISA_MIPS32R2) {
16004 op1 = OPC_DROTR32;
ea63e2c3 16005 }
099e5b4d
LA
16006 /* Fallthrough */
16007 case 0:
d75c135e 16008 check_insn(ctx, ISA_MIPS3);
e189e748 16009 check_mips_64(ctx);
099e5b4d 16010 gen_shift_imm(ctx, op1, rd, rt, sa);
7a387fff 16011 break;
099e5b4d 16012 default:
6af0bf9c
FB
16013 generate_exception(ctx, EXCP_RI);
16014 break;
16015 }
16016 break;
099e5b4d
LA
16017 case OPC_DADD ... OPC_DSUBU:
16018 check_insn(ctx, ISA_MIPS3);
16019 check_mips_64(ctx);
16020 gen_arith(ctx, op1, rd, rs, rt);
16021 break;
16022 case OPC_DSLLV:
16023 case OPC_DSRAV:
16024 check_insn(ctx, ISA_MIPS3);
16025 check_mips_64(ctx);
16026 gen_shift(ctx, op1, rd, rs, rt);
16027 break;
16028 case OPC_DSRLV:
16029 switch ((ctx->opcode >> 6) & 0x1f) {
16030 case 1:
16031 /* drotrv is decoded as dsrlv on non-R2 CPUs */
16032 if (ctx->insn_flags & ISA_MIPS32R2) {
16033 op1 = OPC_DROTRV;
6af0bf9c 16034 }
099e5b4d
LA
16035 /* Fallthrough */
16036 case 0:
16037 check_insn(ctx, ISA_MIPS3);
e189e748 16038 check_mips_64(ctx);
099e5b4d 16039 gen_shift(ctx, op1, rd, rs, rt);
161f85e6 16040 break;
099e5b4d 16041 default:
6af0bf9c
FB
16042 generate_exception(ctx, EXCP_RI);
16043 break;
16044 }
16045 break;
099e5b4d 16046#endif
10dc65db
LA
16047 default:
16048 if (ctx->insn_flags & ISA_MIPS32R6) {
16049 decode_opc_special_r6(env, ctx);
16050 } else {
16051 decode_opc_special_legacy(env, ctx);
16052 }
16053 }
16054}
16055
10dc65db 16056static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
099e5b4d
LA
16057{
16058 int rs, rt, rd;
16059 uint32_t op1;
6c5c1e20 16060
4267d3e6
LA
16061 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16062
099e5b4d
LA
16063 rs = (ctx->opcode >> 21) & 0x1f;
16064 rt = (ctx->opcode >> 16) & 0x1f;
16065 rd = (ctx->opcode >> 11) & 0x1f;
16066
16067 op1 = MASK_SPECIAL2(ctx->opcode);
16068 switch (op1) {
16069 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
16070 case OPC_MSUB ... OPC_MSUBU:
099e5b4d
LA
16071 check_insn(ctx, ISA_MIPS32);
16072 gen_muldiv(ctx, op1, rd & 3, rs, rt);
16073 break;
16074 case OPC_MUL:
099e5b4d
LA
16075 gen_arith(ctx, op1, rd, rs, rt);
16076 break;
fac5a073
LA
16077 case OPC_DIV_G_2F:
16078 case OPC_DIVU_G_2F:
16079 case OPC_MULT_G_2F:
16080 case OPC_MULTU_G_2F:
16081 case OPC_MOD_G_2F:
16082 case OPC_MODU_G_2F:
16083 check_insn(ctx, INSN_LOONGSON2F);
16084 gen_loongson_integer(ctx, op1, rd, rs, rt);
16085 break;
099e5b4d
LA
16086 case OPC_CLO:
16087 case OPC_CLZ:
16088 check_insn(ctx, ISA_MIPS32);
16089 gen_cl(ctx, op1, rd, rs);
16090 break;
16091 case OPC_SDBBP:
16092 /* XXX: not clear which exception should be raised
16093 * when in debug mode...
16094 */
16095 check_insn(ctx, ISA_MIPS32);
16096 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
16097 generate_exception(ctx, EXCP_DBp);
16098 } else {
16099 generate_exception(ctx, EXCP_DBp);
16100 }
16101 /* Treat as NOP. */
16102 break;
9b1a1d68 16103#if defined(TARGET_MIPS64)
099e5b4d
LA
16104 case OPC_DCLO:
16105 case OPC_DCLZ:
16106 check_insn(ctx, ISA_MIPS64);
16107 check_mips_64(ctx);
16108 gen_cl(ctx, op1, rd, rs);
16109 break;
4267d3e6
LA
16110 case OPC_DMULT_G_2F:
16111 case OPC_DMULTU_G_2F:
16112 case OPC_DDIV_G_2F:
16113 case OPC_DDIVU_G_2F:
16114 case OPC_DMOD_G_2F:
16115 case OPC_DMODU_G_2F:
16116 check_insn(ctx, INSN_LOONGSON2F);
16117 gen_loongson_integer(ctx, op1, rd, rs, rt);
16118 break;
10dc65db 16119#endif
4267d3e6
LA
16120 default: /* Invalid */
16121 MIPS_INVAL("special2_legacy");
16122 generate_exception(ctx, EXCP_RI);
16123 break;
10dc65db
LA
16124 }
16125}
16126
16127static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
16128{
15eacb9b
YK
16129 int rs, rt, rd, sa;
16130 uint32_t op1, op2;
10dc65db
LA
16131 int16_t imm;
16132
16133 rs = (ctx->opcode >> 21) & 0x1f;
16134 rt = (ctx->opcode >> 16) & 0x1f;
15eacb9b
YK
16135 rd = (ctx->opcode >> 11) & 0x1f;
16136 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
16137 imm = (int16_t)ctx->opcode >> 7;
16138
16139 op1 = MASK_SPECIAL3(ctx->opcode);
16140 switch (op1) {
bf7910c6
LA
16141 case R6_OPC_PREF:
16142 if (rt >= 24) {
16143 /* hint codes 24-31 are reserved and signal RI */
16144 generate_exception(ctx, EXCP_RI);
16145 }
16146 /* Treat as NOP. */
16147 break;
16148 case R6_OPC_CACHE:
16149 /* Treat as NOP. */
16150 break;
10dc65db
LA
16151 case R6_OPC_SC:
16152 gen_st_cond(ctx, op1, rt, rs, imm);
16153 break;
16154 case R6_OPC_LL:
16155 gen_ld(ctx, op1, rt, rs, imm);
16156 break;
15eacb9b
YK
16157 case OPC_BSHFL:
16158 {
16159 if (rd == 0) {
16160 /* Treat as NOP. */
16161 break;
16162 }
16163 TCGv t0 = tcg_temp_new();
16164 gen_load_gpr(t0, rt);
16165
16166 op2 = MASK_BSHFL(ctx->opcode);
16167 switch (op2) {
16168 case OPC_ALIGN ... OPC_ALIGN_END:
16169 sa &= 3;
16170 if (sa == 0) {
16171 tcg_gen_mov_tl(cpu_gpr[rd], t0);
16172 } else {
16173 TCGv t1 = tcg_temp_new();
16174 TCGv_i64 t2 = tcg_temp_new_i64();
16175 gen_load_gpr(t1, rs);
16176 tcg_gen_concat_tl_i64(t2, t1, t0);
16177 tcg_gen_shri_i64(t2, t2, 8 * (4 - sa));
16178#if defined(TARGET_MIPS64)
16179 tcg_gen_ext32s_i64(cpu_gpr[rd], t2);
16180#else
16181 tcg_gen_trunc_i64_i32(cpu_gpr[rd], t2);
16182#endif
16183 tcg_temp_free_i64(t2);
16184 tcg_temp_free(t1);
16185 }
16186 break;
16187 case OPC_BITSWAP:
16188 gen_helper_bitswap(cpu_gpr[rd], t0);
16189 break;
16190 }
16191 tcg_temp_free(t0);
16192 }
16193 break;
bf7910c6
LA
16194#if defined(TARGET_MIPS64)
16195 case R6_OPC_SCD:
16196 gen_st_cond(ctx, op1, rt, rs, imm);
16197 break;
16198 case R6_OPC_LLD:
16199 gen_ld(ctx, op1, rt, rs, imm);
16200 break;
15eacb9b
YK
16201 case OPC_DBSHFL:
16202 check_mips_64(ctx);
16203 {
16204 if (rd == 0) {
16205 /* Treat as NOP. */
16206 break;
16207 }
16208 TCGv t0 = tcg_temp_new();
16209 gen_load_gpr(t0, rt);
16210
16211 op2 = MASK_DBSHFL(ctx->opcode);
16212 switch (op2) {
16213 case OPC_DALIGN ... OPC_DALIGN_END:
16214 sa &= 7;
16215 if (sa == 0) {
16216 tcg_gen_mov_tl(cpu_gpr[rd], t0);
16217 } else {
16218 TCGv t1 = tcg_temp_new();
16219 gen_load_gpr(t1, rs);
16220 tcg_gen_shli_tl(t0, t0, 8 * sa);
16221 tcg_gen_shri_tl(t1, t1, 8 * (8 - sa));
16222 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
16223 tcg_temp_free(t1);
16224 }
16225 break;
16226 case OPC_DBITSWAP:
16227 gen_helper_dbitswap(cpu_gpr[rd], t0);
16228 break;
16229 }
16230 tcg_temp_free(t0);
16231 }
16232 break;
bf7910c6 16233#endif
10dc65db
LA
16234 default: /* Invalid */
16235 MIPS_INVAL("special3_r6");
16236 generate_exception(ctx, EXCP_RI);
16237 break;
16238 }
16239}
16240
16241static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
16242{
fac5a073 16243 int rs, rt, rd;
099e5b4d 16244 uint32_t op1, op2;
099e5b4d
LA
16245
16246 rs = (ctx->opcode >> 21) & 0x1f;
16247 rt = (ctx->opcode >> 16) & 0x1f;
16248 rd = (ctx->opcode >> 11) & 0x1f;
099e5b4d
LA
16249
16250 op1 = MASK_SPECIAL3(ctx->opcode);
16251 switch (op1) {
099e5b4d
LA
16252 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
16253 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
16254 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
16255 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
16256 * the same mask and op1. */
16257 if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
16258 op2 = MASK_ADDUH_QB(ctx->opcode);
461c08df 16259 switch (op2) {
099e5b4d
LA
16260 case OPC_ADDUH_QB:
16261 case OPC_ADDUH_R_QB:
16262 case OPC_ADDQH_PH:
16263 case OPC_ADDQH_R_PH:
16264 case OPC_ADDQH_W:
16265 case OPC_ADDQH_R_W:
16266 case OPC_SUBUH_QB:
16267 case OPC_SUBUH_R_QB:
16268 case OPC_SUBQH_PH:
16269 case OPC_SUBQH_R_PH:
16270 case OPC_SUBQH_W:
16271 case OPC_SUBQH_R_W:
461c08df
JL
16272 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16273 break;
099e5b4d
LA
16274 case OPC_MUL_PH:
16275 case OPC_MUL_S_PH:
16276 case OPC_MULQ_S_W:
16277 case OPC_MULQ_RS_W:
16278 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
1cb6686c 16279 break;
461c08df 16280 default:
099e5b4d 16281 MIPS_INVAL("MASK ADDUH.QB");
461c08df
JL
16282 generate_exception(ctx, EXCP_RI);
16283 break;
16284 }
099e5b4d
LA
16285 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
16286 gen_loongson_integer(ctx, op1, rd, rs, rt);
16287 } else {
16288 generate_exception(ctx, EXCP_RI);
16289 }
16290 break;
16291 case OPC_LX_DSP:
16292 op2 = MASK_LX(ctx->opcode);
16293 switch (op2) {
16294#if defined(TARGET_MIPS64)
16295 case OPC_LDX:
16296#endif
16297 case OPC_LBUX:
16298 case OPC_LHX:
16299 case OPC_LWX:
16300 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
16301 break;
16302 default: /* Invalid */
16303 MIPS_INVAL("MASK LX");
16304 generate_exception(ctx, EXCP_RI);
16305 break;
16306 }
16307 break;
16308 case OPC_ABSQ_S_PH_DSP:
16309 op2 = MASK_ABSQ_S_PH(ctx->opcode);
16310 switch (op2) {
16311 case OPC_ABSQ_S_QB:
16312 case OPC_ABSQ_S_PH:
16313 case OPC_ABSQ_S_W:
16314 case OPC_PRECEQ_W_PHL:
16315 case OPC_PRECEQ_W_PHR:
16316 case OPC_PRECEQU_PH_QBL:
16317 case OPC_PRECEQU_PH_QBR:
16318 case OPC_PRECEQU_PH_QBLA:
16319 case OPC_PRECEQU_PH_QBRA:
16320 case OPC_PRECEU_PH_QBL:
16321 case OPC_PRECEU_PH_QBR:
16322 case OPC_PRECEU_PH_QBLA:
16323 case OPC_PRECEU_PH_QBRA:
16324 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16325 break;
16326 case OPC_BITREV:
16327 case OPC_REPL_QB:
16328 case OPC_REPLV_QB:
16329 case OPC_REPL_PH:
16330 case OPC_REPLV_PH:
16331 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
16332 break;
16333 default:
16334 MIPS_INVAL("MASK ABSQ_S.PH");
16335 generate_exception(ctx, EXCP_RI);
16336 break;
16337 }
16338 break;
16339 case OPC_ADDU_QB_DSP:
16340 op2 = MASK_ADDU_QB(ctx->opcode);
16341 switch (op2) {
16342 case OPC_ADDQ_PH:
16343 case OPC_ADDQ_S_PH:
16344 case OPC_ADDQ_S_W:
16345 case OPC_ADDU_QB:
16346 case OPC_ADDU_S_QB:
16347 case OPC_ADDU_PH:
16348 case OPC_ADDU_S_PH:
16349 case OPC_SUBQ_PH:
16350 case OPC_SUBQ_S_PH:
16351 case OPC_SUBQ_S_W:
16352 case OPC_SUBU_QB:
16353 case OPC_SUBU_S_QB:
16354 case OPC_SUBU_PH:
16355 case OPC_SUBU_S_PH:
16356 case OPC_ADDSC:
16357 case OPC_ADDWC:
16358 case OPC_MODSUB:
16359 case OPC_RADDU_W_QB:
16360 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16361 break;
16362 case OPC_MULEU_S_PH_QBL:
16363 case OPC_MULEU_S_PH_QBR:
16364 case OPC_MULQ_RS_PH:
16365 case OPC_MULEQ_S_W_PHL:
16366 case OPC_MULEQ_S_W_PHR:
16367 case OPC_MULQ_S_PH:
16368 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
16369 break;
16370 default: /* Invalid */
16371 MIPS_INVAL("MASK ADDU.QB");
16372 generate_exception(ctx, EXCP_RI);
461c08df 16373 break;
461c08df 16374
099e5b4d
LA
16375 }
16376 break;
16377 case OPC_CMPU_EQ_QB_DSP:
16378 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
16379 switch (op2) {
16380 case OPC_PRECR_SRA_PH_W:
16381 case OPC_PRECR_SRA_R_PH_W:
16382 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
461c08df 16383 break;
099e5b4d
LA
16384 case OPC_PRECR_QB_PH:
16385 case OPC_PRECRQ_QB_PH:
16386 case OPC_PRECRQ_PH_W:
16387 case OPC_PRECRQ_RS_PH_W:
16388 case OPC_PRECRQU_S_QB_PH:
16389 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
461c08df 16390 break;
099e5b4d
LA
16391 case OPC_CMPU_EQ_QB:
16392 case OPC_CMPU_LT_QB:
16393 case OPC_CMPU_LE_QB:
16394 case OPC_CMP_EQ_PH:
16395 case OPC_CMP_LT_PH:
16396 case OPC_CMP_LE_PH:
16397 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
77c5fa8b 16398 break;
099e5b4d
LA
16399 case OPC_CMPGU_EQ_QB:
16400 case OPC_CMPGU_LT_QB:
16401 case OPC_CMPGU_LE_QB:
16402 case OPC_CMPGDU_EQ_QB:
16403 case OPC_CMPGDU_LT_QB:
16404 case OPC_CMPGDU_LE_QB:
16405 case OPC_PICK_QB:
16406 case OPC_PICK_PH:
16407 case OPC_PACKRL_PH:
16408 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
16409 break;
16410 default: /* Invalid */
16411 MIPS_INVAL("MASK CMPU.EQ.QB");
16412 generate_exception(ctx, EXCP_RI);
16413 break;
16414 }
16415 break;
16416 case OPC_SHLL_QB_DSP:
16417 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
16418 break;
16419 case OPC_DPA_W_PH_DSP:
16420 op2 = MASK_DPA_W_PH(ctx->opcode);
16421 switch (op2) {
16422 case OPC_DPAU_H_QBL:
16423 case OPC_DPAU_H_QBR:
16424 case OPC_DPSU_H_QBL:
16425 case OPC_DPSU_H_QBR:
16426 case OPC_DPA_W_PH:
16427 case OPC_DPAX_W_PH:
16428 case OPC_DPAQ_S_W_PH:
16429 case OPC_DPAQX_S_W_PH:
16430 case OPC_DPAQX_SA_W_PH:
16431 case OPC_DPS_W_PH:
16432 case OPC_DPSX_W_PH:
16433 case OPC_DPSQ_S_W_PH:
16434 case OPC_DPSQX_S_W_PH:
16435 case OPC_DPSQX_SA_W_PH:
16436 case OPC_MULSAQ_S_W_PH:
16437 case OPC_DPAQ_SA_L_W:
16438 case OPC_DPSQ_SA_L_W:
16439 case OPC_MAQ_S_W_PHL:
16440 case OPC_MAQ_S_W_PHR:
16441 case OPC_MAQ_SA_W_PHL:
16442 case OPC_MAQ_SA_W_PHR:
16443 case OPC_MULSA_W_PH:
16444 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
16445 break;
16446 default: /* Invalid */
16447 MIPS_INVAL("MASK DPAW.PH");
16448 generate_exception(ctx, EXCP_RI);
16449 break;
16450 }
16451 break;
16452 case OPC_INSV_DSP:
16453 op2 = MASK_INSV(ctx->opcode);
16454 switch (op2) {
16455 case OPC_INSV:
16456 check_dsp(ctx);
16457 {
16458 TCGv t0, t1;
16459
16460 if (rt == 0) {
16461 MIPS_DEBUG("NOP");
16462 break;
16463 }
16464
16465 t0 = tcg_temp_new();
16466 t1 = tcg_temp_new();
16467
16468 gen_load_gpr(t0, rt);
16469 gen_load_gpr(t1, rs);
16470
16471 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
16472
16473 tcg_temp_free(t0);
16474 tcg_temp_free(t1);
a22260ae
JL
16475 break;
16476 }
099e5b4d
LA
16477 default: /* Invalid */
16478 MIPS_INVAL("MASK INSV");
16479 generate_exception(ctx, EXCP_RI);
16480 break;
16481 }
16482 break;
16483 case OPC_APPEND_DSP:
16484 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
16485 break;
16486 case OPC_EXTR_W_DSP:
16487 op2 = MASK_EXTR_W(ctx->opcode);
16488 switch (op2) {
16489 case OPC_EXTR_W:
16490 case OPC_EXTR_R_W:
16491 case OPC_EXTR_RS_W:
16492 case OPC_EXTR_S_H:
16493 case OPC_EXTRV_S_H:
16494 case OPC_EXTRV_W:
16495 case OPC_EXTRV_R_W:
16496 case OPC_EXTRV_RS_W:
16497 case OPC_EXTP:
16498 case OPC_EXTPV:
16499 case OPC_EXTPDP:
16500 case OPC_EXTPDPV:
16501 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
16502 break;
16503 case OPC_RDDSP:
16504 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
16505 break;
16506 case OPC_SHILO:
16507 case OPC_SHILOV:
16508 case OPC_MTHLIP:
16509 case OPC_WRDSP:
16510 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
16511 break;
16512 default: /* Invalid */
16513 MIPS_INVAL("MASK EXTR.W");
16514 generate_exception(ctx, EXCP_RI);
16515 break;
16516 }
16517 break;
099e5b4d 16518#if defined(TARGET_MIPS64)
fac5a073
LA
16519 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
16520 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
16521 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
16522 check_insn(ctx, INSN_LOONGSON2E);
16523 gen_loongson_integer(ctx, op1, rd, rs, rt);
099e5b4d 16524 break;
099e5b4d
LA
16525 case OPC_ABSQ_S_QH_DSP:
16526 op2 = MASK_ABSQ_S_QH(ctx->opcode);
16527 switch (op2) {
16528 case OPC_PRECEQ_L_PWL:
16529 case OPC_PRECEQ_L_PWR:
16530 case OPC_PRECEQ_PW_QHL:
16531 case OPC_PRECEQ_PW_QHR:
16532 case OPC_PRECEQ_PW_QHLA:
16533 case OPC_PRECEQ_PW_QHRA:
16534 case OPC_PRECEQU_QH_OBL:
16535 case OPC_PRECEQU_QH_OBR:
16536 case OPC_PRECEQU_QH_OBLA:
16537 case OPC_PRECEQU_QH_OBRA:
16538 case OPC_PRECEU_QH_OBL:
16539 case OPC_PRECEU_QH_OBR:
16540 case OPC_PRECEU_QH_OBLA:
16541 case OPC_PRECEU_QH_OBRA:
16542 case OPC_ABSQ_S_OB:
16543 case OPC_ABSQ_S_PW:
16544 case OPC_ABSQ_S_QH:
16545 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16546 break;
16547 case OPC_REPL_OB:
16548 case OPC_REPL_PW:
16549 case OPC_REPL_QH:
16550 case OPC_REPLV_OB:
16551 case OPC_REPLV_PW:
16552 case OPC_REPLV_QH:
16553 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
16554 break;
16555 default: /* Invalid */
16556 MIPS_INVAL("MASK ABSQ_S.QH");
16557 generate_exception(ctx, EXCP_RI);
16558 break;
16559 }
16560 break;
16561 case OPC_ADDU_OB_DSP:
16562 op2 = MASK_ADDU_OB(ctx->opcode);
16563 switch (op2) {
16564 case OPC_RADDU_L_OB:
16565 case OPC_SUBQ_PW:
16566 case OPC_SUBQ_S_PW:
16567 case OPC_SUBQ_QH:
16568 case OPC_SUBQ_S_QH:
16569 case OPC_SUBU_OB:
16570 case OPC_SUBU_S_OB:
16571 case OPC_SUBU_QH:
16572 case OPC_SUBU_S_QH:
16573 case OPC_SUBUH_OB:
16574 case OPC_SUBUH_R_OB:
16575 case OPC_ADDQ_PW:
16576 case OPC_ADDQ_S_PW:
16577 case OPC_ADDQ_QH:
16578 case OPC_ADDQ_S_QH:
16579 case OPC_ADDU_OB:
16580 case OPC_ADDU_S_OB:
16581 case OPC_ADDU_QH:
16582 case OPC_ADDU_S_QH:
16583 case OPC_ADDUH_OB:
16584 case OPC_ADDUH_R_OB:
16585 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
a22260ae 16586 break;
099e5b4d
LA
16587 case OPC_MULEQ_S_PW_QHL:
16588 case OPC_MULEQ_S_PW_QHR:
16589 case OPC_MULEU_S_QH_OBL:
16590 case OPC_MULEU_S_QH_OBR:
16591 case OPC_MULQ_RS_QH:
16592 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
1cb6686c 16593 break;
099e5b4d
LA
16594 default: /* Invalid */
16595 MIPS_INVAL("MASK ADDU.OB");
16596 generate_exception(ctx, EXCP_RI);
26690560 16597 break;
099e5b4d
LA
16598 }
16599 break;
16600 case OPC_CMPU_EQ_OB_DSP:
16601 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
16602 switch (op2) {
16603 case OPC_PRECR_SRA_QH_PW:
16604 case OPC_PRECR_SRA_R_QH_PW:
16605 /* Return value is rt. */
16606 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
b53371ed 16607 break;
099e5b4d
LA
16608 case OPC_PRECR_OB_QH:
16609 case OPC_PRECRQ_OB_QH:
16610 case OPC_PRECRQ_PW_L:
16611 case OPC_PRECRQ_QH_PW:
16612 case OPC_PRECRQ_RS_QH_PW:
16613 case OPC_PRECRQU_S_OB_QH:
16614 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
4368b29a 16615 break;
099e5b4d
LA
16616 case OPC_CMPU_EQ_OB:
16617 case OPC_CMPU_LT_OB:
16618 case OPC_CMPU_LE_OB:
16619 case OPC_CMP_EQ_QH:
16620 case OPC_CMP_LT_QH:
16621 case OPC_CMP_LE_QH:
16622 case OPC_CMP_EQ_PW:
16623 case OPC_CMP_LT_PW:
16624 case OPC_CMP_LE_PW:
16625 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
7a387fff 16626 break;
099e5b4d
LA
16627 case OPC_CMPGDU_EQ_OB:
16628 case OPC_CMPGDU_LT_OB:
16629 case OPC_CMPGDU_LE_OB:
16630 case OPC_CMPGU_EQ_OB:
16631 case OPC_CMPGU_LT_OB:
16632 case OPC_CMPGU_LE_OB:
16633 case OPC_PACKRL_PW:
16634 case OPC_PICK_OB:
16635 case OPC_PICK_PW:
16636 case OPC_PICK_QH:
16637 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
c6d6dd7c 16638 break;
099e5b4d
LA
16639 default: /* Invalid */
16640 MIPS_INVAL("MASK CMPU_EQ.OB");
16641 generate_exception(ctx, EXCP_RI);
161f85e6 16642 break;
099e5b4d
LA
16643 }
16644 break;
16645 case OPC_DAPPEND_DSP:
16646 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
16647 break;
16648 case OPC_DEXTR_W_DSP:
16649 op2 = MASK_DEXTR_W(ctx->opcode);
16650 switch (op2) {
16651 case OPC_DEXTP:
16652 case OPC_DEXTPDP:
16653 case OPC_DEXTPDPV:
16654 case OPC_DEXTPV:
16655 case OPC_DEXTR_L:
16656 case OPC_DEXTR_R_L:
16657 case OPC_DEXTR_RS_L:
16658 case OPC_DEXTR_W:
16659 case OPC_DEXTR_R_W:
16660 case OPC_DEXTR_RS_W:
16661 case OPC_DEXTR_S_H:
16662 case OPC_DEXTRV_L:
16663 case OPC_DEXTRV_R_L:
16664 case OPC_DEXTRV_RS_L:
16665 case OPC_DEXTRV_S_H:
16666 case OPC_DEXTRV_W:
16667 case OPC_DEXTRV_R_W:
16668 case OPC_DEXTRV_RS_W:
16669 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
461c08df 16670 break;
099e5b4d
LA
16671 case OPC_DMTHLIP:
16672 case OPC_DSHILO:
16673 case OPC_DSHILOV:
16674 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
461c08df 16675 break;
099e5b4d
LA
16676 default: /* Invalid */
16677 MIPS_INVAL("MASK EXTR.W");
16678 generate_exception(ctx, EXCP_RI);
461c08df 16679 break;
099e5b4d
LA
16680 }
16681 break;
16682 case OPC_DPAQ_W_QH_DSP:
16683 op2 = MASK_DPAQ_W_QH(ctx->opcode);
16684 switch (op2) {
16685 case OPC_DPAU_H_OBL:
16686 case OPC_DPAU_H_OBR:
16687 case OPC_DPSU_H_OBL:
16688 case OPC_DPSU_H_OBR:
16689 case OPC_DPA_W_QH:
16690 case OPC_DPAQ_S_W_QH:
16691 case OPC_DPS_W_QH:
16692 case OPC_DPSQ_S_W_QH:
16693 case OPC_MULSAQ_S_W_QH:
16694 case OPC_DPAQ_SA_L_PW:
16695 case OPC_DPSQ_SA_L_PW:
16696 case OPC_MULSAQ_S_L_PW:
16697 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
16698 break;
16699 case OPC_MAQ_S_W_QHLL:
16700 case OPC_MAQ_S_W_QHLR:
16701 case OPC_MAQ_S_W_QHRL:
16702 case OPC_MAQ_S_W_QHRR:
16703 case OPC_MAQ_SA_W_QHLL:
16704 case OPC_MAQ_SA_W_QHLR:
16705 case OPC_MAQ_SA_W_QHRL:
16706 case OPC_MAQ_SA_W_QHRR:
16707 case OPC_MAQ_S_L_PWL:
16708 case OPC_MAQ_S_L_PWR:
16709 case OPC_DMADD:
16710 case OPC_DMADDU:
16711 case OPC_DMSUB:
16712 case OPC_DMSUBU:
16713 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26690560 16714 break;
099e5b4d
LA
16715 default: /* Invalid */
16716 MIPS_INVAL("MASK DPAQ.W.QH");
16717 generate_exception(ctx, EXCP_RI);
b53371ed 16718 break;
099e5b4d
LA
16719 }
16720 break;
16721 case OPC_DINSV_DSP:
16722 op2 = MASK_INSV(ctx->opcode);
16723 switch (op2) {
16724 case OPC_DINSV:
16725 {
16726 TCGv t0, t1;
16727
16728 if (rt == 0) {
16729 MIPS_DEBUG("NOP");
a22260ae
JL
16730 break;
16731 }
099e5b4d 16732 check_dsp(ctx);
1cb6686c 16733
099e5b4d
LA
16734 t0 = tcg_temp_new();
16735 t1 = tcg_temp_new();
1cb6686c 16736
099e5b4d
LA
16737 gen_load_gpr(t0, rt);
16738 gen_load_gpr(t1, rs);
1cb6686c 16739
099e5b4d 16740 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
62eb3b9a 16741
099e5b4d
LA
16742 tcg_temp_free(t0);
16743 tcg_temp_free(t1);
77c5fa8b 16744 break;
099e5b4d 16745 }
7a387fff 16746 default: /* Invalid */
099e5b4d 16747 MIPS_INVAL("MASK DINSV");
7a387fff
TS
16748 generate_exception(ctx, EXCP_RI);
16749 break;
16750 }
16751 break;
099e5b4d
LA
16752 case OPC_SHLL_OB_DSP:
16753 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
16754 break;
16755#endif
fac5a073
LA
16756 default: /* Invalid */
16757 MIPS_INVAL("special3_legacy");
16758 generate_exception(ctx, EXCP_RI);
16759 break;
16760 }
16761}
16762
16763static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
16764{
16765 int rs, rt, rd, sa;
16766 uint32_t op1, op2;
16767
16768 rs = (ctx->opcode >> 21) & 0x1f;
16769 rt = (ctx->opcode >> 16) & 0x1f;
16770 rd = (ctx->opcode >> 11) & 0x1f;
16771 sa = (ctx->opcode >> 6) & 0x1f;
16772
16773 op1 = MASK_SPECIAL3(ctx->opcode);
16774 switch (op1) {
16775 case OPC_EXT:
16776 case OPC_INS:
16777 check_insn(ctx, ISA_MIPS32R2);
16778 gen_bitops(ctx, op1, rt, rs, sa, rd);
16779 break;
16780 case OPC_BSHFL:
fac5a073 16781 op2 = MASK_BSHFL(ctx->opcode);
15eacb9b
YK
16782 switch (op2) {
16783 case OPC_ALIGN ... OPC_ALIGN_END:
16784 case OPC_BITSWAP:
16785 check_insn(ctx, ISA_MIPS32R6);
16786 decode_opc_special3_r6(env, ctx);
16787 break;
16788 default:
16789 check_insn(ctx, ISA_MIPS32R2);
16790 gen_bshfl(ctx, op2, rt, rd);
16791 break;
16792 }
fac5a073
LA
16793 break;
16794#if defined(TARGET_MIPS64)
16795 case OPC_DEXTM ... OPC_DEXT:
16796 case OPC_DINSM ... OPC_DINS:
16797 check_insn(ctx, ISA_MIPS64R2);
16798 check_mips_64(ctx);
16799 gen_bitops(ctx, op1, rt, rs, sa, rd);
16800 break;
16801 case OPC_DBSHFL:
fac5a073 16802 op2 = MASK_DBSHFL(ctx->opcode);
15eacb9b
YK
16803 switch (op2) {
16804 case OPC_DALIGN ... OPC_DALIGN_END:
16805 case OPC_DBITSWAP:
16806 check_insn(ctx, ISA_MIPS32R6);
16807 decode_opc_special3_r6(env, ctx);
16808 break;
16809 default:
16810 check_insn(ctx, ISA_MIPS64R2);
16811 check_mips_64(ctx);
16812 op2 = MASK_DBSHFL(ctx->opcode);
16813 gen_bshfl(ctx, op2, rt, rd);
16814 break;
16815 }
fac5a073
LA
16816 break;
16817#endif
16818 case OPC_RDHWR:
16819 gen_rdhwr(ctx, rt, rd);
16820 break;
16821 case OPC_FORK:
16822 check_insn(ctx, ASE_MT);
16823 {
16824 TCGv t0 = tcg_temp_new();
16825 TCGv t1 = tcg_temp_new();
16826
16827 gen_load_gpr(t0, rt);
16828 gen_load_gpr(t1, rs);
16829 gen_helper_fork(t0, t1);
16830 tcg_temp_free(t0);
16831 tcg_temp_free(t1);
16832 }
16833 break;
16834 case OPC_YIELD:
16835 check_insn(ctx, ASE_MT);
16836 {
16837 TCGv t0 = tcg_temp_new();
16838
16839 save_cpu_state(ctx, 1);
16840 gen_load_gpr(t0, rs);
16841 gen_helper_yield(t0, cpu_env, t0);
16842 gen_store_gpr(t0, rd);
16843 tcg_temp_free(t0);
16844 }
16845 break;
10dc65db
LA
16846 default:
16847 if (ctx->insn_flags & ISA_MIPS32R6) {
16848 decode_opc_special3_r6(env, ctx);
16849 } else {
16850 decode_opc_special3_legacy(env, ctx);
16851 }
099e5b4d
LA
16852 }
16853}
16854
16855static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
16856{
16857 int32_t offset;
16858 int rs, rt, rd, sa;
16859 uint32_t op, op1;
16860 int16_t imm;
16861
16862 /* make sure instructions are on a word boundary */
16863 if (ctx->pc & 0x3) {
16864 env->CP0_BadVAddr = ctx->pc;
16865 generate_exception(ctx, EXCP_AdEL);
16866 return;
16867 }
16868
16869 /* Handle blikely not taken case */
16870 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
16871 int l1 = gen_new_label();
16872
16873 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
16874 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
16875 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
16876 gen_goto_tb(ctx, 1, ctx->pc + 4);
16877 gen_set_label(l1);
16878 }
16879
16880 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
16881 tcg_gen_debug_insn_start(ctx->pc);
16882 }
16883
16884 op = MASK_OP_MAJOR(ctx->opcode);
16885 rs = (ctx->opcode >> 21) & 0x1f;
16886 rt = (ctx->opcode >> 16) & 0x1f;
16887 rd = (ctx->opcode >> 11) & 0x1f;
16888 sa = (ctx->opcode >> 6) & 0x1f;
16889 imm = (int16_t)ctx->opcode;
16890 switch (op) {
16891 case OPC_SPECIAL:
16892 decode_opc_special(env, ctx);
16893 break;
16894 case OPC_SPECIAL2:
4267d3e6 16895 decode_opc_special2_legacy(env, ctx);
099e5b4d
LA
16896 break;
16897 case OPC_SPECIAL3:
16898 decode_opc_special3(env, ctx);
16899 break;
7a387fff
TS
16900 case OPC_REGIMM:
16901 op1 = MASK_REGIMM(ctx->opcode);
16902 switch (op1) {
fecd2646
LA
16903 case OPC_BLTZL: /* REGIMM branches */
16904 case OPC_BGEZL:
16905 case OPC_BLTZALL:
16906 case OPC_BGEZALL:
16907 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16908 case OPC_BLTZ:
16909 case OPC_BGEZ:
b231c103 16910 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
0aefa333 16911 break;
fecd2646
LA
16912 case OPC_BLTZAL:
16913 case OPC_BGEZAL:
0aefa333
YK
16914 if (ctx->insn_flags & ISA_MIPS32R6) {
16915 if (rs == 0) {
16916 /* OPC_NAL, OPC_BAL */
b231c103 16917 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
0aefa333
YK
16918 } else {
16919 generate_exception(ctx, EXCP_RI);
16920 }
16921 } else {
b231c103 16922 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
0aefa333 16923 }
c9602061 16924 break;
7a387fff
TS
16925 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
16926 case OPC_TNEI:
fecd2646 16927 check_insn_opc_removed(ctx, ISA_MIPS32R6);
7a387fff
TS
16928 gen_trap(ctx, op1, rs, -1, imm);
16929 break;
16930 case OPC_SYNCI:
d75c135e 16931 check_insn(ctx, ISA_MIPS32R2);
a83bddd6
DZ
16932 /* Break the TB to be able to sync copied instructions
16933 immediately */
16934 ctx->bstate = BS_STOP;
6af0bf9c 16935 break;
e45a93e2
JL
16936 case OPC_BPOSGE32: /* MIPS DSP branch */
16937#if defined(TARGET_MIPS64)
16938 case OPC_BPOSGE64:
16939#endif
16940 check_dsp(ctx);
b231c103 16941 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
e45a93e2 16942 break;
d4ea6acd
LA
16943#if defined(TARGET_MIPS64)
16944 case OPC_DAHI:
16945 check_insn(ctx, ISA_MIPS32R6);
16946 check_mips_64(ctx);
16947 if (rs != 0) {
16948 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
16949 }
16950 MIPS_DEBUG("dahi %s, %04x", regnames[rs], imm);
16951 break;
16952 case OPC_DATI:
16953 check_insn(ctx, ISA_MIPS32R6);
16954 check_mips_64(ctx);
16955 if (rs != 0) {
16956 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
16957 }
16958 MIPS_DEBUG("dati %s, %04x", regnames[rs], imm);
16959 break;
16960#endif
6af0bf9c 16961 default: /* Invalid */
923617a3 16962 MIPS_INVAL("regimm");
6af0bf9c
FB
16963 generate_exception(ctx, EXCP_RI);
16964 break;
16965 }
16966 break;
7a387fff 16967 case OPC_CP0:
387a8fe5 16968 check_cp0_enabled(ctx);
7a387fff 16969 op1 = MASK_CP0(ctx->opcode);
6af0bf9c 16970 switch (op1) {
7a387fff
TS
16971 case OPC_MFC0:
16972 case OPC_MTC0:
ead9360e
TS
16973 case OPC_MFTR:
16974 case OPC_MTTR:
d26bc211 16975#if defined(TARGET_MIPS64)
7a387fff
TS
16976 case OPC_DMFC0:
16977 case OPC_DMTC0:
16978#endif
f1aa6320 16979#ifndef CONFIG_USER_ONLY
932e71cd 16980 gen_cp0(env, ctx, op1, rt, rd);
0eaef5aa 16981#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
16982 break;
16983 case OPC_C0_FIRST ... OPC_C0_LAST:
f1aa6320 16984#ifndef CONFIG_USER_ONLY
932e71cd 16985 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
0eaef5aa 16986#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
16987 break;
16988 case OPC_MFMC0:
8706c382 16989#ifndef CONFIG_USER_ONLY
932e71cd 16990 {
099e5b4d 16991 uint32_t op2;
35fbce2c 16992 TCGv t0 = tcg_temp_new();
6c5c1e20 16993
0eaef5aa 16994 op2 = MASK_MFMC0(ctx->opcode);
6c5c1e20
TS
16995 switch (op2) {
16996 case OPC_DMT:
d75c135e 16997 check_insn(ctx, ASE_MT);
9ed5726c 16998 gen_helper_dmt(t0);
35fbce2c 16999 gen_store_gpr(t0, rt);
6c5c1e20
TS
17000 break;
17001 case OPC_EMT:
d75c135e 17002 check_insn(ctx, ASE_MT);
9ed5726c 17003 gen_helper_emt(t0);
35fbce2c 17004 gen_store_gpr(t0, rt);
da80682b 17005 break;
6c5c1e20 17006 case OPC_DVPE:
d75c135e 17007 check_insn(ctx, ASE_MT);
895c2d04 17008 gen_helper_dvpe(t0, cpu_env);
35fbce2c 17009 gen_store_gpr(t0, rt);
6c5c1e20
TS
17010 break;
17011 case OPC_EVPE:
d75c135e 17012 check_insn(ctx, ASE_MT);
895c2d04 17013 gen_helper_evpe(t0, cpu_env);
35fbce2c 17014 gen_store_gpr(t0, rt);
6c5c1e20
TS
17015 break;
17016 case OPC_DI:
d75c135e 17017 check_insn(ctx, ISA_MIPS32R2);
867abc7e 17018 save_cpu_state(ctx, 1);
895c2d04 17019 gen_helper_di(t0, cpu_env);
35fbce2c 17020 gen_store_gpr(t0, rt);
6c5c1e20
TS
17021 /* Stop translation as we may have switched the execution mode */
17022 ctx->bstate = BS_STOP;
17023 break;
17024 case OPC_EI:
d75c135e 17025 check_insn(ctx, ISA_MIPS32R2);
867abc7e 17026 save_cpu_state(ctx, 1);
895c2d04 17027 gen_helper_ei(t0, cpu_env);
35fbce2c 17028 gen_store_gpr(t0, rt);
6c5c1e20
TS
17029 /* Stop translation as we may have switched the execution mode */
17030 ctx->bstate = BS_STOP;
17031 break;
17032 default: /* Invalid */
17033 MIPS_INVAL("mfmc0");
17034 generate_exception(ctx, EXCP_RI);
17035 break;
17036 }
6c5c1e20 17037 tcg_temp_free(t0);
7a387fff 17038 }
0eaef5aa 17039#endif /* !CONFIG_USER_ONLY */
6af0bf9c 17040 break;
7a387fff 17041 case OPC_RDPGPR:
d75c135e 17042 check_insn(ctx, ISA_MIPS32R2);
be24bb4f 17043 gen_load_srsgpr(rt, rd);
ead9360e 17044 break;
7a387fff 17045 case OPC_WRPGPR:
d75c135e 17046 check_insn(ctx, ISA_MIPS32R2);
be24bb4f 17047 gen_store_srsgpr(rt, rd);
38121543 17048 break;
6af0bf9c 17049 default:
923617a3 17050 MIPS_INVAL("cp0");
7a387fff 17051 generate_exception(ctx, EXCP_RI);
6af0bf9c
FB
17052 break;
17053 }
17054 break;
31837be3
YK
17055 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
17056 if (ctx->insn_flags & ISA_MIPS32R6) {
17057 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
17058 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
17059 } else {
17060 /* OPC_ADDI */
17061 /* Arithmetic with immediate opcode */
17062 gen_arith_imm(ctx, op, rt, rs, imm);
17063 }
17064 break;
324d9e32 17065 case OPC_ADDIU:
d75c135e 17066 gen_arith_imm(ctx, op, rt, rs, imm);
7a387fff 17067 break;
324d9e32
AJ
17068 case OPC_SLTI: /* Set on less than with immediate opcode */
17069 case OPC_SLTIU:
d75c135e 17070 gen_slt_imm(ctx, op, rt, rs, imm);
324d9e32
AJ
17071 break;
17072 case OPC_ANDI: /* Arithmetic with immediate opcode */
d4ea6acd 17073 case OPC_LUI: /* OPC_AUI */
324d9e32
AJ
17074 case OPC_ORI:
17075 case OPC_XORI:
d75c135e 17076 gen_logic_imm(ctx, op, rt, rs, imm);
324d9e32 17077 break;
7a387fff
TS
17078 case OPC_J ... OPC_JAL: /* Jump */
17079 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103 17080 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
c9602061 17081 break;
31837be3
YK
17082 /* Branch */
17083 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
17084 if (ctx->insn_flags & ISA_MIPS32R6) {
17085 if (rt == 0) {
17086 generate_exception(ctx, EXCP_RI);
17087 break;
17088 }
17089 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
17090 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
17091 } else {
17092 /* OPC_BLEZL */
b231c103 17093 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
17094 }
17095 break;
17096 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
17097 if (ctx->insn_flags & ISA_MIPS32R6) {
17098 if (rt == 0) {
17099 generate_exception(ctx, EXCP_RI);
17100 break;
17101 }
17102 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
17103 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
17104 } else {
17105 /* OPC_BGTZL */
b231c103 17106 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
17107 }
17108 break;
17109 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
17110 if (rt == 0) {
17111 /* OPC_BLEZ */
b231c103 17112 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
17113 } else {
17114 check_insn(ctx, ISA_MIPS32R6);
17115 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
17116 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
17117 }
17118 break;
17119 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
17120 if (rt == 0) {
17121 /* OPC_BGTZ */
b231c103 17122 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
17123 } else {
17124 check_insn(ctx, ISA_MIPS32R6);
17125 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
17126 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
17127 }
17128 break;
17129 case OPC_BEQL:
17130 case OPC_BNEL:
fecd2646 17131 check_insn_opc_removed(ctx, ISA_MIPS32R6);
31837be3
YK
17132 case OPC_BEQ:
17133 case OPC_BNE:
b231c103 17134 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
c9602061 17135 break;
fecd2646
LA
17136 case OPC_LWL: /* Load and stores */
17137 case OPC_LWR:
4368b29a 17138 case OPC_LL:
fecd2646
LA
17139 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17140 case OPC_LB ... OPC_LH:
17141 case OPC_LW ... OPC_LHU:
d75c135e 17142 gen_ld(ctx, op, rt, rs, imm);
5c13fdfd 17143 break;
fecd2646 17144 case OPC_SWL:
7a387fff 17145 case OPC_SWR:
fecd2646
LA
17146 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17147 case OPC_SB ... OPC_SH:
17148 case OPC_SW:
5c13fdfd 17149 gen_st(ctx, op, rt, rs, imm);
7a387fff 17150 break;
d66c7132 17151 case OPC_SC:
4368b29a 17152 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d66c7132
AJ
17153 gen_st_cond(ctx, op, rt, rs, imm);
17154 break;
7a387fff 17155 case OPC_CACHE:
bf7910c6 17156 check_insn_opc_removed(ctx, ISA_MIPS32R6);
2e15497c 17157 check_cp0_enabled(ctx);
d75c135e 17158 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
ead9360e 17159 /* Treat as NOP. */
34ae7b51 17160 break;
7a387fff 17161 case OPC_PREF:
bf7910c6 17162 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d75c135e 17163 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
ead9360e 17164 /* Treat as NOP. */
6af0bf9c 17165 break;
4ad40f36 17166
923617a3 17167 /* Floating point (COP1). */
7a387fff
TS
17168 case OPC_LWC1:
17169 case OPC_LDC1:
17170 case OPC_SWC1:
17171 case OPC_SDC1:
5ab5c041 17172 gen_cop1_ldst(ctx, op, rt, rs, imm);
6ea83fed
FB
17173 break;
17174
7a387fff 17175 case OPC_CP1:
5ab5c041 17176 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 17177 check_cp1_enabled(ctx);
36d23958
TS
17178 op1 = MASK_CP1(ctx->opcode);
17179 switch (op1) {
3a95e3a7
TS
17180 case OPC_MFHC1:
17181 case OPC_MTHC1:
d75c135e 17182 check_insn(ctx, ISA_MIPS32R2);
36d23958
TS
17183 case OPC_MFC1:
17184 case OPC_CFC1:
17185 case OPC_MTC1:
17186 case OPC_CTC1:
e189e748
TS
17187 gen_cp1(ctx, op1, rt, rd);
17188 break;
d26bc211 17189#if defined(TARGET_MIPS64)
36d23958
TS
17190 case OPC_DMFC1:
17191 case OPC_DMTC1:
d75c135e 17192 check_insn(ctx, ISA_MIPS3);
36d23958
TS
17193 gen_cp1(ctx, op1, rt, rd);
17194 break;
e189e748 17195#endif
31837be3
YK
17196 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
17197 if (ctx->insn_flags & ISA_MIPS32R6) {
17198 /* OPC_BC1EQZ */
17199 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
17200 rt, imm << 2);
17201 } else {
17202 /* OPC_BC1ANY2 */
17203 check_cop1x(ctx);
17204 check_insn(ctx, ASE_MIPS3D);
17205 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
17206 (rt >> 2) & 0x7, imm << 2);
17207 }
17208 break;
17209 case OPC_BC1NEZ:
17210 check_insn(ctx, ISA_MIPS32R6);
17211 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
17212 rt, imm << 2);
17213 break;
fbcc6828 17214 case OPC_BC1ANY4:
fecd2646 17215 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b8aa4598 17216 check_cop1x(ctx);
d75c135e 17217 check_insn(ctx, ASE_MIPS3D);
d8a5950a
TS
17218 /* fall through */
17219 case OPC_BC1:
fecd2646 17220 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d75c135e 17221 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
5a5012ec 17222 (rt >> 2) & 0x7, imm << 2);
c9602061 17223 break;
fecd2646
LA
17224 case OPC_PS_FMT:
17225 check_insn_opc_removed(ctx, ISA_MIPS32R6);
36d23958
TS
17226 case OPC_S_FMT:
17227 case OPC_D_FMT:
bf4120ad 17228 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
5a5012ec 17229 (imm >> 8) & 0x7);
36d23958 17230 break;
3f493883
YK
17231 case OPC_W_FMT:
17232 case OPC_L_FMT:
17233 {
17234 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
17235 if (ctx->insn_flags & ISA_MIPS32R6) {
17236 switch (r6_op) {
17237 case R6_OPC_CMP_AF_S:
17238 case R6_OPC_CMP_UN_S:
17239 case R6_OPC_CMP_EQ_S:
17240 case R6_OPC_CMP_UEQ_S:
17241 case R6_OPC_CMP_LT_S:
17242 case R6_OPC_CMP_ULT_S:
17243 case R6_OPC_CMP_LE_S:
17244 case R6_OPC_CMP_ULE_S:
17245 case R6_OPC_CMP_SAF_S:
17246 case R6_OPC_CMP_SUN_S:
17247 case R6_OPC_CMP_SEQ_S:
17248 case R6_OPC_CMP_SEUQ_S:
17249 case R6_OPC_CMP_SLT_S:
17250 case R6_OPC_CMP_SULT_S:
17251 case R6_OPC_CMP_SLE_S:
17252 case R6_OPC_CMP_SULE_S:
17253 case R6_OPC_CMP_OR_S:
17254 case R6_OPC_CMP_UNE_S:
17255 case R6_OPC_CMP_NE_S:
17256 case R6_OPC_CMP_SOR_S:
17257 case R6_OPC_CMP_SUNE_S:
17258 case R6_OPC_CMP_SNE_S:
17259 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
17260 break;
17261 case R6_OPC_CMP_AF_D:
17262 case R6_OPC_CMP_UN_D:
17263 case R6_OPC_CMP_EQ_D:
17264 case R6_OPC_CMP_UEQ_D:
17265 case R6_OPC_CMP_LT_D:
17266 case R6_OPC_CMP_ULT_D:
17267 case R6_OPC_CMP_LE_D:
17268 case R6_OPC_CMP_ULE_D:
17269 case R6_OPC_CMP_SAF_D:
17270 case R6_OPC_CMP_SUN_D:
17271 case R6_OPC_CMP_SEQ_D:
17272 case R6_OPC_CMP_SEUQ_D:
17273 case R6_OPC_CMP_SLT_D:
17274 case R6_OPC_CMP_SULT_D:
17275 case R6_OPC_CMP_SLE_D:
17276 case R6_OPC_CMP_SULE_D:
17277 case R6_OPC_CMP_OR_D:
17278 case R6_OPC_CMP_UNE_D:
17279 case R6_OPC_CMP_NE_D:
17280 case R6_OPC_CMP_SOR_D:
17281 case R6_OPC_CMP_SUNE_D:
17282 case R6_OPC_CMP_SNE_D:
17283 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
17284 break;
17285 default:
17286 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
17287 (imm >> 8) & 0x7);
17288 break;
17289 }
17290 } else {
17291 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
17292 (imm >> 8) & 0x7);
17293 }
17294 break;
17295 }
36d23958 17296 default:
923617a3 17297 MIPS_INVAL("cp1");
e397ee33 17298 generate_exception (ctx, EXCP_RI);
36d23958
TS
17299 break;
17300 }
17301 } else {
17302 generate_exception_err(ctx, EXCP_CpU, 1);
6ea83fed 17303 }
4ad40f36
FB
17304 break;
17305
31837be3
YK
17306 /* Compact branches [R6] and COP2 [non-R6] */
17307 case OPC_BC: /* OPC_LWC2 */
17308 case OPC_BALC: /* OPC_SWC2 */
17309 if (ctx->insn_flags & ISA_MIPS32R6) {
17310 /* OPC_BC, OPC_BALC */
17311 gen_compute_compact_branch(ctx, op, 0, 0,
17312 sextract32(ctx->opcode << 2, 0, 28));
17313 } else {
17314 /* OPC_LWC2, OPC_SWC2 */
17315 /* COP2: Not implemented. */
17316 generate_exception_err(ctx, EXCP_CpU, 2);
17317 }
17318 break;
17319 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
17320 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
17321 if (ctx->insn_flags & ISA_MIPS32R6) {
17322 if (rs != 0) {
17323 /* OPC_BEQZC, OPC_BNEZC */
17324 gen_compute_compact_branch(ctx, op, rs, 0,
17325 sextract32(ctx->opcode << 2, 0, 23));
17326 } else {
17327 /* OPC_JIC, OPC_JIALC */
17328 gen_compute_compact_branch(ctx, op, 0, rt, imm);
17329 }
17330 } else {
17331 /* OPC_LWC2, OPC_SWC2 */
17332 /* COP2: Not implemented. */
17333 generate_exception_err(ctx, EXCP_CpU, 2);
17334 }
4ad40f36 17335 break;
bd277fa1 17336 case OPC_CP2:
d75c135e 17337 check_insn(ctx, INSN_LOONGSON2F);
bd277fa1
RH
17338 /* Note that these instructions use different fields. */
17339 gen_loongson_multimedia(ctx, sa, rd, rt);
17340 break;
4ad40f36 17341
7a387fff 17342 case OPC_CP3:
fecd2646 17343 check_insn_opc_removed(ctx, ISA_MIPS32R6);
5ab5c041 17344 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 17345 check_cp1_enabled(ctx);
36d23958
TS
17346 op1 = MASK_CP3(ctx->opcode);
17347 switch (op1) {
5a5012ec
TS
17348 case OPC_LWXC1:
17349 case OPC_LDXC1:
17350 case OPC_LUXC1:
17351 case OPC_SWXC1:
17352 case OPC_SDXC1:
17353 case OPC_SUXC1:
93b12ccc 17354 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
5a5012ec 17355 break;
e0c84da7 17356 case OPC_PREFX:
ead9360e 17357 /* Treat as NOP. */
e0c84da7 17358 break;
5a5012ec
TS
17359 case OPC_ALNV_PS:
17360 case OPC_MADD_S:
17361 case OPC_MADD_D:
17362 case OPC_MADD_PS:
17363 case OPC_MSUB_S:
17364 case OPC_MSUB_D:
17365 case OPC_MSUB_PS:
17366 case OPC_NMADD_S:
17367 case OPC_NMADD_D:
17368 case OPC_NMADD_PS:
17369 case OPC_NMSUB_S:
17370 case OPC_NMSUB_D:
17371 case OPC_NMSUB_PS:
17372 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
17373 break;
36d23958 17374 default:
923617a3 17375 MIPS_INVAL("cp3");
e397ee33 17376 generate_exception (ctx, EXCP_RI);
36d23958
TS
17377 break;
17378 }
17379 } else {
e397ee33 17380 generate_exception_err(ctx, EXCP_CpU, 1);
7a387fff 17381 }
4ad40f36
FB
17382 break;
17383
d26bc211 17384#if defined(TARGET_MIPS64)
7a387fff 17385 /* MIPS64 opcodes */
7a387fff 17386 case OPC_LDL ... OPC_LDR:
bf7910c6 17387 case OPC_LLD:
fecd2646
LA
17388 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17389 case OPC_LWU:
7a387fff 17390 case OPC_LD:
d75c135e 17391 check_insn(ctx, ISA_MIPS3);
5c13fdfd 17392 check_mips_64(ctx);
d75c135e 17393 gen_ld(ctx, op, rt, rs, imm);
5c13fdfd
AJ
17394 break;
17395 case OPC_SDL ... OPC_SDR:
fecd2646 17396 check_insn_opc_removed(ctx, ISA_MIPS32R6);
7a387fff 17397 case OPC_SD:
d75c135e 17398 check_insn(ctx, ISA_MIPS3);
e189e748 17399 check_mips_64(ctx);
5c13fdfd 17400 gen_st(ctx, op, rt, rs, imm);
7a387fff 17401 break;
d66c7132 17402 case OPC_SCD:
bf7910c6 17403 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d75c135e 17404 check_insn(ctx, ISA_MIPS3);
d66c7132
AJ
17405 check_mips_64(ctx);
17406 gen_st_cond(ctx, op, rt, rs, imm);
17407 break;
31837be3
YK
17408 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
17409 if (ctx->insn_flags & ISA_MIPS32R6) {
17410 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
17411 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
17412 } else {
17413 /* OPC_DADDI */
17414 check_insn(ctx, ISA_MIPS3);
17415 check_mips_64(ctx);
17416 gen_arith_imm(ctx, op, rt, rs, imm);
17417 }
17418 break;
324d9e32 17419 case OPC_DADDIU:
d75c135e 17420 check_insn(ctx, ISA_MIPS3);
e189e748 17421 check_mips_64(ctx);
d75c135e 17422 gen_arith_imm(ctx, op, rt, rs, imm);
7a387fff 17423 break;
31837be3
YK
17424#else
17425 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
17426 if (ctx->insn_flags & ISA_MIPS32R6) {
17427 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
17428 } else {
17429 MIPS_INVAL("major opcode");
17430 generate_exception(ctx, EXCP_RI);
17431 }
17432 break;
6af0bf9c 17433#endif
d4ea6acd
LA
17434 case OPC_DAUI: /* OPC_JALX */
17435 if (ctx->insn_flags & ISA_MIPS32R6) {
17436#if defined(TARGET_MIPS64)
17437 /* OPC_DAUI */
17438 check_mips_64(ctx);
17439 if (rt != 0) {
17440 TCGv t0 = tcg_temp_new();
17441 gen_load_gpr(t0, rs);
17442 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
17443 tcg_temp_free(t0);
17444 }
17445 MIPS_DEBUG("daui %s, %s, %04x", regnames[rt], regnames[rs], imm);
17446#else
17447 generate_exception(ctx, EXCP_RI);
17448 MIPS_INVAL("major opcode");
17449#endif
17450 } else {
17451 /* OPC_JALX */
17452 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
17453 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103 17454 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
d4ea6acd 17455 }
364d4831 17456 break;
7a387fff 17457 case OPC_MDMX:
d75c135e 17458 check_insn(ctx, ASE_MDMX);
7a387fff 17459 /* MDMX: Not implemented. */
d4ea6acd
LA
17460 break;
17461 case OPC_PCREL:
17462 check_insn(ctx, ISA_MIPS32R6);
17463 gen_pcrel(ctx, rs, imm);
17464 break;
6af0bf9c 17465 default: /* Invalid */
923617a3 17466 MIPS_INVAL("major opcode");
6af0bf9c
FB
17467 generate_exception(ctx, EXCP_RI);
17468 break;
17469 }
6af0bf9c
FB
17470}
17471
2cfc5f17 17472static inline void
6429db34
AF
17473gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
17474 bool search_pc)
6af0bf9c 17475{
ed2803da 17476 CPUState *cs = CPU(cpu);
6429db34 17477 CPUMIPSState *env = &cpu->env;
278d0702 17478 DisasContext ctx;
6af0bf9c
FB
17479 target_ulong pc_start;
17480 uint16_t *gen_opc_end;
a1d1bb31 17481 CPUBreakpoint *bp;
6af0bf9c 17482 int j, lj = -1;
2e70f6ef
PB
17483 int num_insns;
17484 int max_insns;
c9602061 17485 int insn_bytes;
240ce26a 17486 int is_delay;
6af0bf9c 17487
93fcfe39
AL
17488 if (search_pc)
17489 qemu_log("search pc %d\n", search_pc);
4ad40f36 17490
6af0bf9c 17491 pc_start = tb->pc;
92414b31 17492 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
6af0bf9c 17493 ctx.pc = pc_start;
4ad40f36 17494 ctx.saved_pc = -1;
ed2803da 17495 ctx.singlestep_enabled = cs->singlestep_enabled;
d75c135e 17496 ctx.insn_flags = env->insn_flags;
5ab5c041 17497 ctx.CP0_Config1 = env->CP0_Config1;
6af0bf9c
FB
17498 ctx.tb = tb;
17499 ctx.bstate = BS_NONE;
e98c0d17 17500 ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
7207c7f9 17501 ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
9456c2fb 17502 ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
4ad40f36 17503 /* Restore delay slot state from the tb context. */
c068688b 17504 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
d279279e 17505 ctx.ulri = env->CP0_Config3 & (1 << CP0C3_ULRI);
fd4a04eb 17506 restore_cpu_state(env, &ctx);
932e71cd 17507#ifdef CONFIG_USER_ONLY
0eaef5aa 17508 ctx.mem_idx = MIPS_HFLAG_UM;
932e71cd 17509#else
0eaef5aa 17510 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
932e71cd 17511#endif
2e70f6ef
PB
17512 num_insns = 0;
17513 max_insns = tb->cflags & CF_COUNT_MASK;
17514 if (max_insns == 0)
17515 max_insns = CF_COUNT_MASK;
d12d51d5 17516 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
806f352d 17517 gen_tb_start();
faf7aaa9 17518 while (ctx.bstate == BS_NONE) {
f0c3c505
AF
17519 if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
17520 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
a1d1bb31 17521 if (bp->pc == ctx.pc) {
278d0702 17522 save_cpu_state(&ctx, 1);
4ad40f36 17523 ctx.bstate = BS_BRANCH;
895c2d04 17524 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
ce62e5ba
TS
17525 /* Include the breakpoint location or the tb won't
17526 * be flushed when it must be. */
17527 ctx.pc += 4;
4ad40f36
FB
17528 goto done_generating;
17529 }
17530 }
17531 }
17532
6af0bf9c 17533 if (search_pc) {
92414b31 17534 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
6af0bf9c
FB
17535 if (lj < j) {
17536 lj++;
17537 while (lj < j)
ab1103de 17538 tcg_ctx.gen_opc_instr_start[lj++] = 0;
6af0bf9c 17539 }
25983cad 17540 tcg_ctx.gen_opc_pc[lj] = ctx.pc;
4ad40f36 17541 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
4636401d 17542 gen_opc_btarget[lj] = ctx.btarget;
ab1103de 17543 tcg_ctx.gen_opc_instr_start[lj] = 1;
c9c99c22 17544 tcg_ctx.gen_opc_icount[lj] = num_insns;
6af0bf9c 17545 }
2e70f6ef
PB
17546 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
17547 gen_io_start();
c9602061 17548
240ce26a 17549 is_delay = ctx.hflags & MIPS_HFLAG_BMASK;
364d4831 17550 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
895c2d04 17551 ctx.opcode = cpu_ldl_code(env, ctx.pc);
c9602061 17552 insn_bytes = 4;
240ce26a 17553 decode_opc(env, &ctx);
d75c135e 17554 } else if (ctx.insn_flags & ASE_MICROMIPS) {
895c2d04 17555 ctx.opcode = cpu_lduw_code(env, ctx.pc);
240ce26a 17556 insn_bytes = decode_micromips_opc(env, &ctx);
d75c135e 17557 } else if (ctx.insn_flags & ASE_MIPS16) {
895c2d04 17558 ctx.opcode = cpu_lduw_code(env, ctx.pc);
240ce26a 17559 insn_bytes = decode_mips16_opc(env, &ctx);
c9602061
NF
17560 } else {
17561 generate_exception(&ctx, EXCP_RI);
3c824109 17562 ctx.bstate = BS_STOP;
c9602061
NF
17563 break;
17564 }
31837be3 17565
b231c103
YK
17566 if (ctx.hflags & MIPS_HFLAG_BMASK) {
17567 if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32))) {
17568 is_delay = 1;
17569 /* force to generate branch as no delay slot is required */
17570 }
17571 }
240ce26a 17572 if (is_delay) {
31837be3 17573 gen_branch(&ctx, insn_bytes);
c9602061
NF
17574 }
17575 ctx.pc += insn_bytes;
17576
2e70f6ef 17577 num_insns++;
4ad40f36 17578
7b270ef2
NF
17579 /* Execute a branch and its delay slot as a single instruction.
17580 This is what GDB expects and is consistent with what the
17581 hardware does (e.g. if a delay slot instruction faults, the
17582 reported PC is the PC of the branch). */
ed2803da 17583 if (cs->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0) {
4ad40f36 17584 break;
ed2803da 17585 }
4ad40f36 17586
6af0bf9c
FB
17587 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
17588 break;
4ad40f36 17589
efd7f486 17590 if (tcg_ctx.gen_opc_ptr >= gen_opc_end) {
faf7aaa9 17591 break;
efd7f486 17592 }
faf7aaa9 17593
2e70f6ef
PB
17594 if (num_insns >= max_insns)
17595 break;
1b530a6d
AJ
17596
17597 if (singlestep)
17598 break;
6af0bf9c 17599 }
ed2803da 17600 if (tb->cflags & CF_LAST_IO) {
2e70f6ef 17601 gen_io_end();
ed2803da
AF
17602 }
17603 if (cs->singlestep_enabled && ctx.bstate != BS_BRANCH) {
278d0702 17604 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
895c2d04 17605 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
16c00cb2 17606 } else {
6958549d 17607 switch (ctx.bstate) {
16c00cb2 17608 case BS_STOP:
df1561e2
TS
17609 gen_goto_tb(&ctx, 0, ctx.pc);
17610 break;
16c00cb2 17611 case BS_NONE:
278d0702 17612 save_cpu_state(&ctx, 0);
16c00cb2
TS
17613 gen_goto_tb(&ctx, 0, ctx.pc);
17614 break;
5a5012ec 17615 case BS_EXCP:
57fec1fe 17616 tcg_gen_exit_tb(0);
16c00cb2 17617 break;
5a5012ec
TS
17618 case BS_BRANCH:
17619 default:
17620 break;
6958549d 17621 }
6af0bf9c 17622 }
4ad40f36 17623done_generating:
806f352d 17624 gen_tb_end(tb, num_insns);
efd7f486 17625 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
6af0bf9c 17626 if (search_pc) {
92414b31 17627 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
6af0bf9c
FB
17628 lj++;
17629 while (lj <= j)
ab1103de 17630 tcg_ctx.gen_opc_instr_start[lj++] = 0;
6af0bf9c
FB
17631 } else {
17632 tb->size = ctx.pc - pc_start;
2e70f6ef 17633 tb->icount = num_insns;
6af0bf9c
FB
17634 }
17635#ifdef DEBUG_DISAS
d12d51d5 17636 LOG_DISAS("\n");
8fec2b8c 17637 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
93fcfe39 17638 qemu_log("IN: %s\n", lookup_symbol(pc_start));
f4359b9f 17639 log_target_disas(env, pc_start, ctx.pc - pc_start, 0);
93fcfe39 17640 qemu_log("\n");
6af0bf9c
FB
17641 }
17642#endif
6af0bf9c
FB
17643}
17644
7db13fae 17645void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
6af0bf9c 17646{
6429db34 17647 gen_intermediate_code_internal(mips_env_get_cpu(env), tb, false);
6af0bf9c
FB
17648}
17649
7db13fae 17650void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
6af0bf9c 17651{
6429db34 17652 gen_intermediate_code_internal(mips_env_get_cpu(env), tb, true);
6af0bf9c
FB
17653}
17654
7db13fae 17655static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
8706c382 17656 int flags)
6ea83fed
FB
17657{
17658 int i;
5e755519 17659 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
5a5012ec 17660
2a5612e6
SW
17661#define printfpr(fp) \
17662 do { \
17663 if (is_fpu64) \
17664 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
17665 " fd:%13g fs:%13g psu: %13g\n", \
17666 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
17667 (double)(fp)->fd, \
17668 (double)(fp)->fs[FP_ENDIAN_IDX], \
17669 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
17670 else { \
17671 fpr_t tmp; \
17672 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
17673 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
17674 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
17675 " fd:%13g fs:%13g psu:%13g\n", \
17676 tmp.w[FP_ENDIAN_IDX], tmp.d, \
17677 (double)tmp.fd, \
17678 (double)tmp.fs[FP_ENDIAN_IDX], \
17679 (double)tmp.fs[!FP_ENDIAN_IDX]); \
17680 } \
6ea83fed
FB
17681 } while(0)
17682
5a5012ec 17683
9a78eead
SW
17684 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
17685 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
f01be154 17686 get_float_exception_flags(&env->active_fpu.fp_status));
5a5012ec
TS
17687 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
17688 fpu_fprintf(f, "%3s: ", fregnames[i]);
f01be154 17689 printfpr(&env->active_fpu.fpr[i]);
6ea83fed
FB
17690 }
17691
17692#undef printfpr
17693}
17694
d26bc211 17695#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16 17696/* Debug help: The architecture requires 32bit code to maintain proper
c7e8a937 17697 sign-extended values on 64bit machines. */
c570fd16
TS
17698
17699#define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
17700
8706c382 17701static void
7db13fae 17702cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f,
9a78eead 17703 fprintf_function cpu_fprintf,
8706c382 17704 int flags)
c570fd16
TS
17705{
17706 int i;
17707
b5dc7732
TS
17708 if (!SIGN_EXT_P(env->active_tc.PC))
17709 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
17710 if (!SIGN_EXT_P(env->active_tc.HI[0]))
17711 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
17712 if (!SIGN_EXT_P(env->active_tc.LO[0]))
17713 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
c570fd16 17714 if (!SIGN_EXT_P(env->btarget))
3594c774 17715 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
c570fd16
TS
17716
17717 for (i = 0; i < 32; i++) {
b5dc7732
TS
17718 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
17719 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
c570fd16
TS
17720 }
17721
17722 if (!SIGN_EXT_P(env->CP0_EPC))
3594c774 17723 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
5499b6ff
AJ
17724 if (!SIGN_EXT_P(env->lladdr))
17725 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
c570fd16
TS
17726}
17727#endif
17728
878096ee
AF
17729void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
17730 int flags)
6af0bf9c 17731{
878096ee
AF
17732 MIPSCPU *cpu = MIPS_CPU(cs);
17733 CPUMIPSState *env = &cpu->env;
6af0bf9c 17734 int i;
3b46e624 17735
a7200c9f
SW
17736 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
17737 " LO=0x" TARGET_FMT_lx " ds %04x "
17738 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
3d5be870
TS
17739 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
17740 env->hflags, env->btarget, env->bcond);
6af0bf9c
FB
17741 for (i = 0; i < 32; i++) {
17742 if ((i & 3) == 0)
17743 cpu_fprintf(f, "GPR%02d:", i);
b5dc7732 17744 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
6af0bf9c
FB
17745 if ((i & 3) == 3)
17746 cpu_fprintf(f, "\n");
17747 }
568b600d 17748
3594c774 17749 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
5e755519 17750 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
3594c774 17751 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
5499b6ff 17752 env->CP0_Config0, env->CP0_Config1, env->lladdr);
5e755519 17753 if (env->hflags & MIPS_HFLAG_FPU)
7a387fff 17754 fpu_dump_state(env, f, cpu_fprintf, flags);
d26bc211 17755#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16
TS
17756 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
17757#endif
6af0bf9c
FB
17758}
17759
78ce64f4 17760void mips_tcg_init(void)
39454628 17761{
f01be154 17762 int i;
39454628
TS
17763 static int inited;
17764
17765 /* Initialize various static tables. */
17766 if (inited)
6958549d 17767 return;
39454628 17768
a7812ae4 17769 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
f2c94b92 17770 TCGV_UNUSED(cpu_gpr[0]);
bb928dbe 17771 for (i = 1; i < 32; i++)
a7812ae4 17772 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
7db13fae 17773 offsetof(CPUMIPSState, active_tc.gpr[i]),
4b2eb8d2 17774 regnames[i]);
d73ee8a2
RH
17775
17776 for (i = 0; i < 32; i++) {
17777 int off = offsetof(CPUMIPSState, active_fpu.fpr[i]);
17778 fpu_f64[i] = tcg_global_mem_new_i64(TCG_AREG0, off, fregnames[i]);
17779 }
17780
a7812ae4 17781 cpu_PC = tcg_global_mem_new(TCG_AREG0,
7db13fae 17782 offsetof(CPUMIPSState, active_tc.PC), "PC");
4b2eb8d2 17783 for (i = 0; i < MIPS_DSP_ACC; i++) {
a7812ae4 17784 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
7db13fae 17785 offsetof(CPUMIPSState, active_tc.HI[i]),
4b2eb8d2 17786 regnames_HI[i]);
a7812ae4 17787 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
7db13fae 17788 offsetof(CPUMIPSState, active_tc.LO[i]),
4b2eb8d2 17789 regnames_LO[i]);
4b2eb8d2 17790 }
a7812ae4 17791 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
7db13fae 17792 offsetof(CPUMIPSState, active_tc.DSPControl),
4b2eb8d2 17793 "DSPControl");
1ba74fb8 17794 bcond = tcg_global_mem_new(TCG_AREG0,
7db13fae 17795 offsetof(CPUMIPSState, bcond), "bcond");
a7812ae4 17796 btarget = tcg_global_mem_new(TCG_AREG0,
7db13fae 17797 offsetof(CPUMIPSState, btarget), "btarget");
41db4607 17798 hflags = tcg_global_mem_new_i32(TCG_AREG0,
7db13fae 17799 offsetof(CPUMIPSState, hflags), "hflags");
41db4607 17800
a7812ae4 17801 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
7db13fae 17802 offsetof(CPUMIPSState, active_fpu.fcr0),
a7812ae4
PB
17803 "fcr0");
17804 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
7db13fae 17805 offsetof(CPUMIPSState, active_fpu.fcr31),
a7812ae4 17806 "fcr31");
39454628
TS
17807
17808 inited = 1;
17809}
17810
aaed909a
FB
17811#include "translate_init.c"
17812
30bf942d 17813MIPSCPU *cpu_mips_init(const char *cpu_model)
6af0bf9c 17814{
0f71a709 17815 MIPSCPU *cpu;
6af0bf9c 17816 CPUMIPSState *env;
c227f099 17817 const mips_def_t *def;
6af0bf9c 17818
aaed909a
FB
17819 def = cpu_mips_find_by_name(cpu_model);
17820 if (!def)
17821 return NULL;
0f71a709
AF
17822 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
17823 env = &cpu->env;
aaed909a
FB
17824 env->cpu_model = def;
17825
51cc2e78
BS
17826#ifndef CONFIG_USER_ONLY
17827 mmu_init(env, def);
17828#endif
17829 fpu_init(env, def);
17830 mvp_init(env, def);
c1caf1d9
AF
17831
17832 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
17833
30bf942d 17834 return cpu;
6ae81775
TS
17835}
17836
1bba0dc9 17837void cpu_state_reset(CPUMIPSState *env)
6ae81775 17838{
55e5c285
AF
17839 MIPSCPU *cpu = mips_env_get_cpu(env);
17840 CPUState *cs = CPU(cpu);
6ae81775 17841
51cc2e78
BS
17842 /* Reset registers to their default values */
17843 env->CP0_PRid = env->cpu_model->CP0_PRid;
17844 env->CP0_Config0 = env->cpu_model->CP0_Config0;
17845#ifdef TARGET_WORDS_BIGENDIAN
17846 env->CP0_Config0 |= (1 << CP0C0_BE);
17847#endif
17848 env->CP0_Config1 = env->cpu_model->CP0_Config1;
17849 env->CP0_Config2 = env->cpu_model->CP0_Config2;
17850 env->CP0_Config3 = env->cpu_model->CP0_Config3;
b4160af1
PJ
17851 env->CP0_Config4 = env->cpu_model->CP0_Config4;
17852 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
b4dd99a3
PJ
17853 env->CP0_Config5 = env->cpu_model->CP0_Config5;
17854 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
51cc2e78
BS
17855 env->CP0_Config6 = env->cpu_model->CP0_Config6;
17856 env->CP0_Config7 = env->cpu_model->CP0_Config7;
2a6e32dd
AJ
17857 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
17858 << env->cpu_model->CP0_LLAddr_shift;
17859 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
51cc2e78
BS
17860 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
17861 env->CCRes = env->cpu_model->CCRes;
17862 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
17863 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
17864 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
17865 env->current_tc = 0;
17866 env->SEGBITS = env->cpu_model->SEGBITS;
17867 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
17868#if defined(TARGET_MIPS64)
17869 if (env->cpu_model->insn_flags & ISA_MIPS3) {
17870 env->SEGMask |= 3ULL << 62;
17871 }
17872#endif
17873 env->PABITS = env->cpu_model->PABITS;
17874 env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
17875 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
17876 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
17877 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
17878 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
17879 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
17880 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
17881 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
17882 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
17883 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
17884 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
7207c7f9
LA
17885 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
17886 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
f1cb0951 17887 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
51cc2e78
BS
17888 env->insn_flags = env->cpu_model->insn_flags;
17889
0eaef5aa 17890#if defined(CONFIG_USER_ONLY)
03e6e501 17891 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
68473f15
RH
17892# ifdef TARGET_MIPS64
17893 /* Enable 64-bit register mode. */
17894 env->CP0_Status |= (1 << CP0St_PX);
17895# endif
17896# ifdef TARGET_ABI_MIPSN64
17897 /* Enable 64-bit address mode. */
17898 env->CP0_Status |= (1 << CP0St_UX);
17899# endif
94159135
MI
17900 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
17901 hardware registers. */
17902 env->CP0_HWREna |= 0x0000000F;
91a75935 17903 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
03e6e501 17904 env->CP0_Status |= (1 << CP0St_CU1);
91a75935 17905 }
6f0af304
PJ
17906 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
17907 env->CP0_Status |= (1 << CP0St_MX);
853c3240 17908 }
4d66261f
PJ
17909# if defined(TARGET_MIPS64)
17910 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
17911 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
17912 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
68473f15
RH
17913 env->CP0_Status |= (1 << CP0St_FR);
17914 }
4d66261f 17915# endif
932e71cd
AJ
17916#else
17917 if (env->hflags & MIPS_HFLAG_BMASK) {
17918 /* If the exception was raised from a delay slot,
17919 come back to the jump. */
17920 env->CP0_ErrorEPC = env->active_tc.PC - 4;
aa328add 17921 } else {
932e71cd
AJ
17922 env->CP0_ErrorEPC = env->active_tc.PC;
17923 }
17924 env->active_tc.PC = (int32_t)0xBFC00000;
51cc2e78
BS
17925 env->CP0_Random = env->tlb->nb_tlb - 1;
17926 env->tlb->tlb_in_use = env->tlb->nb_tlb;
932e71cd 17927 env->CP0_Wired = 0;
0a2672b7
JH
17928 env->CP0_EBase = (cs->cpu_index & 0x3FF);
17929 if (kvm_enabled()) {
17930 env->CP0_EBase |= 0x40000000;
17931 } else {
17932 env->CP0_EBase |= 0x80000000;
17933 }
932e71cd
AJ
17934 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
17935 /* vectored interrupts not implemented, timer on int 7,
17936 no performance counters. */
17937 env->CP0_IntCtl = 0xe0000000;
17938 {
17939 int i;
17940
17941 for (i = 0; i < 7; i++) {
17942 env->CP0_WatchLo[i] = 0;
17943 env->CP0_WatchHi[i] = 0x80000000;
fd88b6ab 17944 }
932e71cd
AJ
17945 env->CP0_WatchLo[7] = 0;
17946 env->CP0_WatchHi[7] = 0;
fd88b6ab 17947 }
932e71cd
AJ
17948 /* Count register increments in debug mode, EJTAG version 1 */
17949 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
9e56e756 17950
4b69c7e2
JH
17951 cpu_mips_store_count(env, 1);
17952
9e56e756
EI
17953 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
17954 int i;
17955
17956 /* Only TC0 on VPE 0 starts as active. */
17957 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
55e5c285 17958 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
9e56e756
EI
17959 env->tcs[i].CP0_TCHalt = 1;
17960 }
17961 env->active_tc.CP0_TCHalt = 1;
259186a7 17962 cs->halted = 1;
9e56e756 17963
55e5c285 17964 if (cs->cpu_index == 0) {
9e56e756
EI
17965 /* VPE0 starts up enabled. */
17966 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
17967 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
17968
17969 /* TC0 starts up unhalted. */
259186a7 17970 cs->halted = 0;
9e56e756
EI
17971 env->active_tc.CP0_TCHalt = 0;
17972 env->tcs[0].CP0_TCHalt = 0;
17973 /* With thread 0 active. */
17974 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
17975 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
17976 }
17977 }
51cc2e78 17978#endif
ddc584bd
LA
17979 if ((env->insn_flags & ISA_MIPS32R6) &&
17980 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
17981 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
17982 env->CP0_Status |= (1 << CP0St_FR);
17983 }
17984
03e6e501 17985 compute_hflags(env);
27103424 17986 cs->exception_index = EXCP_NONE;
6af0bf9c 17987}
d2856f1a 17988
7db13fae 17989void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
d2856f1a 17990{
25983cad 17991 env->active_tc.PC = tcg_ctx.gen_opc_pc[pc_pos];
d2856f1a
AJ
17992 env->hflags &= ~MIPS_HFLAG_BMASK;
17993 env->hflags |= gen_opc_hflags[pc_pos];
4636401d
AJ
17994 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
17995 case MIPS_HFLAG_BR:
17996 break;
17997 case MIPS_HFLAG_BC:
17998 case MIPS_HFLAG_BL:
17999 case MIPS_HFLAG_B:
18000 env->btarget = gen_opc_btarget[pc_pos];
18001 break;
18002 }
d2856f1a 18003}
This page took 3.812061 seconds and 4 git commands to generate.