]> git.proxmox.com Git - mirror_qemu.git/blame - target-mips/translate.c
target-mips: Add ASE DSP multiply instructions
[mirror_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"
6af0bf9c 25#include "disas.h"
57fec1fe 26#include "tcg-op.h"
6af0bf9c 27
a7812ae4
PB
28#include "helper.h"
29#define GEN_HELPER 1
30#include "helper.h"
31
fb7729e2 32#define MIPS_DEBUG_DISAS 0
c570fd16 33//#define MIPS_DEBUG_SIGN_EXTENSIONS
6af0bf9c 34
7a387fff
TS
35/* MIPS major opcodes */
36#define MASK_OP_MAJOR(op) (op & (0x3F << 26))
e37e863f
FB
37
38enum {
39 /* indirect opcode tables */
7a387fff
TS
40 OPC_SPECIAL = (0x00 << 26),
41 OPC_REGIMM = (0x01 << 26),
42 OPC_CP0 = (0x10 << 26),
43 OPC_CP1 = (0x11 << 26),
44 OPC_CP2 = (0x12 << 26),
45 OPC_CP3 = (0x13 << 26),
46 OPC_SPECIAL2 = (0x1C << 26),
47 OPC_SPECIAL3 = (0x1F << 26),
e37e863f 48 /* arithmetic with immediate */
7a387fff
TS
49 OPC_ADDI = (0x08 << 26),
50 OPC_ADDIU = (0x09 << 26),
51 OPC_SLTI = (0x0A << 26),
52 OPC_SLTIU = (0x0B << 26),
324d9e32 53 /* logic with immediate */
7a387fff
TS
54 OPC_ANDI = (0x0C << 26),
55 OPC_ORI = (0x0D << 26),
56 OPC_XORI = (0x0E << 26),
57 OPC_LUI = (0x0F << 26),
324d9e32 58 /* arithmetic with immediate */
7a387fff
TS
59 OPC_DADDI = (0x18 << 26),
60 OPC_DADDIU = (0x19 << 26),
e37e863f 61 /* Jump and branches */
7a387fff
TS
62 OPC_J = (0x02 << 26),
63 OPC_JAL = (0x03 << 26),
620e48f6 64 OPC_JALS = OPC_JAL | 0x5,
7a387fff
TS
65 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
66 OPC_BEQL = (0x14 << 26),
67 OPC_BNE = (0x05 << 26),
68 OPC_BNEL = (0x15 << 26),
69 OPC_BLEZ = (0x06 << 26),
70 OPC_BLEZL = (0x16 << 26),
71 OPC_BGTZ = (0x07 << 26),
72 OPC_BGTZL = (0x17 << 26),
73 OPC_JALX = (0x1D << 26), /* MIPS 16 only */
620e48f6 74 OPC_JALXS = OPC_JALX | 0x5,
e37e863f 75 /* Load and stores */
7a387fff
TS
76 OPC_LDL = (0x1A << 26),
77 OPC_LDR = (0x1B << 26),
78 OPC_LB = (0x20 << 26),
79 OPC_LH = (0x21 << 26),
80 OPC_LWL = (0x22 << 26),
81 OPC_LW = (0x23 << 26),
364d4831 82 OPC_LWPC = OPC_LW | 0x5,
7a387fff
TS
83 OPC_LBU = (0x24 << 26),
84 OPC_LHU = (0x25 << 26),
85 OPC_LWR = (0x26 << 26),
86 OPC_LWU = (0x27 << 26),
87 OPC_SB = (0x28 << 26),
88 OPC_SH = (0x29 << 26),
89 OPC_SWL = (0x2A << 26),
90 OPC_SW = (0x2B << 26),
91 OPC_SDL = (0x2C << 26),
92 OPC_SDR = (0x2D << 26),
93 OPC_SWR = (0x2E << 26),
94 OPC_LL = (0x30 << 26),
95 OPC_LLD = (0x34 << 26),
96 OPC_LD = (0x37 << 26),
364d4831 97 OPC_LDPC = OPC_LD | 0x5,
7a387fff
TS
98 OPC_SC = (0x38 << 26),
99 OPC_SCD = (0x3C << 26),
100 OPC_SD = (0x3F << 26),
e37e863f 101 /* Floating point load/store */
7a387fff
TS
102 OPC_LWC1 = (0x31 << 26),
103 OPC_LWC2 = (0x32 << 26),
104 OPC_LDC1 = (0x35 << 26),
105 OPC_LDC2 = (0x36 << 26),
106 OPC_SWC1 = (0x39 << 26),
107 OPC_SWC2 = (0x3A << 26),
108 OPC_SDC1 = (0x3D << 26),
109 OPC_SDC2 = (0x3E << 26),
110 /* MDMX ASE specific */
111 OPC_MDMX = (0x1E << 26),
e37e863f 112 /* Cache and prefetch */
7a387fff
TS
113 OPC_CACHE = (0x2F << 26),
114 OPC_PREF = (0x33 << 26),
115 /* Reserved major opcode */
116 OPC_MAJOR3B_RESERVED = (0x3B << 26),
e37e863f
FB
117};
118
119/* MIPS special opcodes */
7a387fff
TS
120#define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
121
e37e863f
FB
122enum {
123 /* Shifts */
7a387fff 124 OPC_SLL = 0x00 | OPC_SPECIAL,
e37e863f
FB
125 /* NOP is SLL r0, r0, 0 */
126 /* SSNOP is SLL r0, r0, 1 */
7a387fff
TS
127 /* EHB is SLL r0, r0, 3 */
128 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
ea63e2c3 129 OPC_ROTR = OPC_SRL | (1 << 21),
7a387fff
TS
130 OPC_SRA = 0x03 | OPC_SPECIAL,
131 OPC_SLLV = 0x04 | OPC_SPECIAL,
e189e748 132 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
ea63e2c3 133 OPC_ROTRV = OPC_SRLV | (1 << 6),
7a387fff
TS
134 OPC_SRAV = 0x07 | OPC_SPECIAL,
135 OPC_DSLLV = 0x14 | OPC_SPECIAL,
136 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
ea63e2c3 137 OPC_DROTRV = OPC_DSRLV | (1 << 6),
7a387fff
TS
138 OPC_DSRAV = 0x17 | OPC_SPECIAL,
139 OPC_DSLL = 0x38 | OPC_SPECIAL,
140 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
ea63e2c3 141 OPC_DROTR = OPC_DSRL | (1 << 21),
7a387fff
TS
142 OPC_DSRA = 0x3B | OPC_SPECIAL,
143 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
144 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
ea63e2c3 145 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
7a387fff 146 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
e37e863f 147 /* Multiplication / division */
7a387fff
TS
148 OPC_MULT = 0x18 | OPC_SPECIAL,
149 OPC_MULTU = 0x19 | OPC_SPECIAL,
150 OPC_DIV = 0x1A | OPC_SPECIAL,
151 OPC_DIVU = 0x1B | OPC_SPECIAL,
152 OPC_DMULT = 0x1C | OPC_SPECIAL,
153 OPC_DMULTU = 0x1D | OPC_SPECIAL,
154 OPC_DDIV = 0x1E | OPC_SPECIAL,
155 OPC_DDIVU = 0x1F | OPC_SPECIAL,
e37e863f 156 /* 2 registers arithmetic / logic */
7a387fff
TS
157 OPC_ADD = 0x20 | OPC_SPECIAL,
158 OPC_ADDU = 0x21 | OPC_SPECIAL,
159 OPC_SUB = 0x22 | OPC_SPECIAL,
160 OPC_SUBU = 0x23 | OPC_SPECIAL,
161 OPC_AND = 0x24 | OPC_SPECIAL,
162 OPC_OR = 0x25 | OPC_SPECIAL,
163 OPC_XOR = 0x26 | OPC_SPECIAL,
164 OPC_NOR = 0x27 | OPC_SPECIAL,
165 OPC_SLT = 0x2A | OPC_SPECIAL,
166 OPC_SLTU = 0x2B | OPC_SPECIAL,
167 OPC_DADD = 0x2C | OPC_SPECIAL,
168 OPC_DADDU = 0x2D | OPC_SPECIAL,
169 OPC_DSUB = 0x2E | OPC_SPECIAL,
170 OPC_DSUBU = 0x2F | OPC_SPECIAL,
e37e863f 171 /* Jumps */
7a387fff
TS
172 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
173 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
364d4831 174 OPC_JALRC = OPC_JALR | (0x5 << 6),
620e48f6 175 OPC_JALRS = 0x10 | OPC_SPECIAL | (0x5 << 6),
e37e863f 176 /* Traps */
7a387fff
TS
177 OPC_TGE = 0x30 | OPC_SPECIAL,
178 OPC_TGEU = 0x31 | OPC_SPECIAL,
179 OPC_TLT = 0x32 | OPC_SPECIAL,
180 OPC_TLTU = 0x33 | OPC_SPECIAL,
181 OPC_TEQ = 0x34 | OPC_SPECIAL,
182 OPC_TNE = 0x36 | OPC_SPECIAL,
e37e863f 183 /* HI / LO registers load & stores */
7a387fff
TS
184 OPC_MFHI = 0x10 | OPC_SPECIAL,
185 OPC_MTHI = 0x11 | OPC_SPECIAL,
186 OPC_MFLO = 0x12 | OPC_SPECIAL,
187 OPC_MTLO = 0x13 | OPC_SPECIAL,
e37e863f 188 /* Conditional moves */
7a387fff
TS
189 OPC_MOVZ = 0x0A | OPC_SPECIAL,
190 OPC_MOVN = 0x0B | OPC_SPECIAL,
e37e863f 191
7a387fff 192 OPC_MOVCI = 0x01 | OPC_SPECIAL,
e37e863f
FB
193
194 /* Special */
a0d700e4 195 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
7a387fff
TS
196 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
197 OPC_BREAK = 0x0D | OPC_SPECIAL,
a0d700e4 198 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
7a387fff
TS
199 OPC_SYNC = 0x0F | OPC_SPECIAL,
200
201 OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
202 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
203 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
204 OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
205 OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
206 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
207 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
208};
209
e9c71dd1
TS
210/* Multiplication variants of the vr54xx. */
211#define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
212
213enum {
214 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
215 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
216 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
217 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
218 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
219 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
220 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
221 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
222 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
223 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
224 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
225 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
226 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
227 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
228};
229
7a387fff
TS
230/* REGIMM (rt field) opcodes */
231#define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
232
233enum {
234 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
235 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
236 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
237 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
238 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
3c824109 239 OPC_BLTZALS = OPC_BLTZAL | 0x5, /* microMIPS */
7a387fff
TS
240 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
241 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
3c824109 242 OPC_BGEZALS = OPC_BGEZAL | 0x5, /* microMIPS */
7a387fff
TS
243 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
244 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
245 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
246 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
247 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
248 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
249 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
250 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
e37e863f
FB
251};
252
7a387fff
TS
253/* Special2 opcodes */
254#define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
255
e37e863f 256enum {
7a387fff
TS
257 /* Multiply & xxx operations */
258 OPC_MADD = 0x00 | OPC_SPECIAL2,
259 OPC_MADDU = 0x01 | OPC_SPECIAL2,
260 OPC_MUL = 0x02 | OPC_SPECIAL2,
261 OPC_MSUB = 0x04 | OPC_SPECIAL2,
262 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
161f85e6
AJ
263 /* Loongson 2F */
264 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
265 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
266 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
267 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
268 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
269 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
270 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
271 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
272 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
273 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
274 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
275 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
e37e863f 276 /* Misc */
7a387fff
TS
277 OPC_CLZ = 0x20 | OPC_SPECIAL2,
278 OPC_CLO = 0x21 | OPC_SPECIAL2,
279 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
280 OPC_DCLO = 0x25 | OPC_SPECIAL2,
e37e863f 281 /* Special */
7a387fff
TS
282 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
283};
284
285/* Special3 opcodes */
286#define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
287
288enum {
289 OPC_EXT = 0x00 | OPC_SPECIAL3,
290 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
291 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
292 OPC_DEXT = 0x03 | OPC_SPECIAL3,
293 OPC_INS = 0x04 | OPC_SPECIAL3,
294 OPC_DINSM = 0x05 | OPC_SPECIAL3,
295 OPC_DINSU = 0x06 | OPC_SPECIAL3,
296 OPC_DINS = 0x07 | OPC_SPECIAL3,
ead9360e
TS
297 OPC_FORK = 0x08 | OPC_SPECIAL3,
298 OPC_YIELD = 0x09 | OPC_SPECIAL3,
7a387fff
TS
299 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
300 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
301 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
161f85e6
AJ
302
303 /* Loongson 2E */
304 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
305 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
306 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
307 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
308 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
309 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
310 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
311 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
312 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
313 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
314 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
315 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
9b1a1d68
JL
316
317 /* MIPS DSP Load */
318 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
461c08df
JL
319 /* MIPS DSP Arithmetic */
320 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
321#if defined(TARGET_MIPS64)
322 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
323#endif
324 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
325#if defined(TARGET_MIPS64)
326 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
327#endif
328 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
329 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
330 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
331#if defined(TARGET_MIPS64)
332 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
77c5fa8b
JL
333#endif
334 /* MIPS DSP GPR-Based Shift Sub-class */
335 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
336#if defined(TARGET_MIPS64)
337 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
338#endif
339 /* MIPS DSP Multiply Sub-class insns */
340 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
341 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
342 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
343#if defined(TARGET_MIPS64)
344 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
461c08df 345#endif
e37e863f
FB
346};
347
7a387fff
TS
348/* BSHFL opcodes */
349#define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
350
e37e863f 351enum {
7a387fff
TS
352 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
353 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
354 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
e37e863f
FB
355};
356
7a387fff
TS
357/* DBSHFL opcodes */
358#define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
359
e37e863f 360enum {
7a387fff
TS
361 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
362 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
e37e863f
FB
363};
364
e45a93e2
JL
365/* MIPS DSP REGIMM opcodes */
366enum {
367 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
368#if defined(TARGET_MIPS64)
369 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
370#endif
371};
372
9b1a1d68
JL
373#define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
374/* MIPS DSP Load */
375enum {
376 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
377 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
378 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
379#if defined(TARGET_MIPS64)
380 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
381#endif
382};
383
461c08df
JL
384#define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
385enum {
386 /* MIPS DSP Arithmetic Sub-class */
387 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
388 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
389 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
390 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
391 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
392 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
393 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
394 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
395 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
396 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
397 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
398 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
399 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
400 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
401 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
402 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
403 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
404 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
a22260ae
JL
405 /* MIPS DSP Multiply Sub-class insns */
406 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
407 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
408 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
409 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
410 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
411 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
461c08df
JL
412};
413
414#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
415#define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
416enum {
417 /* MIPS DSP Arithmetic Sub-class */
418 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
419 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
420 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
421 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
422 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
423 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
424 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
425 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
426 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
427 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
428 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
429 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
a22260ae
JL
430 /* MIPS DSP Multiply Sub-class insns */
431 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
432 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
433 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
434 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
461c08df
JL
435};
436
437#define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
438enum {
439 /* MIPS DSP Arithmetic Sub-class */
440 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
441 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
442 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
443 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
444 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
445 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
446 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
447 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
448 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
449 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
450 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
451 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
452 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
453};
454
455#define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
456enum {
457 /* MIPS DSP Arithmetic Sub-class */
458 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
459 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
460 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
461 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
462 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
463 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
464 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
465};
a22260ae 466
77c5fa8b
JL
467#define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
468enum {
469 /* MIPS DSP GPR-Based Shift Sub-class */
470 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
471 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
472 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
473 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
474 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
475 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
476 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
477 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
478 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
479 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
480 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
481 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
482 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
483 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
484 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
485 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
486 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
487 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
488 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
489 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
490 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
491 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
492};
461c08df 493
a22260ae
JL
494#define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
495enum {
496 /* MIPS DSP Multiply Sub-class insns */
497 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
498 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
499 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
500 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
501 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
502 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
503 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
504 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
505 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
506 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
507 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
508 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
509 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
510 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
511 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
512 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
513 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
514 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
515 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
516 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
517 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
518 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
519};
520
461c08df
JL
521#if defined(TARGET_MIPS64)
522#define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
523enum {
524 /* MIPS DSP Arithmetic Sub-class */
525 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
526 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
527 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
528 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
529 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
530 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
531 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
532 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
533 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
534 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
535 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
536 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
537 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
538 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
539 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
540 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
541 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
542};
543#endif
544
545#if defined(TARGET_MIPS64)
546#define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
547enum {
a22260ae
JL
548 /* MIPS DSP Multiply Sub-class insns */
549 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
550 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
551 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
552 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
553 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
461c08df
JL
554 /* MIPS DSP Arithmetic Sub-class */
555 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
556 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
557 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
558 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
559 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
560 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
561 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
562 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
563 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
564 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
565 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
566 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
567 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
568 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
569 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
570 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
571 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
572 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
573 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
574 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
575 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
576};
577#endif
578
579#if defined(TARGET_MIPS64)
580#define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
581enum {
582 /* MIPS DSP Arithmetic Sub-class */
583 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
584 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
585 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
586 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
587 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
588 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
589 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
590 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
591};
592#endif
593
a22260ae
JL
594#if defined(TARGET_MIPS64)
595#define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
596enum {
597 /* MIPS DSP Multiply Sub-class insns */
598 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
599 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
600 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
601 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
602 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
603 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
604 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
605 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
606 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
607 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
608 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
609 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
610 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
611 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
612 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
613 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
614 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
615 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
616 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
617 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
618 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
619 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
620 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
621 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
622 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
623 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
624};
625#endif
626
77c5fa8b
JL
627#if defined(TARGET_MIPS64)
628#define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
629enum {
630 /* MIPS DSP GPR-Based Shift Sub-class */
631 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
632 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
633 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
634 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
635 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
636 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
637 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
638 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
639 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
640 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
641 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
642 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
643 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
644 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
645 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
646 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
647 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
648 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
649 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
650 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
651 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
652 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
653 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
654 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
655 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
656 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
657};
658#endif
659
7a387fff
TS
660/* Coprocessor 0 (rs field) */
661#define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
662
6ea83fed 663enum {
7a387fff
TS
664 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
665 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
666 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
667 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
ead9360e 668 OPC_MFTR = (0x08 << 21) | OPC_CP0,
7a387fff
TS
669 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
670 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
ead9360e 671 OPC_MTTR = (0x0C << 21) | OPC_CP0,
7a387fff
TS
672 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
673 OPC_C0 = (0x10 << 21) | OPC_CP0,
674 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
675 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
6ea83fed 676};
7a387fff
TS
677
678/* MFMC0 opcodes */
b48cfdff 679#define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
7a387fff
TS
680
681enum {
ead9360e
TS
682 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
683 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
684 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
685 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
7a387fff
TS
686 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
687 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
688};
689
690/* Coprocessor 0 (with rs == C0) */
691#define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
692
693enum {
694 OPC_TLBR = 0x01 | OPC_C0,
695 OPC_TLBWI = 0x02 | OPC_C0,
696 OPC_TLBWR = 0x06 | OPC_C0,
697 OPC_TLBP = 0x08 | OPC_C0,
698 OPC_RFE = 0x10 | OPC_C0,
699 OPC_ERET = 0x18 | OPC_C0,
700 OPC_DERET = 0x1F | OPC_C0,
701 OPC_WAIT = 0x20 | OPC_C0,
702};
703
704/* Coprocessor 1 (rs field) */
705#define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
706
bf4120ad
NF
707/* Values for the fmt field in FP instructions */
708enum {
709 /* 0 - 15 are reserved */
e459440a
AJ
710 FMT_S = 16, /* single fp */
711 FMT_D = 17, /* double fp */
712 FMT_E = 18, /* extended fp */
713 FMT_Q = 19, /* quad fp */
714 FMT_W = 20, /* 32-bit fixed */
715 FMT_L = 21, /* 64-bit fixed */
716 FMT_PS = 22, /* paired single fp */
bf4120ad
NF
717 /* 23 - 31 are reserved */
718};
719
7a387fff
TS
720enum {
721 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
722 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
723 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
5a5012ec 724 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
7a387fff
TS
725 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
726 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
727 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
5a5012ec 728 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
7a387fff 729 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
5a5012ec
TS
730 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
731 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
e459440a
AJ
732 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
733 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
734 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
735 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
736 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
737 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
738 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
7a387fff
TS
739};
740
5a5012ec
TS
741#define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
742#define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
743
7a387fff
TS
744enum {
745 OPC_BC1F = (0x00 << 16) | OPC_BC1,
746 OPC_BC1T = (0x01 << 16) | OPC_BC1,
747 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
748 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
749};
750
5a5012ec
TS
751enum {
752 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
753 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
754};
755
756enum {
757 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
758 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
759};
7a387fff
TS
760
761#define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
e0c84da7
TS
762
763enum {
764 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
765 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
766 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
767 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
768 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
769 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
770 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
771 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
772 OPC_BC2 = (0x08 << 21) | OPC_CP2,
773};
774
bd277fa1
RH
775#define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
776
777enum {
778 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
779 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
780 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
781 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
782 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
783 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
784 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
785 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
786
787 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
788 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
789 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
790 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
791 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
792 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
793 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
794 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
795
796 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
797 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
798 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
799 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
800 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
801 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
802 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
803 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
804
805 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
806 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
807 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
808 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
809 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
810 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
811 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
812 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
813
814 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
815 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
816 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
817 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
818 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
819 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
820
821 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
822 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
823 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
824 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
825 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
826 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
827
828 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
829 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
830 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
831 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
832 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
833 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
834
835 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
836 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
837 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
838 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
839 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
840 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
841
842 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
843 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
844 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
845 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
846 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
847 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
848
849 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
850 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
851 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
852 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
853 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
854 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
855
856 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
857 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
858 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
859 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
860 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
861 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
862
863 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
864 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
865 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
866 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
867 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
868 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
869};
870
871
e0c84da7
TS
872#define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
873
874enum {
875 OPC_LWXC1 = 0x00 | OPC_CP3,
876 OPC_LDXC1 = 0x01 | OPC_CP3,
877 OPC_LUXC1 = 0x05 | OPC_CP3,
878 OPC_SWXC1 = 0x08 | OPC_CP3,
879 OPC_SDXC1 = 0x09 | OPC_CP3,
880 OPC_SUXC1 = 0x0D | OPC_CP3,
881 OPC_PREFX = 0x0F | OPC_CP3,
882 OPC_ALNV_PS = 0x1E | OPC_CP3,
883 OPC_MADD_S = 0x20 | OPC_CP3,
884 OPC_MADD_D = 0x21 | OPC_CP3,
885 OPC_MADD_PS = 0x26 | OPC_CP3,
886 OPC_MSUB_S = 0x28 | OPC_CP3,
887 OPC_MSUB_D = 0x29 | OPC_CP3,
888 OPC_MSUB_PS = 0x2E | OPC_CP3,
889 OPC_NMADD_S = 0x30 | OPC_CP3,
fbcc6828 890 OPC_NMADD_D = 0x31 | OPC_CP3,
e0c84da7
TS
891 OPC_NMADD_PS= 0x36 | OPC_CP3,
892 OPC_NMSUB_S = 0x38 | OPC_CP3,
893 OPC_NMSUB_D = 0x39 | OPC_CP3,
894 OPC_NMSUB_PS= 0x3E | OPC_CP3,
895};
896
39454628 897/* global register indices */
a7812ae4
PB
898static TCGv_ptr cpu_env;
899static TCGv cpu_gpr[32], cpu_PC;
4b2eb8d2 900static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
41db4607
AJ
901static TCGv cpu_dspctrl, btarget, bcond;
902static TCGv_i32 hflags;
a7812ae4 903static TCGv_i32 fpu_fcr0, fpu_fcr31;
d73ee8a2 904static TCGv_i64 fpu_f64[32];
aa0bf00b 905
1a7ff922
PB
906static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
907
2e70f6ef
PB
908#include "gen-icount.h"
909
895c2d04 910#define gen_helper_0e0i(name, arg) do { \
a7812ae4 911 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
895c2d04 912 gen_helper_##name(cpu_env, helper_tmp); \
a7812ae4
PB
913 tcg_temp_free_i32(helper_tmp); \
914 } while(0)
be24bb4f 915
895c2d04 916#define gen_helper_0e1i(name, arg1, arg2) do { \
a7812ae4 917 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
895c2d04 918 gen_helper_##name(cpu_env, arg1, helper_tmp); \
a7812ae4
PB
919 tcg_temp_free_i32(helper_tmp); \
920 } while(0)
be24bb4f 921
895c2d04
BS
922#define gen_helper_1e0i(name, ret, arg1) do { \
923 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
924 gen_helper_##name(ret, cpu_env, helper_tmp); \
925 tcg_temp_free_i32(helper_tmp); \
926 } while(0)
927
928#define gen_helper_1e1i(name, ret, arg1, arg2) do { \
929 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
930 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
931 tcg_temp_free_i32(helper_tmp); \
932 } while(0)
933
934#define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
935 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
936 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
937 tcg_temp_free_i32(helper_tmp); \
938 } while(0)
939
940#define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
a7812ae4 941 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
895c2d04 942 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
a7812ae4
PB
943 tcg_temp_free_i32(helper_tmp); \
944 } while(0)
be24bb4f 945
895c2d04 946#define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
a7812ae4 947 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
895c2d04 948 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
a7812ae4
PB
949 tcg_temp_free_i32(helper_tmp); \
950 } while(0)
c239529e 951
8e9ade68
TS
952typedef struct DisasContext {
953 struct TranslationBlock *tb;
954 target_ulong pc, saved_pc;
955 uint32_t opcode;
7b270ef2 956 int singlestep_enabled;
8e9ade68
TS
957 /* Routine used to access memory */
958 int mem_idx;
959 uint32_t hflags, saved_hflags;
960 int bstate;
961 target_ulong btarget;
962} DisasContext;
963
964enum {
965 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
d077b6f7 966 * exception condition */
8e9ade68
TS
967 BS_STOP = 1, /* We want to stop translation for any reason */
968 BS_BRANCH = 2, /* We reached a branch condition */
969 BS_EXCP = 3, /* We reached an exception condition */
970};
971
d73ee8a2
RH
972static const char * const regnames[] = {
973 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
974 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
975 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
976 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
977};
6af0bf9c 978
d73ee8a2
RH
979static const char * const regnames_HI[] = {
980 "HI0", "HI1", "HI2", "HI3",
981};
4b2eb8d2 982
d73ee8a2
RH
983static const char * const regnames_LO[] = {
984 "LO0", "LO1", "LO2", "LO3",
985};
4b2eb8d2 986
d73ee8a2
RH
987static const char * const regnames_ACX[] = {
988 "ACX0", "ACX1", "ACX2", "ACX3",
989};
4b2eb8d2 990
d73ee8a2
RH
991static const char * const fregnames[] = {
992 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
993 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
994 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
995 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
996};
958fb4a9 997
fb7729e2
RH
998#define MIPS_DEBUG(fmt, ...) \
999 do { \
1000 if (MIPS_DEBUG_DISAS) { \
1001 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
1002 TARGET_FMT_lx ": %08x " fmt "\n", \
1003 ctx->pc, ctx->opcode , ## __VA_ARGS__); \
1004 } \
1005 } while (0)
1006
1007#define LOG_DISAS(...) \
1008 do { \
1009 if (MIPS_DEBUG_DISAS) { \
1010 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
1011 } \
1012 } while (0)
958fb4a9 1013
8e9ade68 1014#define MIPS_INVAL(op) \
8e9ade68 1015 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
fb7729e2 1016 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F))
ead9360e 1017
8e9ade68
TS
1018/* General purpose registers moves. */
1019static inline void gen_load_gpr (TCGv t, int reg)
aaa9128a 1020{
8e9ade68
TS
1021 if (reg == 0)
1022 tcg_gen_movi_tl(t, 0);
1023 else
4b2eb8d2 1024 tcg_gen_mov_tl(t, cpu_gpr[reg]);
aaa9128a
TS
1025}
1026
8e9ade68 1027static inline void gen_store_gpr (TCGv t, int reg)
aaa9128a 1028{
8e9ade68 1029 if (reg != 0)
4b2eb8d2 1030 tcg_gen_mov_tl(cpu_gpr[reg], t);
aaa9128a
TS
1031}
1032
b10fa3c9 1033/* Moves to/from ACX register. */
4b2eb8d2 1034static inline void gen_load_ACX (TCGv t, int reg)
893f9865 1035{
4b2eb8d2 1036 tcg_gen_mov_tl(t, cpu_ACX[reg]);
893f9865
TS
1037}
1038
4b2eb8d2 1039static inline void gen_store_ACX (TCGv t, int reg)
893f9865 1040{
4b2eb8d2 1041 tcg_gen_mov_tl(cpu_ACX[reg], t);
893f9865
TS
1042}
1043
8e9ade68 1044/* Moves to/from shadow registers. */
be24bb4f 1045static inline void gen_load_srsgpr (int from, int to)
aaa9128a 1046{
d9bea114 1047 TCGv t0 = tcg_temp_new();
be24bb4f
TS
1048
1049 if (from == 0)
d9bea114 1050 tcg_gen_movi_tl(t0, 0);
8e9ade68 1051 else {
d9bea114 1052 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 1053 TCGv_ptr addr = tcg_temp_new_ptr();
aaa9128a 1054
7db13fae 1055 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
1056 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1057 tcg_gen_andi_i32(t2, t2, 0xf);
1058 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1059 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 1060 tcg_gen_add_ptr(addr, cpu_env, addr);
aaa9128a 1061
d9bea114 1062 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
a7812ae4 1063 tcg_temp_free_ptr(addr);
d9bea114 1064 tcg_temp_free_i32(t2);
8e9ade68 1065 }
d9bea114
AJ
1066 gen_store_gpr(t0, to);
1067 tcg_temp_free(t0);
aaa9128a
TS
1068}
1069
be24bb4f 1070static inline void gen_store_srsgpr (int from, int to)
aaa9128a 1071{
be24bb4f 1072 if (to != 0) {
d9bea114
AJ
1073 TCGv t0 = tcg_temp_new();
1074 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 1075 TCGv_ptr addr = tcg_temp_new_ptr();
be24bb4f 1076
d9bea114 1077 gen_load_gpr(t0, from);
7db13fae 1078 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
1079 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1080 tcg_gen_andi_i32(t2, t2, 0xf);
1081 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1082 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 1083 tcg_gen_add_ptr(addr, cpu_env, addr);
be24bb4f 1084
d9bea114 1085 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
a7812ae4 1086 tcg_temp_free_ptr(addr);
d9bea114
AJ
1087 tcg_temp_free_i32(t2);
1088 tcg_temp_free(t0);
8e9ade68 1089 }
aaa9128a
TS
1090}
1091
aaa9128a 1092/* Floating point register moves. */
d73ee8a2 1093static void gen_load_fpr32(TCGv_i32 t, int reg)
aa0bf00b 1094{
d73ee8a2 1095 tcg_gen_trunc_i64_i32(t, fpu_f64[reg]);
6ea83fed
FB
1096}
1097
d73ee8a2 1098static void gen_store_fpr32(TCGv_i32 t, int reg)
aa0bf00b 1099{
d73ee8a2
RH
1100 TCGv_i64 t64 = tcg_temp_new_i64();
1101 tcg_gen_extu_i32_i64(t64, t);
1102 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1103 tcg_temp_free_i64(t64);
6d066274
AJ
1104}
1105
d73ee8a2 1106static void gen_load_fpr32h(TCGv_i32 t, int reg)
6d066274 1107{
d73ee8a2
RH
1108 TCGv_i64 t64 = tcg_temp_new_i64();
1109 tcg_gen_shri_i64(t64, fpu_f64[reg], 32);
1110 tcg_gen_trunc_i64_i32(t, t64);
1111 tcg_temp_free_i64(t64);
6d066274
AJ
1112}
1113
d73ee8a2 1114static void gen_store_fpr32h(TCGv_i32 t, int reg)
6d066274 1115{
d73ee8a2
RH
1116 TCGv_i64 t64 = tcg_temp_new_i64();
1117 tcg_gen_extu_i32_i64(t64, t);
1118 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1119 tcg_temp_free_i64(t64);
aa0bf00b 1120}
6ea83fed 1121
d73ee8a2 1122static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 1123{
f364515c 1124 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 1125 tcg_gen_mov_i64(t, fpu_f64[reg]);
f364515c 1126 } else {
d73ee8a2 1127 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
aa0bf00b
TS
1128 }
1129}
6ea83fed 1130
d73ee8a2 1131static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 1132{
f364515c 1133 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 1134 tcg_gen_mov_i64(fpu_f64[reg], t);
f364515c 1135 } else {
d73ee8a2
RH
1136 TCGv_i64 t0;
1137 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1138 t0 = tcg_temp_new_i64();
6d066274 1139 tcg_gen_shri_i64(t0, t, 32);
d73ee8a2 1140 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
6d066274 1141 tcg_temp_free_i64(t0);
aa0bf00b
TS
1142 }
1143}
6ea83fed 1144
d94536f4 1145static inline int get_fp_bit (int cc)
a16336e4 1146{
d94536f4
AJ
1147 if (cc)
1148 return 24 + cc;
1149 else
1150 return 23;
a16336e4
TS
1151}
1152
30898801 1153/* Tests */
8e9ade68
TS
1154static inline void gen_save_pc(target_ulong pc)
1155{
1eb75d4a 1156 tcg_gen_movi_tl(cpu_PC, pc);
8e9ade68 1157}
30898801 1158
356265ae 1159static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
6af0bf9c 1160{
d12d51d5 1161 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
6af0bf9c 1162 if (do_save_pc && ctx->pc != ctx->saved_pc) {
9b9e4393 1163 gen_save_pc(ctx->pc);
6af0bf9c
FB
1164 ctx->saved_pc = ctx->pc;
1165 }
1166 if (ctx->hflags != ctx->saved_hflags) {
41db4607 1167 tcg_gen_movi_i32(hflags, ctx->hflags);
6af0bf9c 1168 ctx->saved_hflags = ctx->hflags;
364d4831 1169 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
5a5012ec 1170 case MIPS_HFLAG_BR:
5a5012ec
TS
1171 break;
1172 case MIPS_HFLAG_BC:
5a5012ec 1173 case MIPS_HFLAG_BL:
5a5012ec 1174 case MIPS_HFLAG_B:
d077b6f7 1175 tcg_gen_movi_tl(btarget, ctx->btarget);
5a5012ec 1176 break;
6af0bf9c
FB
1177 }
1178 }
1179}
1180
7db13fae 1181static inline void restore_cpu_state (CPUMIPSState *env, DisasContext *ctx)
5a5012ec 1182{
fd4a04eb 1183 ctx->saved_hflags = ctx->hflags;
364d4831 1184 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
fd4a04eb 1185 case MIPS_HFLAG_BR:
fd4a04eb
TS
1186 break;
1187 case MIPS_HFLAG_BC:
1188 case MIPS_HFLAG_BL:
39454628 1189 case MIPS_HFLAG_B:
fd4a04eb 1190 ctx->btarget = env->btarget;
fd4a04eb 1191 break;
5a5012ec
TS
1192 }
1193}
1194
356265ae 1195static inline void
48d38ca5 1196generate_exception_err (DisasContext *ctx, int excp, int err)
aaa9128a 1197{
a7812ae4
PB
1198 TCGv_i32 texcp = tcg_const_i32(excp);
1199 TCGv_i32 terr = tcg_const_i32(err);
aaa9128a 1200 save_cpu_state(ctx, 1);
895c2d04 1201 gen_helper_raise_exception_err(cpu_env, texcp, terr);
a7812ae4
PB
1202 tcg_temp_free_i32(terr);
1203 tcg_temp_free_i32(texcp);
aaa9128a
TS
1204}
1205
356265ae 1206static inline void
48d38ca5 1207generate_exception (DisasContext *ctx, int excp)
aaa9128a 1208{
6af0bf9c 1209 save_cpu_state(ctx, 1);
895c2d04 1210 gen_helper_0e0i(raise_exception, excp);
6af0bf9c
FB
1211}
1212
48d38ca5 1213/* Addresses computation */
941694d0 1214static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
4ad40f36 1215{
941694d0 1216 tcg_gen_add_tl(ret, arg0, arg1);
48d38ca5
TS
1217
1218#if defined(TARGET_MIPS64)
1219 /* For compatibility with 32-bit code, data reference in user mode
1220 with Status_UX = 0 should be casted to 32-bit and sign extended.
1221 See the MIPS64 PRA manual, section 4.10. */
2623c1ec
AJ
1222 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
1223 !(ctx->hflags & MIPS_HFLAG_UX)) {
941694d0 1224 tcg_gen_ext32s_i64(ret, ret);
48d38ca5
TS
1225 }
1226#endif
4ad40f36
FB
1227}
1228
356265ae 1229static inline void check_cp0_enabled(DisasContext *ctx)
387a8fe5 1230{
fe253235 1231 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
c2c65dab 1232 generate_exception_err(ctx, EXCP_CpU, 0);
387a8fe5
TS
1233}
1234
356265ae 1235static inline void check_cp1_enabled(DisasContext *ctx)
5e755519 1236{
fe253235 1237 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
5e755519
TS
1238 generate_exception_err(ctx, EXCP_CpU, 1);
1239}
1240
b8aa4598
TS
1241/* Verify that the processor is running with COP1X instructions enabled.
1242 This is associated with the nabla symbol in the MIPS32 and MIPS64
1243 opcode tables. */
1244
356265ae 1245static inline void check_cop1x(DisasContext *ctx)
b8aa4598
TS
1246{
1247 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
1248 generate_exception(ctx, EXCP_RI);
1249}
1250
1251/* Verify that the processor is running with 64-bit floating-point
1252 operations enabled. */
1253
356265ae 1254static inline void check_cp1_64bitmode(DisasContext *ctx)
5e755519 1255{
b8aa4598 1256 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
5e755519
TS
1257 generate_exception(ctx, EXCP_RI);
1258}
1259
1260/*
1261 * Verify if floating point register is valid; an operation is not defined
1262 * if bit 0 of any register specification is set and the FR bit in the
1263 * Status register equals zero, since the register numbers specify an
1264 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1265 * in the Status register equals one, both even and odd register numbers
1266 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1267 *
1268 * Multiple 64 bit wide registers can be checked by calling
1269 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1270 */
356265ae 1271static inline void check_cp1_registers(DisasContext *ctx, int regs)
5e755519 1272{
fe253235 1273 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
5e755519
TS
1274 generate_exception(ctx, EXCP_RI);
1275}
1276
853c3240
JL
1277/* Verify that the processor is running with DSP instructions enabled.
1278 This is enabled by CP0 Status register MX(24) bit.
1279 */
1280
1281static inline void check_dsp(DisasContext *ctx)
1282{
1283 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1284 generate_exception(ctx, EXCP_DSPDIS);
1285 }
1286}
1287
1288static inline void check_dspr2(DisasContext *ctx)
1289{
1290 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
1291 generate_exception(ctx, EXCP_DSPDIS);
1292 }
1293}
1294
3a95e3a7 1295/* This code generates a "reserved instruction" exception if the
e189e748 1296 CPU does not support the instruction set corresponding to flags. */
7db13fae 1297static inline void check_insn(CPUMIPSState *env, DisasContext *ctx, int flags)
3a95e3a7 1298{
e189e748 1299 if (unlikely(!(env->insn_flags & flags)))
3a95e3a7
TS
1300 generate_exception(ctx, EXCP_RI);
1301}
1302
e189e748
TS
1303/* This code generates a "reserved instruction" exception if 64-bit
1304 instructions are not enabled. */
356265ae 1305static inline void check_mips_64(DisasContext *ctx)
e189e748 1306{
fe253235 1307 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
e189e748
TS
1308 generate_exception(ctx, EXCP_RI);
1309}
1310
8153667c
NF
1311/* Define small wrappers for gen_load_fpr* so that we have a uniform
1312 calling interface for 32 and 64-bit FPRs. No sense in changing
1313 all callers for gen_load_fpr32 when we need the CTX parameter for
1314 this one use. */
1315#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y)
1316#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1317#define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1318static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1319 int ft, int fs, int cc) \
1320{ \
1321 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
1322 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
1323 switch (ifmt) { \
1324 case FMT_PS: \
1325 check_cp1_64bitmode(ctx); \
1326 break; \
1327 case FMT_D: \
1328 if (abs) { \
1329 check_cop1x(ctx); \
1330 } \
1331 check_cp1_registers(ctx, fs | ft); \
1332 break; \
1333 case FMT_S: \
1334 if (abs) { \
1335 check_cop1x(ctx); \
1336 } \
1337 break; \
1338 } \
1339 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
1340 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
1341 switch (n) { \
895c2d04
BS
1342 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
1343 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
1344 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
1345 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
1346 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
1347 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
1348 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
1349 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
1350 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
1351 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
1352 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
1353 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
1354 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
1355 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
1356 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
1357 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
8153667c
NF
1358 default: abort(); \
1359 } \
1360 tcg_temp_free_i##bits (fp0); \
1361 tcg_temp_free_i##bits (fp1); \
1362}
1363
1364FOP_CONDS(, 0, d, FMT_D, 64)
1365FOP_CONDS(abs, 1, d, FMT_D, 64)
1366FOP_CONDS(, 0, s, FMT_S, 32)
1367FOP_CONDS(abs, 1, s, FMT_S, 32)
1368FOP_CONDS(, 0, ps, FMT_PS, 64)
1369FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1370#undef FOP_CONDS
1371#undef gen_ldcmp_fpr32
1372#undef gen_ldcmp_fpr64
1373
958fb4a9 1374/* load/store instructions. */
d9bea114 1375#define OP_LD(insn,fname) \
5c13fdfd 1376static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
d9bea114
AJ
1377{ \
1378 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
aaa9128a
TS
1379}
1380OP_LD(lb,ld8s);
1381OP_LD(lbu,ld8u);
1382OP_LD(lh,ld16s);
1383OP_LD(lhu,ld16u);
1384OP_LD(lw,ld32s);
1385#if defined(TARGET_MIPS64)
1386OP_LD(lwu,ld32u);
1387OP_LD(ld,ld64);
1388#endif
1389#undef OP_LD
1390
d9bea114 1391#define OP_ST(insn,fname) \
5c13fdfd 1392static inline void op_st_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \
d9bea114
AJ
1393{ \
1394 tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
aaa9128a
TS
1395}
1396OP_ST(sb,st8);
1397OP_ST(sh,st16);
1398OP_ST(sw,st32);
1399#if defined(TARGET_MIPS64)
1400OP_ST(sd,st64);
1401#endif
1402#undef OP_ST
1403
e7139c44 1404#ifdef CONFIG_USER_ONLY
d9bea114 1405#define OP_LD_ATOMIC(insn,fname) \
5c13fdfd 1406static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
d9bea114
AJ
1407{ \
1408 TCGv t0 = tcg_temp_new(); \
1409 tcg_gen_mov_tl(t0, arg1); \
1410 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
7db13fae
AF
1411 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
1412 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
d9bea114 1413 tcg_temp_free(t0); \
aaa9128a 1414}
e7139c44
AJ
1415#else
1416#define OP_LD_ATOMIC(insn,fname) \
5c13fdfd 1417static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
e7139c44 1418{ \
895c2d04 1419 gen_helper_1e1i(insn, ret, arg1, ctx->mem_idx); \
e7139c44
AJ
1420}
1421#endif
aaa9128a
TS
1422OP_LD_ATOMIC(ll,ld32s);
1423#if defined(TARGET_MIPS64)
1424OP_LD_ATOMIC(lld,ld64);
1425#endif
1426#undef OP_LD_ATOMIC
1427
590bc601
PB
1428#ifdef CONFIG_USER_ONLY
1429#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
5c13fdfd 1430static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
590bc601
PB
1431{ \
1432 TCGv t0 = tcg_temp_new(); \
1433 int l1 = gen_new_label(); \
1434 int l2 = gen_new_label(); \
1435 \
1436 tcg_gen_andi_tl(t0, arg2, almask); \
1437 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
7db13fae 1438 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
590bc601
PB
1439 generate_exception(ctx, EXCP_AdES); \
1440 gen_set_label(l1); \
7db13fae 1441 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
590bc601
PB
1442 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
1443 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
7db13fae
AF
1444 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
1445 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
895c2d04 1446 gen_helper_0e0i(raise_exception, EXCP_SC); \
590bc601
PB
1447 gen_set_label(l2); \
1448 tcg_gen_movi_tl(t0, 0); \
1449 gen_store_gpr(t0, rt); \
1450 tcg_temp_free(t0); \
1451}
1452#else
1453#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
5c13fdfd 1454static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
590bc601
PB
1455{ \
1456 TCGv t0 = tcg_temp_new(); \
895c2d04 1457 gen_helper_1e2i(insn, t0, arg1, arg2, ctx->mem_idx); \
590bc601 1458 gen_store_gpr(t0, rt); \
590bc601
PB
1459 tcg_temp_free(t0); \
1460}
1461#endif
590bc601 1462OP_ST_ATOMIC(sc,st32,ld32s,0x3);
aaa9128a 1463#if defined(TARGET_MIPS64)
590bc601 1464OP_ST_ATOMIC(scd,st64,ld64,0x7);
aaa9128a
TS
1465#endif
1466#undef OP_ST_ATOMIC
1467
662d7485
NF
1468static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
1469 int base, int16_t offset)
1470{
1471 if (base == 0) {
1472 tcg_gen_movi_tl(addr, offset);
1473 } else if (offset == 0) {
1474 gen_load_gpr(addr, base);
1475 } else {
1476 tcg_gen_movi_tl(addr, offset);
1477 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
1478 }
1479}
1480
364d4831
NF
1481static target_ulong pc_relative_pc (DisasContext *ctx)
1482{
1483 target_ulong pc = ctx->pc;
1484
1485 if (ctx->hflags & MIPS_HFLAG_BMASK) {
1486 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
1487
1488 pc -= branch_bytes;
1489 }
1490
1491 pc &= ~(target_ulong)3;
1492 return pc;
1493}
1494
5c13fdfd 1495/* Load */
7db13fae 1496static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
afa88c3a 1497 int rt, int base, int16_t offset)
6af0bf9c 1498{
5c13fdfd 1499 const char *opn = "ld";
afa88c3a
AJ
1500 TCGv t0, t1;
1501
1502 if (rt == 0 && env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
1503 /* Loongson CPU uses a load to zero register for prefetch.
1504 We emulate it as a NOP. On other CPU we must perform the
1505 actual memory access. */
1506 MIPS_DEBUG("NOP");
1507 return;
1508 }
6af0bf9c 1509
afa88c3a
AJ
1510 t0 = tcg_temp_new();
1511 t1 = tcg_temp_new();
662d7485 1512 gen_base_offset_addr(ctx, t0, base, offset);
afa88c3a 1513
6af0bf9c 1514 switch (opc) {
d26bc211 1515#if defined(TARGET_MIPS64)
6e473128 1516 case OPC_LWU:
d66c7132 1517 save_cpu_state(ctx, 0);
5c13fdfd 1518 op_ld_lwu(t0, t0, ctx);
78723684 1519 gen_store_gpr(t0, rt);
6e473128
TS
1520 opn = "lwu";
1521 break;
6af0bf9c 1522 case OPC_LD:
d66c7132 1523 save_cpu_state(ctx, 0);
5c13fdfd 1524 op_ld_ld(t0, t0, ctx);
78723684 1525 gen_store_gpr(t0, rt);
6af0bf9c
FB
1526 opn = "ld";
1527 break;
7a387fff 1528 case OPC_LLD:
b835e919 1529 save_cpu_state(ctx, 1);
5c13fdfd 1530 op_ld_lld(t0, t0, ctx);
78723684 1531 gen_store_gpr(t0, rt);
7a387fff
TS
1532 opn = "lld";
1533 break;
6af0bf9c 1534 case OPC_LDL:
c8c2227e 1535 save_cpu_state(ctx, 1);
78723684 1536 gen_load_gpr(t1, rt);
895c2d04 1537 gen_helper_1e2i(ldl, t1, t1, t0, ctx->mem_idx);
78723684 1538 gen_store_gpr(t1, rt);
6af0bf9c
FB
1539 opn = "ldl";
1540 break;
6af0bf9c 1541 case OPC_LDR:
c8c2227e 1542 save_cpu_state(ctx, 1);
78723684 1543 gen_load_gpr(t1, rt);
895c2d04 1544 gen_helper_1e2i(ldr, t1, t1, t0, ctx->mem_idx);
78723684 1545 gen_store_gpr(t1, rt);
6af0bf9c
FB
1546 opn = "ldr";
1547 break;
364d4831 1548 case OPC_LDPC:
b835e919 1549 save_cpu_state(ctx, 0);
364d4831
NF
1550 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1551 gen_op_addr_add(ctx, t0, t0, t1);
5c13fdfd 1552 op_ld_ld(t0, t0, ctx);
364d4831 1553 gen_store_gpr(t0, rt);
5c13fdfd 1554 opn = "ldpc";
364d4831 1555 break;
6af0bf9c 1556#endif
364d4831 1557 case OPC_LWPC:
b835e919 1558 save_cpu_state(ctx, 0);
364d4831
NF
1559 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1560 gen_op_addr_add(ctx, t0, t0, t1);
5c13fdfd 1561 op_ld_lw(t0, t0, ctx);
364d4831 1562 gen_store_gpr(t0, rt);
5c13fdfd 1563 opn = "lwpc";
364d4831 1564 break;
6af0bf9c 1565 case OPC_LW:
d66c7132 1566 save_cpu_state(ctx, 0);
5c13fdfd 1567 op_ld_lw(t0, t0, ctx);
78723684 1568 gen_store_gpr(t0, rt);
6af0bf9c
FB
1569 opn = "lw";
1570 break;
6af0bf9c 1571 case OPC_LH:
d66c7132 1572 save_cpu_state(ctx, 0);
5c13fdfd 1573 op_ld_lh(t0, t0, ctx);
78723684 1574 gen_store_gpr(t0, rt);
6af0bf9c
FB
1575 opn = "lh";
1576 break;
6af0bf9c 1577 case OPC_LHU:
d66c7132 1578 save_cpu_state(ctx, 0);
5c13fdfd 1579 op_ld_lhu(t0, t0, ctx);
78723684 1580 gen_store_gpr(t0, rt);
6af0bf9c
FB
1581 opn = "lhu";
1582 break;
1583 case OPC_LB:
d66c7132 1584 save_cpu_state(ctx, 0);
5c13fdfd 1585 op_ld_lb(t0, t0, ctx);
78723684 1586 gen_store_gpr(t0, rt);
6af0bf9c
FB
1587 opn = "lb";
1588 break;
6af0bf9c 1589 case OPC_LBU:
d66c7132 1590 save_cpu_state(ctx, 0);
5c13fdfd 1591 op_ld_lbu(t0, t0, ctx);
78723684 1592 gen_store_gpr(t0, rt);
6af0bf9c
FB
1593 opn = "lbu";
1594 break;
1595 case OPC_LWL:
c8c2227e 1596 save_cpu_state(ctx, 1);
6958549d 1597 gen_load_gpr(t1, rt);
895c2d04 1598 gen_helper_1e2i(lwl, t1, t1, t0, ctx->mem_idx);
78723684 1599 gen_store_gpr(t1, rt);
6af0bf9c
FB
1600 opn = "lwl";
1601 break;
6af0bf9c 1602 case OPC_LWR:
c8c2227e 1603 save_cpu_state(ctx, 1);
6958549d 1604 gen_load_gpr(t1, rt);
895c2d04 1605 gen_helper_1e2i(lwr, t1, t1, t0, ctx->mem_idx);
78723684 1606 gen_store_gpr(t1, rt);
6af0bf9c
FB
1607 opn = "lwr";
1608 break;
6af0bf9c 1609 case OPC_LL:
e7139c44 1610 save_cpu_state(ctx, 1);
5c13fdfd 1611 op_ld_ll(t0, t0, ctx);
78723684 1612 gen_store_gpr(t0, rt);
6af0bf9c
FB
1613 opn = "ll";
1614 break;
d66c7132 1615 }
2abf314d 1616 (void)opn; /* avoid a compiler warning */
d66c7132
AJ
1617 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1618 tcg_temp_free(t0);
1619 tcg_temp_free(t1);
1620}
1621
5c13fdfd
AJ
1622/* Store */
1623static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
1624 int base, int16_t offset)
1625{
1626 const char *opn = "st";
1627 TCGv t0 = tcg_temp_new();
1628 TCGv t1 = tcg_temp_new();
1629
1630 gen_base_offset_addr(ctx, t0, base, offset);
1631 gen_load_gpr(t1, rt);
1632 switch (opc) {
1633#if defined(TARGET_MIPS64)
1634 case OPC_SD:
1635 save_cpu_state(ctx, 0);
1636 op_st_sd(t1, t0, ctx);
1637 opn = "sd";
1638 break;
1639 case OPC_SDL:
1640 save_cpu_state(ctx, 1);
895c2d04 1641 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
5c13fdfd
AJ
1642 opn = "sdl";
1643 break;
1644 case OPC_SDR:
1645 save_cpu_state(ctx, 1);
895c2d04 1646 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
5c13fdfd
AJ
1647 opn = "sdr";
1648 break;
1649#endif
1650 case OPC_SW:
1651 save_cpu_state(ctx, 0);
1652 op_st_sw(t1, t0, ctx);
1653 opn = "sw";
1654 break;
1655 case OPC_SH:
1656 save_cpu_state(ctx, 0);
1657 op_st_sh(t1, t0, ctx);
1658 opn = "sh";
1659 break;
1660 case OPC_SB:
1661 save_cpu_state(ctx, 0);
1662 op_st_sb(t1, t0, ctx);
1663 opn = "sb";
1664 break;
1665 case OPC_SWL:
1666 save_cpu_state(ctx, 1);
895c2d04 1667 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
5c13fdfd
AJ
1668 opn = "swl";
1669 break;
1670 case OPC_SWR:
1671 save_cpu_state(ctx, 1);
895c2d04 1672 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
5c13fdfd
AJ
1673 opn = "swr";
1674 break;
1675 }
2abf314d 1676 (void)opn; /* avoid a compiler warning */
5c13fdfd
AJ
1677 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1678 tcg_temp_free(t0);
1679 tcg_temp_free(t1);
1680}
1681
1682
d66c7132
AJ
1683/* Store conditional */
1684static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1685 int base, int16_t offset)
1686{
1687 const char *opn = "st_cond";
1688 TCGv t0, t1;
1689
1690 t0 = tcg_temp_local_new();
1691
662d7485 1692 gen_base_offset_addr(ctx, t0, base, offset);
d66c7132
AJ
1693 /* Don't do NOP if destination is zero: we must perform the actual
1694 memory access. */
1695
1696 t1 = tcg_temp_local_new();
1697 gen_load_gpr(t1, rt);
1698 switch (opc) {
1699#if defined(TARGET_MIPS64)
1700 case OPC_SCD:
b835e919 1701 save_cpu_state(ctx, 1);
5c13fdfd 1702 op_st_scd(t1, t0, rt, ctx);
d66c7132
AJ
1703 opn = "scd";
1704 break;
1705#endif
6af0bf9c 1706 case OPC_SC:
e7139c44 1707 save_cpu_state(ctx, 1);
5c13fdfd 1708 op_st_sc(t1, t0, rt, ctx);
6af0bf9c
FB
1709 opn = "sc";
1710 break;
6af0bf9c 1711 }
2abf314d 1712 (void)opn; /* avoid a compiler warning */
6af0bf9c 1713 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
78723684 1714 tcg_temp_free(t1);
d66c7132 1715 tcg_temp_free(t0);
6af0bf9c
FB
1716}
1717
6ea83fed 1718/* Load and store */
7a387fff 1719static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
356265ae 1720 int base, int16_t offset)
6ea83fed 1721{
923617a3 1722 const char *opn = "flt_ldst";
4e2474d6 1723 TCGv t0 = tcg_temp_new();
6ea83fed 1724
662d7485 1725 gen_base_offset_addr(ctx, t0, base, offset);
6ea83fed 1726 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 1727 memory access. */
6ea83fed
FB
1728 switch (opc) {
1729 case OPC_LWC1:
b6d96bed 1730 {
a7812ae4 1731 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 1732
c407df81
AJ
1733 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
1734 tcg_gen_trunc_tl_i32(fp0, t0);
b6d96bed 1735 gen_store_fpr32(fp0, ft);
a7812ae4 1736 tcg_temp_free_i32(fp0);
b6d96bed 1737 }
6ea83fed
FB
1738 opn = "lwc1";
1739 break;
1740 case OPC_SWC1:
b6d96bed 1741 {
a7812ae4
PB
1742 TCGv_i32 fp0 = tcg_temp_new_i32();
1743 TCGv t1 = tcg_temp_new();
b6d96bed
TS
1744
1745 gen_load_fpr32(fp0, ft);
a7812ae4
PB
1746 tcg_gen_extu_i32_tl(t1, fp0);
1747 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1748 tcg_temp_free(t1);
1749 tcg_temp_free_i32(fp0);
b6d96bed 1750 }
6ea83fed
FB
1751 opn = "swc1";
1752 break;
1753 case OPC_LDC1:
b6d96bed 1754 {
a7812ae4 1755 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
1756
1757 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1758 gen_store_fpr64(ctx, fp0, ft);
a7812ae4 1759 tcg_temp_free_i64(fp0);
b6d96bed 1760 }
6ea83fed
FB
1761 opn = "ldc1";
1762 break;
1763 case OPC_SDC1:
b6d96bed 1764 {
a7812ae4 1765 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
1766
1767 gen_load_fpr64(ctx, fp0, ft);
1768 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 1769 tcg_temp_free_i64(fp0);
b6d96bed 1770 }
6ea83fed
FB
1771 opn = "sdc1";
1772 break;
1773 default:
923617a3 1774 MIPS_INVAL(opn);
e397ee33 1775 generate_exception(ctx, EXCP_RI);
78723684 1776 goto out;
6ea83fed 1777 }
2abf314d 1778 (void)opn; /* avoid a compiler warning */
6ea83fed 1779 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
78723684
TS
1780 out:
1781 tcg_temp_free(t0);
6ea83fed 1782}
6ea83fed 1783
7db13fae 1784static void gen_cop1_ldst(CPUMIPSState *env, DisasContext *ctx,
26ebe468
NF
1785 uint32_t op, int rt, int rs, int16_t imm)
1786{
1787 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
1788 check_cp1_enabled(ctx);
1789 gen_flt_ldst(ctx, op, rt, rs, imm);
1790 } else {
1791 generate_exception_err(ctx, EXCP_CpU, 1);
1792 }
1793}
1794
6af0bf9c 1795/* Arithmetic with immediate operand */
7db13fae 1796static void gen_arith_imm (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
e189e748 1797 int rt, int rs, int16_t imm)
6af0bf9c 1798{
324d9e32 1799 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
923617a3 1800 const char *opn = "imm arith";
6af0bf9c 1801
7a387fff 1802 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
ead9360e
TS
1803 /* If no destination, treat it as a NOP.
1804 For addi, we must generate the overflow exception when needed. */
6af0bf9c 1805 MIPS_DEBUG("NOP");
324d9e32 1806 return;
6af0bf9c
FB
1807 }
1808 switch (opc) {
1809 case OPC_ADDI:
48d38ca5 1810 {
324d9e32
AJ
1811 TCGv t0 = tcg_temp_local_new();
1812 TCGv t1 = tcg_temp_new();
1813 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1814 int l1 = gen_new_label();
1815
324d9e32
AJ
1816 gen_load_gpr(t1, rs);
1817 tcg_gen_addi_tl(t0, t1, uimm);
1818 tcg_gen_ext32s_tl(t0, t0);
48d38ca5 1819
324d9e32
AJ
1820 tcg_gen_xori_tl(t1, t1, ~uimm);
1821 tcg_gen_xori_tl(t2, t0, uimm);
1822 tcg_gen_and_tl(t1, t1, t2);
1823 tcg_temp_free(t2);
1824 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1825 tcg_temp_free(t1);
48d38ca5
TS
1826 /* operands of same sign, result different sign */
1827 generate_exception(ctx, EXCP_OVERFLOW);
1828 gen_set_label(l1);
78723684 1829 tcg_gen_ext32s_tl(t0, t0);
324d9e32
AJ
1830 gen_store_gpr(t0, rt);
1831 tcg_temp_free(t0);
48d38ca5 1832 }
6af0bf9c
FB
1833 opn = "addi";
1834 break;
1835 case OPC_ADDIU:
324d9e32
AJ
1836 if (rs != 0) {
1837 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1838 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1839 } else {
1840 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1841 }
6af0bf9c
FB
1842 opn = "addiu";
1843 break;
d26bc211 1844#if defined(TARGET_MIPS64)
7a387fff 1845 case OPC_DADDI:
48d38ca5 1846 {
324d9e32
AJ
1847 TCGv t0 = tcg_temp_local_new();
1848 TCGv t1 = tcg_temp_new();
1849 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1850 int l1 = gen_new_label();
1851
324d9e32
AJ
1852 gen_load_gpr(t1, rs);
1853 tcg_gen_addi_tl(t0, t1, uimm);
48d38ca5 1854
324d9e32
AJ
1855 tcg_gen_xori_tl(t1, t1, ~uimm);
1856 tcg_gen_xori_tl(t2, t0, uimm);
1857 tcg_gen_and_tl(t1, t1, t2);
1858 tcg_temp_free(t2);
1859 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1860 tcg_temp_free(t1);
48d38ca5
TS
1861 /* operands of same sign, result different sign */
1862 generate_exception(ctx, EXCP_OVERFLOW);
1863 gen_set_label(l1);
324d9e32
AJ
1864 gen_store_gpr(t0, rt);
1865 tcg_temp_free(t0);
48d38ca5 1866 }
7a387fff
TS
1867 opn = "daddi";
1868 break;
1869 case OPC_DADDIU:
324d9e32
AJ
1870 if (rs != 0) {
1871 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1872 } else {
1873 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1874 }
7a387fff
TS
1875 opn = "daddiu";
1876 break;
1877#endif
324d9e32 1878 }
2abf314d 1879 (void)opn; /* avoid a compiler warning */
324d9e32
AJ
1880 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1881}
1882
1883/* Logic with immediate operand */
9fa77488
RH
1884static void gen_logic_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1885 int rt, int rs, int16_t imm)
324d9e32
AJ
1886{
1887 target_ulong uimm;
1888 const char *opn = "imm logic";
1889
1890 if (rt == 0) {
1891 /* If no destination, treat it as a NOP. */
1892 MIPS_DEBUG("NOP");
1893 return;
1894 }
1895 uimm = (uint16_t)imm;
1896 switch (opc) {
6af0bf9c 1897 case OPC_ANDI:
324d9e32
AJ
1898 if (likely(rs != 0))
1899 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1900 else
1901 tcg_gen_movi_tl(cpu_gpr[rt], 0);
6af0bf9c
FB
1902 opn = "andi";
1903 break;
1904 case OPC_ORI:
324d9e32
AJ
1905 if (rs != 0)
1906 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1907 else
1908 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
6af0bf9c
FB
1909 opn = "ori";
1910 break;
1911 case OPC_XORI:
324d9e32
AJ
1912 if (likely(rs != 0))
1913 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1914 else
1915 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
6af0bf9c
FB
1916 opn = "xori";
1917 break;
1918 case OPC_LUI:
324d9e32 1919 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
6af0bf9c
FB
1920 opn = "lui";
1921 break;
324d9e32 1922 }
2abf314d 1923 (void)opn; /* avoid a compiler warning */
324d9e32
AJ
1924 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1925}
1926
1927/* Set on less than with immediate operand */
9fa77488
RH
1928static void gen_slt_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1929 int rt, int rs, int16_t imm)
324d9e32
AJ
1930{
1931 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1932 const char *opn = "imm arith";
1933 TCGv t0;
1934
1935 if (rt == 0) {
1936 /* If no destination, treat it as a NOP. */
1937 MIPS_DEBUG("NOP");
1938 return;
1939 }
1940 t0 = tcg_temp_new();
1941 gen_load_gpr(t0, rs);
1942 switch (opc) {
1943 case OPC_SLTI:
e68dd28f 1944 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
1945 opn = "slti";
1946 break;
1947 case OPC_SLTIU:
e68dd28f 1948 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
1949 opn = "sltiu";
1950 break;
1951 }
2abf314d 1952 (void)opn; /* avoid a compiler warning */
324d9e32
AJ
1953 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1954 tcg_temp_free(t0);
1955}
1956
1957/* Shifts with immediate operand */
7db13fae 1958static void gen_shift_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
324d9e32
AJ
1959 int rt, int rs, int16_t imm)
1960{
1961 target_ulong uimm = ((uint16_t)imm) & 0x1f;
1962 const char *opn = "imm shift";
1963 TCGv t0;
1964
1965 if (rt == 0) {
1966 /* If no destination, treat it as a NOP. */
1967 MIPS_DEBUG("NOP");
1968 return;
1969 }
1970
1971 t0 = tcg_temp_new();
1972 gen_load_gpr(t0, rs);
1973 switch (opc) {
6af0bf9c 1974 case OPC_SLL:
78723684 1975 tcg_gen_shli_tl(t0, t0, uimm);
324d9e32 1976 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
6af0bf9c
FB
1977 opn = "sll";
1978 break;
1979 case OPC_SRA:
324d9e32 1980 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
6af0bf9c
FB
1981 opn = "sra";
1982 break;
1983 case OPC_SRL:
ea63e2c3
NF
1984 if (uimm != 0) {
1985 tcg_gen_ext32u_tl(t0, t0);
1986 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1987 } else {
1988 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
5a63bcb2 1989 }
ea63e2c3
NF
1990 opn = "srl";
1991 break;
1992 case OPC_ROTR:
1993 if (uimm != 0) {
1994 TCGv_i32 t1 = tcg_temp_new_i32();
1995
1996 tcg_gen_trunc_tl_i32(t1, t0);
1997 tcg_gen_rotri_i32(t1, t1, uimm);
1998 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
1999 tcg_temp_free_i32(t1);
3399e30f
NF
2000 } else {
2001 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
ea63e2c3
NF
2002 }
2003 opn = "rotr";
7a387fff 2004 break;
d26bc211 2005#if defined(TARGET_MIPS64)
7a387fff 2006 case OPC_DSLL:
324d9e32 2007 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
2008 opn = "dsll";
2009 break;
2010 case OPC_DSRA:
324d9e32 2011 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
2012 opn = "dsra";
2013 break;
2014 case OPC_DSRL:
ea63e2c3
NF
2015 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2016 opn = "dsrl";
2017 break;
2018 case OPC_DROTR:
2019 if (uimm != 0) {
2020 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3399e30f
NF
2021 } else {
2022 tcg_gen_mov_tl(cpu_gpr[rt], t0);
5a63bcb2 2023 }
ea63e2c3 2024 opn = "drotr";
7a387fff
TS
2025 break;
2026 case OPC_DSLL32:
324d9e32 2027 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
2028 opn = "dsll32";
2029 break;
2030 case OPC_DSRA32:
324d9e32 2031 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
2032 opn = "dsra32";
2033 break;
2034 case OPC_DSRL32:
ea63e2c3
NF
2035 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2036 opn = "dsrl32";
2037 break;
2038 case OPC_DROTR32:
2039 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2040 opn = "drotr32";
6af0bf9c 2041 break;
7a387fff 2042#endif
6af0bf9c 2043 }
2abf314d 2044 (void)opn; /* avoid a compiler warning */
93b12ccc 2045 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
78723684 2046 tcg_temp_free(t0);
6af0bf9c
FB
2047}
2048
2049/* Arithmetic */
7db13fae 2050static void gen_arith (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
2051 int rd, int rs, int rt)
2052{
923617a3 2053 const char *opn = "arith";
6af0bf9c 2054
7a387fff
TS
2055 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2056 && opc != OPC_DADD && opc != OPC_DSUB) {
ead9360e
TS
2057 /* If no destination, treat it as a NOP.
2058 For add & sub, we must generate the overflow exception when needed. */
6af0bf9c 2059 MIPS_DEBUG("NOP");
460f00c4 2060 return;
185f0762 2061 }
460f00c4 2062
6af0bf9c
FB
2063 switch (opc) {
2064 case OPC_ADD:
48d38ca5 2065 {
460f00c4
AJ
2066 TCGv t0 = tcg_temp_local_new();
2067 TCGv t1 = tcg_temp_new();
2068 TCGv t2 = tcg_temp_new();
48d38ca5
TS
2069 int l1 = gen_new_label();
2070
460f00c4
AJ
2071 gen_load_gpr(t1, rs);
2072 gen_load_gpr(t2, rt);
2073 tcg_gen_add_tl(t0, t1, t2);
2074 tcg_gen_ext32s_tl(t0, t0);
2075 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 2076 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 2077 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
2078 tcg_temp_free(t2);
2079 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2080 tcg_temp_free(t1);
48d38ca5
TS
2081 /* operands of same sign, result different sign */
2082 generate_exception(ctx, EXCP_OVERFLOW);
2083 gen_set_label(l1);
460f00c4
AJ
2084 gen_store_gpr(t0, rd);
2085 tcg_temp_free(t0);
48d38ca5 2086 }
6af0bf9c
FB
2087 opn = "add";
2088 break;
2089 case OPC_ADDU:
460f00c4
AJ
2090 if (rs != 0 && rt != 0) {
2091 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2092 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2093 } else if (rs == 0 && rt != 0) {
2094 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2095 } else if (rs != 0 && rt == 0) {
2096 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2097 } else {
2098 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2099 }
6af0bf9c
FB
2100 opn = "addu";
2101 break;
2102 case OPC_SUB:
48d38ca5 2103 {
460f00c4
AJ
2104 TCGv t0 = tcg_temp_local_new();
2105 TCGv t1 = tcg_temp_new();
2106 TCGv t2 = tcg_temp_new();
48d38ca5
TS
2107 int l1 = gen_new_label();
2108
460f00c4
AJ
2109 gen_load_gpr(t1, rs);
2110 gen_load_gpr(t2, rt);
2111 tcg_gen_sub_tl(t0, t1, t2);
2112 tcg_gen_ext32s_tl(t0, t0);
2113 tcg_gen_xor_tl(t2, t1, t2);
2114 tcg_gen_xor_tl(t1, t0, t1);
2115 tcg_gen_and_tl(t1, t1, t2);
2116 tcg_temp_free(t2);
2117 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2118 tcg_temp_free(t1);
31e3104f 2119 /* operands of different sign, first operand and result different sign */
48d38ca5
TS
2120 generate_exception(ctx, EXCP_OVERFLOW);
2121 gen_set_label(l1);
460f00c4
AJ
2122 gen_store_gpr(t0, rd);
2123 tcg_temp_free(t0);
48d38ca5 2124 }
6af0bf9c
FB
2125 opn = "sub";
2126 break;
2127 case OPC_SUBU:
460f00c4
AJ
2128 if (rs != 0 && rt != 0) {
2129 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2130 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2131 } else if (rs == 0 && rt != 0) {
2132 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
6bb72b18 2133 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
460f00c4
AJ
2134 } else if (rs != 0 && rt == 0) {
2135 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2136 } else {
2137 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2138 }
6af0bf9c
FB
2139 opn = "subu";
2140 break;
d26bc211 2141#if defined(TARGET_MIPS64)
7a387fff 2142 case OPC_DADD:
48d38ca5 2143 {
460f00c4
AJ
2144 TCGv t0 = tcg_temp_local_new();
2145 TCGv t1 = tcg_temp_new();
2146 TCGv t2 = tcg_temp_new();
48d38ca5
TS
2147 int l1 = gen_new_label();
2148
460f00c4
AJ
2149 gen_load_gpr(t1, rs);
2150 gen_load_gpr(t2, rt);
2151 tcg_gen_add_tl(t0, t1, t2);
2152 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 2153 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 2154 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
2155 tcg_temp_free(t2);
2156 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2157 tcg_temp_free(t1);
48d38ca5
TS
2158 /* operands of same sign, result different sign */
2159 generate_exception(ctx, EXCP_OVERFLOW);
2160 gen_set_label(l1);
460f00c4
AJ
2161 gen_store_gpr(t0, rd);
2162 tcg_temp_free(t0);
48d38ca5 2163 }
7a387fff
TS
2164 opn = "dadd";
2165 break;
2166 case OPC_DADDU:
460f00c4
AJ
2167 if (rs != 0 && rt != 0) {
2168 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2169 } else if (rs == 0 && rt != 0) {
2170 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2171 } else if (rs != 0 && rt == 0) {
2172 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2173 } else {
2174 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2175 }
7a387fff
TS
2176 opn = "daddu";
2177 break;
2178 case OPC_DSUB:
48d38ca5 2179 {
460f00c4
AJ
2180 TCGv t0 = tcg_temp_local_new();
2181 TCGv t1 = tcg_temp_new();
2182 TCGv t2 = tcg_temp_new();
48d38ca5
TS
2183 int l1 = gen_new_label();
2184
460f00c4
AJ
2185 gen_load_gpr(t1, rs);
2186 gen_load_gpr(t2, rt);
2187 tcg_gen_sub_tl(t0, t1, t2);
2188 tcg_gen_xor_tl(t2, t1, t2);
2189 tcg_gen_xor_tl(t1, t0, t1);
2190 tcg_gen_and_tl(t1, t1, t2);
2191 tcg_temp_free(t2);
2192 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2193 tcg_temp_free(t1);
31e3104f 2194 /* operands of different sign, first operand and result different sign */
48d38ca5
TS
2195 generate_exception(ctx, EXCP_OVERFLOW);
2196 gen_set_label(l1);
460f00c4
AJ
2197 gen_store_gpr(t0, rd);
2198 tcg_temp_free(t0);
48d38ca5 2199 }
7a387fff
TS
2200 opn = "dsub";
2201 break;
2202 case OPC_DSUBU:
460f00c4
AJ
2203 if (rs != 0 && rt != 0) {
2204 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2205 } else if (rs == 0 && rt != 0) {
2206 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2207 } else if (rs != 0 && rt == 0) {
2208 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2209 } else {
2210 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2211 }
7a387fff
TS
2212 opn = "dsubu";
2213 break;
2214#endif
460f00c4
AJ
2215 case OPC_MUL:
2216 if (likely(rs != 0 && rt != 0)) {
2217 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2218 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2219 } else {
2220 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2221 }
2222 opn = "mul";
6af0bf9c 2223 break;
460f00c4 2224 }
2abf314d 2225 (void)opn; /* avoid a compiler warning */
460f00c4
AJ
2226 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2227}
2228
2229/* Conditional move */
9fa77488
RH
2230static void gen_cond_move(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
2231 int rd, int rs, int rt)
460f00c4
AJ
2232{
2233 const char *opn = "cond move";
2234 int l1;
2235
2236 if (rd == 0) {
2237 /* If no destination, treat it as a NOP.
2238 For add & sub, we must generate the overflow exception when needed. */
2239 MIPS_DEBUG("NOP");
2240 return;
2241 }
2242
2243 l1 = gen_new_label();
2244 switch (opc) {
2245 case OPC_MOVN:
2246 if (likely(rt != 0))
2247 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1);
2248 else
2249 tcg_gen_br(l1);
2250 opn = "movn";
6af0bf9c 2251 break;
460f00c4
AJ
2252 case OPC_MOVZ:
2253 if (likely(rt != 0))
2254 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1);
2255 opn = "movz";
2256 break;
2257 }
2258 if (rs != 0)
2259 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2260 else
2261 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2262 gen_set_label(l1);
2263
2abf314d 2264 (void)opn; /* avoid a compiler warning */
460f00c4
AJ
2265 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2266}
2267
2268/* Logic */
9fa77488
RH
2269static void gen_logic(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
2270 int rd, int rs, int rt)
460f00c4
AJ
2271{
2272 const char *opn = "logic";
2273
2274 if (rd == 0) {
2275 /* If no destination, treat it as a NOP. */
2276 MIPS_DEBUG("NOP");
2277 return;
2278 }
2279
2280 switch (opc) {
6af0bf9c 2281 case OPC_AND:
460f00c4
AJ
2282 if (likely(rs != 0 && rt != 0)) {
2283 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2284 } else {
2285 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2286 }
6af0bf9c
FB
2287 opn = "and";
2288 break;
2289 case OPC_NOR:
460f00c4
AJ
2290 if (rs != 0 && rt != 0) {
2291 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2292 } else if (rs == 0 && rt != 0) {
2293 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2294 } else if (rs != 0 && rt == 0) {
2295 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2296 } else {
2297 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2298 }
6af0bf9c
FB
2299 opn = "nor";
2300 break;
2301 case OPC_OR:
460f00c4
AJ
2302 if (likely(rs != 0 && rt != 0)) {
2303 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2304 } else if (rs == 0 && rt != 0) {
2305 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2306 } else if (rs != 0 && rt == 0) {
2307 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2308 } else {
2309 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2310 }
6af0bf9c
FB
2311 opn = "or";
2312 break;
2313 case OPC_XOR:
460f00c4
AJ
2314 if (likely(rs != 0 && rt != 0)) {
2315 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2316 } else if (rs == 0 && rt != 0) {
2317 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2318 } else if (rs != 0 && rt == 0) {
2319 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2320 } else {
2321 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2322 }
6af0bf9c
FB
2323 opn = "xor";
2324 break;
460f00c4 2325 }
2abf314d 2326 (void)opn; /* avoid a compiler warning */
460f00c4
AJ
2327 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2328}
2329
2330/* Set on lower than */
9fa77488
RH
2331static void gen_slt(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
2332 int rd, int rs, int rt)
460f00c4
AJ
2333{
2334 const char *opn = "slt";
2335 TCGv t0, t1;
2336
2337 if (rd == 0) {
2338 /* If no destination, treat it as a NOP. */
2339 MIPS_DEBUG("NOP");
2340 return;
2341 }
2342
2343 t0 = tcg_temp_new();
2344 t1 = tcg_temp_new();
2345 gen_load_gpr(t0, rs);
2346 gen_load_gpr(t1, rt);
2347 switch (opc) {
2348 case OPC_SLT:
e68dd28f 2349 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
460f00c4 2350 opn = "slt";
6af0bf9c 2351 break;
460f00c4 2352 case OPC_SLTU:
e68dd28f 2353 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
460f00c4
AJ
2354 opn = "sltu";
2355 break;
2356 }
2abf314d 2357 (void)opn; /* avoid a compiler warning */
460f00c4
AJ
2358 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2359 tcg_temp_free(t0);
2360 tcg_temp_free(t1);
2361}
20c4c97c 2362
460f00c4 2363/* Shifts */
7db13fae 2364static void gen_shift (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
460f00c4
AJ
2365 int rd, int rs, int rt)
2366{
2367 const char *opn = "shifts";
2368 TCGv t0, t1;
20c4c97c 2369
460f00c4
AJ
2370 if (rd == 0) {
2371 /* If no destination, treat it as a NOP.
2372 For add & sub, we must generate the overflow exception when needed. */
2373 MIPS_DEBUG("NOP");
2374 return;
2375 }
2376
2377 t0 = tcg_temp_new();
2378 t1 = tcg_temp_new();
2379 gen_load_gpr(t0, rs);
2380 gen_load_gpr(t1, rt);
2381 switch (opc) {
6af0bf9c 2382 case OPC_SLLV:
78723684
TS
2383 tcg_gen_andi_tl(t0, t0, 0x1f);
2384 tcg_gen_shl_tl(t0, t1, t0);
460f00c4 2385 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6af0bf9c
FB
2386 opn = "sllv";
2387 break;
2388 case OPC_SRAV:
78723684 2389 tcg_gen_andi_tl(t0, t0, 0x1f);
460f00c4 2390 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
6af0bf9c
FB
2391 opn = "srav";
2392 break;
2393 case OPC_SRLV:
ea63e2c3
NF
2394 tcg_gen_ext32u_tl(t1, t1);
2395 tcg_gen_andi_tl(t0, t0, 0x1f);
2396 tcg_gen_shr_tl(t0, t1, t0);
2397 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2398 opn = "srlv";
2399 break;
2400 case OPC_ROTRV:
2401 {
2402 TCGv_i32 t2 = tcg_temp_new_i32();
2403 TCGv_i32 t3 = tcg_temp_new_i32();
2404
2405 tcg_gen_trunc_tl_i32(t2, t0);
2406 tcg_gen_trunc_tl_i32(t3, t1);
2407 tcg_gen_andi_i32(t2, t2, 0x1f);
2408 tcg_gen_rotr_i32(t2, t3, t2);
2409 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
2410 tcg_temp_free_i32(t2);
2411 tcg_temp_free_i32(t3);
2412 opn = "rotrv";
5a63bcb2 2413 }
7a387fff 2414 break;
d26bc211 2415#if defined(TARGET_MIPS64)
7a387fff 2416 case OPC_DSLLV:
78723684 2417 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 2418 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
2419 opn = "dsllv";
2420 break;
2421 case OPC_DSRAV:
78723684 2422 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 2423 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
2424 opn = "dsrav";
2425 break;
2426 case OPC_DSRLV:
ea63e2c3
NF
2427 tcg_gen_andi_tl(t0, t0, 0x3f);
2428 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
2429 opn = "dsrlv";
2430 break;
2431 case OPC_DROTRV:
2432 tcg_gen_andi_tl(t0, t0, 0x3f);
2433 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
2434 opn = "drotrv";
6af0bf9c 2435 break;
7a387fff 2436#endif
6af0bf9c 2437 }
2abf314d 2438 (void)opn; /* avoid a compiler warning */
6af0bf9c 2439 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
78723684
TS
2440 tcg_temp_free(t0);
2441 tcg_temp_free(t1);
6af0bf9c
FB
2442}
2443
2444/* Arithmetic on HI/LO registers */
7a387fff 2445static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
6af0bf9c 2446{
923617a3 2447 const char *opn = "hilo";
4133498f 2448 unsigned int acc;
6af0bf9c
FB
2449
2450 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
ead9360e 2451 /* Treat as NOP. */
6af0bf9c 2452 MIPS_DEBUG("NOP");
a1f6684d 2453 return;
6af0bf9c 2454 }
4133498f
JL
2455
2456 if (opc == OPC_MFHI || opc == OPC_MFLO) {
2457 acc = ((ctx->opcode) >> 21) & 0x03;
2458 } else {
2459 acc = ((ctx->opcode) >> 11) & 0x03;
2460 }
2461
2462 if (acc != 0) {
2463 check_dsp(ctx);
2464 }
2465
6af0bf9c
FB
2466 switch (opc) {
2467 case OPC_MFHI:
4133498f
JL
2468#if defined(TARGET_MIPS64)
2469 if (acc != 0) {
2470 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
2471 } else
2472#endif
2473 {
2474 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
2475 }
6af0bf9c
FB
2476 opn = "mfhi";
2477 break;
2478 case OPC_MFLO:
4133498f
JL
2479#if defined(TARGET_MIPS64)
2480 if (acc != 0) {
2481 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
2482 } else
2483#endif
2484 {
2485 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
2486 }
6af0bf9c
FB
2487 opn = "mflo";
2488 break;
2489 case OPC_MTHI:
4133498f
JL
2490 if (reg != 0) {
2491#if defined(TARGET_MIPS64)
2492 if (acc != 0) {
2493 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
2494 } else
2495#endif
2496 {
2497 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
2498 }
2499 } else {
2500 tcg_gen_movi_tl(cpu_HI[acc], 0);
2501 }
6af0bf9c
FB
2502 opn = "mthi";
2503 break;
2504 case OPC_MTLO:
4133498f
JL
2505 if (reg != 0) {
2506#if defined(TARGET_MIPS64)
2507 if (acc != 0) {
2508 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
2509 } else
2510#endif
2511 {
2512 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
2513 }
2514 } else {
2515 tcg_gen_movi_tl(cpu_LO[acc], 0);
2516 }
6af0bf9c
FB
2517 opn = "mtlo";
2518 break;
6af0bf9c 2519 }
2abf314d 2520 (void)opn; /* avoid a compiler warning */
6af0bf9c
FB
2521 MIPS_DEBUG("%s %s", opn, regnames[reg]);
2522}
2523
7a387fff 2524static void gen_muldiv (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
2525 int rs, int rt)
2526{
923617a3 2527 const char *opn = "mul/div";
d45f89f4 2528 TCGv t0, t1;
4133498f 2529 unsigned int acc;
d45f89f4
AJ
2530
2531 switch (opc) {
2532 case OPC_DIV:
2533 case OPC_DIVU:
2534#if defined(TARGET_MIPS64)
2535 case OPC_DDIV:
2536 case OPC_DDIVU:
2537#endif
2538 t0 = tcg_temp_local_new();
2539 t1 = tcg_temp_local_new();
2540 break;
2541 default:
2542 t0 = tcg_temp_new();
2543 t1 = tcg_temp_new();
2544 break;
2545 }
6af0bf9c 2546
78723684
TS
2547 gen_load_gpr(t0, rs);
2548 gen_load_gpr(t1, rt);
6af0bf9c
FB
2549 switch (opc) {
2550 case OPC_DIV:
48d38ca5
TS
2551 {
2552 int l1 = gen_new_label();
d45f89f4 2553 int l2 = gen_new_label();
48d38ca5 2554
d45f89f4
AJ
2555 tcg_gen_ext32s_tl(t0, t0);
2556 tcg_gen_ext32s_tl(t1, t1);
78723684 2557 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
d45f89f4
AJ
2558 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2559 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2560
2561 tcg_gen_mov_tl(cpu_LO[0], t0);
2562 tcg_gen_movi_tl(cpu_HI[0], 0);
2563 tcg_gen_br(l1);
2564 gen_set_label(l2);
2565 tcg_gen_div_tl(cpu_LO[0], t0, t1);
2566 tcg_gen_rem_tl(cpu_HI[0], t0, t1);
2567 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2568 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
48d38ca5
TS
2569 gen_set_label(l1);
2570 }
6af0bf9c
FB
2571 opn = "div";
2572 break;
2573 case OPC_DIVU:
48d38ca5
TS
2574 {
2575 int l1 = gen_new_label();
2576
0c0ed03b
AJ
2577 tcg_gen_ext32u_tl(t0, t0);
2578 tcg_gen_ext32u_tl(t1, t1);
78723684 2579 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
d45f89f4
AJ
2580 tcg_gen_divu_tl(cpu_LO[0], t0, t1);
2581 tcg_gen_remu_tl(cpu_HI[0], t0, t1);
2582 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2583 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
48d38ca5
TS
2584 gen_set_label(l1);
2585 }
6af0bf9c
FB
2586 opn = "divu";
2587 break;
2588 case OPC_MULT:
214c465f 2589 {
d45f89f4
AJ
2590 TCGv_i64 t2 = tcg_temp_new_i64();
2591 TCGv_i64 t3 = tcg_temp_new_i64();
4133498f
JL
2592 acc = ((ctx->opcode) >> 11) & 0x03;
2593 if (acc != 0) {
2594 check_dsp(ctx);
2595 }
d45f89f4
AJ
2596
2597 tcg_gen_ext_tl_i64(t2, t0);
2598 tcg_gen_ext_tl_i64(t3, t1);
2599 tcg_gen_mul_i64(t2, t2, t3);
2600 tcg_temp_free_i64(t3);
2601 tcg_gen_trunc_i64_tl(t0, t2);
2602 tcg_gen_shri_i64(t2, t2, 32);
2603 tcg_gen_trunc_i64_tl(t1, t2);
2604 tcg_temp_free_i64(t2);
4133498f
JL
2605 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2606 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
214c465f 2607 }
6af0bf9c
FB
2608 opn = "mult";
2609 break;
2610 case OPC_MULTU:
214c465f 2611 {
d45f89f4
AJ
2612 TCGv_i64 t2 = tcg_temp_new_i64();
2613 TCGv_i64 t3 = tcg_temp_new_i64();
4133498f
JL
2614 acc = ((ctx->opcode) >> 11) & 0x03;
2615 if (acc != 0) {
2616 check_dsp(ctx);
2617 }
214c465f 2618
78723684
TS
2619 tcg_gen_ext32u_tl(t0, t0);
2620 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
2621 tcg_gen_extu_tl_i64(t2, t0);
2622 tcg_gen_extu_tl_i64(t3, t1);
2623 tcg_gen_mul_i64(t2, t2, t3);
2624 tcg_temp_free_i64(t3);
2625 tcg_gen_trunc_i64_tl(t0, t2);
2626 tcg_gen_shri_i64(t2, t2, 32);
2627 tcg_gen_trunc_i64_tl(t1, t2);
2628 tcg_temp_free_i64(t2);
4133498f
JL
2629 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2630 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
214c465f 2631 }
6af0bf9c
FB
2632 opn = "multu";
2633 break;
d26bc211 2634#if defined(TARGET_MIPS64)
7a387fff 2635 case OPC_DDIV:
48d38ca5
TS
2636 {
2637 int l1 = gen_new_label();
d45f89f4 2638 int l2 = gen_new_label();
48d38ca5 2639
78723684 2640 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
d45f89f4
AJ
2641 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2642 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2643 tcg_gen_mov_tl(cpu_LO[0], t0);
2644 tcg_gen_movi_tl(cpu_HI[0], 0);
2645 tcg_gen_br(l1);
2646 gen_set_label(l2);
2647 tcg_gen_div_i64(cpu_LO[0], t0, t1);
2648 tcg_gen_rem_i64(cpu_HI[0], t0, t1);
48d38ca5
TS
2649 gen_set_label(l1);
2650 }
7a387fff
TS
2651 opn = "ddiv";
2652 break;
2653 case OPC_DDIVU:
48d38ca5
TS
2654 {
2655 int l1 = gen_new_label();
2656
78723684 2657 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
b10fa3c9
AJ
2658 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2659 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
48d38ca5
TS
2660 gen_set_label(l1);
2661 }
7a387fff
TS
2662 opn = "ddivu";
2663 break;
2664 case OPC_DMULT:
895c2d04 2665 gen_helper_dmult(cpu_env, t0, t1);
7a387fff
TS
2666 opn = "dmult";
2667 break;
2668 case OPC_DMULTU:
895c2d04 2669 gen_helper_dmultu(cpu_env, t0, t1);
7a387fff
TS
2670 opn = "dmultu";
2671 break;
2672#endif
6af0bf9c 2673 case OPC_MADD:
214c465f 2674 {
d45f89f4
AJ
2675 TCGv_i64 t2 = tcg_temp_new_i64();
2676 TCGv_i64 t3 = tcg_temp_new_i64();
4133498f
JL
2677 acc = ((ctx->opcode) >> 11) & 0x03;
2678 if (acc != 0) {
2679 check_dsp(ctx);
2680 }
d45f89f4
AJ
2681
2682 tcg_gen_ext_tl_i64(t2, t0);
2683 tcg_gen_ext_tl_i64(t3, t1);
2684 tcg_gen_mul_i64(t2, t2, t3);
4133498f 2685 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
2686 tcg_gen_add_i64(t2, t2, t3);
2687 tcg_temp_free_i64(t3);
2688 tcg_gen_trunc_i64_tl(t0, t2);
2689 tcg_gen_shri_i64(t2, t2, 32);
2690 tcg_gen_trunc_i64_tl(t1, t2);
2691 tcg_temp_free_i64(t2);
4133498f
JL
2692 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2693 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
214c465f 2694 }
6af0bf9c
FB
2695 opn = "madd";
2696 break;
2697 case OPC_MADDU:
4133498f 2698 {
d45f89f4
AJ
2699 TCGv_i64 t2 = tcg_temp_new_i64();
2700 TCGv_i64 t3 = tcg_temp_new_i64();
4133498f
JL
2701 acc = ((ctx->opcode) >> 11) & 0x03;
2702 if (acc != 0) {
2703 check_dsp(ctx);
2704 }
214c465f 2705
78723684
TS
2706 tcg_gen_ext32u_tl(t0, t0);
2707 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
2708 tcg_gen_extu_tl_i64(t2, t0);
2709 tcg_gen_extu_tl_i64(t3, t1);
2710 tcg_gen_mul_i64(t2, t2, t3);
4133498f 2711 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
2712 tcg_gen_add_i64(t2, t2, t3);
2713 tcg_temp_free_i64(t3);
2714 tcg_gen_trunc_i64_tl(t0, t2);
2715 tcg_gen_shri_i64(t2, t2, 32);
2716 tcg_gen_trunc_i64_tl(t1, t2);
2717 tcg_temp_free_i64(t2);
4133498f
JL
2718 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2719 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
214c465f 2720 }
6af0bf9c
FB
2721 opn = "maddu";
2722 break;
2723 case OPC_MSUB:
214c465f 2724 {
d45f89f4
AJ
2725 TCGv_i64 t2 = tcg_temp_new_i64();
2726 TCGv_i64 t3 = tcg_temp_new_i64();
4133498f
JL
2727 acc = ((ctx->opcode) >> 11) & 0x03;
2728 if (acc != 0) {
2729 check_dsp(ctx);
2730 }
d45f89f4
AJ
2731
2732 tcg_gen_ext_tl_i64(t2, t0);
2733 tcg_gen_ext_tl_i64(t3, t1);
2734 tcg_gen_mul_i64(t2, t2, t3);
4133498f 2735 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 2736 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4
AJ
2737 tcg_temp_free_i64(t3);
2738 tcg_gen_trunc_i64_tl(t0, t2);
2739 tcg_gen_shri_i64(t2, t2, 32);
2740 tcg_gen_trunc_i64_tl(t1, t2);
2741 tcg_temp_free_i64(t2);
4133498f
JL
2742 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2743 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
214c465f 2744 }
6af0bf9c
FB
2745 opn = "msub";
2746 break;
2747 case OPC_MSUBU:
214c465f 2748 {
d45f89f4
AJ
2749 TCGv_i64 t2 = tcg_temp_new_i64();
2750 TCGv_i64 t3 = tcg_temp_new_i64();
4133498f
JL
2751 acc = ((ctx->opcode) >> 11) & 0x03;
2752 if (acc != 0) {
2753 check_dsp(ctx);
2754 }
214c465f 2755
78723684
TS
2756 tcg_gen_ext32u_tl(t0, t0);
2757 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
2758 tcg_gen_extu_tl_i64(t2, t0);
2759 tcg_gen_extu_tl_i64(t3, t1);
2760 tcg_gen_mul_i64(t2, t2, t3);
4133498f 2761 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 2762 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4
AJ
2763 tcg_temp_free_i64(t3);
2764 tcg_gen_trunc_i64_tl(t0, t2);
2765 tcg_gen_shri_i64(t2, t2, 32);
2766 tcg_gen_trunc_i64_tl(t1, t2);
2767 tcg_temp_free_i64(t2);
4133498f
JL
2768 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2769 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
214c465f 2770 }
6af0bf9c
FB
2771 opn = "msubu";
2772 break;
2773 default:
923617a3 2774 MIPS_INVAL(opn);
6af0bf9c 2775 generate_exception(ctx, EXCP_RI);
78723684 2776 goto out;
6af0bf9c 2777 }
2abf314d 2778 (void)opn; /* avoid a compiler warning */
6af0bf9c 2779 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
78723684
TS
2780 out:
2781 tcg_temp_free(t0);
2782 tcg_temp_free(t1);
6af0bf9c
FB
2783}
2784
e9c71dd1
TS
2785static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2786 int rd, int rs, int rt)
2787{
2788 const char *opn = "mul vr54xx";
f157bfe1
AJ
2789 TCGv t0 = tcg_temp_new();
2790 TCGv t1 = tcg_temp_new();
e9c71dd1 2791
6c5c1e20
TS
2792 gen_load_gpr(t0, rs);
2793 gen_load_gpr(t1, rt);
e9c71dd1
TS
2794
2795 switch (opc) {
2796 case OPC_VR54XX_MULS:
895c2d04 2797 gen_helper_muls(t0, cpu_env, t0, t1);
e9c71dd1 2798 opn = "muls";
6958549d 2799 break;
e9c71dd1 2800 case OPC_VR54XX_MULSU:
895c2d04 2801 gen_helper_mulsu(t0, cpu_env, t0, t1);
e9c71dd1 2802 opn = "mulsu";
6958549d 2803 break;
e9c71dd1 2804 case OPC_VR54XX_MACC:
895c2d04 2805 gen_helper_macc(t0, cpu_env, t0, t1);
e9c71dd1 2806 opn = "macc";
6958549d 2807 break;
e9c71dd1 2808 case OPC_VR54XX_MACCU:
895c2d04 2809 gen_helper_maccu(t0, cpu_env, t0, t1);
e9c71dd1 2810 opn = "maccu";
6958549d 2811 break;
e9c71dd1 2812 case OPC_VR54XX_MSAC:
895c2d04 2813 gen_helper_msac(t0, cpu_env, t0, t1);
e9c71dd1 2814 opn = "msac";
6958549d 2815 break;
e9c71dd1 2816 case OPC_VR54XX_MSACU:
895c2d04 2817 gen_helper_msacu(t0, cpu_env, t0, t1);
e9c71dd1 2818 opn = "msacu";
6958549d 2819 break;
e9c71dd1 2820 case OPC_VR54XX_MULHI:
895c2d04 2821 gen_helper_mulhi(t0, cpu_env, t0, t1);
e9c71dd1 2822 opn = "mulhi";
6958549d 2823 break;
e9c71dd1 2824 case OPC_VR54XX_MULHIU:
895c2d04 2825 gen_helper_mulhiu(t0, cpu_env, t0, t1);
e9c71dd1 2826 opn = "mulhiu";
6958549d 2827 break;
e9c71dd1 2828 case OPC_VR54XX_MULSHI:
895c2d04 2829 gen_helper_mulshi(t0, cpu_env, t0, t1);
e9c71dd1 2830 opn = "mulshi";
6958549d 2831 break;
e9c71dd1 2832 case OPC_VR54XX_MULSHIU:
895c2d04 2833 gen_helper_mulshiu(t0, cpu_env, t0, t1);
e9c71dd1 2834 opn = "mulshiu";
6958549d 2835 break;
e9c71dd1 2836 case OPC_VR54XX_MACCHI:
895c2d04 2837 gen_helper_macchi(t0, cpu_env, t0, t1);
e9c71dd1 2838 opn = "macchi";
6958549d 2839 break;
e9c71dd1 2840 case OPC_VR54XX_MACCHIU:
895c2d04 2841 gen_helper_macchiu(t0, cpu_env, t0, t1);
e9c71dd1 2842 opn = "macchiu";
6958549d 2843 break;
e9c71dd1 2844 case OPC_VR54XX_MSACHI:
895c2d04 2845 gen_helper_msachi(t0, cpu_env, t0, t1);
e9c71dd1 2846 opn = "msachi";
6958549d 2847 break;
e9c71dd1 2848 case OPC_VR54XX_MSACHIU:
895c2d04 2849 gen_helper_msachiu(t0, cpu_env, t0, t1);
e9c71dd1 2850 opn = "msachiu";
6958549d 2851 break;
e9c71dd1
TS
2852 default:
2853 MIPS_INVAL("mul vr54xx");
2854 generate_exception(ctx, EXCP_RI);
6c5c1e20 2855 goto out;
e9c71dd1 2856 }
6c5c1e20 2857 gen_store_gpr(t0, rd);
2abf314d 2858 (void)opn; /* avoid a compiler warning */
e9c71dd1 2859 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
6c5c1e20
TS
2860
2861 out:
2862 tcg_temp_free(t0);
2863 tcg_temp_free(t1);
e9c71dd1
TS
2864}
2865
7a387fff 2866static void gen_cl (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
2867 int rd, int rs)
2868{
923617a3 2869 const char *opn = "CLx";
20e1fb52 2870 TCGv t0;
6c5c1e20 2871
6af0bf9c 2872 if (rd == 0) {
ead9360e 2873 /* Treat as NOP. */
6af0bf9c 2874 MIPS_DEBUG("NOP");
20e1fb52 2875 return;
6af0bf9c 2876 }
20e1fb52 2877 t0 = tcg_temp_new();
6c5c1e20 2878 gen_load_gpr(t0, rs);
6af0bf9c
FB
2879 switch (opc) {
2880 case OPC_CLO:
20e1fb52 2881 gen_helper_clo(cpu_gpr[rd], t0);
6af0bf9c
FB
2882 opn = "clo";
2883 break;
2884 case OPC_CLZ:
20e1fb52 2885 gen_helper_clz(cpu_gpr[rd], t0);
6af0bf9c
FB
2886 opn = "clz";
2887 break;
d26bc211 2888#if defined(TARGET_MIPS64)
7a387fff 2889 case OPC_DCLO:
20e1fb52 2890 gen_helper_dclo(cpu_gpr[rd], t0);
7a387fff
TS
2891 opn = "dclo";
2892 break;
2893 case OPC_DCLZ:
20e1fb52 2894 gen_helper_dclz(cpu_gpr[rd], t0);
7a387fff
TS
2895 opn = "dclz";
2896 break;
2897#endif
6af0bf9c 2898 }
2abf314d 2899 (void)opn; /* avoid a compiler warning */
6af0bf9c 2900 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
6c5c1e20 2901 tcg_temp_free(t0);
6af0bf9c
FB
2902}
2903
161f85e6 2904/* Godson integer instructions */
bd277fa1
RH
2905static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
2906 int rd, int rs, int rt)
161f85e6
AJ
2907{
2908 const char *opn = "loongson";
2909 TCGv t0, t1;
2910
2911 if (rd == 0) {
2912 /* Treat as NOP. */
2913 MIPS_DEBUG("NOP");
2914 return;
2915 }
2916
2917 switch (opc) {
2918 case OPC_MULT_G_2E:
2919 case OPC_MULT_G_2F:
2920 case OPC_MULTU_G_2E:
2921 case OPC_MULTU_G_2F:
2922#if defined(TARGET_MIPS64)
2923 case OPC_DMULT_G_2E:
2924 case OPC_DMULT_G_2F:
2925 case OPC_DMULTU_G_2E:
2926 case OPC_DMULTU_G_2F:
2927#endif
2928 t0 = tcg_temp_new();
2929 t1 = tcg_temp_new();
2930 break;
2931 default:
2932 t0 = tcg_temp_local_new();
2933 t1 = tcg_temp_local_new();
2934 break;
2935 }
2936
2937 gen_load_gpr(t0, rs);
2938 gen_load_gpr(t1, rt);
2939
2940 switch (opc) {
2941 case OPC_MULT_G_2E:
2942 case OPC_MULT_G_2F:
2943 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2944 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2945 opn = "mult.g";
2946 break;
2947 case OPC_MULTU_G_2E:
2948 case OPC_MULTU_G_2F:
2949 tcg_gen_ext32u_tl(t0, t0);
2950 tcg_gen_ext32u_tl(t1, t1);
2951 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2952 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2953 opn = "multu.g";
2954 break;
2955 case OPC_DIV_G_2E:
2956 case OPC_DIV_G_2F:
2957 {
2958 int l1 = gen_new_label();
2959 int l2 = gen_new_label();
2960 int l3 = gen_new_label();
2961 tcg_gen_ext32s_tl(t0, t0);
2962 tcg_gen_ext32s_tl(t1, t1);
2963 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2964 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2965 tcg_gen_br(l3);
2966 gen_set_label(l1);
2967 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2968 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2969 tcg_gen_mov_tl(cpu_gpr[rd], t0);
2970 tcg_gen_br(l3);
2971 gen_set_label(l2);
2972 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2973 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2974 gen_set_label(l3);
2975 }
2976 opn = "div.g";
2977 break;
2978 case OPC_DIVU_G_2E:
2979 case OPC_DIVU_G_2F:
2980 {
2981 int l1 = gen_new_label();
2982 int l2 = gen_new_label();
2983 tcg_gen_ext32u_tl(t0, t0);
2984 tcg_gen_ext32u_tl(t1, t1);
2985 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2986 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2987 tcg_gen_br(l2);
2988 gen_set_label(l1);
2989 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
2990 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2991 gen_set_label(l2);
2992 }
2993 opn = "divu.g";
2994 break;
2995 case OPC_MOD_G_2E:
2996 case OPC_MOD_G_2F:
2997 {
2998 int l1 = gen_new_label();
2999 int l2 = gen_new_label();
3000 int l3 = gen_new_label();
3001 tcg_gen_ext32u_tl(t0, t0);
3002 tcg_gen_ext32u_tl(t1, t1);
3003 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3004 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3005 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3006 gen_set_label(l1);
3007 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3008 tcg_gen_br(l3);
3009 gen_set_label(l2);
3010 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3011 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3012 gen_set_label(l3);
3013 }
3014 opn = "mod.g";
3015 break;
3016 case OPC_MODU_G_2E:
3017 case OPC_MODU_G_2F:
3018 {
3019 int l1 = gen_new_label();
3020 int l2 = gen_new_label();
3021 tcg_gen_ext32u_tl(t0, t0);
3022 tcg_gen_ext32u_tl(t1, t1);
3023 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3024 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3025 tcg_gen_br(l2);
3026 gen_set_label(l1);
3027 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3028 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3029 gen_set_label(l2);
3030 }
3031 opn = "modu.g";
3032 break;
3033#if defined(TARGET_MIPS64)
3034 case OPC_DMULT_G_2E:
3035 case OPC_DMULT_G_2F:
3036 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3037 opn = "dmult.g";
3038 break;
3039 case OPC_DMULTU_G_2E:
3040 case OPC_DMULTU_G_2F:
3041 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3042 opn = "dmultu.g";
3043 break;
3044 case OPC_DDIV_G_2E:
3045 case OPC_DDIV_G_2F:
3046 {
3047 int l1 = gen_new_label();
3048 int l2 = gen_new_label();
3049 int l3 = gen_new_label();
3050 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3051 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3052 tcg_gen_br(l3);
3053 gen_set_label(l1);
3054 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3055 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3056 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3057 tcg_gen_br(l3);
3058 gen_set_label(l2);
3059 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3060 gen_set_label(l3);
3061 }
3062 opn = "ddiv.g";
3063 break;
3064 case OPC_DDIVU_G_2E:
3065 case OPC_DDIVU_G_2F:
3066 {
3067 int l1 = gen_new_label();
3068 int l2 = gen_new_label();
3069 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3070 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3071 tcg_gen_br(l2);
3072 gen_set_label(l1);
3073 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3074 gen_set_label(l2);
3075 }
3076 opn = "ddivu.g";
3077 break;
3078 case OPC_DMOD_G_2E:
3079 case OPC_DMOD_G_2F:
3080 {
3081 int l1 = gen_new_label();
3082 int l2 = gen_new_label();
3083 int l3 = gen_new_label();
3084 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3085 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3086 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3087 gen_set_label(l1);
3088 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3089 tcg_gen_br(l3);
3090 gen_set_label(l2);
3091 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3092 gen_set_label(l3);
3093 }
3094 opn = "dmod.g";
3095 break;
3096 case OPC_DMODU_G_2E:
3097 case OPC_DMODU_G_2F:
3098 {
3099 int l1 = gen_new_label();
3100 int l2 = gen_new_label();
3101 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3102 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3103 tcg_gen_br(l2);
3104 gen_set_label(l1);
3105 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3106 gen_set_label(l2);
3107 }
3108 opn = "dmodu.g";
3109 break;
3110#endif
3111 }
3112
2abf314d 3113 (void)opn; /* avoid a compiler warning */
161f85e6
AJ
3114 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
3115 tcg_temp_free(t0);
3116 tcg_temp_free(t1);
3117}
3118
bd277fa1
RH
3119/* Loongson multimedia instructions */
3120static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
3121{
3122 const char *opn = "loongson_cp2";
3123 uint32_t opc, shift_max;
3124 TCGv_i64 t0, t1;
3125
3126 opc = MASK_LMI(ctx->opcode);
3127 switch (opc) {
3128 case OPC_ADD_CP2:
3129 case OPC_SUB_CP2:
3130 case OPC_DADD_CP2:
3131 case OPC_DSUB_CP2:
3132 t0 = tcg_temp_local_new_i64();
3133 t1 = tcg_temp_local_new_i64();
3134 break;
3135 default:
3136 t0 = tcg_temp_new_i64();
3137 t1 = tcg_temp_new_i64();
3138 break;
3139 }
3140
3141 gen_load_fpr64(ctx, t0, rs);
3142 gen_load_fpr64(ctx, t1, rt);
3143
3144#define LMI_HELPER(UP, LO) \
3145 case OPC_##UP: gen_helper_##LO(t0, t0, t1); opn = #LO; break
3146#define LMI_HELPER_1(UP, LO) \
3147 case OPC_##UP: gen_helper_##LO(t0, t0); opn = #LO; break
3148#define LMI_DIRECT(UP, LO, OP) \
3149 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); opn = #LO; break
3150
3151 switch (opc) {
3152 LMI_HELPER(PADDSH, paddsh);
3153 LMI_HELPER(PADDUSH, paddush);
3154 LMI_HELPER(PADDH, paddh);
3155 LMI_HELPER(PADDW, paddw);
3156 LMI_HELPER(PADDSB, paddsb);
3157 LMI_HELPER(PADDUSB, paddusb);
3158 LMI_HELPER(PADDB, paddb);
3159
3160 LMI_HELPER(PSUBSH, psubsh);
3161 LMI_HELPER(PSUBUSH, psubush);
3162 LMI_HELPER(PSUBH, psubh);
3163 LMI_HELPER(PSUBW, psubw);
3164 LMI_HELPER(PSUBSB, psubsb);
3165 LMI_HELPER(PSUBUSB, psubusb);
3166 LMI_HELPER(PSUBB, psubb);
3167
3168 LMI_HELPER(PSHUFH, pshufh);
3169 LMI_HELPER(PACKSSWH, packsswh);
3170 LMI_HELPER(PACKSSHB, packsshb);
3171 LMI_HELPER(PACKUSHB, packushb);
3172
3173 LMI_HELPER(PUNPCKLHW, punpcklhw);
3174 LMI_HELPER(PUNPCKHHW, punpckhhw);
3175 LMI_HELPER(PUNPCKLBH, punpcklbh);
3176 LMI_HELPER(PUNPCKHBH, punpckhbh);
3177 LMI_HELPER(PUNPCKLWD, punpcklwd);
3178 LMI_HELPER(PUNPCKHWD, punpckhwd);
3179
3180 LMI_HELPER(PAVGH, pavgh);
3181 LMI_HELPER(PAVGB, pavgb);
3182 LMI_HELPER(PMAXSH, pmaxsh);
3183 LMI_HELPER(PMINSH, pminsh);
3184 LMI_HELPER(PMAXUB, pmaxub);
3185 LMI_HELPER(PMINUB, pminub);
3186
3187 LMI_HELPER(PCMPEQW, pcmpeqw);
3188 LMI_HELPER(PCMPGTW, pcmpgtw);
3189 LMI_HELPER(PCMPEQH, pcmpeqh);
3190 LMI_HELPER(PCMPGTH, pcmpgth);
3191 LMI_HELPER(PCMPEQB, pcmpeqb);
3192 LMI_HELPER(PCMPGTB, pcmpgtb);
3193
3194 LMI_HELPER(PSLLW, psllw);
3195 LMI_HELPER(PSLLH, psllh);
3196 LMI_HELPER(PSRLW, psrlw);
3197 LMI_HELPER(PSRLH, psrlh);
3198 LMI_HELPER(PSRAW, psraw);
3199 LMI_HELPER(PSRAH, psrah);
3200
3201 LMI_HELPER(PMULLH, pmullh);
3202 LMI_HELPER(PMULHH, pmulhh);
3203 LMI_HELPER(PMULHUH, pmulhuh);
3204 LMI_HELPER(PMADDHW, pmaddhw);
3205
3206 LMI_HELPER(PASUBUB, pasubub);
3207 LMI_HELPER_1(BIADD, biadd);
3208 LMI_HELPER_1(PMOVMSKB, pmovmskb);
3209
3210 LMI_DIRECT(PADDD, paddd, add);
3211 LMI_DIRECT(PSUBD, psubd, sub);
3212 LMI_DIRECT(XOR_CP2, xor, xor);
3213 LMI_DIRECT(NOR_CP2, nor, nor);
3214 LMI_DIRECT(AND_CP2, and, and);
3215 LMI_DIRECT(PANDN, pandn, andc);
3216 LMI_DIRECT(OR, or, or);
3217
3218 case OPC_PINSRH_0:
3219 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
3220 opn = "pinsrh_0";
3221 break;
3222 case OPC_PINSRH_1:
3223 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
3224 opn = "pinsrh_1";
3225 break;
3226 case OPC_PINSRH_2:
3227 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
3228 opn = "pinsrh_2";
3229 break;
3230 case OPC_PINSRH_3:
3231 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
3232 opn = "pinsrh_3";
3233 break;
3234
3235 case OPC_PEXTRH:
3236 tcg_gen_andi_i64(t1, t1, 3);
3237 tcg_gen_shli_i64(t1, t1, 4);
3238 tcg_gen_shr_i64(t0, t0, t1);
3239 tcg_gen_ext16u_i64(t0, t0);
3240 opn = "pextrh";
3241 break;
3242
3243 case OPC_ADDU_CP2:
3244 tcg_gen_add_i64(t0, t0, t1);
3245 tcg_gen_ext32s_i64(t0, t0);
3246 opn = "addu";
3247 break;
3248 case OPC_SUBU_CP2:
3249 tcg_gen_sub_i64(t0, t0, t1);
3250 tcg_gen_ext32s_i64(t0, t0);
3251 opn = "addu";
3252 break;
3253
3254 case OPC_SLL_CP2:
3255 opn = "sll";
3256 shift_max = 32;
3257 goto do_shift;
3258 case OPC_SRL_CP2:
3259 opn = "srl";
3260 shift_max = 32;
3261 goto do_shift;
3262 case OPC_SRA_CP2:
3263 opn = "sra";
3264 shift_max = 32;
3265 goto do_shift;
3266 case OPC_DSLL_CP2:
3267 opn = "dsll";
3268 shift_max = 64;
3269 goto do_shift;
3270 case OPC_DSRL_CP2:
3271 opn = "dsrl";
3272 shift_max = 64;
3273 goto do_shift;
3274 case OPC_DSRA_CP2:
3275 opn = "dsra";
3276 shift_max = 64;
3277 goto do_shift;
3278 do_shift:
3279 /* Make sure shift count isn't TCG undefined behaviour. */
3280 tcg_gen_andi_i64(t1, t1, shift_max - 1);
3281
3282 switch (opc) {
3283 case OPC_SLL_CP2:
3284 case OPC_DSLL_CP2:
3285 tcg_gen_shl_i64(t0, t0, t1);
3286 break;
3287 case OPC_SRA_CP2:
3288 case OPC_DSRA_CP2:
3289 /* Since SRA is UndefinedResult without sign-extended inputs,
3290 we can treat SRA and DSRA the same. */
3291 tcg_gen_sar_i64(t0, t0, t1);
3292 break;
3293 case OPC_SRL_CP2:
3294 /* We want to shift in zeros for SRL; zero-extend first. */
3295 tcg_gen_ext32u_i64(t0, t0);
3296 /* FALLTHRU */
3297 case OPC_DSRL_CP2:
3298 tcg_gen_shr_i64(t0, t0, t1);
3299 break;
3300 }
3301
3302 if (shift_max == 32) {
3303 tcg_gen_ext32s_i64(t0, t0);
3304 }
3305
3306 /* Shifts larger than MAX produce zero. */
3307 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
3308 tcg_gen_neg_i64(t1, t1);
3309 tcg_gen_and_i64(t0, t0, t1);
3310 break;
3311
3312 case OPC_ADD_CP2:
3313 case OPC_DADD_CP2:
3314 {
3315 TCGv_i64 t2 = tcg_temp_new_i64();
3316 int lab = gen_new_label();
3317
3318 tcg_gen_mov_i64(t2, t0);
3319 tcg_gen_add_i64(t0, t1, t2);
3320 if (opc == OPC_ADD_CP2) {
3321 tcg_gen_ext32s_i64(t0, t0);
3322 }
3323 tcg_gen_xor_i64(t1, t1, t2);
3324 tcg_gen_xor_i64(t2, t2, t0);
3325 tcg_gen_andc_i64(t1, t2, t1);
3326 tcg_temp_free_i64(t2);
3327 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
3328 generate_exception(ctx, EXCP_OVERFLOW);
3329 gen_set_label(lab);
3330
3331 opn = (opc == OPC_ADD_CP2 ? "add" : "dadd");
3332 break;
3333 }
3334
3335 case OPC_SUB_CP2:
3336 case OPC_DSUB_CP2:
3337 {
3338 TCGv_i64 t2 = tcg_temp_new_i64();
3339 int lab = gen_new_label();
3340
3341 tcg_gen_mov_i64(t2, t0);
3342 tcg_gen_sub_i64(t0, t1, t2);
3343 if (opc == OPC_SUB_CP2) {
3344 tcg_gen_ext32s_i64(t0, t0);
3345 }
3346 tcg_gen_xor_i64(t1, t1, t2);
3347 tcg_gen_xor_i64(t2, t2, t0);
3348 tcg_gen_and_i64(t1, t1, t2);
3349 tcg_temp_free_i64(t2);
3350 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
3351 generate_exception(ctx, EXCP_OVERFLOW);
3352 gen_set_label(lab);
3353
3354 opn = (opc == OPC_SUB_CP2 ? "sub" : "dsub");
3355 break;
3356 }
3357
3358 case OPC_PMULUW:
3359 tcg_gen_ext32u_i64(t0, t0);
3360 tcg_gen_ext32u_i64(t1, t1);
3361 tcg_gen_mul_i64(t0, t0, t1);
3362 opn = "pmuluw";
3363 break;
3364
3365 case OPC_SEQU_CP2:
3366 case OPC_SEQ_CP2:
3367 case OPC_SLTU_CP2:
3368 case OPC_SLT_CP2:
3369 case OPC_SLEU_CP2:
3370 case OPC_SLE_CP2:
3371 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
3372 FD field is the CC field? */
3373 default:
3374 MIPS_INVAL(opn);
3375 generate_exception(ctx, EXCP_RI);
3376 return;
3377 }
3378
3379#undef LMI_HELPER
3380#undef LMI_DIRECT
3381
3382 gen_store_fpr64(ctx, t0, rd);
3383
3384 (void)opn; /* avoid a compiler warning */
3385 MIPS_DEBUG("%s %s, %s, %s", opn,
3386 fregnames[rd], fregnames[rs], fregnames[rt]);
3387 tcg_temp_free_i64(t0);
3388 tcg_temp_free_i64(t1);
3389}
3390
6af0bf9c 3391/* Traps */
7a387fff 3392static void gen_trap (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
3393 int rs, int rt, int16_t imm)
3394{
3395 int cond;
cdc0faa6 3396 TCGv t0 = tcg_temp_new();
1ba74fb8 3397 TCGv t1 = tcg_temp_new();
6af0bf9c
FB
3398
3399 cond = 0;
3400 /* Load needed operands */
3401 switch (opc) {
3402 case OPC_TEQ:
3403 case OPC_TGE:
3404 case OPC_TGEU:
3405 case OPC_TLT:
3406 case OPC_TLTU:
3407 case OPC_TNE:
3408 /* Compare two registers */
3409 if (rs != rt) {
be24bb4f
TS
3410 gen_load_gpr(t0, rs);
3411 gen_load_gpr(t1, rt);
6af0bf9c
FB
3412 cond = 1;
3413 }
179e32bb 3414 break;
6af0bf9c
FB
3415 case OPC_TEQI:
3416 case OPC_TGEI:
3417 case OPC_TGEIU:
3418 case OPC_TLTI:
3419 case OPC_TLTIU:
3420 case OPC_TNEI:
3421 /* Compare register to immediate */
3422 if (rs != 0 || imm != 0) {
be24bb4f
TS
3423 gen_load_gpr(t0, rs);
3424 tcg_gen_movi_tl(t1, (int32_t)imm);
6af0bf9c
FB
3425 cond = 1;
3426 }
3427 break;
3428 }
3429 if (cond == 0) {
3430 switch (opc) {
3431 case OPC_TEQ: /* rs == rs */
3432 case OPC_TEQI: /* r0 == 0 */
3433 case OPC_TGE: /* rs >= rs */
3434 case OPC_TGEI: /* r0 >= 0 */
3435 case OPC_TGEU: /* rs >= rs unsigned */
3436 case OPC_TGEIU: /* r0 >= 0 unsigned */
3437 /* Always trap */
cdc0faa6 3438 generate_exception(ctx, EXCP_TRAP);
6af0bf9c
FB
3439 break;
3440 case OPC_TLT: /* rs < rs */
3441 case OPC_TLTI: /* r0 < 0 */
3442 case OPC_TLTU: /* rs < rs unsigned */
3443 case OPC_TLTIU: /* r0 < 0 unsigned */
3444 case OPC_TNE: /* rs != rs */
3445 case OPC_TNEI: /* r0 != 0 */
ead9360e 3446 /* Never trap: treat as NOP. */
cdc0faa6 3447 break;
6af0bf9c
FB
3448 }
3449 } else {
cdc0faa6
AJ
3450 int l1 = gen_new_label();
3451
6af0bf9c
FB
3452 switch (opc) {
3453 case OPC_TEQ:
3454 case OPC_TEQI:
cdc0faa6 3455 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6af0bf9c
FB
3456 break;
3457 case OPC_TGE:
3458 case OPC_TGEI:
cdc0faa6 3459 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6af0bf9c
FB
3460 break;
3461 case OPC_TGEU:
3462 case OPC_TGEIU:
cdc0faa6 3463 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6af0bf9c
FB
3464 break;
3465 case OPC_TLT:
3466 case OPC_TLTI:
cdc0faa6 3467 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6af0bf9c
FB
3468 break;
3469 case OPC_TLTU:
3470 case OPC_TLTIU:
cdc0faa6 3471 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6af0bf9c
FB
3472 break;
3473 case OPC_TNE:
3474 case OPC_TNEI:
cdc0faa6 3475 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6af0bf9c 3476 break;
6af0bf9c 3477 }
cdc0faa6 3478 generate_exception(ctx, EXCP_TRAP);
08ba7963
TS
3479 gen_set_label(l1);
3480 }
be24bb4f
TS
3481 tcg_temp_free(t0);
3482 tcg_temp_free(t1);
6af0bf9c
FB
3483}
3484
356265ae 3485static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
c53be334 3486{
6e256c93
FB
3487 TranslationBlock *tb;
3488 tb = ctx->tb;
7b270ef2
NF
3489 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
3490 likely(!ctx->singlestep_enabled)) {
57fec1fe 3491 tcg_gen_goto_tb(n);
9b9e4393 3492 gen_save_pc(dest);
4b4a72e5 3493 tcg_gen_exit_tb((tcg_target_long)tb + n);
6e256c93 3494 } else {
9b9e4393 3495 gen_save_pc(dest);
7b270ef2
NF
3496 if (ctx->singlestep_enabled) {
3497 save_cpu_state(ctx, 0);
895c2d04 3498 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
7b270ef2 3499 }
57fec1fe 3500 tcg_gen_exit_tb(0);
6e256c93 3501 }
c53be334
FB
3502}
3503
6af0bf9c 3504/* Branches (before delay slot) */
7a387fff 3505static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
7dca4ad0 3506 int insn_bytes,
6af0bf9c
FB
3507 int rs, int rt, int32_t offset)
3508{
d077b6f7 3509 target_ulong btgt = -1;
3ad4bb2d 3510 int blink = 0;
2fdbad25 3511 int bcond_compute = 0;
1ba74fb8
AJ
3512 TCGv t0 = tcg_temp_new();
3513 TCGv t1 = tcg_temp_new();
3ad4bb2d
TS
3514
3515 if (ctx->hflags & MIPS_HFLAG_BMASK) {
923617a3 3516#ifdef MIPS_DEBUG_DISAS
d12d51d5 3517 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
923617a3 3518#endif
3ad4bb2d 3519 generate_exception(ctx, EXCP_RI);
6c5c1e20 3520 goto out;
3ad4bb2d 3521 }
6af0bf9c 3522
6af0bf9c
FB
3523 /* Load needed operands */
3524 switch (opc) {
3525 case OPC_BEQ:
3526 case OPC_BEQL:
3527 case OPC_BNE:
3528 case OPC_BNEL:
3529 /* Compare two registers */
3530 if (rs != rt) {
6c5c1e20
TS
3531 gen_load_gpr(t0, rs);
3532 gen_load_gpr(t1, rt);
2fdbad25 3533 bcond_compute = 1;
6af0bf9c 3534 }
7dca4ad0 3535 btgt = ctx->pc + insn_bytes + offset;
6af0bf9c
FB
3536 break;
3537 case OPC_BGEZ:
3538 case OPC_BGEZAL:
3c824109 3539 case OPC_BGEZALS:
6af0bf9c
FB
3540 case OPC_BGEZALL:
3541 case OPC_BGEZL:
3542 case OPC_BGTZ:
3543 case OPC_BGTZL:
3544 case OPC_BLEZ:
3545 case OPC_BLEZL:
3546 case OPC_BLTZ:
3547 case OPC_BLTZAL:
3c824109 3548 case OPC_BLTZALS:
6af0bf9c
FB
3549 case OPC_BLTZALL:
3550 case OPC_BLTZL:
3551 /* Compare to zero */
3552 if (rs != 0) {
6c5c1e20 3553 gen_load_gpr(t0, rs);
2fdbad25 3554 bcond_compute = 1;
6af0bf9c 3555 }
7dca4ad0 3556 btgt = ctx->pc + insn_bytes + offset;
6af0bf9c 3557 break;
e45a93e2
JL
3558 case OPC_BPOSGE32:
3559#if defined(TARGET_MIPS64)
3560 case OPC_BPOSGE64:
3561 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
3562#else
3563 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
3564#endif
3565 bcond_compute = 1;
3566 btgt = ctx->pc + insn_bytes + offset;
3567 break;
6af0bf9c
FB
3568 case OPC_J:
3569 case OPC_JAL:
364d4831 3570 case OPC_JALX:
620e48f6
NF
3571 case OPC_JALS:
3572 case OPC_JALXS:
6af0bf9c 3573 /* Jump to immediate */
7dca4ad0 3574 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
6af0bf9c
FB
3575 break;
3576 case OPC_JR:
3577 case OPC_JALR:
364d4831 3578 case OPC_JALRC:
620e48f6 3579 case OPC_JALRS:
6af0bf9c 3580 /* Jump to register */
7a387fff
TS
3581 if (offset != 0 && offset != 16) {
3582 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
cbeb0857 3583 others are reserved. */
923617a3 3584 MIPS_INVAL("jump hint");
6af0bf9c 3585 generate_exception(ctx, EXCP_RI);
6c5c1e20 3586 goto out;
6af0bf9c 3587 }
d077b6f7 3588 gen_load_gpr(btarget, rs);
6af0bf9c
FB
3589 break;
3590 default:
3591 MIPS_INVAL("branch/jump");
3592 generate_exception(ctx, EXCP_RI);
6c5c1e20 3593 goto out;
6af0bf9c 3594 }
2fdbad25 3595 if (bcond_compute == 0) {
6af0bf9c
FB
3596 /* No condition to be computed */
3597 switch (opc) {
3598 case OPC_BEQ: /* rx == rx */
3599 case OPC_BEQL: /* rx == rx likely */
3600 case OPC_BGEZ: /* 0 >= 0 */
3601 case OPC_BGEZL: /* 0 >= 0 likely */
3602 case OPC_BLEZ: /* 0 <= 0 */
3603 case OPC_BLEZL: /* 0 <= 0 likely */
3604 /* Always take */
4ad40f36 3605 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
3606 MIPS_DEBUG("balways");
3607 break;
3c824109 3608 case OPC_BGEZALS:
6af0bf9c
FB
3609 case OPC_BGEZAL: /* 0 >= 0 */
3610 case OPC_BGEZALL: /* 0 >= 0 likely */
3c824109
NF
3611 ctx->hflags |= (opc == OPC_BGEZALS
3612 ? MIPS_HFLAG_BDS16
3613 : MIPS_HFLAG_BDS32);
6af0bf9c
FB
3614 /* Always take and link */
3615 blink = 31;
4ad40f36 3616 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
3617 MIPS_DEBUG("balways and link");
3618 break;
3619 case OPC_BNE: /* rx != rx */
3620 case OPC_BGTZ: /* 0 > 0 */
3621 case OPC_BLTZ: /* 0 < 0 */
ead9360e 3622 /* Treat as NOP. */
6af0bf9c 3623 MIPS_DEBUG("bnever (NOP)");
6c5c1e20 3624 goto out;
3c824109 3625 case OPC_BLTZALS:
eeef26cd 3626 case OPC_BLTZAL: /* 0 < 0 */
3c824109
NF
3627 ctx->hflags |= (opc == OPC_BLTZALS
3628 ? MIPS_HFLAG_BDS16
3629 : MIPS_HFLAG_BDS32);
3630 /* Handle as an unconditional branch to get correct delay
3631 slot checking. */
3632 blink = 31;
3633 btgt = ctx->pc + (opc == OPC_BLTZALS ? 6 : 8);
3634 ctx->hflags |= MIPS_HFLAG_B;
9898128f 3635 MIPS_DEBUG("bnever and link");
3c824109 3636 break;
eeef26cd 3637 case OPC_BLTZALL: /* 0 < 0 likely */
1ba74fb8 3638 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
9898128f
TS
3639 /* Skip the instruction in the delay slot */
3640 MIPS_DEBUG("bnever, link and skip");
3641 ctx->pc += 4;
6c5c1e20 3642 goto out;
6af0bf9c
FB
3643 case OPC_BNEL: /* rx != rx likely */
3644 case OPC_BGTZL: /* 0 > 0 likely */
6af0bf9c
FB
3645 case OPC_BLTZL: /* 0 < 0 likely */
3646 /* Skip the instruction in the delay slot */
3647 MIPS_DEBUG("bnever and skip");
9898128f 3648 ctx->pc += 4;
6c5c1e20 3649 goto out;
6af0bf9c 3650 case OPC_J:
4ad40f36 3651 ctx->hflags |= MIPS_HFLAG_B;
d077b6f7 3652 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
6af0bf9c 3653 break;
620e48f6 3654 case OPC_JALXS:
364d4831
NF
3655 case OPC_JALX:
3656 ctx->hflags |= MIPS_HFLAG_BX;
3657 /* Fallthrough */
620e48f6 3658 case OPC_JALS:
6af0bf9c
FB
3659 case OPC_JAL:
3660 blink = 31;
4ad40f36 3661 ctx->hflags |= MIPS_HFLAG_B;
620e48f6 3662 ctx->hflags |= ((opc == OPC_JALS || opc == OPC_JALXS)
364d4831
NF
3663 ? MIPS_HFLAG_BDS16
3664 : MIPS_HFLAG_BDS32);
d077b6f7 3665 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
6af0bf9c
FB
3666 break;
3667 case OPC_JR:
4ad40f36 3668 ctx->hflags |= MIPS_HFLAG_BR;
620e48f6
NF
3669 if (insn_bytes == 4)
3670 ctx->hflags |= MIPS_HFLAG_BDS32;
6af0bf9c
FB
3671 MIPS_DEBUG("jr %s", regnames[rs]);
3672 break;
620e48f6 3673 case OPC_JALRS:
6af0bf9c 3674 case OPC_JALR:
364d4831 3675 case OPC_JALRC:
6af0bf9c 3676 blink = rt;
4ad40f36 3677 ctx->hflags |= MIPS_HFLAG_BR;
620e48f6
NF
3678 ctx->hflags |= (opc == OPC_JALRS
3679 ? MIPS_HFLAG_BDS16
3680 : MIPS_HFLAG_BDS32);
6af0bf9c
FB
3681 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
3682 break;
3683 default:
3684 MIPS_INVAL("branch/jump");
3685 generate_exception(ctx, EXCP_RI);
6c5c1e20 3686 goto out;
6af0bf9c
FB
3687 }
3688 } else {
3689 switch (opc) {
3690 case OPC_BEQ:
e68dd28f 3691 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
923617a3 3692 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
d077b6f7 3693 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
3694 goto not_likely;
3695 case OPC_BEQL:
e68dd28f 3696 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
923617a3 3697 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
d077b6f7 3698 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
3699 goto likely;
3700 case OPC_BNE:
e68dd28f 3701 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
923617a3 3702 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
d077b6f7 3703 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
3704 goto not_likely;
3705 case OPC_BNEL:
e68dd28f 3706 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
923617a3 3707 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
d077b6f7 3708 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
3709 goto likely;
3710 case OPC_BGEZ:
e68dd28f 3711 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
d077b6f7 3712 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
3713 goto not_likely;
3714 case OPC_BGEZL:
e68dd28f 3715 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
d077b6f7 3716 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 3717 goto likely;
3c824109 3718 case OPC_BGEZALS:
6af0bf9c 3719 case OPC_BGEZAL:
3c824109
NF
3720 ctx->hflags |= (opc == OPC_BGEZALS
3721 ? MIPS_HFLAG_BDS16
3722 : MIPS_HFLAG_BDS32);
e68dd28f 3723 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
d077b6f7 3724 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
3725 blink = 31;
3726 goto not_likely;
3727 case OPC_BGEZALL:
e68dd28f 3728 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c 3729 blink = 31;
d077b6f7 3730 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
3731 goto likely;
3732 case OPC_BGTZ:
e68dd28f 3733 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
d077b6f7 3734 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
3735 goto not_likely;
3736 case OPC_BGTZL:
e68dd28f 3737 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
d077b6f7 3738 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
3739 goto likely;
3740 case OPC_BLEZ:
e68dd28f 3741 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
d077b6f7 3742 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
3743 goto not_likely;
3744 case OPC_BLEZL:
e68dd28f 3745 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
d077b6f7 3746 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
3747 goto likely;
3748 case OPC_BLTZ:
e68dd28f 3749 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
d077b6f7 3750 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
3751 goto not_likely;
3752 case OPC_BLTZL:
e68dd28f 3753 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
d077b6f7 3754 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 3755 goto likely;
e45a93e2
JL
3756 case OPC_BPOSGE32:
3757 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
3758 MIPS_DEBUG("bposge32 " TARGET_FMT_lx, btgt);
3759 goto not_likely;
3760#if defined(TARGET_MIPS64)
3761 case OPC_BPOSGE64:
3762 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
3763 MIPS_DEBUG("bposge64 " TARGET_FMT_lx, btgt);
3764 goto not_likely;
3765#endif
3c824109 3766 case OPC_BLTZALS:
6af0bf9c 3767 case OPC_BLTZAL:
3c824109
NF
3768 ctx->hflags |= (opc == OPC_BLTZALS
3769 ? MIPS_HFLAG_BDS16
3770 : MIPS_HFLAG_BDS32);
e68dd28f 3771 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 3772 blink = 31;
d077b6f7 3773 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 3774 not_likely:
4ad40f36 3775 ctx->hflags |= MIPS_HFLAG_BC;
6af0bf9c
FB
3776 break;
3777 case OPC_BLTZALL:
e68dd28f 3778 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 3779 blink = 31;
d077b6f7 3780 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 3781 likely:
4ad40f36 3782 ctx->hflags |= MIPS_HFLAG_BL;
6af0bf9c 3783 break;
c53f4a62
TS
3784 default:
3785 MIPS_INVAL("conditional branch/jump");
3786 generate_exception(ctx, EXCP_RI);
6c5c1e20 3787 goto out;
6af0bf9c 3788 }
6af0bf9c 3789 }
923617a3 3790 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
d077b6f7 3791 blink, ctx->hflags, btgt);
9b9e4393 3792
d077b6f7 3793 ctx->btarget = btgt;
6af0bf9c 3794 if (blink > 0) {
364d4831
NF
3795 int post_delay = insn_bytes;
3796 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
3797
3798 if (opc != OPC_JALRC)
3799 post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4);
3800
3801 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
6af0bf9c 3802 }
6c5c1e20
TS
3803
3804 out:
364d4831
NF
3805 if (insn_bytes == 2)
3806 ctx->hflags |= MIPS_HFLAG_B16;
6c5c1e20
TS
3807 tcg_temp_free(t0);
3808 tcg_temp_free(t1);
6af0bf9c
FB
3809}
3810
7a387fff
TS
3811/* special3 bitfield operations */
3812static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
356265ae 3813 int rs, int lsb, int msb)
7a387fff 3814{
a7812ae4
PB
3815 TCGv t0 = tcg_temp_new();
3816 TCGv t1 = tcg_temp_new();
505ad7c2 3817 target_ulong mask;
6c5c1e20
TS
3818
3819 gen_load_gpr(t1, rs);
7a387fff
TS
3820 switch (opc) {
3821 case OPC_EXT:
3822 if (lsb + msb > 31)
3823 goto fail;
505ad7c2
AJ
3824 tcg_gen_shri_tl(t0, t1, lsb);
3825 if (msb != 31) {
3826 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
3827 } else {
3828 tcg_gen_ext32s_tl(t0, t0);
3829 }
7a387fff 3830 break;
c6d6dd7c 3831#if defined(TARGET_MIPS64)
7a387fff 3832 case OPC_DEXTM:
505ad7c2
AJ
3833 tcg_gen_shri_tl(t0, t1, lsb);
3834 if (msb != 31) {
3835 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
3836 }
7a387fff
TS
3837 break;
3838 case OPC_DEXTU:
505ad7c2
AJ
3839 tcg_gen_shri_tl(t0, t1, lsb + 32);
3840 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
7a387fff
TS
3841 break;
3842 case OPC_DEXT:
505ad7c2
AJ
3843 tcg_gen_shri_tl(t0, t1, lsb);
3844 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
7a387fff 3845 break;
c6d6dd7c 3846#endif
7a387fff
TS
3847 case OPC_INS:
3848 if (lsb > msb)
3849 goto fail;
505ad7c2 3850 mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
6c5c1e20 3851 gen_load_gpr(t0, rt);
505ad7c2
AJ
3852 tcg_gen_andi_tl(t0, t0, ~mask);
3853 tcg_gen_shli_tl(t1, t1, lsb);
3854 tcg_gen_andi_tl(t1, t1, mask);
3855 tcg_gen_or_tl(t0, t0, t1);
3856 tcg_gen_ext32s_tl(t0, t0);
7a387fff 3857 break;
c6d6dd7c 3858#if defined(TARGET_MIPS64)
7a387fff
TS
3859 case OPC_DINSM:
3860 if (lsb > msb)
3861 goto fail;
505ad7c2 3862 mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
6c5c1e20 3863 gen_load_gpr(t0, rt);
505ad7c2
AJ
3864 tcg_gen_andi_tl(t0, t0, ~mask);
3865 tcg_gen_shli_tl(t1, t1, lsb);
3866 tcg_gen_andi_tl(t1, t1, mask);
3867 tcg_gen_or_tl(t0, t0, t1);
7a387fff
TS
3868 break;
3869 case OPC_DINSU:
3870 if (lsb > msb)
3871 goto fail;
6fbab869 3872 mask = ((1ULL << (msb - lsb + 1)) - 1) << (lsb + 32);
6c5c1e20 3873 gen_load_gpr(t0, rt);
505ad7c2
AJ
3874 tcg_gen_andi_tl(t0, t0, ~mask);
3875 tcg_gen_shli_tl(t1, t1, lsb + 32);
3876 tcg_gen_andi_tl(t1, t1, mask);
3877 tcg_gen_or_tl(t0, t0, t1);
7a387fff
TS
3878 break;
3879 case OPC_DINS:
3880 if (lsb > msb)
3881 goto fail;
6c5c1e20 3882 gen_load_gpr(t0, rt);
505ad7c2
AJ
3883 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
3884 gen_load_gpr(t0, rt);
3885 tcg_gen_andi_tl(t0, t0, ~mask);
3886 tcg_gen_shli_tl(t1, t1, lsb);
3887 tcg_gen_andi_tl(t1, t1, mask);
3888 tcg_gen_or_tl(t0, t0, t1);
7a387fff 3889 break;
c6d6dd7c 3890#endif
7a387fff
TS
3891 default:
3892fail:
3893 MIPS_INVAL("bitops");
3894 generate_exception(ctx, EXCP_RI);
6c5c1e20
TS
3895 tcg_temp_free(t0);
3896 tcg_temp_free(t1);
7a387fff
TS
3897 return;
3898 }
6c5c1e20
TS
3899 gen_store_gpr(t0, rt);
3900 tcg_temp_free(t0);
3901 tcg_temp_free(t1);
7a387fff
TS
3902}
3903
49bcf33c
AJ
3904static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
3905{
3a55fa47 3906 TCGv t0;
49bcf33c 3907
3a55fa47
AJ
3908 if (rd == 0) {
3909 /* If no destination, treat it as a NOP. */
3910 MIPS_DEBUG("NOP");
3911 return;
3912 }
3913
3914 t0 = tcg_temp_new();
3915 gen_load_gpr(t0, rt);
49bcf33c
AJ
3916 switch (op2) {
3917 case OPC_WSBH:
3a55fa47
AJ
3918 {
3919 TCGv t1 = tcg_temp_new();
3920
3921 tcg_gen_shri_tl(t1, t0, 8);
3922 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
3923 tcg_gen_shli_tl(t0, t0, 8);
3924 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
3925 tcg_gen_or_tl(t0, t0, t1);
3926 tcg_temp_free(t1);
3927 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3928 }
49bcf33c
AJ
3929 break;
3930 case OPC_SEB:
3a55fa47 3931 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
3932 break;
3933 case OPC_SEH:
3a55fa47 3934 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
3935 break;
3936#if defined(TARGET_MIPS64)
3937 case OPC_DSBH:
3a55fa47
AJ
3938 {
3939 TCGv t1 = tcg_temp_new();
3940
3941 tcg_gen_shri_tl(t1, t0, 8);
3942 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
3943 tcg_gen_shli_tl(t0, t0, 8);
3944 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
3945 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3946 tcg_temp_free(t1);
3947 }
49bcf33c
AJ
3948 break;
3949 case OPC_DSHD:
3a55fa47
AJ
3950 {
3951 TCGv t1 = tcg_temp_new();
3952
3953 tcg_gen_shri_tl(t1, t0, 16);
3954 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
3955 tcg_gen_shli_tl(t0, t0, 16);
3956 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
3957 tcg_gen_or_tl(t0, t0, t1);
3958 tcg_gen_shri_tl(t1, t0, 32);
3959 tcg_gen_shli_tl(t0, t0, 32);
3960 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3961 tcg_temp_free(t1);
3962 }
49bcf33c
AJ
3963 break;
3964#endif
3965 default:
3966 MIPS_INVAL("bsfhl");
3967 generate_exception(ctx, EXCP_RI);
3968 tcg_temp_free(t0);
49bcf33c
AJ
3969 return;
3970 }
49bcf33c 3971 tcg_temp_free(t0);
49bcf33c
AJ
3972}
3973
f1aa6320 3974#ifndef CONFIG_USER_ONLY
0eaef5aa 3975/* CP0 (MMU and control) */
d9bea114 3976static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
4f57689a 3977{
d9bea114 3978 TCGv_i32 t0 = tcg_temp_new_i32();
4f57689a 3979
d9bea114
AJ
3980 tcg_gen_ld_i32(t0, cpu_env, off);
3981 tcg_gen_ext_i32_tl(arg, t0);
3982 tcg_temp_free_i32(t0);
4f57689a
TS
3983}
3984
d9bea114 3985static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
4f57689a 3986{
d9bea114
AJ
3987 tcg_gen_ld_tl(arg, cpu_env, off);
3988 tcg_gen_ext32s_tl(arg, arg);
4f57689a
TS
3989}
3990
d9bea114 3991static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
f1aa6320 3992{
d9bea114 3993 TCGv_i32 t0 = tcg_temp_new_i32();
f1aa6320 3994
d9bea114
AJ
3995 tcg_gen_trunc_tl_i32(t0, arg);
3996 tcg_gen_st_i32(t0, cpu_env, off);
3997 tcg_temp_free_i32(t0);
f1aa6320
TS
3998}
3999
d9bea114 4000static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
f1aa6320 4001{
d9bea114
AJ
4002 tcg_gen_ext32s_tl(arg, arg);
4003 tcg_gen_st_tl(arg, cpu_env, off);
f1aa6320
TS
4004}
4005
7db13fae 4006static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
873eb012 4007{
7a387fff 4008 const char *rn = "invalid";
873eb012 4009
e189e748
TS
4010 if (sel != 0)
4011 check_insn(env, ctx, ISA_MIPS32);
4012
873eb012
TS
4013 switch (reg) {
4014 case 0:
7a387fff
TS
4015 switch (sel) {
4016 case 0:
7db13fae 4017 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7a387fff
TS
4018 rn = "Index";
4019 break;
4020 case 1:
7385ac0b 4021 check_insn(env, ctx, ASE_MT);
895c2d04 4022 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7a387fff 4023 rn = "MVPControl";
ead9360e 4024 break;
7a387fff 4025 case 2:
7385ac0b 4026 check_insn(env, ctx, ASE_MT);
895c2d04 4027 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7a387fff 4028 rn = "MVPConf0";
ead9360e 4029 break;
7a387fff 4030 case 3:
7385ac0b 4031 check_insn(env, ctx, ASE_MT);
895c2d04 4032 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7a387fff 4033 rn = "MVPConf1";
ead9360e 4034 break;
7a387fff
TS
4035 default:
4036 goto die;
4037 }
873eb012
TS
4038 break;
4039 case 1:
7a387fff
TS
4040 switch (sel) {
4041 case 0:
895c2d04 4042 gen_helper_mfc0_random(arg, cpu_env);
7a387fff 4043 rn = "Random";
2423f660 4044 break;
7a387fff 4045 case 1:
7385ac0b 4046 check_insn(env, ctx, ASE_MT);
7db13fae 4047 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7a387fff 4048 rn = "VPEControl";
ead9360e 4049 break;
7a387fff 4050 case 2:
7385ac0b 4051 check_insn(env, ctx, ASE_MT);
7db13fae 4052 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7a387fff 4053 rn = "VPEConf0";
ead9360e 4054 break;
7a387fff 4055 case 3:
7385ac0b 4056 check_insn(env, ctx, ASE_MT);
7db13fae 4057 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7a387fff 4058 rn = "VPEConf1";
ead9360e 4059 break;
7a387fff 4060 case 4:
7385ac0b 4061 check_insn(env, ctx, ASE_MT);
7db13fae 4062 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
7a387fff 4063 rn = "YQMask";
ead9360e 4064 break;
7a387fff 4065 case 5:
7385ac0b 4066 check_insn(env, ctx, ASE_MT);
7db13fae 4067 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
7a387fff 4068 rn = "VPESchedule";
ead9360e 4069 break;
7a387fff 4070 case 6:
7385ac0b 4071 check_insn(env, ctx, ASE_MT);
7db13fae 4072 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7a387fff 4073 rn = "VPEScheFBack";
ead9360e 4074 break;
7a387fff 4075 case 7:
7385ac0b 4076 check_insn(env, ctx, ASE_MT);
7db13fae 4077 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7a387fff 4078 rn = "VPEOpt";
ead9360e 4079 break;
7a387fff
TS
4080 default:
4081 goto die;
4082 }
873eb012
TS
4083 break;
4084 case 2:
7a387fff
TS
4085 switch (sel) {
4086 case 0:
7db13fae 4087 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
d9bea114 4088 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
4089 rn = "EntryLo0";
4090 break;
7a387fff 4091 case 1:
7385ac0b 4092 check_insn(env, ctx, ASE_MT);
895c2d04 4093 gen_helper_mfc0_tcstatus(arg, cpu_env);
2423f660 4094 rn = "TCStatus";
ead9360e 4095 break;
7a387fff 4096 case 2:
7385ac0b 4097 check_insn(env, ctx, ASE_MT);
895c2d04 4098 gen_helper_mfc0_tcbind(arg, cpu_env);
2423f660 4099 rn = "TCBind";
ead9360e 4100 break;
7a387fff 4101 case 3:
7385ac0b 4102 check_insn(env, ctx, ASE_MT);
895c2d04 4103 gen_helper_mfc0_tcrestart(arg, cpu_env);
2423f660 4104 rn = "TCRestart";
ead9360e 4105 break;
7a387fff 4106 case 4:
7385ac0b 4107 check_insn(env, ctx, ASE_MT);
895c2d04 4108 gen_helper_mfc0_tchalt(arg, cpu_env);
2423f660 4109 rn = "TCHalt";
ead9360e 4110 break;
7a387fff 4111 case 5:
7385ac0b 4112 check_insn(env, ctx, ASE_MT);
895c2d04 4113 gen_helper_mfc0_tccontext(arg, cpu_env);
2423f660 4114 rn = "TCContext";
ead9360e 4115 break;
7a387fff 4116 case 6:
7385ac0b 4117 check_insn(env, ctx, ASE_MT);
895c2d04 4118 gen_helper_mfc0_tcschedule(arg, cpu_env);
2423f660 4119 rn = "TCSchedule";
ead9360e 4120 break;
7a387fff 4121 case 7:
7385ac0b 4122 check_insn(env, ctx, ASE_MT);
895c2d04 4123 gen_helper_mfc0_tcschefback(arg, cpu_env);
2423f660 4124 rn = "TCScheFBack";
ead9360e 4125 break;
7a387fff
TS
4126 default:
4127 goto die;
4128 }
873eb012
TS
4129 break;
4130 case 3:
7a387fff
TS
4131 switch (sel) {
4132 case 0:
7db13fae 4133 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
d9bea114 4134 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
4135 rn = "EntryLo1";
4136 break;
7a387fff
TS
4137 default:
4138 goto die;
1579a72e 4139 }
873eb012
TS
4140 break;
4141 case 4:
7a387fff
TS
4142 switch (sel) {
4143 case 0:
7db13fae 4144 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
d9bea114 4145 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
4146 rn = "Context";
4147 break;
7a387fff 4148 case 1:
d9bea114 4149// gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
2423f660
TS
4150 rn = "ContextConfig";
4151// break;
7a387fff
TS
4152 default:
4153 goto die;
1579a72e 4154 }
873eb012
TS
4155 break;
4156 case 5:
7a387fff
TS
4157 switch (sel) {
4158 case 0:
7db13fae 4159 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
2423f660
TS
4160 rn = "PageMask";
4161 break;
7a387fff 4162 case 1:
e189e748 4163 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4164 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
2423f660
TS
4165 rn = "PageGrain";
4166 break;
7a387fff
TS
4167 default:
4168 goto die;
1579a72e 4169 }
873eb012
TS
4170 break;
4171 case 6:
7a387fff
TS
4172 switch (sel) {
4173 case 0:
7db13fae 4174 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
2423f660
TS
4175 rn = "Wired";
4176 break;
7a387fff 4177 case 1:
e189e748 4178 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4179 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
2423f660 4180 rn = "SRSConf0";
ead9360e 4181 break;
7a387fff 4182 case 2:
e189e748 4183 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4184 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
2423f660 4185 rn = "SRSConf1";
ead9360e 4186 break;
7a387fff 4187 case 3:
e189e748 4188 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4189 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
2423f660 4190 rn = "SRSConf2";
ead9360e 4191 break;
7a387fff 4192 case 4:
e189e748 4193 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4194 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
2423f660 4195 rn = "SRSConf3";
ead9360e 4196 break;
7a387fff 4197 case 5:
e189e748 4198 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4199 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
2423f660 4200 rn = "SRSConf4";
ead9360e 4201 break;
7a387fff
TS
4202 default:
4203 goto die;
1579a72e 4204 }
873eb012 4205 break;
8c0fdd85 4206 case 7:
7a387fff
TS
4207 switch (sel) {
4208 case 0:
e189e748 4209 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4210 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
2423f660
TS
4211 rn = "HWREna";
4212 break;
7a387fff
TS
4213 default:
4214 goto die;
1579a72e 4215 }
8c0fdd85 4216 break;
873eb012 4217 case 8:
7a387fff
TS
4218 switch (sel) {
4219 case 0:
7db13fae 4220 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
d9bea114 4221 tcg_gen_ext32s_tl(arg, arg);
f0b3f3ae 4222 rn = "BadVAddr";
2423f660 4223 break;
7a387fff
TS
4224 default:
4225 goto die;
4226 }
873eb012
TS
4227 break;
4228 case 9:
7a387fff
TS
4229 switch (sel) {
4230 case 0:
2e70f6ef
PB
4231 /* Mark as an IO operation because we read the time. */
4232 if (use_icount)
4233 gen_io_start();
895c2d04 4234 gen_helper_mfc0_count(arg, cpu_env);
2e70f6ef
PB
4235 if (use_icount) {
4236 gen_io_end();
2e70f6ef 4237 }
55807224
EI
4238 /* Break the TB to be able to take timer interrupts immediately
4239 after reading count. */
4240 ctx->bstate = BS_STOP;
2423f660
TS
4241 rn = "Count";
4242 break;
4243 /* 6,7 are implementation dependent */
7a387fff
TS
4244 default:
4245 goto die;
2423f660 4246 }
873eb012
TS
4247 break;
4248 case 10:
7a387fff
TS
4249 switch (sel) {
4250 case 0:
7db13fae 4251 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
d9bea114 4252 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
4253 rn = "EntryHi";
4254 break;
7a387fff
TS
4255 default:
4256 goto die;
1579a72e 4257 }
873eb012
TS
4258 break;
4259 case 11:
7a387fff
TS
4260 switch (sel) {
4261 case 0:
7db13fae 4262 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
2423f660
TS
4263 rn = "Compare";
4264 break;
4265 /* 6,7 are implementation dependent */
7a387fff
TS
4266 default:
4267 goto die;
2423f660 4268 }
873eb012
TS
4269 break;
4270 case 12:
7a387fff
TS
4271 switch (sel) {
4272 case 0:
7db13fae 4273 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
2423f660
TS
4274 rn = "Status";
4275 break;
7a387fff 4276 case 1:
e189e748 4277 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4278 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
2423f660
TS
4279 rn = "IntCtl";
4280 break;
7a387fff 4281 case 2:
e189e748 4282 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4283 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
2423f660
TS
4284 rn = "SRSCtl";
4285 break;
7a387fff 4286 case 3:
e189e748 4287 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4288 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
2423f660 4289 rn = "SRSMap";
fd88b6ab 4290 break;
7a387fff
TS
4291 default:
4292 goto die;
4293 }
873eb012
TS
4294 break;
4295 case 13:
7a387fff
TS
4296 switch (sel) {
4297 case 0:
7db13fae 4298 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
2423f660
TS
4299 rn = "Cause";
4300 break;
7a387fff
TS
4301 default:
4302 goto die;
4303 }
873eb012
TS
4304 break;
4305 case 14:
7a387fff
TS
4306 switch (sel) {
4307 case 0:
7db13fae 4308 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
d9bea114 4309 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
4310 rn = "EPC";
4311 break;
7a387fff
TS
4312 default:
4313 goto die;
1579a72e 4314 }
873eb012
TS
4315 break;
4316 case 15:
7a387fff
TS
4317 switch (sel) {
4318 case 0:
7db13fae 4319 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
2423f660
TS
4320 rn = "PRid";
4321 break;
7a387fff 4322 case 1:
e189e748 4323 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4324 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
2423f660
TS
4325 rn = "EBase";
4326 break;
7a387fff
TS
4327 default:
4328 goto die;
4329 }
873eb012
TS
4330 break;
4331 case 16:
4332 switch (sel) {
4333 case 0:
7db13fae 4334 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
873eb012
TS
4335 rn = "Config";
4336 break;
4337 case 1:
7db13fae 4338 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
873eb012
TS
4339 rn = "Config1";
4340 break;
7a387fff 4341 case 2:
7db13fae 4342 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7a387fff
TS
4343 rn = "Config2";
4344 break;
4345 case 3:
7db13fae 4346 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7a387fff
TS
4347 rn = "Config3";
4348 break;
e397ee33
TS
4349 /* 4,5 are reserved */
4350 /* 6,7 are implementation dependent */
4351 case 6:
7db13fae 4352 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
e397ee33
TS
4353 rn = "Config6";
4354 break;
4355 case 7:
7db13fae 4356 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
e397ee33
TS
4357 rn = "Config7";
4358 break;
873eb012 4359 default:
873eb012
TS
4360 goto die;
4361 }
4362 break;
4363 case 17:
7a387fff
TS
4364 switch (sel) {
4365 case 0:
895c2d04 4366 gen_helper_mfc0_lladdr(arg, cpu_env);
2423f660
TS
4367 rn = "LLAddr";
4368 break;
7a387fff
TS
4369 default:
4370 goto die;
4371 }
873eb012
TS
4372 break;
4373 case 18:
7a387fff 4374 switch (sel) {
fd88b6ab 4375 case 0 ... 7:
895c2d04 4376 gen_helper_1e0i(mfc0_watchlo, arg, sel);
2423f660
TS
4377 rn = "WatchLo";
4378 break;
7a387fff
TS
4379 default:
4380 goto die;
4381 }
873eb012
TS
4382 break;
4383 case 19:
7a387fff 4384 switch (sel) {
fd88b6ab 4385 case 0 ...7:
895c2d04 4386 gen_helper_1e0i(mfc0_watchhi, arg, sel);
2423f660
TS
4387 rn = "WatchHi";
4388 break;
7a387fff
TS
4389 default:
4390 goto die;
4391 }
873eb012 4392 break;
8c0fdd85 4393 case 20:
7a387fff
TS
4394 switch (sel) {
4395 case 0:
d26bc211 4396#if defined(TARGET_MIPS64)
e189e748 4397 check_insn(env, ctx, ISA_MIPS3);
7db13fae 4398 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
d9bea114 4399 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
4400 rn = "XContext";
4401 break;
703eaf37 4402#endif
7a387fff
TS
4403 default:
4404 goto die;
4405 }
8c0fdd85
TS
4406 break;
4407 case 21:
7a387fff
TS
4408 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4409 switch (sel) {
4410 case 0:
7db13fae 4411 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
2423f660
TS
4412 rn = "Framemask";
4413 break;
7a387fff
TS
4414 default:
4415 goto die;
4416 }
8c0fdd85
TS
4417 break;
4418 case 22:
d9bea114 4419 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
4420 rn = "'Diagnostic"; /* implementation dependent */
4421 break;
873eb012 4422 case 23:
7a387fff
TS
4423 switch (sel) {
4424 case 0:
895c2d04 4425 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
2423f660
TS
4426 rn = "Debug";
4427 break;
7a387fff 4428 case 1:
d9bea114 4429// gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
2423f660
TS
4430 rn = "TraceControl";
4431// break;
7a387fff 4432 case 2:
d9bea114 4433// gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
2423f660
TS
4434 rn = "TraceControl2";
4435// break;
7a387fff 4436 case 3:
d9bea114 4437// gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
2423f660
TS
4438 rn = "UserTraceData";
4439// break;
7a387fff 4440 case 4:
d9bea114 4441// gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
2423f660
TS
4442 rn = "TraceBPC";
4443// break;
7a387fff
TS
4444 default:
4445 goto die;
4446 }
873eb012
TS
4447 break;
4448 case 24:
7a387fff
TS
4449 switch (sel) {
4450 case 0:
f0b3f3ae 4451 /* EJTAG support */
7db13fae 4452 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
d9bea114 4453 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
4454 rn = "DEPC";
4455 break;
7a387fff
TS
4456 default:
4457 goto die;
4458 }
873eb012 4459 break;
8c0fdd85 4460 case 25:
7a387fff
TS
4461 switch (sel) {
4462 case 0:
7db13fae 4463 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
2423f660 4464 rn = "Performance0";
7a387fff
TS
4465 break;
4466 case 1:
d9bea114 4467// gen_helper_mfc0_performance1(arg);
2423f660
TS
4468 rn = "Performance1";
4469// break;
7a387fff 4470 case 2:
d9bea114 4471// gen_helper_mfc0_performance2(arg);
2423f660
TS
4472 rn = "Performance2";
4473// break;
7a387fff 4474 case 3:
d9bea114 4475// gen_helper_mfc0_performance3(arg);
2423f660
TS
4476 rn = "Performance3";
4477// break;
7a387fff 4478 case 4:
d9bea114 4479// gen_helper_mfc0_performance4(arg);
2423f660
TS
4480 rn = "Performance4";
4481// break;
7a387fff 4482 case 5:
d9bea114 4483// gen_helper_mfc0_performance5(arg);
2423f660
TS
4484 rn = "Performance5";
4485// break;
7a387fff 4486 case 6:
d9bea114 4487// gen_helper_mfc0_performance6(arg);
2423f660
TS
4488 rn = "Performance6";
4489// break;
7a387fff 4490 case 7:
d9bea114 4491// gen_helper_mfc0_performance7(arg);
2423f660
TS
4492 rn = "Performance7";
4493// break;
7a387fff
TS
4494 default:
4495 goto die;
4496 }
8c0fdd85
TS
4497 break;
4498 case 26:
d9bea114 4499 tcg_gen_movi_tl(arg, 0); /* unimplemented */
da80682b
AJ
4500 rn = "ECC";
4501 break;
8c0fdd85 4502 case 27:
7a387fff 4503 switch (sel) {
7a387fff 4504 case 0 ... 3:
d9bea114 4505 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
4506 rn = "CacheErr";
4507 break;
7a387fff
TS
4508 default:
4509 goto die;
4510 }
8c0fdd85 4511 break;
873eb012
TS
4512 case 28:
4513 switch (sel) {
4514 case 0:
7a387fff
TS
4515 case 2:
4516 case 4:
4517 case 6:
7db13fae 4518 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
873eb012
TS
4519 rn = "TagLo";
4520 break;
4521 case 1:
7a387fff
TS
4522 case 3:
4523 case 5:
4524 case 7:
7db13fae 4525 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
873eb012
TS
4526 rn = "DataLo";
4527 break;
4528 default:
873eb012
TS
4529 goto die;
4530 }
4531 break;
8c0fdd85 4532 case 29:
7a387fff
TS
4533 switch (sel) {
4534 case 0:
4535 case 2:
4536 case 4:
4537 case 6:
7db13fae 4538 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7a387fff
TS
4539 rn = "TagHi";
4540 break;
4541 case 1:
4542 case 3:
4543 case 5:
4544 case 7:
7db13fae 4545 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7a387fff
TS
4546 rn = "DataHi";
4547 break;
4548 default:
4549 goto die;
4550 }
8c0fdd85 4551 break;
873eb012 4552 case 30:
7a387fff
TS
4553 switch (sel) {
4554 case 0:
7db13fae 4555 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
d9bea114 4556 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
4557 rn = "ErrorEPC";
4558 break;
7a387fff
TS
4559 default:
4560 goto die;
4561 }
873eb012
TS
4562 break;
4563 case 31:
7a387fff
TS
4564 switch (sel) {
4565 case 0:
f0b3f3ae 4566 /* EJTAG support */
7db13fae 4567 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
4568 rn = "DESAVE";
4569 break;
7a387fff
TS
4570 default:
4571 goto die;
4572 }
873eb012
TS
4573 break;
4574 default:
873eb012
TS
4575 goto die;
4576 }
2abf314d 4577 (void)rn; /* avoid a compiler warning */
d12d51d5 4578 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
873eb012
TS
4579 return;
4580
4581die:
d12d51d5 4582 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
873eb012
TS
4583 generate_exception(ctx, EXCP_RI);
4584}
4585
7db13fae 4586static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
8c0fdd85 4587{
7a387fff
TS
4588 const char *rn = "invalid";
4589
e189e748
TS
4590 if (sel != 0)
4591 check_insn(env, ctx, ISA_MIPS32);
4592
2e70f6ef
PB
4593 if (use_icount)
4594 gen_io_start();
4595
8c0fdd85
TS
4596 switch (reg) {
4597 case 0:
7a387fff
TS
4598 switch (sel) {
4599 case 0:
895c2d04 4600 gen_helper_mtc0_index(cpu_env, arg);
7a387fff
TS
4601 rn = "Index";
4602 break;
4603 case 1:
7385ac0b 4604 check_insn(env, ctx, ASE_MT);
895c2d04 4605 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7a387fff 4606 rn = "MVPControl";
ead9360e 4607 break;
7a387fff 4608 case 2:
7385ac0b 4609 check_insn(env, ctx, ASE_MT);
ead9360e 4610 /* ignored */
7a387fff 4611 rn = "MVPConf0";
ead9360e 4612 break;
7a387fff 4613 case 3:
7385ac0b 4614 check_insn(env, ctx, ASE_MT);
ead9360e 4615 /* ignored */
7a387fff 4616 rn = "MVPConf1";
ead9360e 4617 break;
7a387fff
TS
4618 default:
4619 goto die;
4620 }
8c0fdd85
TS
4621 break;
4622 case 1:
7a387fff
TS
4623 switch (sel) {
4624 case 0:
2423f660 4625 /* ignored */
7a387fff 4626 rn = "Random";
2423f660 4627 break;
7a387fff 4628 case 1:
7385ac0b 4629 check_insn(env, ctx, ASE_MT);
895c2d04 4630 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7a387fff 4631 rn = "VPEControl";
ead9360e 4632 break;
7a387fff 4633 case 2:
7385ac0b 4634 check_insn(env, ctx, ASE_MT);
895c2d04 4635 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7a387fff 4636 rn = "VPEConf0";
ead9360e 4637 break;
7a387fff 4638 case 3:
7385ac0b 4639 check_insn(env, ctx, ASE_MT);
895c2d04 4640 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7a387fff 4641 rn = "VPEConf1";
ead9360e 4642 break;
7a387fff 4643 case 4:
7385ac0b 4644 check_insn(env, ctx, ASE_MT);
895c2d04 4645 gen_helper_mtc0_yqmask(cpu_env, arg);
7a387fff 4646 rn = "YQMask";
ead9360e 4647 break;
7a387fff 4648 case 5:
7385ac0b 4649 check_insn(env, ctx, ASE_MT);
7db13fae 4650 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
7a387fff 4651 rn = "VPESchedule";
ead9360e 4652 break;
7a387fff 4653 case 6:
7385ac0b 4654 check_insn(env, ctx, ASE_MT);
7db13fae 4655 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7a387fff 4656 rn = "VPEScheFBack";
ead9360e 4657 break;
7a387fff 4658 case 7:
7385ac0b 4659 check_insn(env, ctx, ASE_MT);
895c2d04 4660 gen_helper_mtc0_vpeopt(cpu_env, arg);
7a387fff 4661 rn = "VPEOpt";
ead9360e 4662 break;
7a387fff
TS
4663 default:
4664 goto die;
4665 }
8c0fdd85
TS
4666 break;
4667 case 2:
7a387fff
TS
4668 switch (sel) {
4669 case 0:
895c2d04 4670 gen_helper_mtc0_entrylo0(cpu_env, arg);
2423f660
TS
4671 rn = "EntryLo0";
4672 break;
7a387fff 4673 case 1:
7385ac0b 4674 check_insn(env, ctx, ASE_MT);
895c2d04 4675 gen_helper_mtc0_tcstatus(cpu_env, arg);
2423f660 4676 rn = "TCStatus";
ead9360e 4677 break;
7a387fff 4678 case 2:
7385ac0b 4679 check_insn(env, ctx, ASE_MT);
895c2d04 4680 gen_helper_mtc0_tcbind(cpu_env, arg);
2423f660 4681 rn = "TCBind";
ead9360e 4682 break;
7a387fff 4683 case 3:
7385ac0b 4684 check_insn(env, ctx, ASE_MT);
895c2d04 4685 gen_helper_mtc0_tcrestart(cpu_env, arg);
2423f660 4686 rn = "TCRestart";
ead9360e 4687 break;
7a387fff 4688 case 4:
7385ac0b 4689 check_insn(env, ctx, ASE_MT);
895c2d04 4690 gen_helper_mtc0_tchalt(cpu_env, arg);
2423f660 4691 rn = "TCHalt";
ead9360e 4692 break;
7a387fff 4693 case 5:
7385ac0b 4694 check_insn(env, ctx, ASE_MT);
895c2d04 4695 gen_helper_mtc0_tccontext(cpu_env, arg);
2423f660 4696 rn = "TCContext";
ead9360e 4697 break;
7a387fff 4698 case 6:
7385ac0b 4699 check_insn(env, ctx, ASE_MT);
895c2d04 4700 gen_helper_mtc0_tcschedule(cpu_env, arg);
2423f660 4701 rn = "TCSchedule";
ead9360e 4702 break;
7a387fff 4703 case 7:
7385ac0b 4704 check_insn(env, ctx, ASE_MT);
895c2d04 4705 gen_helper_mtc0_tcschefback(cpu_env, arg);
2423f660 4706 rn = "TCScheFBack";
ead9360e 4707 break;
7a387fff
TS
4708 default:
4709 goto die;
4710 }
8c0fdd85
TS
4711 break;
4712 case 3:
7a387fff
TS
4713 switch (sel) {
4714 case 0:
895c2d04 4715 gen_helper_mtc0_entrylo1(cpu_env, arg);
2423f660
TS
4716 rn = "EntryLo1";
4717 break;
7a387fff
TS
4718 default:
4719 goto die;
876d4b07 4720 }
8c0fdd85
TS
4721 break;
4722 case 4:
7a387fff
TS
4723 switch (sel) {
4724 case 0:
895c2d04 4725 gen_helper_mtc0_context(cpu_env, arg);
2423f660
TS
4726 rn = "Context";
4727 break;
7a387fff 4728 case 1:
895c2d04 4729// gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
2423f660
TS
4730 rn = "ContextConfig";
4731// break;
7a387fff
TS
4732 default:
4733 goto die;
876d4b07 4734 }
8c0fdd85
TS
4735 break;
4736 case 5:
7a387fff
TS
4737 switch (sel) {
4738 case 0:
895c2d04 4739 gen_helper_mtc0_pagemask(cpu_env, arg);
2423f660
TS
4740 rn = "PageMask";
4741 break;
7a387fff 4742 case 1:
e189e748 4743 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4744 gen_helper_mtc0_pagegrain(cpu_env, arg);
2423f660
TS
4745 rn = "PageGrain";
4746 break;
7a387fff
TS
4747 default:
4748 goto die;
876d4b07 4749 }
8c0fdd85
TS
4750 break;
4751 case 6:
7a387fff
TS
4752 switch (sel) {
4753 case 0:
895c2d04 4754 gen_helper_mtc0_wired(cpu_env, arg);
2423f660
TS
4755 rn = "Wired";
4756 break;
7a387fff 4757 case 1:
e189e748 4758 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4759 gen_helper_mtc0_srsconf0(cpu_env, arg);
2423f660 4760 rn = "SRSConf0";
ead9360e 4761 break;
7a387fff 4762 case 2:
e189e748 4763 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4764 gen_helper_mtc0_srsconf1(cpu_env, arg);
2423f660 4765 rn = "SRSConf1";
ead9360e 4766 break;
7a387fff 4767 case 3:
e189e748 4768 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4769 gen_helper_mtc0_srsconf2(cpu_env, arg);
2423f660 4770 rn = "SRSConf2";
ead9360e 4771 break;
7a387fff 4772 case 4:
e189e748 4773 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4774 gen_helper_mtc0_srsconf3(cpu_env, arg);
2423f660 4775 rn = "SRSConf3";
ead9360e 4776 break;
7a387fff 4777 case 5:
e189e748 4778 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4779 gen_helper_mtc0_srsconf4(cpu_env, arg);
2423f660 4780 rn = "SRSConf4";
ead9360e 4781 break;
7a387fff
TS
4782 default:
4783 goto die;
876d4b07 4784 }
8c0fdd85
TS
4785 break;
4786 case 7:
7a387fff
TS
4787 switch (sel) {
4788 case 0:
e189e748 4789 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4790 gen_helper_mtc0_hwrena(cpu_env, arg);
2423f660
TS
4791 rn = "HWREna";
4792 break;
7a387fff
TS
4793 default:
4794 goto die;
876d4b07 4795 }
8c0fdd85
TS
4796 break;
4797 case 8:
7a387fff 4798 /* ignored */
f0b3f3ae 4799 rn = "BadVAddr";
8c0fdd85
TS
4800 break;
4801 case 9:
7a387fff
TS
4802 switch (sel) {
4803 case 0:
895c2d04 4804 gen_helper_mtc0_count(cpu_env, arg);
2423f660
TS
4805 rn = "Count";
4806 break;
876d4b07 4807 /* 6,7 are implementation dependent */
7a387fff
TS
4808 default:
4809 goto die;
876d4b07 4810 }
8c0fdd85
TS
4811 break;
4812 case 10:
7a387fff
TS
4813 switch (sel) {
4814 case 0:
895c2d04 4815 gen_helper_mtc0_entryhi(cpu_env, arg);
2423f660
TS
4816 rn = "EntryHi";
4817 break;
7a387fff
TS
4818 default:
4819 goto die;
876d4b07 4820 }
8c0fdd85
TS
4821 break;
4822 case 11:
7a387fff
TS
4823 switch (sel) {
4824 case 0:
895c2d04 4825 gen_helper_mtc0_compare(cpu_env, arg);
2423f660
TS
4826 rn = "Compare";
4827 break;
4828 /* 6,7 are implementation dependent */
7a387fff
TS
4829 default:
4830 goto die;
876d4b07 4831 }
8c0fdd85
TS
4832 break;
4833 case 12:
7a387fff
TS
4834 switch (sel) {
4835 case 0:
867abc7e 4836 save_cpu_state(ctx, 1);
895c2d04 4837 gen_helper_mtc0_status(cpu_env, arg);
8487327a
TS
4838 /* BS_STOP isn't good enough here, hflags may have changed. */
4839 gen_save_pc(ctx->pc + 4);
4840 ctx->bstate = BS_EXCP;
2423f660
TS
4841 rn = "Status";
4842 break;
7a387fff 4843 case 1:
e189e748 4844 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4845 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a
TS
4846 /* Stop translation as we may have switched the execution mode */
4847 ctx->bstate = BS_STOP;
2423f660
TS
4848 rn = "IntCtl";
4849 break;
7a387fff 4850 case 2:
e189e748 4851 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4852 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a
TS
4853 /* Stop translation as we may have switched the execution mode */
4854 ctx->bstate = BS_STOP;
2423f660
TS
4855 rn = "SRSCtl";
4856 break;
7a387fff 4857 case 3:
e189e748 4858 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4859 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a
TS
4860 /* Stop translation as we may have switched the execution mode */
4861 ctx->bstate = BS_STOP;
2423f660 4862 rn = "SRSMap";
fd88b6ab 4863 break;
7a387fff
TS
4864 default:
4865 goto die;
876d4b07 4866 }
8c0fdd85
TS
4867 break;
4868 case 13:
7a387fff
TS
4869 switch (sel) {
4870 case 0:
867abc7e 4871 save_cpu_state(ctx, 1);
895c2d04 4872 gen_helper_mtc0_cause(cpu_env, arg);
2423f660
TS
4873 rn = "Cause";
4874 break;
7a387fff
TS
4875 default:
4876 goto die;
876d4b07 4877 }
8c0fdd85
TS
4878 break;
4879 case 14:
7a387fff
TS
4880 switch (sel) {
4881 case 0:
7db13fae 4882 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
2423f660
TS
4883 rn = "EPC";
4884 break;
7a387fff
TS
4885 default:
4886 goto die;
876d4b07 4887 }
8c0fdd85
TS
4888 break;
4889 case 15:
7a387fff
TS
4890 switch (sel) {
4891 case 0:
2423f660
TS
4892 /* ignored */
4893 rn = "PRid";
4894 break;
7a387fff 4895 case 1:
e189e748 4896 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4897 gen_helper_mtc0_ebase(cpu_env, arg);
2423f660
TS
4898 rn = "EBase";
4899 break;
7a387fff
TS
4900 default:
4901 goto die;
1579a72e 4902 }
8c0fdd85
TS
4903 break;
4904 case 16:
4905 switch (sel) {
4906 case 0:
895c2d04 4907 gen_helper_mtc0_config0(cpu_env, arg);
7a387fff 4908 rn = "Config";
2423f660
TS
4909 /* Stop translation as we may have switched the execution mode */
4910 ctx->bstate = BS_STOP;
7a387fff
TS
4911 break;
4912 case 1:
e397ee33 4913 /* ignored, read only */
7a387fff
TS
4914 rn = "Config1";
4915 break;
4916 case 2:
895c2d04 4917 gen_helper_mtc0_config2(cpu_env, arg);
7a387fff 4918 rn = "Config2";
2423f660
TS
4919 /* Stop translation as we may have switched the execution mode */
4920 ctx->bstate = BS_STOP;
8c0fdd85 4921 break;
7a387fff 4922 case 3:
e397ee33 4923 /* ignored, read only */
7a387fff
TS
4924 rn = "Config3";
4925 break;
e397ee33
TS
4926 /* 4,5 are reserved */
4927 /* 6,7 are implementation dependent */
4928 case 6:
4929 /* ignored */
4930 rn = "Config6";
4931 break;
4932 case 7:
4933 /* ignored */
4934 rn = "Config7";
4935 break;
8c0fdd85
TS
4936 default:
4937 rn = "Invalid config selector";
4938 goto die;
4939 }
4940 break;
4941 case 17:
7a387fff
TS
4942 switch (sel) {
4943 case 0:
895c2d04 4944 gen_helper_mtc0_lladdr(cpu_env, arg);
2423f660
TS
4945 rn = "LLAddr";
4946 break;
7a387fff
TS
4947 default:
4948 goto die;
4949 }
8c0fdd85
TS
4950 break;
4951 case 18:
7a387fff 4952 switch (sel) {
fd88b6ab 4953 case 0 ... 7:
895c2d04 4954 gen_helper_0e1i(mtc0_watchlo, arg, sel);
2423f660
TS
4955 rn = "WatchLo";
4956 break;
7a387fff
TS
4957 default:
4958 goto die;
4959 }
8c0fdd85
TS
4960 break;
4961 case 19:
7a387fff 4962 switch (sel) {
fd88b6ab 4963 case 0 ... 7:
895c2d04 4964 gen_helper_0e1i(mtc0_watchhi, arg, sel);
2423f660
TS
4965 rn = "WatchHi";
4966 break;
7a387fff
TS
4967 default:
4968 goto die;
4969 }
8c0fdd85
TS
4970 break;
4971 case 20:
7a387fff
TS
4972 switch (sel) {
4973 case 0:
d26bc211 4974#if defined(TARGET_MIPS64)
e189e748 4975 check_insn(env, ctx, ISA_MIPS3);
895c2d04 4976 gen_helper_mtc0_xcontext(cpu_env, arg);
2423f660
TS
4977 rn = "XContext";
4978 break;
703eaf37 4979#endif
7a387fff
TS
4980 default:
4981 goto die;
4982 }
8c0fdd85
TS
4983 break;
4984 case 21:
7a387fff
TS
4985 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4986 switch (sel) {
4987 case 0:
895c2d04 4988 gen_helper_mtc0_framemask(cpu_env, arg);
2423f660
TS
4989 rn = "Framemask";
4990 break;
7a387fff
TS
4991 default:
4992 goto die;
4993 }
4994 break;
8c0fdd85 4995 case 22:
7a387fff
TS
4996 /* ignored */
4997 rn = "Diagnostic"; /* implementation dependent */
2423f660 4998 break;
8c0fdd85 4999 case 23:
7a387fff
TS
5000 switch (sel) {
5001 case 0:
895c2d04 5002 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8487327a
TS
5003 /* BS_STOP isn't good enough here, hflags may have changed. */
5004 gen_save_pc(ctx->pc + 4);
5005 ctx->bstate = BS_EXCP;
2423f660
TS
5006 rn = "Debug";
5007 break;
7a387fff 5008 case 1:
895c2d04 5009// gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
2423f660 5010 rn = "TraceControl";
8487327a
TS
5011 /* Stop translation as we may have switched the execution mode */
5012 ctx->bstate = BS_STOP;
2423f660 5013// break;
7a387fff 5014 case 2:
895c2d04 5015// gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
2423f660 5016 rn = "TraceControl2";
8487327a
TS
5017 /* Stop translation as we may have switched the execution mode */
5018 ctx->bstate = BS_STOP;
2423f660 5019// break;
7a387fff 5020 case 3:
8487327a
TS
5021 /* Stop translation as we may have switched the execution mode */
5022 ctx->bstate = BS_STOP;
895c2d04 5023// gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
2423f660 5024 rn = "UserTraceData";
8487327a
TS
5025 /* Stop translation as we may have switched the execution mode */
5026 ctx->bstate = BS_STOP;
2423f660 5027// break;
7a387fff 5028 case 4:
895c2d04 5029// gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
8487327a
TS
5030 /* Stop translation as we may have switched the execution mode */
5031 ctx->bstate = BS_STOP;
2423f660
TS
5032 rn = "TraceBPC";
5033// break;
7a387fff
TS
5034 default:
5035 goto die;
5036 }
8c0fdd85
TS
5037 break;
5038 case 24:
7a387fff
TS
5039 switch (sel) {
5040 case 0:
f1aa6320 5041 /* EJTAG support */
7db13fae 5042 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
2423f660
TS
5043 rn = "DEPC";
5044 break;
7a387fff
TS
5045 default:
5046 goto die;
5047 }
8c0fdd85
TS
5048 break;
5049 case 25:
7a387fff
TS
5050 switch (sel) {
5051 case 0:
895c2d04 5052 gen_helper_mtc0_performance0(cpu_env, arg);
2423f660
TS
5053 rn = "Performance0";
5054 break;
7a387fff 5055 case 1:
d9bea114 5056// gen_helper_mtc0_performance1(arg);
2423f660
TS
5057 rn = "Performance1";
5058// break;
7a387fff 5059 case 2:
d9bea114 5060// gen_helper_mtc0_performance2(arg);
2423f660
TS
5061 rn = "Performance2";
5062// break;
7a387fff 5063 case 3:
d9bea114 5064// gen_helper_mtc0_performance3(arg);
2423f660
TS
5065 rn = "Performance3";
5066// break;
7a387fff 5067 case 4:
d9bea114 5068// gen_helper_mtc0_performance4(arg);
2423f660
TS
5069 rn = "Performance4";
5070// break;
7a387fff 5071 case 5:
d9bea114 5072// gen_helper_mtc0_performance5(arg);
2423f660
TS
5073 rn = "Performance5";
5074// break;
7a387fff 5075 case 6:
d9bea114 5076// gen_helper_mtc0_performance6(arg);
2423f660
TS
5077 rn = "Performance6";
5078// break;
7a387fff 5079 case 7:
d9bea114 5080// gen_helper_mtc0_performance7(arg);
2423f660
TS
5081 rn = "Performance7";
5082// break;
7a387fff
TS
5083 default:
5084 goto die;
5085 }
8c0fdd85
TS
5086 break;
5087 case 26:
2423f660 5088 /* ignored */
8c0fdd85 5089 rn = "ECC";
2423f660 5090 break;
8c0fdd85 5091 case 27:
7a387fff
TS
5092 switch (sel) {
5093 case 0 ... 3:
2423f660
TS
5094 /* ignored */
5095 rn = "CacheErr";
5096 break;
7a387fff
TS
5097 default:
5098 goto die;
5099 }
8c0fdd85
TS
5100 break;
5101 case 28:
5102 switch (sel) {
5103 case 0:
7a387fff
TS
5104 case 2:
5105 case 4:
5106 case 6:
895c2d04 5107 gen_helper_mtc0_taglo(cpu_env, arg);
8c0fdd85
TS
5108 rn = "TagLo";
5109 break;
7a387fff
TS
5110 case 1:
5111 case 3:
5112 case 5:
5113 case 7:
895c2d04 5114 gen_helper_mtc0_datalo(cpu_env, arg);
7a387fff
TS
5115 rn = "DataLo";
5116 break;
8c0fdd85 5117 default:
8c0fdd85
TS
5118 goto die;
5119 }
5120 break;
5121 case 29:
7a387fff
TS
5122 switch (sel) {
5123 case 0:
5124 case 2:
5125 case 4:
5126 case 6:
895c2d04 5127 gen_helper_mtc0_taghi(cpu_env, arg);
7a387fff
TS
5128 rn = "TagHi";
5129 break;
5130 case 1:
5131 case 3:
5132 case 5:
5133 case 7:
895c2d04 5134 gen_helper_mtc0_datahi(cpu_env, arg);
7a387fff
TS
5135 rn = "DataHi";
5136 break;
5137 default:
5138 rn = "invalid sel";
5139 goto die;
5140 }
8c0fdd85
TS
5141 break;
5142 case 30:
7a387fff
TS
5143 switch (sel) {
5144 case 0:
7db13fae 5145 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
2423f660
TS
5146 rn = "ErrorEPC";
5147 break;
7a387fff
TS
5148 default:
5149 goto die;
5150 }
8c0fdd85
TS
5151 break;
5152 case 31:
7a387fff
TS
5153 switch (sel) {
5154 case 0:
f1aa6320 5155 /* EJTAG support */
7db13fae 5156 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
5157 rn = "DESAVE";
5158 break;
7a387fff
TS
5159 default:
5160 goto die;
5161 }
2423f660
TS
5162 /* Stop translation as we may have switched the execution mode */
5163 ctx->bstate = BS_STOP;
8c0fdd85
TS
5164 break;
5165 default:
8c0fdd85
TS
5166 goto die;
5167 }
2abf314d 5168 (void)rn; /* avoid a compiler warning */
d12d51d5 5169 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
bf20dc07 5170 /* For simplicity assume that all writes can cause interrupts. */
2e70f6ef
PB
5171 if (use_icount) {
5172 gen_io_end();
5173 ctx->bstate = BS_STOP;
5174 }
8c0fdd85
TS
5175 return;
5176
5177die:
d12d51d5 5178 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
8c0fdd85
TS
5179 generate_exception(ctx, EXCP_RI);
5180}
5181
d26bc211 5182#if defined(TARGET_MIPS64)
7db13fae 5183static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8
TS
5184{
5185 const char *rn = "invalid";
5186
e189e748
TS
5187 if (sel != 0)
5188 check_insn(env, ctx, ISA_MIPS64);
5189
9c2149c8
TS
5190 switch (reg) {
5191 case 0:
5192 switch (sel) {
5193 case 0:
7db13fae 5194 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
9c2149c8
TS
5195 rn = "Index";
5196 break;
5197 case 1:
7385ac0b 5198 check_insn(env, ctx, ASE_MT);
895c2d04 5199 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
9c2149c8 5200 rn = "MVPControl";
ead9360e 5201 break;
9c2149c8 5202 case 2:
7385ac0b 5203 check_insn(env, ctx, ASE_MT);
895c2d04 5204 gen_helper_mfc0_mvpconf0(arg, cpu_env);
9c2149c8 5205 rn = "MVPConf0";
ead9360e 5206 break;
9c2149c8 5207 case 3:
7385ac0b 5208 check_insn(env, ctx, ASE_MT);
895c2d04 5209 gen_helper_mfc0_mvpconf1(arg, cpu_env);
9c2149c8 5210 rn = "MVPConf1";
ead9360e 5211 break;
9c2149c8
TS
5212 default:
5213 goto die;
5214 }
5215 break;
5216 case 1:
5217 switch (sel) {
5218 case 0:
895c2d04 5219 gen_helper_mfc0_random(arg, cpu_env);
9c2149c8 5220 rn = "Random";
2423f660 5221 break;
9c2149c8 5222 case 1:
7385ac0b 5223 check_insn(env, ctx, ASE_MT);
7db13fae 5224 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
9c2149c8 5225 rn = "VPEControl";
ead9360e 5226 break;
9c2149c8 5227 case 2:
7385ac0b 5228 check_insn(env, ctx, ASE_MT);
7db13fae 5229 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
9c2149c8 5230 rn = "VPEConf0";
ead9360e 5231 break;
9c2149c8 5232 case 3:
7385ac0b 5233 check_insn(env, ctx, ASE_MT);
7db13fae 5234 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
9c2149c8 5235 rn = "VPEConf1";
ead9360e 5236 break;
9c2149c8 5237 case 4:
7385ac0b 5238 check_insn(env, ctx, ASE_MT);
7db13fae 5239 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
9c2149c8 5240 rn = "YQMask";
ead9360e 5241 break;
9c2149c8 5242 case 5:
7385ac0b 5243 check_insn(env, ctx, ASE_MT);
7db13fae 5244 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
9c2149c8 5245 rn = "VPESchedule";
ead9360e 5246 break;
9c2149c8 5247 case 6:
7385ac0b 5248 check_insn(env, ctx, ASE_MT);
7db13fae 5249 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
9c2149c8 5250 rn = "VPEScheFBack";
ead9360e 5251 break;
9c2149c8 5252 case 7:
7385ac0b 5253 check_insn(env, ctx, ASE_MT);
7db13fae 5254 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
9c2149c8 5255 rn = "VPEOpt";
ead9360e 5256 break;
9c2149c8
TS
5257 default:
5258 goto die;
5259 }
5260 break;
5261 case 2:
5262 switch (sel) {
5263 case 0:
7db13fae 5264 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
2423f660
TS
5265 rn = "EntryLo0";
5266 break;
9c2149c8 5267 case 1:
7385ac0b 5268 check_insn(env, ctx, ASE_MT);
895c2d04 5269 gen_helper_mfc0_tcstatus(arg, cpu_env);
2423f660 5270 rn = "TCStatus";
ead9360e 5271 break;
9c2149c8 5272 case 2:
7385ac0b 5273 check_insn(env, ctx, ASE_MT);
895c2d04 5274 gen_helper_mfc0_tcbind(arg, cpu_env);
2423f660 5275 rn = "TCBind";
ead9360e 5276 break;
9c2149c8 5277 case 3:
7385ac0b 5278 check_insn(env, ctx, ASE_MT);
895c2d04 5279 gen_helper_dmfc0_tcrestart(arg, cpu_env);
2423f660 5280 rn = "TCRestart";
ead9360e 5281 break;
9c2149c8 5282 case 4:
7385ac0b 5283 check_insn(env, ctx, ASE_MT);
895c2d04 5284 gen_helper_dmfc0_tchalt(arg, cpu_env);
2423f660 5285 rn = "TCHalt";
ead9360e 5286 break;
9c2149c8 5287 case 5:
7385ac0b 5288 check_insn(env, ctx, ASE_MT);
895c2d04 5289 gen_helper_dmfc0_tccontext(arg, cpu_env);
2423f660 5290 rn = "TCContext";
ead9360e 5291 break;
9c2149c8 5292 case 6:
7385ac0b 5293 check_insn(env, ctx, ASE_MT);
895c2d04 5294 gen_helper_dmfc0_tcschedule(arg, cpu_env);
2423f660 5295 rn = "TCSchedule";
ead9360e 5296 break;
9c2149c8 5297 case 7:
7385ac0b 5298 check_insn(env, ctx, ASE_MT);
895c2d04 5299 gen_helper_dmfc0_tcschefback(arg, cpu_env);
2423f660 5300 rn = "TCScheFBack";
ead9360e 5301 break;
9c2149c8
TS
5302 default:
5303 goto die;
5304 }
5305 break;
5306 case 3:
5307 switch (sel) {
5308 case 0:
7db13fae 5309 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
2423f660
TS
5310 rn = "EntryLo1";
5311 break;
9c2149c8
TS
5312 default:
5313 goto die;
1579a72e 5314 }
9c2149c8
TS
5315 break;
5316 case 4:
5317 switch (sel) {
5318 case 0:
7db13fae 5319 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
2423f660
TS
5320 rn = "Context";
5321 break;
9c2149c8 5322 case 1:
d9bea114 5323// gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
2423f660
TS
5324 rn = "ContextConfig";
5325// break;
9c2149c8
TS
5326 default:
5327 goto die;
876d4b07 5328 }
9c2149c8
TS
5329 break;
5330 case 5:
5331 switch (sel) {
5332 case 0:
7db13fae 5333 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
2423f660
TS
5334 rn = "PageMask";
5335 break;
9c2149c8 5336 case 1:
e189e748 5337 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5338 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
2423f660
TS
5339 rn = "PageGrain";
5340 break;
9c2149c8
TS
5341 default:
5342 goto die;
876d4b07 5343 }
9c2149c8
TS
5344 break;
5345 case 6:
5346 switch (sel) {
5347 case 0:
7db13fae 5348 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
2423f660
TS
5349 rn = "Wired";
5350 break;
9c2149c8 5351 case 1:
e189e748 5352 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5353 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
2423f660 5354 rn = "SRSConf0";
ead9360e 5355 break;
9c2149c8 5356 case 2:
e189e748 5357 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5358 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
2423f660 5359 rn = "SRSConf1";
ead9360e 5360 break;
9c2149c8 5361 case 3:
e189e748 5362 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5363 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
2423f660 5364 rn = "SRSConf2";
ead9360e 5365 break;
9c2149c8 5366 case 4:
e189e748 5367 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5368 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
2423f660 5369 rn = "SRSConf3";
ead9360e 5370 break;
9c2149c8 5371 case 5:
e189e748 5372 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5373 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
2423f660 5374 rn = "SRSConf4";
ead9360e 5375 break;
9c2149c8
TS
5376 default:
5377 goto die;
876d4b07 5378 }
9c2149c8
TS
5379 break;
5380 case 7:
5381 switch (sel) {
5382 case 0:
e189e748 5383 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5384 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
2423f660
TS
5385 rn = "HWREna";
5386 break;
9c2149c8
TS
5387 default:
5388 goto die;
876d4b07 5389 }
9c2149c8
TS
5390 break;
5391 case 8:
5392 switch (sel) {
5393 case 0:
7db13fae 5394 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
f0b3f3ae 5395 rn = "BadVAddr";
2423f660 5396 break;
9c2149c8
TS
5397 default:
5398 goto die;
876d4b07 5399 }
9c2149c8
TS
5400 break;
5401 case 9:
5402 switch (sel) {
5403 case 0:
2e70f6ef
PB
5404 /* Mark as an IO operation because we read the time. */
5405 if (use_icount)
5406 gen_io_start();
895c2d04 5407 gen_helper_mfc0_count(arg, cpu_env);
2e70f6ef
PB
5408 if (use_icount) {
5409 gen_io_end();
2e70f6ef 5410 }
55807224
EI
5411 /* Break the TB to be able to take timer interrupts immediately
5412 after reading count. */
5413 ctx->bstate = BS_STOP;
2423f660
TS
5414 rn = "Count";
5415 break;
5416 /* 6,7 are implementation dependent */
9c2149c8
TS
5417 default:
5418 goto die;
876d4b07 5419 }
9c2149c8
TS
5420 break;
5421 case 10:
5422 switch (sel) {
5423 case 0:
7db13fae 5424 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
2423f660
TS
5425 rn = "EntryHi";
5426 break;
9c2149c8
TS
5427 default:
5428 goto die;
876d4b07 5429 }
9c2149c8
TS
5430 break;
5431 case 11:
5432 switch (sel) {
5433 case 0:
7db13fae 5434 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
2423f660
TS
5435 rn = "Compare";
5436 break;
876d4b07 5437 /* 6,7 are implementation dependent */
9c2149c8
TS
5438 default:
5439 goto die;
876d4b07 5440 }
9c2149c8
TS
5441 break;
5442 case 12:
5443 switch (sel) {
5444 case 0:
7db13fae 5445 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
2423f660
TS
5446 rn = "Status";
5447 break;
9c2149c8 5448 case 1:
e189e748 5449 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5450 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
2423f660
TS
5451 rn = "IntCtl";
5452 break;
9c2149c8 5453 case 2:
e189e748 5454 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5455 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
2423f660
TS
5456 rn = "SRSCtl";
5457 break;
9c2149c8 5458 case 3:
e189e748 5459 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5460 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
2423f660
TS
5461 rn = "SRSMap";
5462 break;
9c2149c8
TS
5463 default:
5464 goto die;
876d4b07 5465 }
9c2149c8
TS
5466 break;
5467 case 13:
5468 switch (sel) {
5469 case 0:
7db13fae 5470 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
2423f660
TS
5471 rn = "Cause";
5472 break;
9c2149c8
TS
5473 default:
5474 goto die;
876d4b07 5475 }
9c2149c8
TS
5476 break;
5477 case 14:
5478 switch (sel) {
5479 case 0:
7db13fae 5480 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
2423f660
TS
5481 rn = "EPC";
5482 break;
9c2149c8
TS
5483 default:
5484 goto die;
876d4b07 5485 }
9c2149c8
TS
5486 break;
5487 case 15:
5488 switch (sel) {
5489 case 0:
7db13fae 5490 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
2423f660
TS
5491 rn = "PRid";
5492 break;
9c2149c8 5493 case 1:
e189e748 5494 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5495 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
2423f660
TS
5496 rn = "EBase";
5497 break;
9c2149c8
TS
5498 default:
5499 goto die;
876d4b07 5500 }
9c2149c8
TS
5501 break;
5502 case 16:
5503 switch (sel) {
5504 case 0:
7db13fae 5505 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
9c2149c8
TS
5506 rn = "Config";
5507 break;
5508 case 1:
7db13fae 5509 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
9c2149c8
TS
5510 rn = "Config1";
5511 break;
5512 case 2:
7db13fae 5513 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
9c2149c8
TS
5514 rn = "Config2";
5515 break;
5516 case 3:
7db13fae 5517 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
9c2149c8
TS
5518 rn = "Config3";
5519 break;
5520 /* 6,7 are implementation dependent */
f0b3f3ae 5521 case 6:
7db13fae 5522 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
f0b3f3ae
TS
5523 rn = "Config6";
5524 break;
5525 case 7:
7db13fae 5526 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
f0b3f3ae
TS
5527 rn = "Config7";
5528 break;
9c2149c8
TS
5529 default:
5530 goto die;
5531 }
5532 break;
5533 case 17:
5534 switch (sel) {
5535 case 0:
895c2d04 5536 gen_helper_dmfc0_lladdr(arg, cpu_env);
2423f660
TS
5537 rn = "LLAddr";
5538 break;
9c2149c8
TS
5539 default:
5540 goto die;
5541 }
5542 break;
5543 case 18:
5544 switch (sel) {
fd88b6ab 5545 case 0 ... 7:
895c2d04 5546 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
2423f660
TS
5547 rn = "WatchLo";
5548 break;
9c2149c8
TS
5549 default:
5550 goto die;
5551 }
5552 break;
5553 case 19:
5554 switch (sel) {
fd88b6ab 5555 case 0 ... 7:
895c2d04 5556 gen_helper_1e0i(mfc0_watchhi, arg, sel);
2423f660
TS
5557 rn = "WatchHi";
5558 break;
9c2149c8
TS
5559 default:
5560 goto die;
5561 }
5562 break;
5563 case 20:
5564 switch (sel) {
5565 case 0:
e189e748 5566 check_insn(env, ctx, ISA_MIPS3);
7db13fae 5567 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
2423f660
TS
5568 rn = "XContext";
5569 break;
9c2149c8
TS
5570 default:
5571 goto die;
5572 }
5573 break;
5574 case 21:
5575 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5576 switch (sel) {
5577 case 0:
7db13fae 5578 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
2423f660
TS
5579 rn = "Framemask";
5580 break;
9c2149c8
TS
5581 default:
5582 goto die;
5583 }
5584 break;
5585 case 22:
d9bea114 5586 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
5587 rn = "'Diagnostic"; /* implementation dependent */
5588 break;
9c2149c8
TS
5589 case 23:
5590 switch (sel) {
5591 case 0:
895c2d04 5592 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
2423f660
TS
5593 rn = "Debug";
5594 break;
9c2149c8 5595 case 1:
895c2d04 5596// gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
2423f660
TS
5597 rn = "TraceControl";
5598// break;
9c2149c8 5599 case 2:
895c2d04 5600// gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
2423f660
TS
5601 rn = "TraceControl2";
5602// break;
9c2149c8 5603 case 3:
895c2d04 5604// gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
2423f660
TS
5605 rn = "UserTraceData";
5606// break;
9c2149c8 5607 case 4:
895c2d04 5608// gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
2423f660
TS
5609 rn = "TraceBPC";
5610// break;
9c2149c8
TS
5611 default:
5612 goto die;
5613 }
5614 break;
5615 case 24:
5616 switch (sel) {
5617 case 0:
f0b3f3ae 5618 /* EJTAG support */
7db13fae 5619 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
2423f660
TS
5620 rn = "DEPC";
5621 break;
9c2149c8
TS
5622 default:
5623 goto die;
5624 }
5625 break;
5626 case 25:
5627 switch (sel) {
5628 case 0:
7db13fae 5629 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
2423f660 5630 rn = "Performance0";
9c2149c8
TS
5631 break;
5632 case 1:
d9bea114 5633// gen_helper_dmfc0_performance1(arg);
2423f660
TS
5634 rn = "Performance1";
5635// break;
9c2149c8 5636 case 2:
d9bea114 5637// gen_helper_dmfc0_performance2(arg);
2423f660
TS
5638 rn = "Performance2";
5639// break;
9c2149c8 5640 case 3:
d9bea114 5641// gen_helper_dmfc0_performance3(arg);
2423f660
TS
5642 rn = "Performance3";
5643// break;
9c2149c8 5644 case 4:
d9bea114 5645// gen_helper_dmfc0_performance4(arg);
2423f660
TS
5646 rn = "Performance4";
5647// break;
9c2149c8 5648 case 5:
d9bea114 5649// gen_helper_dmfc0_performance5(arg);
2423f660
TS
5650 rn = "Performance5";
5651// break;
9c2149c8 5652 case 6:
d9bea114 5653// gen_helper_dmfc0_performance6(arg);
2423f660
TS
5654 rn = "Performance6";
5655// break;
9c2149c8 5656 case 7:
d9bea114 5657// gen_helper_dmfc0_performance7(arg);
2423f660
TS
5658 rn = "Performance7";
5659// break;
9c2149c8
TS
5660 default:
5661 goto die;
5662 }
5663 break;
5664 case 26:
d9bea114 5665 tcg_gen_movi_tl(arg, 0); /* unimplemented */
da80682b
AJ
5666 rn = "ECC";
5667 break;
9c2149c8
TS
5668 case 27:
5669 switch (sel) {
5670 /* ignored */
5671 case 0 ... 3:
d9bea114 5672 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
5673 rn = "CacheErr";
5674 break;
9c2149c8
TS
5675 default:
5676 goto die;
5677 }
5678 break;
5679 case 28:
5680 switch (sel) {
5681 case 0:
5682 case 2:
5683 case 4:
5684 case 6:
7db13fae 5685 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
9c2149c8
TS
5686 rn = "TagLo";
5687 break;
5688 case 1:
5689 case 3:
5690 case 5:
5691 case 7:
7db13fae 5692 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
9c2149c8
TS
5693 rn = "DataLo";
5694 break;
5695 default:
5696 goto die;
5697 }
5698 break;
5699 case 29:
5700 switch (sel) {
5701 case 0:
5702 case 2:
5703 case 4:
5704 case 6:
7db13fae 5705 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
9c2149c8
TS
5706 rn = "TagHi";
5707 break;
5708 case 1:
5709 case 3:
5710 case 5:
5711 case 7:
7db13fae 5712 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
9c2149c8
TS
5713 rn = "DataHi";
5714 break;
5715 default:
5716 goto die;
5717 }
5718 break;
5719 case 30:
5720 switch (sel) {
5721 case 0:
7db13fae 5722 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
2423f660
TS
5723 rn = "ErrorEPC";
5724 break;
9c2149c8
TS
5725 default:
5726 goto die;
5727 }
5728 break;
5729 case 31:
5730 switch (sel) {
5731 case 0:
f0b3f3ae 5732 /* EJTAG support */
7db13fae 5733 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
5734 rn = "DESAVE";
5735 break;
9c2149c8
TS
5736 default:
5737 goto die;
5738 }
5739 break;
5740 default:
876d4b07 5741 goto die;
9c2149c8 5742 }
2abf314d 5743 (void)rn; /* avoid a compiler warning */
d12d51d5 5744 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
5745 return;
5746
5747die:
d12d51d5 5748 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
5749 generate_exception(ctx, EXCP_RI);
5750}
5751
7db13fae 5752static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8
TS
5753{
5754 const char *rn = "invalid";
5755
e189e748
TS
5756 if (sel != 0)
5757 check_insn(env, ctx, ISA_MIPS64);
5758
2e70f6ef
PB
5759 if (use_icount)
5760 gen_io_start();
5761
9c2149c8
TS
5762 switch (reg) {
5763 case 0:
5764 switch (sel) {
5765 case 0:
895c2d04 5766 gen_helper_mtc0_index(cpu_env, arg);
9c2149c8
TS
5767 rn = "Index";
5768 break;
5769 case 1:
7385ac0b 5770 check_insn(env, ctx, ASE_MT);
895c2d04 5771 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
9c2149c8 5772 rn = "MVPControl";
ead9360e 5773 break;
9c2149c8 5774 case 2:
7385ac0b 5775 check_insn(env, ctx, ASE_MT);
ead9360e 5776 /* ignored */
9c2149c8 5777 rn = "MVPConf0";
ead9360e 5778 break;
9c2149c8 5779 case 3:
7385ac0b 5780 check_insn(env, ctx, ASE_MT);
ead9360e 5781 /* ignored */
9c2149c8 5782 rn = "MVPConf1";
ead9360e 5783 break;
9c2149c8
TS
5784 default:
5785 goto die;
5786 }
5787 break;
5788 case 1:
5789 switch (sel) {
5790 case 0:
2423f660 5791 /* ignored */
9c2149c8 5792 rn = "Random";
2423f660 5793 break;
9c2149c8 5794 case 1:
7385ac0b 5795 check_insn(env, ctx, ASE_MT);
895c2d04 5796 gen_helper_mtc0_vpecontrol(cpu_env, arg);
9c2149c8 5797 rn = "VPEControl";
ead9360e 5798 break;
9c2149c8 5799 case 2:
7385ac0b 5800 check_insn(env, ctx, ASE_MT);
895c2d04 5801 gen_helper_mtc0_vpeconf0(cpu_env, arg);
9c2149c8 5802 rn = "VPEConf0";
ead9360e 5803 break;
9c2149c8 5804 case 3:
7385ac0b 5805 check_insn(env, ctx, ASE_MT);
895c2d04 5806 gen_helper_mtc0_vpeconf1(cpu_env, arg);
9c2149c8 5807 rn = "VPEConf1";
ead9360e 5808 break;
9c2149c8 5809 case 4:
7385ac0b 5810 check_insn(env, ctx, ASE_MT);
895c2d04 5811 gen_helper_mtc0_yqmask(cpu_env, arg);
9c2149c8 5812 rn = "YQMask";
ead9360e 5813 break;
9c2149c8 5814 case 5:
7385ac0b 5815 check_insn(env, ctx, ASE_MT);
7db13fae 5816 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
9c2149c8 5817 rn = "VPESchedule";
ead9360e 5818 break;
9c2149c8 5819 case 6:
7385ac0b 5820 check_insn(env, ctx, ASE_MT);
7db13fae 5821 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
9c2149c8 5822 rn = "VPEScheFBack";
ead9360e 5823 break;
9c2149c8 5824 case 7:
7385ac0b 5825 check_insn(env, ctx, ASE_MT);
895c2d04 5826 gen_helper_mtc0_vpeopt(cpu_env, arg);
9c2149c8 5827 rn = "VPEOpt";
ead9360e 5828 break;
9c2149c8
TS
5829 default:
5830 goto die;
5831 }
5832 break;
5833 case 2:
5834 switch (sel) {
5835 case 0:
895c2d04 5836 gen_helper_mtc0_entrylo0(cpu_env, arg);
2423f660
TS
5837 rn = "EntryLo0";
5838 break;
9c2149c8 5839 case 1:
7385ac0b 5840 check_insn(env, ctx, ASE_MT);
895c2d04 5841 gen_helper_mtc0_tcstatus(cpu_env, arg);
2423f660 5842 rn = "TCStatus";
ead9360e 5843 break;
9c2149c8 5844 case 2:
7385ac0b 5845 check_insn(env, ctx, ASE_MT);
895c2d04 5846 gen_helper_mtc0_tcbind(cpu_env, arg);
2423f660 5847 rn = "TCBind";
ead9360e 5848 break;
9c2149c8 5849 case 3:
7385ac0b 5850 check_insn(env, ctx, ASE_MT);
895c2d04 5851 gen_helper_mtc0_tcrestart(cpu_env, arg);
2423f660 5852 rn = "TCRestart";
ead9360e 5853 break;
9c2149c8 5854 case 4:
7385ac0b 5855 check_insn(env, ctx, ASE_MT);
895c2d04 5856 gen_helper_mtc0_tchalt(cpu_env, arg);
2423f660 5857 rn = "TCHalt";
ead9360e 5858 break;
9c2149c8 5859 case 5:
7385ac0b 5860 check_insn(env, ctx, ASE_MT);
895c2d04 5861 gen_helper_mtc0_tccontext(cpu_env, arg);
2423f660 5862 rn = "TCContext";
ead9360e 5863 break;
9c2149c8 5864 case 6:
7385ac0b 5865 check_insn(env, ctx, ASE_MT);
895c2d04 5866 gen_helper_mtc0_tcschedule(cpu_env, arg);
2423f660 5867 rn = "TCSchedule";
ead9360e 5868 break;
9c2149c8 5869 case 7:
7385ac0b 5870 check_insn(env, ctx, ASE_MT);
895c2d04 5871 gen_helper_mtc0_tcschefback(cpu_env, arg);
2423f660 5872 rn = "TCScheFBack";
ead9360e 5873 break;
9c2149c8
TS
5874 default:
5875 goto die;
5876 }
5877 break;
5878 case 3:
5879 switch (sel) {
5880 case 0:
895c2d04 5881 gen_helper_mtc0_entrylo1(cpu_env, arg);
2423f660
TS
5882 rn = "EntryLo1";
5883 break;
9c2149c8
TS
5884 default:
5885 goto die;
876d4b07 5886 }
9c2149c8
TS
5887 break;
5888 case 4:
5889 switch (sel) {
5890 case 0:
895c2d04 5891 gen_helper_mtc0_context(cpu_env, arg);
2423f660
TS
5892 rn = "Context";
5893 break;
9c2149c8 5894 case 1:
895c2d04 5895// gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
2423f660
TS
5896 rn = "ContextConfig";
5897// break;
9c2149c8
TS
5898 default:
5899 goto die;
876d4b07 5900 }
9c2149c8
TS
5901 break;
5902 case 5:
5903 switch (sel) {
5904 case 0:
895c2d04 5905 gen_helper_mtc0_pagemask(cpu_env, arg);
2423f660
TS
5906 rn = "PageMask";
5907 break;
9c2149c8 5908 case 1:
e189e748 5909 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5910 gen_helper_mtc0_pagegrain(cpu_env, arg);
2423f660
TS
5911 rn = "PageGrain";
5912 break;
9c2149c8
TS
5913 default:
5914 goto die;
876d4b07 5915 }
9c2149c8
TS
5916 break;
5917 case 6:
5918 switch (sel) {
5919 case 0:
895c2d04 5920 gen_helper_mtc0_wired(cpu_env, arg);
2423f660
TS
5921 rn = "Wired";
5922 break;
9c2149c8 5923 case 1:
e189e748 5924 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5925 gen_helper_mtc0_srsconf0(cpu_env, arg);
2423f660 5926 rn = "SRSConf0";
ead9360e 5927 break;
9c2149c8 5928 case 2:
e189e748 5929 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5930 gen_helper_mtc0_srsconf1(cpu_env, arg);
2423f660 5931 rn = "SRSConf1";
ead9360e 5932 break;
9c2149c8 5933 case 3:
e189e748 5934 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5935 gen_helper_mtc0_srsconf2(cpu_env, arg);
2423f660 5936 rn = "SRSConf2";
ead9360e 5937 break;
9c2149c8 5938 case 4:
e189e748 5939 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5940 gen_helper_mtc0_srsconf3(cpu_env, arg);
2423f660 5941 rn = "SRSConf3";
ead9360e 5942 break;
9c2149c8 5943 case 5:
e189e748 5944 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5945 gen_helper_mtc0_srsconf4(cpu_env, arg);
2423f660 5946 rn = "SRSConf4";
ead9360e 5947 break;
9c2149c8
TS
5948 default:
5949 goto die;
876d4b07 5950 }
9c2149c8
TS
5951 break;
5952 case 7:
5953 switch (sel) {
5954 case 0:
e189e748 5955 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5956 gen_helper_mtc0_hwrena(cpu_env, arg);
2423f660
TS
5957 rn = "HWREna";
5958 break;
9c2149c8
TS
5959 default:
5960 goto die;
876d4b07 5961 }
9c2149c8
TS
5962 break;
5963 case 8:
5964 /* ignored */
f0b3f3ae 5965 rn = "BadVAddr";
9c2149c8
TS
5966 break;
5967 case 9:
5968 switch (sel) {
5969 case 0:
895c2d04 5970 gen_helper_mtc0_count(cpu_env, arg);
2423f660
TS
5971 rn = "Count";
5972 break;
876d4b07 5973 /* 6,7 are implementation dependent */
9c2149c8
TS
5974 default:
5975 goto die;
876d4b07
TS
5976 }
5977 /* Stop translation as we may have switched the execution mode */
5978 ctx->bstate = BS_STOP;
9c2149c8
TS
5979 break;
5980 case 10:
5981 switch (sel) {
5982 case 0:
895c2d04 5983 gen_helper_mtc0_entryhi(cpu_env, arg);
2423f660
TS
5984 rn = "EntryHi";
5985 break;
9c2149c8
TS
5986 default:
5987 goto die;
876d4b07 5988 }
9c2149c8
TS
5989 break;
5990 case 11:
5991 switch (sel) {
5992 case 0:
895c2d04 5993 gen_helper_mtc0_compare(cpu_env, arg);
2423f660
TS
5994 rn = "Compare";
5995 break;
876d4b07 5996 /* 6,7 are implementation dependent */
9c2149c8
TS
5997 default:
5998 goto die;
876d4b07 5999 }
de9a95f0
AJ
6000 /* Stop translation as we may have switched the execution mode */
6001 ctx->bstate = BS_STOP;
9c2149c8
TS
6002 break;
6003 case 12:
6004 switch (sel) {
6005 case 0:
867abc7e 6006 save_cpu_state(ctx, 1);
895c2d04 6007 gen_helper_mtc0_status(cpu_env, arg);
8487327a
TS
6008 /* BS_STOP isn't good enough here, hflags may have changed. */
6009 gen_save_pc(ctx->pc + 4);
6010 ctx->bstate = BS_EXCP;
2423f660
TS
6011 rn = "Status";
6012 break;
9c2149c8 6013 case 1:
e189e748 6014 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 6015 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a
TS
6016 /* Stop translation as we may have switched the execution mode */
6017 ctx->bstate = BS_STOP;
2423f660
TS
6018 rn = "IntCtl";
6019 break;
9c2149c8 6020 case 2:
e189e748 6021 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 6022 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a
TS
6023 /* Stop translation as we may have switched the execution mode */
6024 ctx->bstate = BS_STOP;
2423f660
TS
6025 rn = "SRSCtl";
6026 break;
9c2149c8 6027 case 3:
e189e748 6028 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 6029 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a
TS
6030 /* Stop translation as we may have switched the execution mode */
6031 ctx->bstate = BS_STOP;
2423f660
TS
6032 rn = "SRSMap";
6033 break;
6034 default:
9c2149c8 6035 goto die;
876d4b07 6036 }
9c2149c8
TS
6037 break;
6038 case 13:
6039 switch (sel) {
6040 case 0:
867abc7e 6041 save_cpu_state(ctx, 1);
5dc5d9f0
AJ
6042 /* Mark as an IO operation because we may trigger a software
6043 interrupt. */
6044 if (use_icount) {
6045 gen_io_start();
6046 }
895c2d04 6047 gen_helper_mtc0_cause(cpu_env, arg);
5dc5d9f0
AJ
6048 if (use_icount) {
6049 gen_io_end();
6050 }
6051 /* Stop translation as we may have triggered an intetrupt */
6052 ctx->bstate = BS_STOP;
2423f660
TS
6053 rn = "Cause";
6054 break;
9c2149c8
TS
6055 default:
6056 goto die;
876d4b07 6057 }
9c2149c8
TS
6058 break;
6059 case 14:
6060 switch (sel) {
6061 case 0:
7db13fae 6062 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
2423f660
TS
6063 rn = "EPC";
6064 break;
9c2149c8
TS
6065 default:
6066 goto die;
876d4b07 6067 }
9c2149c8
TS
6068 break;
6069 case 15:
6070 switch (sel) {
6071 case 0:
2423f660
TS
6072 /* ignored */
6073 rn = "PRid";
6074 break;
9c2149c8 6075 case 1:
e189e748 6076 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 6077 gen_helper_mtc0_ebase(cpu_env, arg);
2423f660
TS
6078 rn = "EBase";
6079 break;
9c2149c8
TS
6080 default:
6081 goto die;
876d4b07 6082 }
9c2149c8
TS
6083 break;
6084 case 16:
6085 switch (sel) {
6086 case 0:
895c2d04 6087 gen_helper_mtc0_config0(cpu_env, arg);
9c2149c8 6088 rn = "Config";
2423f660
TS
6089 /* Stop translation as we may have switched the execution mode */
6090 ctx->bstate = BS_STOP;
9c2149c8
TS
6091 break;
6092 case 1:
1fc7bf6e 6093 /* ignored, read only */
9c2149c8
TS
6094 rn = "Config1";
6095 break;
6096 case 2:
895c2d04 6097 gen_helper_mtc0_config2(cpu_env, arg);
9c2149c8 6098 rn = "Config2";
2423f660
TS
6099 /* Stop translation as we may have switched the execution mode */
6100 ctx->bstate = BS_STOP;
9c2149c8
TS
6101 break;
6102 case 3:
2423f660 6103 /* ignored */
9c2149c8
TS
6104 rn = "Config3";
6105 break;
6106 /* 6,7 are implementation dependent */
6107 default:
6108 rn = "Invalid config selector";
6109 goto die;
6110 }
9c2149c8
TS
6111 break;
6112 case 17:
6113 switch (sel) {
6114 case 0:
895c2d04 6115 gen_helper_mtc0_lladdr(cpu_env, arg);
2423f660
TS
6116 rn = "LLAddr";
6117 break;
9c2149c8
TS
6118 default:
6119 goto die;
6120 }
6121 break;
6122 case 18:
6123 switch (sel) {
fd88b6ab 6124 case 0 ... 7:
895c2d04 6125 gen_helper_0e1i(mtc0_watchlo, arg, sel);
2423f660
TS
6126 rn = "WatchLo";
6127 break;
9c2149c8
TS
6128 default:
6129 goto die;
6130 }
6131 break;
6132 case 19:
6133 switch (sel) {
fd88b6ab 6134 case 0 ... 7:
895c2d04 6135 gen_helper_0e1i(mtc0_watchhi, arg, sel);
2423f660
TS
6136 rn = "WatchHi";
6137 break;
9c2149c8
TS
6138 default:
6139 goto die;
6140 }
6141 break;
6142 case 20:
6143 switch (sel) {
6144 case 0:
e189e748 6145 check_insn(env, ctx, ISA_MIPS3);
895c2d04 6146 gen_helper_mtc0_xcontext(cpu_env, arg);
2423f660
TS
6147 rn = "XContext";
6148 break;
9c2149c8
TS
6149 default:
6150 goto die;
6151 }
6152 break;
6153 case 21:
6154 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6155 switch (sel) {
6156 case 0:
895c2d04 6157 gen_helper_mtc0_framemask(cpu_env, arg);
2423f660
TS
6158 rn = "Framemask";
6159 break;
9c2149c8
TS
6160 default:
6161 goto die;
6162 }
6163 break;
6164 case 22:
6165 /* ignored */
6166 rn = "Diagnostic"; /* implementation dependent */
876d4b07 6167 break;
9c2149c8
TS
6168 case 23:
6169 switch (sel) {
6170 case 0:
895c2d04 6171 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8487327a
TS
6172 /* BS_STOP isn't good enough here, hflags may have changed. */
6173 gen_save_pc(ctx->pc + 4);
6174 ctx->bstate = BS_EXCP;
2423f660
TS
6175 rn = "Debug";
6176 break;
9c2149c8 6177 case 1:
895c2d04 6178// gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
8487327a
TS
6179 /* Stop translation as we may have switched the execution mode */
6180 ctx->bstate = BS_STOP;
2423f660
TS
6181 rn = "TraceControl";
6182// break;
9c2149c8 6183 case 2:
895c2d04 6184// gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
8487327a
TS
6185 /* Stop translation as we may have switched the execution mode */
6186 ctx->bstate = BS_STOP;
2423f660
TS
6187 rn = "TraceControl2";
6188// break;
9c2149c8 6189 case 3:
895c2d04 6190// gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
8487327a
TS
6191 /* Stop translation as we may have switched the execution mode */
6192 ctx->bstate = BS_STOP;
2423f660
TS
6193 rn = "UserTraceData";
6194// break;
9c2149c8 6195 case 4:
895c2d04 6196// gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
8487327a
TS
6197 /* Stop translation as we may have switched the execution mode */
6198 ctx->bstate = BS_STOP;
2423f660
TS
6199 rn = "TraceBPC";
6200// break;
9c2149c8
TS
6201 default:
6202 goto die;
6203 }
9c2149c8
TS
6204 break;
6205 case 24:
6206 switch (sel) {
6207 case 0:
f1aa6320 6208 /* EJTAG support */
7db13fae 6209 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
2423f660
TS
6210 rn = "DEPC";
6211 break;
9c2149c8
TS
6212 default:
6213 goto die;
6214 }
6215 break;
6216 case 25:
6217 switch (sel) {
6218 case 0:
895c2d04 6219 gen_helper_mtc0_performance0(cpu_env, arg);
2423f660
TS
6220 rn = "Performance0";
6221 break;
9c2149c8 6222 case 1:
895c2d04 6223// gen_helper_mtc0_performance1(cpu_env, arg);
2423f660
TS
6224 rn = "Performance1";
6225// break;
9c2149c8 6226 case 2:
895c2d04 6227// gen_helper_mtc0_performance2(cpu_env, arg);
2423f660
TS
6228 rn = "Performance2";
6229// break;
9c2149c8 6230 case 3:
895c2d04 6231// gen_helper_mtc0_performance3(cpu_env, arg);
2423f660
TS
6232 rn = "Performance3";
6233// break;
9c2149c8 6234 case 4:
895c2d04 6235// gen_helper_mtc0_performance4(cpu_env, arg);
2423f660
TS
6236 rn = "Performance4";
6237// break;
9c2149c8 6238 case 5:
895c2d04 6239// gen_helper_mtc0_performance5(cpu_env, arg);
2423f660
TS
6240 rn = "Performance5";
6241// break;
9c2149c8 6242 case 6:
895c2d04 6243// gen_helper_mtc0_performance6(cpu_env, arg);
2423f660
TS
6244 rn = "Performance6";
6245// break;
9c2149c8 6246 case 7:
895c2d04 6247// gen_helper_mtc0_performance7(cpu_env, arg);
2423f660
TS
6248 rn = "Performance7";
6249// break;
9c2149c8
TS
6250 default:
6251 goto die;
6252 }
876d4b07 6253 break;
9c2149c8 6254 case 26:
876d4b07 6255 /* ignored */
9c2149c8 6256 rn = "ECC";
876d4b07 6257 break;
9c2149c8
TS
6258 case 27:
6259 switch (sel) {
6260 case 0 ... 3:
2423f660
TS
6261 /* ignored */
6262 rn = "CacheErr";
6263 break;
9c2149c8
TS
6264 default:
6265 goto die;
6266 }
876d4b07 6267 break;
9c2149c8
TS
6268 case 28:
6269 switch (sel) {
6270 case 0:
6271 case 2:
6272 case 4:
6273 case 6:
895c2d04 6274 gen_helper_mtc0_taglo(cpu_env, arg);
9c2149c8
TS
6275 rn = "TagLo";
6276 break;
6277 case 1:
6278 case 3:
6279 case 5:
6280 case 7:
895c2d04 6281 gen_helper_mtc0_datalo(cpu_env, arg);
9c2149c8
TS
6282 rn = "DataLo";
6283 break;
6284 default:
6285 goto die;
6286 }
6287 break;
6288 case 29:
6289 switch (sel) {
6290 case 0:
6291 case 2:
6292 case 4:
6293 case 6:
895c2d04 6294 gen_helper_mtc0_taghi(cpu_env, arg);
9c2149c8
TS
6295 rn = "TagHi";
6296 break;
6297 case 1:
6298 case 3:
6299 case 5:
6300 case 7:
895c2d04 6301 gen_helper_mtc0_datahi(cpu_env, arg);
9c2149c8
TS
6302 rn = "DataHi";
6303 break;
6304 default:
6305 rn = "invalid sel";
6306 goto die;
6307 }
876d4b07 6308 break;
9c2149c8
TS
6309 case 30:
6310 switch (sel) {
6311 case 0:
7db13fae 6312 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
2423f660
TS
6313 rn = "ErrorEPC";
6314 break;
9c2149c8
TS
6315 default:
6316 goto die;
6317 }
6318 break;
6319 case 31:
6320 switch (sel) {
6321 case 0:
f1aa6320 6322 /* EJTAG support */
7db13fae 6323 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
6324 rn = "DESAVE";
6325 break;
9c2149c8
TS
6326 default:
6327 goto die;
6328 }
876d4b07
TS
6329 /* Stop translation as we may have switched the execution mode */
6330 ctx->bstate = BS_STOP;
9c2149c8
TS
6331 break;
6332 default:
876d4b07 6333 goto die;
9c2149c8 6334 }
2abf314d 6335 (void)rn; /* avoid a compiler warning */
d12d51d5 6336 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
bf20dc07 6337 /* For simplicity assume that all writes can cause interrupts. */
2e70f6ef
PB
6338 if (use_icount) {
6339 gen_io_end();
6340 ctx->bstate = BS_STOP;
6341 }
9c2149c8
TS
6342 return;
6343
6344die:
d12d51d5 6345 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
6346 generate_exception(ctx, EXCP_RI);
6347}
d26bc211 6348#endif /* TARGET_MIPS64 */
9c2149c8 6349
7db13fae 6350static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
ead9360e
TS
6351 int u, int sel, int h)
6352{
6353 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 6354 TCGv t0 = tcg_temp_local_new();
ead9360e
TS
6355
6356 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
6357 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
6358 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
1a3fd9c3 6359 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
6360 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
6361 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
1a3fd9c3 6362 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
6363 else if (u == 0) {
6364 switch (rt) {
5a25ce94
EI
6365 case 1:
6366 switch (sel) {
6367 case 1:
895c2d04 6368 gen_helper_mftc0_vpecontrol(t0, cpu_env);
5a25ce94
EI
6369 break;
6370 case 2:
895c2d04 6371 gen_helper_mftc0_vpeconf0(t0, cpu_env);
5a25ce94
EI
6372 break;
6373 default:
6374 goto die;
6375 break;
6376 }
6377 break;
ead9360e
TS
6378 case 2:
6379 switch (sel) {
6380 case 1:
895c2d04 6381 gen_helper_mftc0_tcstatus(t0, cpu_env);
ead9360e
TS
6382 break;
6383 case 2:
895c2d04 6384 gen_helper_mftc0_tcbind(t0, cpu_env);
ead9360e
TS
6385 break;
6386 case 3:
895c2d04 6387 gen_helper_mftc0_tcrestart(t0, cpu_env);
ead9360e
TS
6388 break;
6389 case 4:
895c2d04 6390 gen_helper_mftc0_tchalt(t0, cpu_env);
ead9360e
TS
6391 break;
6392 case 5:
895c2d04 6393 gen_helper_mftc0_tccontext(t0, cpu_env);
ead9360e
TS
6394 break;
6395 case 6:
895c2d04 6396 gen_helper_mftc0_tcschedule(t0, cpu_env);
ead9360e
TS
6397 break;
6398 case 7:
895c2d04 6399 gen_helper_mftc0_tcschefback(t0, cpu_env);
ead9360e
TS
6400 break;
6401 default:
1a3fd9c3 6402 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
6403 break;
6404 }
6405 break;
6406 case 10:
6407 switch (sel) {
6408 case 0:
895c2d04 6409 gen_helper_mftc0_entryhi(t0, cpu_env);
ead9360e
TS
6410 break;
6411 default:
1a3fd9c3 6412 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
6413 break;
6414 }
6415 case 12:
6416 switch (sel) {
6417 case 0:
895c2d04 6418 gen_helper_mftc0_status(t0, cpu_env);
ead9360e
TS
6419 break;
6420 default:
1a3fd9c3 6421 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
6422 break;
6423 }
5a25ce94
EI
6424 case 13:
6425 switch (sel) {
6426 case 0:
895c2d04 6427 gen_helper_mftc0_cause(t0, cpu_env);
5a25ce94
EI
6428 break;
6429 default:
6430 goto die;
6431 break;
6432 }
6433 break;
6434 case 14:
6435 switch (sel) {
6436 case 0:
895c2d04 6437 gen_helper_mftc0_epc(t0, cpu_env);
5a25ce94
EI
6438 break;
6439 default:
6440 goto die;
6441 break;
6442 }
6443 break;
6444 case 15:
6445 switch (sel) {
6446 case 1:
895c2d04 6447 gen_helper_mftc0_ebase(t0, cpu_env);
5a25ce94
EI
6448 break;
6449 default:
6450 goto die;
6451 break;
6452 }
6453 break;
6454 case 16:
6455 switch (sel) {
6456 case 0 ... 7:
895c2d04 6457 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
5a25ce94
EI
6458 break;
6459 default:
6460 goto die;
6461 break;
6462 }
6463 break;
ead9360e
TS
6464 case 23:
6465 switch (sel) {
6466 case 0:
895c2d04 6467 gen_helper_mftc0_debug(t0, cpu_env);
ead9360e
TS
6468 break;
6469 default:
1a3fd9c3 6470 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
6471 break;
6472 }
6473 break;
6474 default:
1a3fd9c3 6475 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
6476 }
6477 } else switch (sel) {
6478 /* GPR registers. */
6479 case 0:
895c2d04 6480 gen_helper_1e0i(mftgpr, t0, rt);
ead9360e
TS
6481 break;
6482 /* Auxiliary CPU registers */
6483 case 1:
6484 switch (rt) {
6485 case 0:
895c2d04 6486 gen_helper_1e0i(mftlo, t0, 0);
ead9360e
TS
6487 break;
6488 case 1:
895c2d04 6489 gen_helper_1e0i(mfthi, t0, 0);
ead9360e
TS
6490 break;
6491 case 2:
895c2d04 6492 gen_helper_1e0i(mftacx, t0, 0);
ead9360e
TS
6493 break;
6494 case 4:
895c2d04 6495 gen_helper_1e0i(mftlo, t0, 1);
ead9360e
TS
6496 break;
6497 case 5:
895c2d04 6498 gen_helper_1e0i(mfthi, t0, 1);
ead9360e
TS
6499 break;
6500 case 6:
895c2d04 6501 gen_helper_1e0i(mftacx, t0, 1);
ead9360e
TS
6502 break;
6503 case 8:
895c2d04 6504 gen_helper_1e0i(mftlo, t0, 2);
ead9360e
TS
6505 break;
6506 case 9:
895c2d04 6507 gen_helper_1e0i(mfthi, t0, 2);
ead9360e
TS
6508 break;
6509 case 10:
895c2d04 6510 gen_helper_1e0i(mftacx, t0, 2);
ead9360e
TS
6511 break;
6512 case 12:
895c2d04 6513 gen_helper_1e0i(mftlo, t0, 3);
ead9360e
TS
6514 break;
6515 case 13:
895c2d04 6516 gen_helper_1e0i(mfthi, t0, 3);
ead9360e
TS
6517 break;
6518 case 14:
895c2d04 6519 gen_helper_1e0i(mftacx, t0, 3);
ead9360e
TS
6520 break;
6521 case 16:
895c2d04 6522 gen_helper_mftdsp(t0, cpu_env);
ead9360e
TS
6523 break;
6524 default:
6525 goto die;
6526 }
6527 break;
6528 /* Floating point (COP1). */
6529 case 2:
6530 /* XXX: For now we support only a single FPU context. */
6531 if (h == 0) {
a7812ae4 6532 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6533
6534 gen_load_fpr32(fp0, rt);
6535 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 6536 tcg_temp_free_i32(fp0);
ead9360e 6537 } else {
a7812ae4 6538 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6539
6540 gen_load_fpr32h(fp0, rt);
6541 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 6542 tcg_temp_free_i32(fp0);
ead9360e
TS
6543 }
6544 break;
6545 case 3:
6546 /* XXX: For now we support only a single FPU context. */
895c2d04 6547 gen_helper_1e0i(cfc1, t0, rt);
ead9360e
TS
6548 break;
6549 /* COP2: Not implemented. */
6550 case 4:
6551 case 5:
6552 /* fall through */
6553 default:
6554 goto die;
6555 }
d12d51d5 6556 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
1a3fd9c3
TS
6557 gen_store_gpr(t0, rd);
6558 tcg_temp_free(t0);
ead9360e
TS
6559 return;
6560
6561die:
1a3fd9c3 6562 tcg_temp_free(t0);
d12d51d5 6563 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
ead9360e
TS
6564 generate_exception(ctx, EXCP_RI);
6565}
6566
7db13fae 6567static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
ead9360e
TS
6568 int u, int sel, int h)
6569{
6570 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 6571 TCGv t0 = tcg_temp_local_new();
ead9360e 6572
1a3fd9c3 6573 gen_load_gpr(t0, rt);
ead9360e 6574 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
6575 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
6576 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
ead9360e
TS
6577 /* NOP */ ;
6578 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
6579 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
6580 /* NOP */ ;
6581 else if (u == 0) {
6582 switch (rd) {
5a25ce94
EI
6583 case 1:
6584 switch (sel) {
6585 case 1:
895c2d04 6586 gen_helper_mttc0_vpecontrol(cpu_env, t0);
5a25ce94
EI
6587 break;
6588 case 2:
895c2d04 6589 gen_helper_mttc0_vpeconf0(cpu_env, t0);
5a25ce94
EI
6590 break;
6591 default:
6592 goto die;
6593 break;
6594 }
6595 break;
ead9360e
TS
6596 case 2:
6597 switch (sel) {
6598 case 1:
895c2d04 6599 gen_helper_mttc0_tcstatus(cpu_env, t0);
ead9360e
TS
6600 break;
6601 case 2:
895c2d04 6602 gen_helper_mttc0_tcbind(cpu_env, t0);
ead9360e
TS
6603 break;
6604 case 3:
895c2d04 6605 gen_helper_mttc0_tcrestart(cpu_env, t0);
ead9360e
TS
6606 break;
6607 case 4:
895c2d04 6608 gen_helper_mttc0_tchalt(cpu_env, t0);
ead9360e
TS
6609 break;
6610 case 5:
895c2d04 6611 gen_helper_mttc0_tccontext(cpu_env, t0);
ead9360e
TS
6612 break;
6613 case 6:
895c2d04 6614 gen_helper_mttc0_tcschedule(cpu_env, t0);
ead9360e
TS
6615 break;
6616 case 7:
895c2d04 6617 gen_helper_mttc0_tcschefback(cpu_env, t0);
ead9360e
TS
6618 break;
6619 default:
1a3fd9c3 6620 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
6621 break;
6622 }
6623 break;
6624 case 10:
6625 switch (sel) {
6626 case 0:
895c2d04 6627 gen_helper_mttc0_entryhi(cpu_env, t0);
ead9360e
TS
6628 break;
6629 default:
1a3fd9c3 6630 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
6631 break;
6632 }
6633 case 12:
6634 switch (sel) {
6635 case 0:
895c2d04 6636 gen_helper_mttc0_status(cpu_env, t0);
ead9360e
TS
6637 break;
6638 default:
1a3fd9c3 6639 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
6640 break;
6641 }
5a25ce94
EI
6642 case 13:
6643 switch (sel) {
6644 case 0:
895c2d04 6645 gen_helper_mttc0_cause(cpu_env, t0);
5a25ce94
EI
6646 break;
6647 default:
6648 goto die;
6649 break;
6650 }
6651 break;
6652 case 15:
6653 switch (sel) {
6654 case 1:
895c2d04 6655 gen_helper_mttc0_ebase(cpu_env, t0);
5a25ce94
EI
6656 break;
6657 default:
6658 goto die;
6659 break;
6660 }
6661 break;
ead9360e
TS
6662 case 23:
6663 switch (sel) {
6664 case 0:
895c2d04 6665 gen_helper_mttc0_debug(cpu_env, t0);
ead9360e
TS
6666 break;
6667 default:
1a3fd9c3 6668 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
6669 break;
6670 }
6671 break;
6672 default:
1a3fd9c3 6673 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
6674 }
6675 } else switch (sel) {
6676 /* GPR registers. */
6677 case 0:
895c2d04 6678 gen_helper_0e1i(mttgpr, t0, rd);
ead9360e
TS
6679 break;
6680 /* Auxiliary CPU registers */
6681 case 1:
6682 switch (rd) {
6683 case 0:
895c2d04 6684 gen_helper_0e1i(mttlo, t0, 0);
ead9360e
TS
6685 break;
6686 case 1:
895c2d04 6687 gen_helper_0e1i(mtthi, t0, 0);
ead9360e
TS
6688 break;
6689 case 2:
895c2d04 6690 gen_helper_0e1i(mttacx, t0, 0);
ead9360e
TS
6691 break;
6692 case 4:
895c2d04 6693 gen_helper_0e1i(mttlo, t0, 1);
ead9360e
TS
6694 break;
6695 case 5:
895c2d04 6696 gen_helper_0e1i(mtthi, t0, 1);
ead9360e
TS
6697 break;
6698 case 6:
895c2d04 6699 gen_helper_0e1i(mttacx, t0, 1);
ead9360e
TS
6700 break;
6701 case 8:
895c2d04 6702 gen_helper_0e1i(mttlo, t0, 2);
ead9360e
TS
6703 break;
6704 case 9:
895c2d04 6705 gen_helper_0e1i(mtthi, t0, 2);
ead9360e
TS
6706 break;
6707 case 10:
895c2d04 6708 gen_helper_0e1i(mttacx, t0, 2);
ead9360e
TS
6709 break;
6710 case 12:
895c2d04 6711 gen_helper_0e1i(mttlo, t0, 3);
ead9360e
TS
6712 break;
6713 case 13:
895c2d04 6714 gen_helper_0e1i(mtthi, t0, 3);
ead9360e
TS
6715 break;
6716 case 14:
895c2d04 6717 gen_helper_0e1i(mttacx, t0, 3);
ead9360e
TS
6718 break;
6719 case 16:
895c2d04 6720 gen_helper_mttdsp(cpu_env, t0);
ead9360e
TS
6721 break;
6722 default:
6723 goto die;
6724 }
6725 break;
6726 /* Floating point (COP1). */
6727 case 2:
6728 /* XXX: For now we support only a single FPU context. */
6729 if (h == 0) {
a7812ae4 6730 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6731
6732 tcg_gen_trunc_tl_i32(fp0, t0);
6733 gen_store_fpr32(fp0, rd);
a7812ae4 6734 tcg_temp_free_i32(fp0);
ead9360e 6735 } else {
a7812ae4 6736 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6737
6738 tcg_gen_trunc_tl_i32(fp0, t0);
6739 gen_store_fpr32h(fp0, rd);
a7812ae4 6740 tcg_temp_free_i32(fp0);
ead9360e
TS
6741 }
6742 break;
6743 case 3:
6744 /* XXX: For now we support only a single FPU context. */
895c2d04 6745 gen_helper_0e1i(ctc1, t0, rd);
ead9360e
TS
6746 break;
6747 /* COP2: Not implemented. */
6748 case 4:
6749 case 5:
6750 /* fall through */
6751 default:
6752 goto die;
6753 }
d12d51d5 6754 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
1a3fd9c3 6755 tcg_temp_free(t0);
ead9360e
TS
6756 return;
6757
6758die:
1a3fd9c3 6759 tcg_temp_free(t0);
d12d51d5 6760 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
ead9360e
TS
6761 generate_exception(ctx, EXCP_RI);
6762}
6763
7db13fae 6764static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
6af0bf9c 6765{
287c4b84 6766 const char *opn = "ldst";
6af0bf9c 6767
2e15497c 6768 check_cp0_enabled(ctx);
6af0bf9c
FB
6769 switch (opc) {
6770 case OPC_MFC0:
6771 if (rt == 0) {
ead9360e 6772 /* Treat as NOP. */
6af0bf9c
FB
6773 return;
6774 }
1fc7bf6e 6775 gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
6af0bf9c
FB
6776 opn = "mfc0";
6777 break;
6778 case OPC_MTC0:
1a3fd9c3 6779 {
1fc7bf6e 6780 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
6781
6782 gen_load_gpr(t0, rt);
1a3fd9c3
TS
6783 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
6784 tcg_temp_free(t0);
6785 }
6af0bf9c
FB
6786 opn = "mtc0";
6787 break;
d26bc211 6788#if defined(TARGET_MIPS64)
9c2149c8 6789 case OPC_DMFC0:
e189e748 6790 check_insn(env, ctx, ISA_MIPS3);
9c2149c8 6791 if (rt == 0) {
ead9360e 6792 /* Treat as NOP. */
9c2149c8
TS
6793 return;
6794 }
1fc7bf6e 6795 gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9c2149c8
TS
6796 opn = "dmfc0";
6797 break;
6798 case OPC_DMTC0:
e189e748 6799 check_insn(env, ctx, ISA_MIPS3);
1a3fd9c3 6800 {
1fc7bf6e 6801 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
6802
6803 gen_load_gpr(t0, rt);
1a3fd9c3
TS
6804 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
6805 tcg_temp_free(t0);
6806 }
9c2149c8
TS
6807 opn = "dmtc0";
6808 break;
534ce69f 6809#endif
ead9360e 6810 case OPC_MFTR:
7385ac0b 6811 check_insn(env, ctx, ASE_MT);
ead9360e
TS
6812 if (rd == 0) {
6813 /* Treat as NOP. */
6814 return;
6815 }
6c5c1e20 6816 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
ead9360e 6817 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
ead9360e
TS
6818 opn = "mftr";
6819 break;
6820 case OPC_MTTR:
7385ac0b 6821 check_insn(env, ctx, ASE_MT);
6c5c1e20 6822 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
ead9360e
TS
6823 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
6824 opn = "mttr";
6825 break;
6af0bf9c 6826 case OPC_TLBWI:
6af0bf9c 6827 opn = "tlbwi";
c01fccd2 6828 if (!env->tlb->helper_tlbwi)
29929e34 6829 goto die;
895c2d04 6830 gen_helper_tlbwi(cpu_env);
6af0bf9c
FB
6831 break;
6832 case OPC_TLBWR:
6af0bf9c 6833 opn = "tlbwr";
c01fccd2 6834 if (!env->tlb->helper_tlbwr)
29929e34 6835 goto die;
895c2d04 6836 gen_helper_tlbwr(cpu_env);
6af0bf9c
FB
6837 break;
6838 case OPC_TLBP:
6af0bf9c 6839 opn = "tlbp";
c01fccd2 6840 if (!env->tlb->helper_tlbp)
29929e34 6841 goto die;
895c2d04 6842 gen_helper_tlbp(cpu_env);
6af0bf9c
FB
6843 break;
6844 case OPC_TLBR:
6af0bf9c 6845 opn = "tlbr";
c01fccd2 6846 if (!env->tlb->helper_tlbr)
29929e34 6847 goto die;
895c2d04 6848 gen_helper_tlbr(cpu_env);
6af0bf9c 6849 break;
6af0bf9c
FB
6850 case OPC_ERET:
6851 opn = "eret";
e189e748 6852 check_insn(env, ctx, ISA_MIPS2);
895c2d04 6853 gen_helper_eret(cpu_env);
6af0bf9c
FB
6854 ctx->bstate = BS_EXCP;
6855 break;
6856 case OPC_DERET:
6857 opn = "deret";
e189e748 6858 check_insn(env, ctx, ISA_MIPS32);
6af0bf9c 6859 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
923617a3 6860 MIPS_INVAL(opn);
6af0bf9c
FB
6861 generate_exception(ctx, EXCP_RI);
6862 } else {
895c2d04 6863 gen_helper_deret(cpu_env);
6af0bf9c
FB
6864 ctx->bstate = BS_EXCP;
6865 }
6866 break;
4ad40f36
FB
6867 case OPC_WAIT:
6868 opn = "wait";
e189e748 6869 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
4ad40f36
FB
6870 /* If we get an exception, we want to restart at next instruction */
6871 ctx->pc += 4;
6872 save_cpu_state(ctx, 1);
6873 ctx->pc -= 4;
895c2d04 6874 gen_helper_wait(cpu_env);
4ad40f36
FB
6875 ctx->bstate = BS_EXCP;
6876 break;
6af0bf9c 6877 default:
29929e34 6878 die:
923617a3 6879 MIPS_INVAL(opn);
6af0bf9c
FB
6880 generate_exception(ctx, EXCP_RI);
6881 return;
6882 }
2abf314d 6883 (void)opn; /* avoid a compiler warning */
6af0bf9c
FB
6884 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
6885}
f1aa6320 6886#endif /* !CONFIG_USER_ONLY */
6af0bf9c 6887
6ea83fed 6888/* CP1 Branches (before delay slot) */
7db13fae 6889static void gen_compute_branch1 (CPUMIPSState *env, DisasContext *ctx, uint32_t op,
5a5012ec 6890 int32_t cc, int32_t offset)
6ea83fed
FB
6891{
6892 target_ulong btarget;
923617a3 6893 const char *opn = "cp1 cond branch";
a7812ae4 6894 TCGv_i32 t0 = tcg_temp_new_i32();
6ea83fed 6895
e189e748
TS
6896 if (cc != 0)
6897 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
6898
6ea83fed
FB
6899 btarget = ctx->pc + 4 + offset;
6900
7a387fff
TS
6901 switch (op) {
6902 case OPC_BC1F:
d94536f4
AJ
6903 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6904 tcg_gen_not_i32(t0, t0);
6905 tcg_gen_andi_i32(t0, t0, 1);
6906 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 6907 opn = "bc1f";
6ea83fed 6908 goto not_likely;
7a387fff 6909 case OPC_BC1FL:
d94536f4
AJ
6910 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6911 tcg_gen_not_i32(t0, t0);
6912 tcg_gen_andi_i32(t0, t0, 1);
6913 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 6914 opn = "bc1fl";
6ea83fed 6915 goto likely;
7a387fff 6916 case OPC_BC1T:
d94536f4
AJ
6917 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6918 tcg_gen_andi_i32(t0, t0, 1);
6919 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 6920 opn = "bc1t";
5a5012ec 6921 goto not_likely;
7a387fff 6922 case OPC_BC1TL:
d94536f4
AJ
6923 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6924 tcg_gen_andi_i32(t0, t0, 1);
6925 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 6926 opn = "bc1tl";
6ea83fed
FB
6927 likely:
6928 ctx->hflags |= MIPS_HFLAG_BL;
6929 break;
5a5012ec 6930 case OPC_BC1FANY2:
a16336e4 6931 {
d94536f4
AJ
6932 TCGv_i32 t1 = tcg_temp_new_i32();
6933 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6934 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
d7f66b52 6935 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 6936 tcg_temp_free_i32(t1);
d94536f4
AJ
6937 tcg_gen_andi_i32(t0, t0, 1);
6938 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 6939 }
fd4a04eb 6940 opn = "bc1any2f";
5a5012ec
TS
6941 goto not_likely;
6942 case OPC_BC1TANY2:
a16336e4 6943 {
d94536f4
AJ
6944 TCGv_i32 t1 = tcg_temp_new_i32();
6945 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6946 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6947 tcg_gen_or_i32(t0, t0, t1);
6948 tcg_temp_free_i32(t1);
6949 tcg_gen_andi_i32(t0, t0, 1);
6950 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 6951 }
fd4a04eb 6952 opn = "bc1any2t";
5a5012ec
TS
6953 goto not_likely;
6954 case OPC_BC1FANY4:
a16336e4 6955 {
d94536f4
AJ
6956 TCGv_i32 t1 = tcg_temp_new_i32();
6957 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6958 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
d7f66b52 6959 tcg_gen_and_i32(t0, t0, t1);
d94536f4 6960 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
d7f66b52 6961 tcg_gen_and_i32(t0, t0, t1);
d94536f4 6962 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
d7f66b52 6963 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 6964 tcg_temp_free_i32(t1);
d94536f4
AJ
6965 tcg_gen_andi_i32(t0, t0, 1);
6966 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 6967 }
fd4a04eb 6968 opn = "bc1any4f";
5a5012ec
TS
6969 goto not_likely;
6970 case OPC_BC1TANY4:
a16336e4 6971 {
d94536f4
AJ
6972 TCGv_i32 t1 = tcg_temp_new_i32();
6973 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6974 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6975 tcg_gen_or_i32(t0, t0, t1);
6976 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6977 tcg_gen_or_i32(t0, t0, t1);
6978 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
6979 tcg_gen_or_i32(t0, t0, t1);
6980 tcg_temp_free_i32(t1);
6981 tcg_gen_andi_i32(t0, t0, 1);
6982 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 6983 }
fd4a04eb 6984 opn = "bc1any4t";
5a5012ec
TS
6985 not_likely:
6986 ctx->hflags |= MIPS_HFLAG_BC;
5a5012ec
TS
6987 break;
6988 default:
923617a3 6989 MIPS_INVAL(opn);
e397ee33 6990 generate_exception (ctx, EXCP_RI);
6c5c1e20 6991 goto out;
6ea83fed 6992 }
2abf314d 6993 (void)opn; /* avoid a compiler warning */
923617a3 6994 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
6ea83fed
FB
6995 ctx->hflags, btarget);
6996 ctx->btarget = btarget;
6c5c1e20
TS
6997
6998 out:
a7812ae4 6999 tcg_temp_free_i32(t0);
6ea83fed
FB
7000}
7001
6af0bf9c 7002/* Coprocessor 1 (FPU) */
5a5012ec 7003
5a5012ec
TS
7004#define FOP(func, fmt) (((fmt) << 21) | (func))
7005
bf4120ad
NF
7006enum fopcode {
7007 OPC_ADD_S = FOP(0, FMT_S),
7008 OPC_SUB_S = FOP(1, FMT_S),
7009 OPC_MUL_S = FOP(2, FMT_S),
7010 OPC_DIV_S = FOP(3, FMT_S),
7011 OPC_SQRT_S = FOP(4, FMT_S),
7012 OPC_ABS_S = FOP(5, FMT_S),
7013 OPC_MOV_S = FOP(6, FMT_S),
7014 OPC_NEG_S = FOP(7, FMT_S),
7015 OPC_ROUND_L_S = FOP(8, FMT_S),
7016 OPC_TRUNC_L_S = FOP(9, FMT_S),
7017 OPC_CEIL_L_S = FOP(10, FMT_S),
7018 OPC_FLOOR_L_S = FOP(11, FMT_S),
7019 OPC_ROUND_W_S = FOP(12, FMT_S),
7020 OPC_TRUNC_W_S = FOP(13, FMT_S),
7021 OPC_CEIL_W_S = FOP(14, FMT_S),
7022 OPC_FLOOR_W_S = FOP(15, FMT_S),
7023 OPC_MOVCF_S = FOP(17, FMT_S),
7024 OPC_MOVZ_S = FOP(18, FMT_S),
7025 OPC_MOVN_S = FOP(19, FMT_S),
7026 OPC_RECIP_S = FOP(21, FMT_S),
7027 OPC_RSQRT_S = FOP(22, FMT_S),
7028 OPC_RECIP2_S = FOP(28, FMT_S),
7029 OPC_RECIP1_S = FOP(29, FMT_S),
7030 OPC_RSQRT1_S = FOP(30, FMT_S),
7031 OPC_RSQRT2_S = FOP(31, FMT_S),
7032 OPC_CVT_D_S = FOP(33, FMT_S),
7033 OPC_CVT_W_S = FOP(36, FMT_S),
7034 OPC_CVT_L_S = FOP(37, FMT_S),
7035 OPC_CVT_PS_S = FOP(38, FMT_S),
7036 OPC_CMP_F_S = FOP (48, FMT_S),
7037 OPC_CMP_UN_S = FOP (49, FMT_S),
7038 OPC_CMP_EQ_S = FOP (50, FMT_S),
7039 OPC_CMP_UEQ_S = FOP (51, FMT_S),
7040 OPC_CMP_OLT_S = FOP (52, FMT_S),
7041 OPC_CMP_ULT_S = FOP (53, FMT_S),
7042 OPC_CMP_OLE_S = FOP (54, FMT_S),
7043 OPC_CMP_ULE_S = FOP (55, FMT_S),
7044 OPC_CMP_SF_S = FOP (56, FMT_S),
7045 OPC_CMP_NGLE_S = FOP (57, FMT_S),
7046 OPC_CMP_SEQ_S = FOP (58, FMT_S),
7047 OPC_CMP_NGL_S = FOP (59, FMT_S),
7048 OPC_CMP_LT_S = FOP (60, FMT_S),
7049 OPC_CMP_NGE_S = FOP (61, FMT_S),
7050 OPC_CMP_LE_S = FOP (62, FMT_S),
7051 OPC_CMP_NGT_S = FOP (63, FMT_S),
7052
7053 OPC_ADD_D = FOP(0, FMT_D),
7054 OPC_SUB_D = FOP(1, FMT_D),
7055 OPC_MUL_D = FOP(2, FMT_D),
7056 OPC_DIV_D = FOP(3, FMT_D),
7057 OPC_SQRT_D = FOP(4, FMT_D),
7058 OPC_ABS_D = FOP(5, FMT_D),
7059 OPC_MOV_D = FOP(6, FMT_D),
7060 OPC_NEG_D = FOP(7, FMT_D),
7061 OPC_ROUND_L_D = FOP(8, FMT_D),
7062 OPC_TRUNC_L_D = FOP(9, FMT_D),
7063 OPC_CEIL_L_D = FOP(10, FMT_D),
7064 OPC_FLOOR_L_D = FOP(11, FMT_D),
7065 OPC_ROUND_W_D = FOP(12, FMT_D),
7066 OPC_TRUNC_W_D = FOP(13, FMT_D),
7067 OPC_CEIL_W_D = FOP(14, FMT_D),
7068 OPC_FLOOR_W_D = FOP(15, FMT_D),
7069 OPC_MOVCF_D = FOP(17, FMT_D),
7070 OPC_MOVZ_D = FOP(18, FMT_D),
7071 OPC_MOVN_D = FOP(19, FMT_D),
7072 OPC_RECIP_D = FOP(21, FMT_D),
7073 OPC_RSQRT_D = FOP(22, FMT_D),
7074 OPC_RECIP2_D = FOP(28, FMT_D),
7075 OPC_RECIP1_D = FOP(29, FMT_D),
7076 OPC_RSQRT1_D = FOP(30, FMT_D),
7077 OPC_RSQRT2_D = FOP(31, FMT_D),
7078 OPC_CVT_S_D = FOP(32, FMT_D),
7079 OPC_CVT_W_D = FOP(36, FMT_D),
7080 OPC_CVT_L_D = FOP(37, FMT_D),
7081 OPC_CMP_F_D = FOP (48, FMT_D),
7082 OPC_CMP_UN_D = FOP (49, FMT_D),
7083 OPC_CMP_EQ_D = FOP (50, FMT_D),
7084 OPC_CMP_UEQ_D = FOP (51, FMT_D),
7085 OPC_CMP_OLT_D = FOP (52, FMT_D),
7086 OPC_CMP_ULT_D = FOP (53, FMT_D),
7087 OPC_CMP_OLE_D = FOP (54, FMT_D),
7088 OPC_CMP_ULE_D = FOP (55, FMT_D),
7089 OPC_CMP_SF_D = FOP (56, FMT_D),
7090 OPC_CMP_NGLE_D = FOP (57, FMT_D),
7091 OPC_CMP_SEQ_D = FOP (58, FMT_D),
7092 OPC_CMP_NGL_D = FOP (59, FMT_D),
7093 OPC_CMP_LT_D = FOP (60, FMT_D),
7094 OPC_CMP_NGE_D = FOP (61, FMT_D),
7095 OPC_CMP_LE_D = FOP (62, FMT_D),
7096 OPC_CMP_NGT_D = FOP (63, FMT_D),
7097
7098 OPC_CVT_S_W = FOP(32, FMT_W),
7099 OPC_CVT_D_W = FOP(33, FMT_W),
7100 OPC_CVT_S_L = FOP(32, FMT_L),
7101 OPC_CVT_D_L = FOP(33, FMT_L),
7102 OPC_CVT_PS_PW = FOP(38, FMT_W),
7103
7104 OPC_ADD_PS = FOP(0, FMT_PS),
7105 OPC_SUB_PS = FOP(1, FMT_PS),
7106 OPC_MUL_PS = FOP(2, FMT_PS),
7107 OPC_DIV_PS = FOP(3, FMT_PS),
7108 OPC_ABS_PS = FOP(5, FMT_PS),
7109 OPC_MOV_PS = FOP(6, FMT_PS),
7110 OPC_NEG_PS = FOP(7, FMT_PS),
7111 OPC_MOVCF_PS = FOP(17, FMT_PS),
7112 OPC_MOVZ_PS = FOP(18, FMT_PS),
7113 OPC_MOVN_PS = FOP(19, FMT_PS),
7114 OPC_ADDR_PS = FOP(24, FMT_PS),
7115 OPC_MULR_PS = FOP(26, FMT_PS),
7116 OPC_RECIP2_PS = FOP(28, FMT_PS),
7117 OPC_RECIP1_PS = FOP(29, FMT_PS),
7118 OPC_RSQRT1_PS = FOP(30, FMT_PS),
7119 OPC_RSQRT2_PS = FOP(31, FMT_PS),
7120
7121 OPC_CVT_S_PU = FOP(32, FMT_PS),
7122 OPC_CVT_PW_PS = FOP(36, FMT_PS),
7123 OPC_CVT_S_PL = FOP(40, FMT_PS),
7124 OPC_PLL_PS = FOP(44, FMT_PS),
7125 OPC_PLU_PS = FOP(45, FMT_PS),
7126 OPC_PUL_PS = FOP(46, FMT_PS),
7127 OPC_PUU_PS = FOP(47, FMT_PS),
7128 OPC_CMP_F_PS = FOP (48, FMT_PS),
7129 OPC_CMP_UN_PS = FOP (49, FMT_PS),
7130 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
7131 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
7132 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
7133 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
7134 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
7135 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
7136 OPC_CMP_SF_PS = FOP (56, FMT_PS),
7137 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
7138 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
7139 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
7140 OPC_CMP_LT_PS = FOP (60, FMT_PS),
7141 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
7142 OPC_CMP_LE_PS = FOP (62, FMT_PS),
7143 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
7144};
7145
7a387fff 7146static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6ea83fed 7147{
923617a3 7148 const char *opn = "cp1 move";
72c3a3ee 7149 TCGv t0 = tcg_temp_new();
6ea83fed
FB
7150
7151 switch (opc) {
7152 case OPC_MFC1:
b6d96bed 7153 {
a7812ae4 7154 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7155
7156 gen_load_fpr32(fp0, fs);
7157 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 7158 tcg_temp_free_i32(fp0);
6958549d 7159 }
6c5c1e20 7160 gen_store_gpr(t0, rt);
6ea83fed
FB
7161 opn = "mfc1";
7162 break;
7163 case OPC_MTC1:
6c5c1e20 7164 gen_load_gpr(t0, rt);
b6d96bed 7165 {
a7812ae4 7166 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7167
7168 tcg_gen_trunc_tl_i32(fp0, t0);
7169 gen_store_fpr32(fp0, fs);
a7812ae4 7170 tcg_temp_free_i32(fp0);
6958549d 7171 }
6ea83fed
FB
7172 opn = "mtc1";
7173 break;
7174 case OPC_CFC1:
895c2d04 7175 gen_helper_1e0i(cfc1, t0, fs);
6c5c1e20 7176 gen_store_gpr(t0, rt);
6ea83fed
FB
7177 opn = "cfc1";
7178 break;
7179 case OPC_CTC1:
6c5c1e20 7180 gen_load_gpr(t0, rt);
895c2d04 7181 gen_helper_0e1i(ctc1, t0, fs);
6ea83fed
FB
7182 opn = "ctc1";
7183 break;
72c3a3ee 7184#if defined(TARGET_MIPS64)
9c2149c8 7185 case OPC_DMFC1:
72c3a3ee 7186 gen_load_fpr64(ctx, t0, fs);
6c5c1e20 7187 gen_store_gpr(t0, rt);
5a5012ec
TS
7188 opn = "dmfc1";
7189 break;
9c2149c8 7190 case OPC_DMTC1:
6c5c1e20 7191 gen_load_gpr(t0, rt);
72c3a3ee 7192 gen_store_fpr64(ctx, t0, fs);
5a5012ec
TS
7193 opn = "dmtc1";
7194 break;
72c3a3ee 7195#endif
5a5012ec 7196 case OPC_MFHC1:
b6d96bed 7197 {
a7812ae4 7198 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7199
7200 gen_load_fpr32h(fp0, fs);
7201 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 7202 tcg_temp_free_i32(fp0);
6958549d 7203 }
6c5c1e20 7204 gen_store_gpr(t0, rt);
5a5012ec
TS
7205 opn = "mfhc1";
7206 break;
7207 case OPC_MTHC1:
6c5c1e20 7208 gen_load_gpr(t0, rt);
b6d96bed 7209 {
a7812ae4 7210 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7211
7212 tcg_gen_trunc_tl_i32(fp0, t0);
7213 gen_store_fpr32h(fp0, fs);
a7812ae4 7214 tcg_temp_free_i32(fp0);
6958549d 7215 }
5a5012ec
TS
7216 opn = "mthc1";
7217 break;
6ea83fed 7218 default:
923617a3 7219 MIPS_INVAL(opn);
e397ee33 7220 generate_exception (ctx, EXCP_RI);
6c5c1e20 7221 goto out;
6ea83fed 7222 }
2abf314d 7223 (void)opn; /* avoid a compiler warning */
6ea83fed 7224 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
6c5c1e20
TS
7225
7226 out:
7227 tcg_temp_free(t0);
6ea83fed
FB
7228}
7229
5a5012ec
TS
7230static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
7231{
af58f9ca 7232 int l1;
e214b9bb 7233 TCGCond cond;
af58f9ca
AJ
7234 TCGv_i32 t0;
7235
7236 if (rd == 0) {
7237 /* Treat as NOP. */
7238 return;
7239 }
6ea83fed 7240
e214b9bb 7241 if (tf)
e214b9bb 7242 cond = TCG_COND_EQ;
27848470
TS
7243 else
7244 cond = TCG_COND_NE;
7245
af58f9ca
AJ
7246 l1 = gen_new_label();
7247 t0 = tcg_temp_new_i32();
fa31af0e 7248 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
af58f9ca 7249 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 7250 tcg_temp_free_i32(t0);
af58f9ca
AJ
7251 if (rs == 0) {
7252 tcg_gen_movi_tl(cpu_gpr[rd], 0);
7253 } else {
7254 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
7255 }
e214b9bb 7256 gen_set_label(l1);
5a5012ec
TS
7257}
7258
b6d96bed 7259static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
a16336e4 7260{
a16336e4 7261 int cond;
cbc37b28 7262 TCGv_i32 t0 = tcg_temp_new_i32();
a16336e4
TS
7263 int l1 = gen_new_label();
7264
a16336e4
TS
7265 if (tf)
7266 cond = TCG_COND_EQ;
7267 else
7268 cond = TCG_COND_NE;
7269
fa31af0e 7270 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28
AJ
7271 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7272 gen_load_fpr32(t0, fs);
7273 gen_store_fpr32(t0, fd);
a16336e4 7274 gen_set_label(l1);
cbc37b28 7275 tcg_temp_free_i32(t0);
5a5012ec 7276}
a16336e4 7277
b6d96bed 7278static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
a16336e4 7279{
a16336e4 7280 int cond;
cbc37b28
AJ
7281 TCGv_i32 t0 = tcg_temp_new_i32();
7282 TCGv_i64 fp0;
a16336e4
TS
7283 int l1 = gen_new_label();
7284
a16336e4
TS
7285 if (tf)
7286 cond = TCG_COND_EQ;
7287 else
7288 cond = TCG_COND_NE;
7289
fa31af0e 7290 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 7291 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 7292 tcg_temp_free_i32(t0);
11f94258 7293 fp0 = tcg_temp_new_i64();
9bf3eb2c 7294 gen_load_fpr64(ctx, fp0, fs);
9bf3eb2c 7295 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7296 tcg_temp_free_i64(fp0);
cbc37b28 7297 gen_set_label(l1);
a16336e4
TS
7298}
7299
b6d96bed 7300static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
a16336e4
TS
7301{
7302 int cond;
cbc37b28 7303 TCGv_i32 t0 = tcg_temp_new_i32();
a16336e4
TS
7304 int l1 = gen_new_label();
7305 int l2 = gen_new_label();
7306
7307 if (tf)
7308 cond = TCG_COND_EQ;
7309 else
7310 cond = TCG_COND_NE;
7311
fa31af0e 7312 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28
AJ
7313 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7314 gen_load_fpr32(t0, fs);
7315 gen_store_fpr32(t0, fd);
a16336e4 7316 gen_set_label(l1);
9bf3eb2c 7317
fa31af0e 7318 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
cbc37b28
AJ
7319 tcg_gen_brcondi_i32(cond, t0, 0, l2);
7320 gen_load_fpr32h(t0, fs);
7321 gen_store_fpr32h(t0, fd);
52a0e9eb 7322 tcg_temp_free_i32(t0);
a16336e4 7323 gen_set_label(l2);
a16336e4
TS
7324}
7325
6ea83fed 7326
bf4120ad 7327static void gen_farith (DisasContext *ctx, enum fopcode op1,
5e755519 7328 int ft, int fs, int fd, int cc)
6ea83fed 7329{
923617a3 7330 const char *opn = "farith";
6ea83fed
FB
7331 const char *condnames[] = {
7332 "c.f",
7333 "c.un",
7334 "c.eq",
7335 "c.ueq",
7336 "c.olt",
7337 "c.ult",
7338 "c.ole",
7339 "c.ule",
7340 "c.sf",
7341 "c.ngle",
7342 "c.seq",
7343 "c.ngl",
7344 "c.lt",
7345 "c.nge",
7346 "c.le",
7347 "c.ngt",
7348 };
5a1e8ffb
TS
7349 const char *condnames_abs[] = {
7350 "cabs.f",
7351 "cabs.un",
7352 "cabs.eq",
7353 "cabs.ueq",
7354 "cabs.olt",
7355 "cabs.ult",
7356 "cabs.ole",
7357 "cabs.ule",
7358 "cabs.sf",
7359 "cabs.ngle",
7360 "cabs.seq",
7361 "cabs.ngl",
7362 "cabs.lt",
7363 "cabs.nge",
7364 "cabs.le",
7365 "cabs.ngt",
7366 };
7367 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
7a387fff
TS
7368 uint32_t func = ctx->opcode & 0x3f;
7369
bf4120ad
NF
7370 switch (op1) {
7371 case OPC_ADD_S:
b6d96bed 7372 {
a7812ae4
PB
7373 TCGv_i32 fp0 = tcg_temp_new_i32();
7374 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7375
7376 gen_load_fpr32(fp0, fs);
7377 gen_load_fpr32(fp1, ft);
895c2d04 7378 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
a7812ae4 7379 tcg_temp_free_i32(fp1);
b6d96bed 7380 gen_store_fpr32(fp0, fd);
a7812ae4 7381 tcg_temp_free_i32(fp0);
b6d96bed 7382 }
5a5012ec 7383 opn = "add.s";
5a1e8ffb 7384 optype = BINOP;
5a5012ec 7385 break;
bf4120ad 7386 case OPC_SUB_S:
b6d96bed 7387 {
a7812ae4
PB
7388 TCGv_i32 fp0 = tcg_temp_new_i32();
7389 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7390
7391 gen_load_fpr32(fp0, fs);
7392 gen_load_fpr32(fp1, ft);
895c2d04 7393 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
a7812ae4 7394 tcg_temp_free_i32(fp1);
b6d96bed 7395 gen_store_fpr32(fp0, fd);
a7812ae4 7396 tcg_temp_free_i32(fp0);
b6d96bed 7397 }
5a5012ec 7398 opn = "sub.s";
5a1e8ffb 7399 optype = BINOP;
5a5012ec 7400 break;
bf4120ad 7401 case OPC_MUL_S:
b6d96bed 7402 {
a7812ae4
PB
7403 TCGv_i32 fp0 = tcg_temp_new_i32();
7404 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7405
7406 gen_load_fpr32(fp0, fs);
7407 gen_load_fpr32(fp1, ft);
895c2d04 7408 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
a7812ae4 7409 tcg_temp_free_i32(fp1);
b6d96bed 7410 gen_store_fpr32(fp0, fd);
a7812ae4 7411 tcg_temp_free_i32(fp0);
b6d96bed 7412 }
5a5012ec 7413 opn = "mul.s";
5a1e8ffb 7414 optype = BINOP;
5a5012ec 7415 break;
bf4120ad 7416 case OPC_DIV_S:
b6d96bed 7417 {
a7812ae4
PB
7418 TCGv_i32 fp0 = tcg_temp_new_i32();
7419 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7420
7421 gen_load_fpr32(fp0, fs);
7422 gen_load_fpr32(fp1, ft);
895c2d04 7423 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
a7812ae4 7424 tcg_temp_free_i32(fp1);
b6d96bed 7425 gen_store_fpr32(fp0, fd);
a7812ae4 7426 tcg_temp_free_i32(fp0);
b6d96bed 7427 }
5a5012ec 7428 opn = "div.s";
5a1e8ffb 7429 optype = BINOP;
5a5012ec 7430 break;
bf4120ad 7431 case OPC_SQRT_S:
b6d96bed 7432 {
a7812ae4 7433 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7434
7435 gen_load_fpr32(fp0, fs);
895c2d04 7436 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
b6d96bed 7437 gen_store_fpr32(fp0, fd);
a7812ae4 7438 tcg_temp_free_i32(fp0);
b6d96bed 7439 }
5a5012ec
TS
7440 opn = "sqrt.s";
7441 break;
bf4120ad 7442 case OPC_ABS_S:
b6d96bed 7443 {
a7812ae4 7444 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7445
7446 gen_load_fpr32(fp0, fs);
a7812ae4 7447 gen_helper_float_abs_s(fp0, fp0);
b6d96bed 7448 gen_store_fpr32(fp0, fd);
a7812ae4 7449 tcg_temp_free_i32(fp0);
b6d96bed 7450 }
5a5012ec
TS
7451 opn = "abs.s";
7452 break;
bf4120ad 7453 case OPC_MOV_S:
b6d96bed 7454 {
a7812ae4 7455 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7456
7457 gen_load_fpr32(fp0, fs);
7458 gen_store_fpr32(fp0, fd);
a7812ae4 7459 tcg_temp_free_i32(fp0);
b6d96bed 7460 }
5a5012ec
TS
7461 opn = "mov.s";
7462 break;
bf4120ad 7463 case OPC_NEG_S:
b6d96bed 7464 {
a7812ae4 7465 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7466
7467 gen_load_fpr32(fp0, fs);
a7812ae4 7468 gen_helper_float_chs_s(fp0, fp0);
b6d96bed 7469 gen_store_fpr32(fp0, fd);
a7812ae4 7470 tcg_temp_free_i32(fp0);
b6d96bed 7471 }
5a5012ec
TS
7472 opn = "neg.s";
7473 break;
bf4120ad 7474 case OPC_ROUND_L_S:
5e755519 7475 check_cp1_64bitmode(ctx);
b6d96bed 7476 {
a7812ae4
PB
7477 TCGv_i32 fp32 = tcg_temp_new_i32();
7478 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7479
7480 gen_load_fpr32(fp32, fs);
895c2d04 7481 gen_helper_float_roundl_s(fp64, cpu_env, fp32);
a7812ae4 7482 tcg_temp_free_i32(fp32);
b6d96bed 7483 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 7484 tcg_temp_free_i64(fp64);
b6d96bed 7485 }
5a5012ec
TS
7486 opn = "round.l.s";
7487 break;
bf4120ad 7488 case OPC_TRUNC_L_S:
5e755519 7489 check_cp1_64bitmode(ctx);
b6d96bed 7490 {
a7812ae4
PB
7491 TCGv_i32 fp32 = tcg_temp_new_i32();
7492 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7493
7494 gen_load_fpr32(fp32, fs);
895c2d04 7495 gen_helper_float_truncl_s(fp64, cpu_env, fp32);
a7812ae4 7496 tcg_temp_free_i32(fp32);
b6d96bed 7497 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 7498 tcg_temp_free_i64(fp64);
b6d96bed 7499 }
5a5012ec
TS
7500 opn = "trunc.l.s";
7501 break;
bf4120ad 7502 case OPC_CEIL_L_S:
5e755519 7503 check_cp1_64bitmode(ctx);
b6d96bed 7504 {
a7812ae4
PB
7505 TCGv_i32 fp32 = tcg_temp_new_i32();
7506 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7507
7508 gen_load_fpr32(fp32, fs);
895c2d04 7509 gen_helper_float_ceill_s(fp64, cpu_env, fp32);
a7812ae4 7510 tcg_temp_free_i32(fp32);
b6d96bed 7511 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 7512 tcg_temp_free_i64(fp64);
b6d96bed 7513 }
5a5012ec
TS
7514 opn = "ceil.l.s";
7515 break;
bf4120ad 7516 case OPC_FLOOR_L_S:
5e755519 7517 check_cp1_64bitmode(ctx);
b6d96bed 7518 {
a7812ae4
PB
7519 TCGv_i32 fp32 = tcg_temp_new_i32();
7520 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7521
7522 gen_load_fpr32(fp32, fs);
895c2d04 7523 gen_helper_float_floorl_s(fp64, cpu_env, fp32);
a7812ae4 7524 tcg_temp_free_i32(fp32);
b6d96bed 7525 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 7526 tcg_temp_free_i64(fp64);
b6d96bed 7527 }
5a5012ec
TS
7528 opn = "floor.l.s";
7529 break;
bf4120ad 7530 case OPC_ROUND_W_S:
b6d96bed 7531 {
a7812ae4 7532 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7533
7534 gen_load_fpr32(fp0, fs);
895c2d04 7535 gen_helper_float_roundw_s(fp0, cpu_env, fp0);
b6d96bed 7536 gen_store_fpr32(fp0, fd);
a7812ae4 7537 tcg_temp_free_i32(fp0);
b6d96bed 7538 }
5a5012ec
TS
7539 opn = "round.w.s";
7540 break;
bf4120ad 7541 case OPC_TRUNC_W_S:
b6d96bed 7542 {
a7812ae4 7543 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7544
7545 gen_load_fpr32(fp0, fs);
895c2d04 7546 gen_helper_float_truncw_s(fp0, cpu_env, fp0);
b6d96bed 7547 gen_store_fpr32(fp0, fd);
a7812ae4 7548 tcg_temp_free_i32(fp0);
b6d96bed 7549 }
5a5012ec
TS
7550 opn = "trunc.w.s";
7551 break;
bf4120ad 7552 case OPC_CEIL_W_S:
b6d96bed 7553 {
a7812ae4 7554 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7555
7556 gen_load_fpr32(fp0, fs);
895c2d04 7557 gen_helper_float_ceilw_s(fp0, cpu_env, fp0);
b6d96bed 7558 gen_store_fpr32(fp0, fd);
a7812ae4 7559 tcg_temp_free_i32(fp0);
b6d96bed 7560 }
5a5012ec
TS
7561 opn = "ceil.w.s";
7562 break;
bf4120ad 7563 case OPC_FLOOR_W_S:
b6d96bed 7564 {
a7812ae4 7565 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7566
7567 gen_load_fpr32(fp0, fs);
895c2d04 7568 gen_helper_float_floorw_s(fp0, cpu_env, fp0);
b6d96bed 7569 gen_store_fpr32(fp0, fd);
a7812ae4 7570 tcg_temp_free_i32(fp0);
b6d96bed 7571 }
5a5012ec
TS
7572 opn = "floor.w.s";
7573 break;
bf4120ad 7574 case OPC_MOVCF_S:
b6d96bed 7575 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec
TS
7576 opn = "movcf.s";
7577 break;
bf4120ad 7578 case OPC_MOVZ_S:
a16336e4
TS
7579 {
7580 int l1 = gen_new_label();
c9297f4d 7581 TCGv_i32 fp0;
a16336e4 7582
c9297f4d
AJ
7583 if (ft != 0) {
7584 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7585 }
7586 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7587 gen_load_fpr32(fp0, fs);
7588 gen_store_fpr32(fp0, fd);
a7812ae4 7589 tcg_temp_free_i32(fp0);
a16336e4
TS
7590 gen_set_label(l1);
7591 }
5a5012ec
TS
7592 opn = "movz.s";
7593 break;
bf4120ad 7594 case OPC_MOVN_S:
a16336e4
TS
7595 {
7596 int l1 = gen_new_label();
c9297f4d
AJ
7597 TCGv_i32 fp0;
7598
7599 if (ft != 0) {
7600 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7601 fp0 = tcg_temp_new_i32();
7602 gen_load_fpr32(fp0, fs);
7603 gen_store_fpr32(fp0, fd);
7604 tcg_temp_free_i32(fp0);
7605 gen_set_label(l1);
7606 }
a16336e4 7607 }
5a5012ec
TS
7608 opn = "movn.s";
7609 break;
bf4120ad 7610 case OPC_RECIP_S:
b8aa4598 7611 check_cop1x(ctx);
b6d96bed 7612 {
a7812ae4 7613 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7614
7615 gen_load_fpr32(fp0, fs);
895c2d04 7616 gen_helper_float_recip_s(fp0, cpu_env, fp0);
b6d96bed 7617 gen_store_fpr32(fp0, fd);
a7812ae4 7618 tcg_temp_free_i32(fp0);
b6d96bed 7619 }
57fa1fb3
TS
7620 opn = "recip.s";
7621 break;
bf4120ad 7622 case OPC_RSQRT_S:
b8aa4598 7623 check_cop1x(ctx);
b6d96bed 7624 {
a7812ae4 7625 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7626
7627 gen_load_fpr32(fp0, fs);
895c2d04 7628 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
b6d96bed 7629 gen_store_fpr32(fp0, fd);
a7812ae4 7630 tcg_temp_free_i32(fp0);
b6d96bed 7631 }
57fa1fb3
TS
7632 opn = "rsqrt.s";
7633 break;
bf4120ad 7634 case OPC_RECIP2_S:
5e755519 7635 check_cp1_64bitmode(ctx);
b6d96bed 7636 {
a7812ae4
PB
7637 TCGv_i32 fp0 = tcg_temp_new_i32();
7638 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7639
7640 gen_load_fpr32(fp0, fs);
d22d7289 7641 gen_load_fpr32(fp1, ft);
895c2d04 7642 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
a7812ae4 7643 tcg_temp_free_i32(fp1);
b6d96bed 7644 gen_store_fpr32(fp0, fd);
a7812ae4 7645 tcg_temp_free_i32(fp0);
b6d96bed 7646 }
57fa1fb3
TS
7647 opn = "recip2.s";
7648 break;
bf4120ad 7649 case OPC_RECIP1_S:
5e755519 7650 check_cp1_64bitmode(ctx);
b6d96bed 7651 {
a7812ae4 7652 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7653
7654 gen_load_fpr32(fp0, fs);
895c2d04 7655 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
b6d96bed 7656 gen_store_fpr32(fp0, fd);
a7812ae4 7657 tcg_temp_free_i32(fp0);
b6d96bed 7658 }
57fa1fb3
TS
7659 opn = "recip1.s";
7660 break;
bf4120ad 7661 case OPC_RSQRT1_S:
5e755519 7662 check_cp1_64bitmode(ctx);
b6d96bed 7663 {
a7812ae4 7664 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7665
7666 gen_load_fpr32(fp0, fs);
895c2d04 7667 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
b6d96bed 7668 gen_store_fpr32(fp0, fd);
a7812ae4 7669 tcg_temp_free_i32(fp0);
b6d96bed 7670 }
57fa1fb3
TS
7671 opn = "rsqrt1.s";
7672 break;
bf4120ad 7673 case OPC_RSQRT2_S:
5e755519 7674 check_cp1_64bitmode(ctx);
b6d96bed 7675 {
a7812ae4
PB
7676 TCGv_i32 fp0 = tcg_temp_new_i32();
7677 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7678
7679 gen_load_fpr32(fp0, fs);
7680 gen_load_fpr32(fp1, ft);
895c2d04 7681 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
a7812ae4 7682 tcg_temp_free_i32(fp1);
b6d96bed 7683 gen_store_fpr32(fp0, fd);
a7812ae4 7684 tcg_temp_free_i32(fp0);
b6d96bed 7685 }
57fa1fb3
TS
7686 opn = "rsqrt2.s";
7687 break;
bf4120ad 7688 case OPC_CVT_D_S:
5e755519 7689 check_cp1_registers(ctx, fd);
b6d96bed 7690 {
a7812ae4
PB
7691 TCGv_i32 fp32 = tcg_temp_new_i32();
7692 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7693
7694 gen_load_fpr32(fp32, fs);
895c2d04 7695 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
a7812ae4 7696 tcg_temp_free_i32(fp32);
b6d96bed 7697 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 7698 tcg_temp_free_i64(fp64);
b6d96bed 7699 }
5a5012ec
TS
7700 opn = "cvt.d.s";
7701 break;
bf4120ad 7702 case OPC_CVT_W_S:
b6d96bed 7703 {
a7812ae4 7704 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7705
7706 gen_load_fpr32(fp0, fs);
895c2d04 7707 gen_helper_float_cvtw_s(fp0, cpu_env, fp0);
b6d96bed 7708 gen_store_fpr32(fp0, fd);
a7812ae4 7709 tcg_temp_free_i32(fp0);
b6d96bed 7710 }
5a5012ec
TS
7711 opn = "cvt.w.s";
7712 break;
bf4120ad 7713 case OPC_CVT_L_S:
5e755519 7714 check_cp1_64bitmode(ctx);
b6d96bed 7715 {
a7812ae4
PB
7716 TCGv_i32 fp32 = tcg_temp_new_i32();
7717 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7718
7719 gen_load_fpr32(fp32, fs);
895c2d04 7720 gen_helper_float_cvtl_s(fp64, cpu_env, fp32);
a7812ae4 7721 tcg_temp_free_i32(fp32);
b6d96bed 7722 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 7723 tcg_temp_free_i64(fp64);
b6d96bed 7724 }
5a5012ec
TS
7725 opn = "cvt.l.s";
7726 break;
bf4120ad 7727 case OPC_CVT_PS_S:
5e755519 7728 check_cp1_64bitmode(ctx);
b6d96bed 7729 {
a7812ae4
PB
7730 TCGv_i64 fp64 = tcg_temp_new_i64();
7731 TCGv_i32 fp32_0 = tcg_temp_new_i32();
7732 TCGv_i32 fp32_1 = tcg_temp_new_i32();
b6d96bed
TS
7733
7734 gen_load_fpr32(fp32_0, fs);
7735 gen_load_fpr32(fp32_1, ft);
13d24f49 7736 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
a7812ae4
PB
7737 tcg_temp_free_i32(fp32_1);
7738 tcg_temp_free_i32(fp32_0);
36aa55dc 7739 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 7740 tcg_temp_free_i64(fp64);
b6d96bed 7741 }
5a5012ec
TS
7742 opn = "cvt.ps.s";
7743 break;
bf4120ad
NF
7744 case OPC_CMP_F_S:
7745 case OPC_CMP_UN_S:
7746 case OPC_CMP_EQ_S:
7747 case OPC_CMP_UEQ_S:
7748 case OPC_CMP_OLT_S:
7749 case OPC_CMP_ULT_S:
7750 case OPC_CMP_OLE_S:
7751 case OPC_CMP_ULE_S:
7752 case OPC_CMP_SF_S:
7753 case OPC_CMP_NGLE_S:
7754 case OPC_CMP_SEQ_S:
7755 case OPC_CMP_NGL_S:
7756 case OPC_CMP_LT_S:
7757 case OPC_CMP_NGE_S:
7758 case OPC_CMP_LE_S:
7759 case OPC_CMP_NGT_S:
8153667c
NF
7760 if (ctx->opcode & (1 << 6)) {
7761 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
7762 opn = condnames_abs[func-48];
7763 } else {
7764 gen_cmp_s(ctx, func-48, ft, fs, cc);
7765 opn = condnames[func-48];
5a1e8ffb 7766 }
5a5012ec 7767 break;
bf4120ad 7768 case OPC_ADD_D:
5e755519 7769 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 7770 {
a7812ae4
PB
7771 TCGv_i64 fp0 = tcg_temp_new_i64();
7772 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7773
7774 gen_load_fpr64(ctx, fp0, fs);
7775 gen_load_fpr64(ctx, fp1, ft);
895c2d04 7776 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
a7812ae4 7777 tcg_temp_free_i64(fp1);
b6d96bed 7778 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7779 tcg_temp_free_i64(fp0);
b6d96bed 7780 }
6ea83fed 7781 opn = "add.d";
5a1e8ffb 7782 optype = BINOP;
6ea83fed 7783 break;
bf4120ad 7784 case OPC_SUB_D:
5e755519 7785 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 7786 {
a7812ae4
PB
7787 TCGv_i64 fp0 = tcg_temp_new_i64();
7788 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7789
7790 gen_load_fpr64(ctx, fp0, fs);
7791 gen_load_fpr64(ctx, fp1, ft);
895c2d04 7792 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
a7812ae4 7793 tcg_temp_free_i64(fp1);
b6d96bed 7794 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7795 tcg_temp_free_i64(fp0);
b6d96bed 7796 }
6ea83fed 7797 opn = "sub.d";
5a1e8ffb 7798 optype = BINOP;
6ea83fed 7799 break;
bf4120ad 7800 case OPC_MUL_D:
5e755519 7801 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 7802 {
a7812ae4
PB
7803 TCGv_i64 fp0 = tcg_temp_new_i64();
7804 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7805
7806 gen_load_fpr64(ctx, fp0, fs);
7807 gen_load_fpr64(ctx, fp1, ft);
895c2d04 7808 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
a7812ae4 7809 tcg_temp_free_i64(fp1);
b6d96bed 7810 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7811 tcg_temp_free_i64(fp0);
b6d96bed 7812 }
6ea83fed 7813 opn = "mul.d";
5a1e8ffb 7814 optype = BINOP;
6ea83fed 7815 break;
bf4120ad 7816 case OPC_DIV_D:
5e755519 7817 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 7818 {
a7812ae4
PB
7819 TCGv_i64 fp0 = tcg_temp_new_i64();
7820 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7821
7822 gen_load_fpr64(ctx, fp0, fs);
7823 gen_load_fpr64(ctx, fp1, ft);
895c2d04 7824 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
a7812ae4 7825 tcg_temp_free_i64(fp1);
b6d96bed 7826 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7827 tcg_temp_free_i64(fp0);
b6d96bed 7828 }
6ea83fed 7829 opn = "div.d";
5a1e8ffb 7830 optype = BINOP;
6ea83fed 7831 break;
bf4120ad 7832 case OPC_SQRT_D:
5e755519 7833 check_cp1_registers(ctx, fs | fd);
b6d96bed 7834 {
a7812ae4 7835 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7836
7837 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7838 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
b6d96bed 7839 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7840 tcg_temp_free_i64(fp0);
b6d96bed 7841 }
6ea83fed
FB
7842 opn = "sqrt.d";
7843 break;
bf4120ad 7844 case OPC_ABS_D:
5e755519 7845 check_cp1_registers(ctx, fs | fd);
b6d96bed 7846 {
a7812ae4 7847 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7848
7849 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7850 gen_helper_float_abs_d(fp0, fp0);
b6d96bed 7851 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7852 tcg_temp_free_i64(fp0);
b6d96bed 7853 }
6ea83fed
FB
7854 opn = "abs.d";
7855 break;
bf4120ad 7856 case OPC_MOV_D:
5e755519 7857 check_cp1_registers(ctx, fs | fd);
b6d96bed 7858 {
a7812ae4 7859 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7860
7861 gen_load_fpr64(ctx, fp0, fs);
7862 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7863 tcg_temp_free_i64(fp0);
b6d96bed 7864 }
6ea83fed
FB
7865 opn = "mov.d";
7866 break;
bf4120ad 7867 case OPC_NEG_D:
5e755519 7868 check_cp1_registers(ctx, fs | fd);
b6d96bed 7869 {
a7812ae4 7870 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7871
7872 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7873 gen_helper_float_chs_d(fp0, fp0);
b6d96bed 7874 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7875 tcg_temp_free_i64(fp0);
b6d96bed 7876 }
6ea83fed
FB
7877 opn = "neg.d";
7878 break;
bf4120ad 7879 case OPC_ROUND_L_D:
5e755519 7880 check_cp1_64bitmode(ctx);
b6d96bed 7881 {
a7812ae4 7882 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7883
7884 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7885 gen_helper_float_roundl_d(fp0, cpu_env, fp0);
b6d96bed 7886 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7887 tcg_temp_free_i64(fp0);
b6d96bed 7888 }
5a5012ec
TS
7889 opn = "round.l.d";
7890 break;
bf4120ad 7891 case OPC_TRUNC_L_D:
5e755519 7892 check_cp1_64bitmode(ctx);
b6d96bed 7893 {
a7812ae4 7894 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7895
7896 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7897 gen_helper_float_truncl_d(fp0, cpu_env, fp0);
b6d96bed 7898 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7899 tcg_temp_free_i64(fp0);
b6d96bed 7900 }
5a5012ec
TS
7901 opn = "trunc.l.d";
7902 break;
bf4120ad 7903 case OPC_CEIL_L_D:
5e755519 7904 check_cp1_64bitmode(ctx);
b6d96bed 7905 {
a7812ae4 7906 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7907
7908 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7909 gen_helper_float_ceill_d(fp0, cpu_env, fp0);
b6d96bed 7910 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7911 tcg_temp_free_i64(fp0);
b6d96bed 7912 }
5a5012ec
TS
7913 opn = "ceil.l.d";
7914 break;
bf4120ad 7915 case OPC_FLOOR_L_D:
5e755519 7916 check_cp1_64bitmode(ctx);
b6d96bed 7917 {
a7812ae4 7918 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7919
7920 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7921 gen_helper_float_floorl_d(fp0, cpu_env, fp0);
b6d96bed 7922 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7923 tcg_temp_free_i64(fp0);
b6d96bed 7924 }
5a5012ec
TS
7925 opn = "floor.l.d";
7926 break;
bf4120ad 7927 case OPC_ROUND_W_D:
5e755519 7928 check_cp1_registers(ctx, fs);
b6d96bed 7929 {
a7812ae4
PB
7930 TCGv_i32 fp32 = tcg_temp_new_i32();
7931 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7932
7933 gen_load_fpr64(ctx, fp64, fs);
895c2d04 7934 gen_helper_float_roundw_d(fp32, cpu_env, fp64);
a7812ae4 7935 tcg_temp_free_i64(fp64);
b6d96bed 7936 gen_store_fpr32(fp32, fd);
a7812ae4 7937 tcg_temp_free_i32(fp32);
b6d96bed 7938 }
6ea83fed
FB
7939 opn = "round.w.d";
7940 break;
bf4120ad 7941 case OPC_TRUNC_W_D:
5e755519 7942 check_cp1_registers(ctx, fs);
b6d96bed 7943 {
a7812ae4
PB
7944 TCGv_i32 fp32 = tcg_temp_new_i32();
7945 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7946
7947 gen_load_fpr64(ctx, fp64, fs);
895c2d04 7948 gen_helper_float_truncw_d(fp32, cpu_env, fp64);
a7812ae4 7949 tcg_temp_free_i64(fp64);
b6d96bed 7950 gen_store_fpr32(fp32, fd);
a7812ae4 7951 tcg_temp_free_i32(fp32);
b6d96bed 7952 }
6ea83fed
FB
7953 opn = "trunc.w.d";
7954 break;
bf4120ad 7955 case OPC_CEIL_W_D:
5e755519 7956 check_cp1_registers(ctx, fs);
b6d96bed 7957 {
a7812ae4
PB
7958 TCGv_i32 fp32 = tcg_temp_new_i32();
7959 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7960
7961 gen_load_fpr64(ctx, fp64, fs);
895c2d04 7962 gen_helper_float_ceilw_d(fp32, cpu_env, fp64);
a7812ae4 7963 tcg_temp_free_i64(fp64);
b6d96bed 7964 gen_store_fpr32(fp32, fd);
a7812ae4 7965 tcg_temp_free_i32(fp32);
b6d96bed 7966 }
6ea83fed
FB
7967 opn = "ceil.w.d";
7968 break;
bf4120ad 7969 case OPC_FLOOR_W_D:
5e755519 7970 check_cp1_registers(ctx, fs);
b6d96bed 7971 {
a7812ae4
PB
7972 TCGv_i32 fp32 = tcg_temp_new_i32();
7973 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7974
7975 gen_load_fpr64(ctx, fp64, fs);
895c2d04 7976 gen_helper_float_floorw_d(fp32, cpu_env, fp64);
a7812ae4 7977 tcg_temp_free_i64(fp64);
b6d96bed 7978 gen_store_fpr32(fp32, fd);
a7812ae4 7979 tcg_temp_free_i32(fp32);
b6d96bed 7980 }
7a387fff 7981 opn = "floor.w.d";
6ea83fed 7982 break;
bf4120ad 7983 case OPC_MOVCF_D:
b6d96bed 7984 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 7985 opn = "movcf.d";
dd016883 7986 break;
bf4120ad 7987 case OPC_MOVZ_D:
a16336e4
TS
7988 {
7989 int l1 = gen_new_label();
c9297f4d 7990 TCGv_i64 fp0;
a16336e4 7991
c9297f4d
AJ
7992 if (ft != 0) {
7993 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7994 }
7995 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7996 gen_load_fpr64(ctx, fp0, fs);
7997 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7998 tcg_temp_free_i64(fp0);
a16336e4
TS
7999 gen_set_label(l1);
8000 }
5a5012ec
TS
8001 opn = "movz.d";
8002 break;
bf4120ad 8003 case OPC_MOVN_D:
a16336e4
TS
8004 {
8005 int l1 = gen_new_label();
c9297f4d
AJ
8006 TCGv_i64 fp0;
8007
8008 if (ft != 0) {
8009 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
8010 fp0 = tcg_temp_new_i64();
8011 gen_load_fpr64(ctx, fp0, fs);
8012 gen_store_fpr64(ctx, fp0, fd);
8013 tcg_temp_free_i64(fp0);
8014 gen_set_label(l1);
8015 }
a16336e4 8016 }
5a5012ec 8017 opn = "movn.d";
6ea83fed 8018 break;
bf4120ad 8019 case OPC_RECIP_D:
b8aa4598 8020 check_cp1_64bitmode(ctx);
b6d96bed 8021 {
a7812ae4 8022 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8023
8024 gen_load_fpr64(ctx, fp0, fs);
895c2d04 8025 gen_helper_float_recip_d(fp0, cpu_env, fp0);
b6d96bed 8026 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8027 tcg_temp_free_i64(fp0);
b6d96bed 8028 }
57fa1fb3
TS
8029 opn = "recip.d";
8030 break;
bf4120ad 8031 case OPC_RSQRT_D:
b8aa4598 8032 check_cp1_64bitmode(ctx);
b6d96bed 8033 {
a7812ae4 8034 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8035
8036 gen_load_fpr64(ctx, fp0, fs);
895c2d04 8037 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
b6d96bed 8038 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8039 tcg_temp_free_i64(fp0);
b6d96bed 8040 }
57fa1fb3
TS
8041 opn = "rsqrt.d";
8042 break;
bf4120ad 8043 case OPC_RECIP2_D:
5e755519 8044 check_cp1_64bitmode(ctx);
b6d96bed 8045 {
a7812ae4
PB
8046 TCGv_i64 fp0 = tcg_temp_new_i64();
8047 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
8048
8049 gen_load_fpr64(ctx, fp0, fs);
8050 gen_load_fpr64(ctx, fp1, ft);
895c2d04 8051 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
a7812ae4 8052 tcg_temp_free_i64(fp1);
b6d96bed 8053 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8054 tcg_temp_free_i64(fp0);
b6d96bed 8055 }
57fa1fb3
TS
8056 opn = "recip2.d";
8057 break;
bf4120ad 8058 case OPC_RECIP1_D:
5e755519 8059 check_cp1_64bitmode(ctx);
b6d96bed 8060 {
a7812ae4 8061 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8062
8063 gen_load_fpr64(ctx, fp0, fs);
895c2d04 8064 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
b6d96bed 8065 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8066 tcg_temp_free_i64(fp0);
b6d96bed 8067 }
57fa1fb3
TS
8068 opn = "recip1.d";
8069 break;
bf4120ad 8070 case OPC_RSQRT1_D:
5e755519 8071 check_cp1_64bitmode(ctx);
b6d96bed 8072 {
a7812ae4 8073 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8074
8075 gen_load_fpr64(ctx, fp0, fs);
895c2d04 8076 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
b6d96bed 8077 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8078 tcg_temp_free_i64(fp0);
b6d96bed 8079 }
57fa1fb3
TS
8080 opn = "rsqrt1.d";
8081 break;
bf4120ad 8082 case OPC_RSQRT2_D:
5e755519 8083 check_cp1_64bitmode(ctx);
b6d96bed 8084 {
a7812ae4
PB
8085 TCGv_i64 fp0 = tcg_temp_new_i64();
8086 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
8087
8088 gen_load_fpr64(ctx, fp0, fs);
8089 gen_load_fpr64(ctx, fp1, ft);
895c2d04 8090 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
a7812ae4 8091 tcg_temp_free_i64(fp1);
b6d96bed 8092 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8093 tcg_temp_free_i64(fp0);
b6d96bed 8094 }
57fa1fb3
TS
8095 opn = "rsqrt2.d";
8096 break;
bf4120ad
NF
8097 case OPC_CMP_F_D:
8098 case OPC_CMP_UN_D:
8099 case OPC_CMP_EQ_D:
8100 case OPC_CMP_UEQ_D:
8101 case OPC_CMP_OLT_D:
8102 case OPC_CMP_ULT_D:
8103 case OPC_CMP_OLE_D:
8104 case OPC_CMP_ULE_D:
8105 case OPC_CMP_SF_D:
8106 case OPC_CMP_NGLE_D:
8107 case OPC_CMP_SEQ_D:
8108 case OPC_CMP_NGL_D:
8109 case OPC_CMP_LT_D:
8110 case OPC_CMP_NGE_D:
8111 case OPC_CMP_LE_D:
8112 case OPC_CMP_NGT_D:
8153667c
NF
8113 if (ctx->opcode & (1 << 6)) {
8114 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
8115 opn = condnames_abs[func-48];
8116 } else {
8117 gen_cmp_d(ctx, func-48, ft, fs, cc);
8118 opn = condnames[func-48];
5a1e8ffb 8119 }
6ea83fed 8120 break;
bf4120ad 8121 case OPC_CVT_S_D:
5e755519 8122 check_cp1_registers(ctx, fs);
b6d96bed 8123 {
a7812ae4
PB
8124 TCGv_i32 fp32 = tcg_temp_new_i32();
8125 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
8126
8127 gen_load_fpr64(ctx, fp64, fs);
895c2d04 8128 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
a7812ae4 8129 tcg_temp_free_i64(fp64);
b6d96bed 8130 gen_store_fpr32(fp32, fd);
a7812ae4 8131 tcg_temp_free_i32(fp32);
b6d96bed 8132 }
5a5012ec
TS
8133 opn = "cvt.s.d";
8134 break;
bf4120ad 8135 case OPC_CVT_W_D:
5e755519 8136 check_cp1_registers(ctx, fs);
b6d96bed 8137 {
a7812ae4
PB
8138 TCGv_i32 fp32 = tcg_temp_new_i32();
8139 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
8140
8141 gen_load_fpr64(ctx, fp64, fs);
895c2d04 8142 gen_helper_float_cvtw_d(fp32, cpu_env, fp64);
a7812ae4 8143 tcg_temp_free_i64(fp64);
b6d96bed 8144 gen_store_fpr32(fp32, fd);
a7812ae4 8145 tcg_temp_free_i32(fp32);
b6d96bed 8146 }
5a5012ec
TS
8147 opn = "cvt.w.d";
8148 break;
bf4120ad 8149 case OPC_CVT_L_D:
5e755519 8150 check_cp1_64bitmode(ctx);
b6d96bed 8151 {
a7812ae4 8152 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8153
8154 gen_load_fpr64(ctx, fp0, fs);
895c2d04 8155 gen_helper_float_cvtl_d(fp0, cpu_env, fp0);
b6d96bed 8156 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8157 tcg_temp_free_i64(fp0);
b6d96bed 8158 }
5a5012ec
TS
8159 opn = "cvt.l.d";
8160 break;
bf4120ad 8161 case OPC_CVT_S_W:
b6d96bed 8162 {
a7812ae4 8163 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
8164
8165 gen_load_fpr32(fp0, fs);
895c2d04 8166 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
b6d96bed 8167 gen_store_fpr32(fp0, fd);
a7812ae4 8168 tcg_temp_free_i32(fp0);
b6d96bed 8169 }
5a5012ec 8170 opn = "cvt.s.w";
6ea83fed 8171 break;
bf4120ad 8172 case OPC_CVT_D_W:
5e755519 8173 check_cp1_registers(ctx, fd);
b6d96bed 8174 {
a7812ae4
PB
8175 TCGv_i32 fp32 = tcg_temp_new_i32();
8176 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
8177
8178 gen_load_fpr32(fp32, fs);
895c2d04 8179 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
a7812ae4 8180 tcg_temp_free_i32(fp32);
b6d96bed 8181 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 8182 tcg_temp_free_i64(fp64);
b6d96bed 8183 }
5a5012ec
TS
8184 opn = "cvt.d.w";
8185 break;
bf4120ad 8186 case OPC_CVT_S_L:
5e755519 8187 check_cp1_64bitmode(ctx);
b6d96bed 8188 {
a7812ae4
PB
8189 TCGv_i32 fp32 = tcg_temp_new_i32();
8190 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
8191
8192 gen_load_fpr64(ctx, fp64, fs);
895c2d04 8193 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
a7812ae4 8194 tcg_temp_free_i64(fp64);
b6d96bed 8195 gen_store_fpr32(fp32, fd);
a7812ae4 8196 tcg_temp_free_i32(fp32);
b6d96bed 8197 }
5a5012ec
TS
8198 opn = "cvt.s.l";
8199 break;
bf4120ad 8200 case OPC_CVT_D_L:
5e755519 8201 check_cp1_64bitmode(ctx);
b6d96bed 8202 {
a7812ae4 8203 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8204
8205 gen_load_fpr64(ctx, fp0, fs);
895c2d04 8206 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
b6d96bed 8207 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8208 tcg_temp_free_i64(fp0);
b6d96bed 8209 }
5a5012ec
TS
8210 opn = "cvt.d.l";
8211 break;
bf4120ad 8212 case OPC_CVT_PS_PW:
5e755519 8213 check_cp1_64bitmode(ctx);
b6d96bed 8214 {
a7812ae4 8215 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8216
8217 gen_load_fpr64(ctx, fp0, fs);
895c2d04 8218 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
b6d96bed 8219 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8220 tcg_temp_free_i64(fp0);
b6d96bed 8221 }
5a5012ec
TS
8222 opn = "cvt.ps.pw";
8223 break;
bf4120ad 8224 case OPC_ADD_PS:
5e755519 8225 check_cp1_64bitmode(ctx);
b6d96bed 8226 {
a7812ae4
PB
8227 TCGv_i64 fp0 = tcg_temp_new_i64();
8228 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
8229
8230 gen_load_fpr64(ctx, fp0, fs);
8231 gen_load_fpr64(ctx, fp1, ft);
895c2d04 8232 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 8233 tcg_temp_free_i64(fp1);
b6d96bed 8234 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8235 tcg_temp_free_i64(fp0);
b6d96bed 8236 }
5a5012ec 8237 opn = "add.ps";
6ea83fed 8238 break;
bf4120ad 8239 case OPC_SUB_PS:
5e755519 8240 check_cp1_64bitmode(ctx);
b6d96bed 8241 {
a7812ae4
PB
8242 TCGv_i64 fp0 = tcg_temp_new_i64();
8243 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
8244
8245 gen_load_fpr64(ctx, fp0, fs);
8246 gen_load_fpr64(ctx, fp1, ft);
895c2d04 8247 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 8248 tcg_temp_free_i64(fp1);
b6d96bed 8249 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8250 tcg_temp_free_i64(fp0);
b6d96bed 8251 }
5a5012ec 8252 opn = "sub.ps";
6ea83fed 8253 break;
bf4120ad 8254 case OPC_MUL_PS:
5e755519 8255 check_cp1_64bitmode(ctx);
b6d96bed 8256 {
a7812ae4
PB
8257 TCGv_i64 fp0 = tcg_temp_new_i64();
8258 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
8259
8260 gen_load_fpr64(ctx, fp0, fs);
8261 gen_load_fpr64(ctx, fp1, ft);
895c2d04 8262 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 8263 tcg_temp_free_i64(fp1);
b6d96bed 8264 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8265 tcg_temp_free_i64(fp0);
b6d96bed 8266 }
5a5012ec 8267 opn = "mul.ps";
6ea83fed 8268 break;
bf4120ad 8269 case OPC_ABS_PS:
5e755519 8270 check_cp1_64bitmode(ctx);
b6d96bed 8271 {
a7812ae4 8272 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8273
8274 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 8275 gen_helper_float_abs_ps(fp0, fp0);
b6d96bed 8276 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8277 tcg_temp_free_i64(fp0);
b6d96bed 8278 }
5a5012ec 8279 opn = "abs.ps";
6ea83fed 8280 break;
bf4120ad 8281 case OPC_MOV_PS:
5e755519 8282 check_cp1_64bitmode(ctx);
b6d96bed 8283 {
a7812ae4 8284 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8285
8286 gen_load_fpr64(ctx, fp0, fs);
8287 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8288 tcg_temp_free_i64(fp0);
b6d96bed 8289 }
5a5012ec 8290 opn = "mov.ps";
6ea83fed 8291 break;
bf4120ad 8292 case OPC_NEG_PS:
5e755519 8293 check_cp1_64bitmode(ctx);
b6d96bed 8294 {
a7812ae4 8295 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8296
8297 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 8298 gen_helper_float_chs_ps(fp0, fp0);
b6d96bed 8299 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8300 tcg_temp_free_i64(fp0);
b6d96bed 8301 }
5a5012ec 8302 opn = "neg.ps";
6ea83fed 8303 break;
bf4120ad 8304 case OPC_MOVCF_PS:
5e755519 8305 check_cp1_64bitmode(ctx);
b6d96bed 8306 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 8307 opn = "movcf.ps";
6ea83fed 8308 break;
bf4120ad 8309 case OPC_MOVZ_PS:
5e755519 8310 check_cp1_64bitmode(ctx);
a16336e4
TS
8311 {
8312 int l1 = gen_new_label();
30a3848b 8313 TCGv_i64 fp0;
a16336e4 8314
c9297f4d
AJ
8315 if (ft != 0)
8316 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
8317 fp0 = tcg_temp_new_i64();
8318 gen_load_fpr64(ctx, fp0, fs);
8319 gen_store_fpr64(ctx, fp0, fd);
8320 tcg_temp_free_i64(fp0);
a16336e4
TS
8321 gen_set_label(l1);
8322 }
5a5012ec 8323 opn = "movz.ps";
6ea83fed 8324 break;
bf4120ad 8325 case OPC_MOVN_PS:
5e755519 8326 check_cp1_64bitmode(ctx);
a16336e4
TS
8327 {
8328 int l1 = gen_new_label();
30a3848b 8329 TCGv_i64 fp0;
c9297f4d
AJ
8330
8331 if (ft != 0) {
8332 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
8333 fp0 = tcg_temp_new_i64();
8334 gen_load_fpr64(ctx, fp0, fs);
8335 gen_store_fpr64(ctx, fp0, fd);
8336 tcg_temp_free_i64(fp0);
8337 gen_set_label(l1);
8338 }
a16336e4 8339 }
5a5012ec 8340 opn = "movn.ps";
6ea83fed 8341 break;
bf4120ad 8342 case OPC_ADDR_PS:
5e755519 8343 check_cp1_64bitmode(ctx);
b6d96bed 8344 {
a7812ae4
PB
8345 TCGv_i64 fp0 = tcg_temp_new_i64();
8346 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
8347
8348 gen_load_fpr64(ctx, fp0, ft);
8349 gen_load_fpr64(ctx, fp1, fs);
895c2d04 8350 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 8351 tcg_temp_free_i64(fp1);
b6d96bed 8352 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8353 tcg_temp_free_i64(fp0);
b6d96bed 8354 }
fbcc6828
TS
8355 opn = "addr.ps";
8356 break;
bf4120ad 8357 case OPC_MULR_PS:
5e755519 8358 check_cp1_64bitmode(ctx);
b6d96bed 8359 {
a7812ae4
PB
8360 TCGv_i64 fp0 = tcg_temp_new_i64();
8361 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
8362
8363 gen_load_fpr64(ctx, fp0, ft);
8364 gen_load_fpr64(ctx, fp1, fs);
895c2d04 8365 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 8366 tcg_temp_free_i64(fp1);
b6d96bed 8367 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8368 tcg_temp_free_i64(fp0);
b6d96bed 8369 }
57fa1fb3
TS
8370 opn = "mulr.ps";
8371 break;
bf4120ad 8372 case OPC_RECIP2_PS:
5e755519 8373 check_cp1_64bitmode(ctx);
b6d96bed 8374 {
a7812ae4
PB
8375 TCGv_i64 fp0 = tcg_temp_new_i64();
8376 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
8377
8378 gen_load_fpr64(ctx, fp0, fs);
d22d7289 8379 gen_load_fpr64(ctx, fp1, ft);
895c2d04 8380 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 8381 tcg_temp_free_i64(fp1);
b6d96bed 8382 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8383 tcg_temp_free_i64(fp0);
b6d96bed 8384 }
57fa1fb3
TS
8385 opn = "recip2.ps";
8386 break;
bf4120ad 8387 case OPC_RECIP1_PS:
5e755519 8388 check_cp1_64bitmode(ctx);
b6d96bed 8389 {
a7812ae4 8390 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8391
8392 gen_load_fpr64(ctx, fp0, fs);
895c2d04 8393 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
b6d96bed 8394 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8395 tcg_temp_free_i64(fp0);
b6d96bed 8396 }
57fa1fb3
TS
8397 opn = "recip1.ps";
8398 break;
bf4120ad 8399 case OPC_RSQRT1_PS:
5e755519 8400 check_cp1_64bitmode(ctx);
b6d96bed 8401 {
a7812ae4 8402 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8403
8404 gen_load_fpr64(ctx, fp0, fs);
895c2d04 8405 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
b6d96bed 8406 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8407 tcg_temp_free_i64(fp0);
b6d96bed 8408 }
57fa1fb3
TS
8409 opn = "rsqrt1.ps";
8410 break;
bf4120ad 8411 case OPC_RSQRT2_PS:
5e755519 8412 check_cp1_64bitmode(ctx);
b6d96bed 8413 {
a7812ae4
PB
8414 TCGv_i64 fp0 = tcg_temp_new_i64();
8415 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
8416
8417 gen_load_fpr64(ctx, fp0, fs);
8418 gen_load_fpr64(ctx, fp1, ft);
895c2d04 8419 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 8420 tcg_temp_free_i64(fp1);
b6d96bed 8421 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8422 tcg_temp_free_i64(fp0);
b6d96bed 8423 }
57fa1fb3
TS
8424 opn = "rsqrt2.ps";
8425 break;
bf4120ad 8426 case OPC_CVT_S_PU:
5e755519 8427 check_cp1_64bitmode(ctx);
b6d96bed 8428 {
a7812ae4 8429 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
8430
8431 gen_load_fpr32h(fp0, fs);
895c2d04 8432 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
b6d96bed 8433 gen_store_fpr32(fp0, fd);
a7812ae4 8434 tcg_temp_free_i32(fp0);
b6d96bed 8435 }
5a5012ec 8436 opn = "cvt.s.pu";
dd016883 8437 break;
bf4120ad 8438 case OPC_CVT_PW_PS:
5e755519 8439 check_cp1_64bitmode(ctx);
b6d96bed 8440 {
a7812ae4 8441 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8442
8443 gen_load_fpr64(ctx, fp0, fs);
895c2d04 8444 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
b6d96bed 8445 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8446 tcg_temp_free_i64(fp0);
b6d96bed 8447 }
5a5012ec 8448 opn = "cvt.pw.ps";
6ea83fed 8449 break;
bf4120ad 8450 case OPC_CVT_S_PL:
5e755519 8451 check_cp1_64bitmode(ctx);
b6d96bed 8452 {
a7812ae4 8453 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
8454
8455 gen_load_fpr32(fp0, fs);
895c2d04 8456 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
b6d96bed 8457 gen_store_fpr32(fp0, fd);
a7812ae4 8458 tcg_temp_free_i32(fp0);
b6d96bed 8459 }
5a5012ec 8460 opn = "cvt.s.pl";
6ea83fed 8461 break;
bf4120ad 8462 case OPC_PLL_PS:
5e755519 8463 check_cp1_64bitmode(ctx);
b6d96bed 8464 {
a7812ae4
PB
8465 TCGv_i32 fp0 = tcg_temp_new_i32();
8466 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
8467
8468 gen_load_fpr32(fp0, fs);
8469 gen_load_fpr32(fp1, ft);
8470 gen_store_fpr32h(fp0, fd);
8471 gen_store_fpr32(fp1, fd);
a7812ae4
PB
8472 tcg_temp_free_i32(fp0);
8473 tcg_temp_free_i32(fp1);
b6d96bed 8474 }
5a5012ec 8475 opn = "pll.ps";
6ea83fed 8476 break;
bf4120ad 8477 case OPC_PLU_PS:
5e755519 8478 check_cp1_64bitmode(ctx);
b6d96bed 8479 {
a7812ae4
PB
8480 TCGv_i32 fp0 = tcg_temp_new_i32();
8481 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
8482
8483 gen_load_fpr32(fp0, fs);
8484 gen_load_fpr32h(fp1, ft);
8485 gen_store_fpr32(fp1, fd);
8486 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
8487 tcg_temp_free_i32(fp0);
8488 tcg_temp_free_i32(fp1);
b6d96bed 8489 }
5a5012ec
TS
8490 opn = "plu.ps";
8491 break;
bf4120ad 8492 case OPC_PUL_PS:
5e755519 8493 check_cp1_64bitmode(ctx);
b6d96bed 8494 {
a7812ae4
PB
8495 TCGv_i32 fp0 = tcg_temp_new_i32();
8496 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
8497
8498 gen_load_fpr32h(fp0, fs);
8499 gen_load_fpr32(fp1, ft);
8500 gen_store_fpr32(fp1, fd);
8501 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
8502 tcg_temp_free_i32(fp0);
8503 tcg_temp_free_i32(fp1);
b6d96bed 8504 }
5a5012ec
TS
8505 opn = "pul.ps";
8506 break;
bf4120ad 8507 case OPC_PUU_PS:
5e755519 8508 check_cp1_64bitmode(ctx);
b6d96bed 8509 {
a7812ae4
PB
8510 TCGv_i32 fp0 = tcg_temp_new_i32();
8511 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
8512
8513 gen_load_fpr32h(fp0, fs);
8514 gen_load_fpr32h(fp1, ft);
8515 gen_store_fpr32(fp1, fd);
8516 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
8517 tcg_temp_free_i32(fp0);
8518 tcg_temp_free_i32(fp1);
b6d96bed 8519 }
5a5012ec
TS
8520 opn = "puu.ps";
8521 break;
bf4120ad
NF
8522 case OPC_CMP_F_PS:
8523 case OPC_CMP_UN_PS:
8524 case OPC_CMP_EQ_PS:
8525 case OPC_CMP_UEQ_PS:
8526 case OPC_CMP_OLT_PS:
8527 case OPC_CMP_ULT_PS:
8528 case OPC_CMP_OLE_PS:
8529 case OPC_CMP_ULE_PS:
8530 case OPC_CMP_SF_PS:
8531 case OPC_CMP_NGLE_PS:
8532 case OPC_CMP_SEQ_PS:
8533 case OPC_CMP_NGL_PS:
8534 case OPC_CMP_LT_PS:
8535 case OPC_CMP_NGE_PS:
8536 case OPC_CMP_LE_PS:
8537 case OPC_CMP_NGT_PS:
8153667c
NF
8538 if (ctx->opcode & (1 << 6)) {
8539 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
8540 opn = condnames_abs[func-48];
8541 } else {
8542 gen_cmp_ps(ctx, func-48, ft, fs, cc);
8543 opn = condnames[func-48];
5a1e8ffb 8544 }
6ea83fed 8545 break;
5a5012ec 8546 default:
923617a3 8547 MIPS_INVAL(opn);
e397ee33 8548 generate_exception (ctx, EXCP_RI);
6ea83fed
FB
8549 return;
8550 }
2abf314d 8551 (void)opn; /* avoid a compiler warning */
5a1e8ffb
TS
8552 switch (optype) {
8553 case BINOP:
6ea83fed 8554 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
5a1e8ffb
TS
8555 break;
8556 case CMPOP:
8557 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
8558 break;
8559 default:
6ea83fed 8560 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
5a1e8ffb
TS
8561 break;
8562 }
6ea83fed 8563}
6af0bf9c 8564
5a5012ec 8565/* Coprocessor 3 (FPU) */
5e755519
TS
8566static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
8567 int fd, int fs, int base, int index)
7a387fff 8568{
923617a3 8569 const char *opn = "extended float load/store";
93b12ccc 8570 int store = 0;
4e2474d6 8571 TCGv t0 = tcg_temp_new();
7a387fff 8572
93b12ccc 8573 if (base == 0) {
6c5c1e20 8574 gen_load_gpr(t0, index);
93b12ccc 8575 } else if (index == 0) {
6c5c1e20 8576 gen_load_gpr(t0, base);
93b12ccc 8577 } else {
05168674 8578 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
93b12ccc 8579 }
5a5012ec 8580 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 8581 memory access. */
4e2474d6 8582 save_cpu_state(ctx, 0);
5a5012ec
TS
8583 switch (opc) {
8584 case OPC_LWXC1:
8c0ab41f 8585 check_cop1x(ctx);
b6d96bed 8586 {
a7812ae4 8587 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 8588
585c88d5
AJ
8589 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
8590 tcg_gen_trunc_tl_i32(fp0, t0);
b6d96bed 8591 gen_store_fpr32(fp0, fd);
a7812ae4 8592 tcg_temp_free_i32(fp0);
b6d96bed 8593 }
5a5012ec
TS
8594 opn = "lwxc1";
8595 break;
8596 case OPC_LDXC1:
8c0ab41f
AJ
8597 check_cop1x(ctx);
8598 check_cp1_registers(ctx, fd);
b6d96bed 8599 {
a7812ae4 8600 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8601
8602 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
8603 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8604 tcg_temp_free_i64(fp0);
b6d96bed 8605 }
5a5012ec
TS
8606 opn = "ldxc1";
8607 break;
8608 case OPC_LUXC1:
8c0ab41f 8609 check_cp1_64bitmode(ctx);
6c5c1e20 8610 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 8611 {
a7812ae4 8612 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8613
8614 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
8615 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8616 tcg_temp_free_i64(fp0);
b6d96bed 8617 }
5a5012ec
TS
8618 opn = "luxc1";
8619 break;
8620 case OPC_SWXC1:
8c0ab41f 8621 check_cop1x(ctx);
b6d96bed 8622 {
a7812ae4 8623 TCGv_i32 fp0 = tcg_temp_new_i32();
585c88d5 8624 TCGv t1 = tcg_temp_new();
b6d96bed
TS
8625
8626 gen_load_fpr32(fp0, fs);
a7812ae4
PB
8627 tcg_gen_extu_i32_tl(t1, fp0);
8628 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
8629 tcg_temp_free_i32(fp0);
a6035857 8630 tcg_temp_free(t1);
b6d96bed 8631 }
5a5012ec 8632 opn = "swxc1";
93b12ccc 8633 store = 1;
5a5012ec
TS
8634 break;
8635 case OPC_SDXC1:
8c0ab41f
AJ
8636 check_cop1x(ctx);
8637 check_cp1_registers(ctx, fs);
b6d96bed 8638 {
a7812ae4 8639 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8640
8641 gen_load_fpr64(ctx, fp0, fs);
8642 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 8643 tcg_temp_free_i64(fp0);
b6d96bed 8644 }
5a5012ec 8645 opn = "sdxc1";
93b12ccc 8646 store = 1;
5a5012ec
TS
8647 break;
8648 case OPC_SUXC1:
8c0ab41f 8649 check_cp1_64bitmode(ctx);
6c5c1e20 8650 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 8651 {
a7812ae4 8652 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8653
8654 gen_load_fpr64(ctx, fp0, fs);
8655 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 8656 tcg_temp_free_i64(fp0);
b6d96bed 8657 }
5a5012ec 8658 opn = "suxc1";
93b12ccc 8659 store = 1;
5a5012ec 8660 break;
5a5012ec 8661 }
6c5c1e20 8662 tcg_temp_free(t0);
2abf314d 8663 (void)opn; (void)store; /* avoid compiler warnings */
93b12ccc
TS
8664 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
8665 regnames[index], regnames[base]);
5a5012ec
TS
8666}
8667
5e755519
TS
8668static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
8669 int fd, int fr, int fs, int ft)
5a5012ec 8670{
923617a3 8671 const char *opn = "flt3_arith";
5a5012ec 8672
5a5012ec
TS
8673 switch (opc) {
8674 case OPC_ALNV_PS:
b8aa4598 8675 check_cp1_64bitmode(ctx);
a16336e4 8676 {
a7812ae4 8677 TCGv t0 = tcg_temp_local_new();
c905fdac
AJ
8678 TCGv_i32 fp = tcg_temp_new_i32();
8679 TCGv_i32 fph = tcg_temp_new_i32();
a16336e4
TS
8680 int l1 = gen_new_label();
8681 int l2 = gen_new_label();
8682
6c5c1e20
TS
8683 gen_load_gpr(t0, fr);
8684 tcg_gen_andi_tl(t0, t0, 0x7);
6c5c1e20
TS
8685
8686 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
c905fdac
AJ
8687 gen_load_fpr32(fp, fs);
8688 gen_load_fpr32h(fph, fs);
8689 gen_store_fpr32(fp, fd);
8690 gen_store_fpr32h(fph, fd);
a16336e4
TS
8691 tcg_gen_br(l2);
8692 gen_set_label(l1);
6c5c1e20
TS
8693 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
8694 tcg_temp_free(t0);
a16336e4 8695#ifdef TARGET_WORDS_BIGENDIAN
c905fdac
AJ
8696 gen_load_fpr32(fp, fs);
8697 gen_load_fpr32h(fph, ft);
8698 gen_store_fpr32h(fp, fd);
8699 gen_store_fpr32(fph, fd);
a16336e4 8700#else
c905fdac
AJ
8701 gen_load_fpr32h(fph, fs);
8702 gen_load_fpr32(fp, ft);
8703 gen_store_fpr32(fph, fd);
8704 gen_store_fpr32h(fp, fd);
a16336e4
TS
8705#endif
8706 gen_set_label(l2);
c905fdac
AJ
8707 tcg_temp_free_i32(fp);
8708 tcg_temp_free_i32(fph);
a16336e4 8709 }
5a5012ec
TS
8710 opn = "alnv.ps";
8711 break;
8712 case OPC_MADD_S:
b8aa4598 8713 check_cop1x(ctx);
b6d96bed 8714 {
a7812ae4
PB
8715 TCGv_i32 fp0 = tcg_temp_new_i32();
8716 TCGv_i32 fp1 = tcg_temp_new_i32();
8717 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
8718
8719 gen_load_fpr32(fp0, fs);
8720 gen_load_fpr32(fp1, ft);
8721 gen_load_fpr32(fp2, fr);
895c2d04 8722 gen_helper_float_muladd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8723 tcg_temp_free_i32(fp0);
8724 tcg_temp_free_i32(fp1);
b6d96bed 8725 gen_store_fpr32(fp2, fd);
a7812ae4 8726 tcg_temp_free_i32(fp2);
b6d96bed 8727 }
5a5012ec
TS
8728 opn = "madd.s";
8729 break;
8730 case OPC_MADD_D:
b8aa4598
TS
8731 check_cop1x(ctx);
8732 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 8733 {
a7812ae4
PB
8734 TCGv_i64 fp0 = tcg_temp_new_i64();
8735 TCGv_i64 fp1 = tcg_temp_new_i64();
8736 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8737
8738 gen_load_fpr64(ctx, fp0, fs);
8739 gen_load_fpr64(ctx, fp1, ft);
8740 gen_load_fpr64(ctx, fp2, fr);
895c2d04 8741 gen_helper_float_muladd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8742 tcg_temp_free_i64(fp0);
8743 tcg_temp_free_i64(fp1);
b6d96bed 8744 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8745 tcg_temp_free_i64(fp2);
b6d96bed 8746 }
5a5012ec
TS
8747 opn = "madd.d";
8748 break;
8749 case OPC_MADD_PS:
b8aa4598 8750 check_cp1_64bitmode(ctx);
b6d96bed 8751 {
a7812ae4
PB
8752 TCGv_i64 fp0 = tcg_temp_new_i64();
8753 TCGv_i64 fp1 = tcg_temp_new_i64();
8754 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8755
8756 gen_load_fpr64(ctx, fp0, fs);
8757 gen_load_fpr64(ctx, fp1, ft);
8758 gen_load_fpr64(ctx, fp2, fr);
895c2d04 8759 gen_helper_float_muladd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8760 tcg_temp_free_i64(fp0);
8761 tcg_temp_free_i64(fp1);
b6d96bed 8762 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8763 tcg_temp_free_i64(fp2);
b6d96bed 8764 }
5a5012ec
TS
8765 opn = "madd.ps";
8766 break;
8767 case OPC_MSUB_S:
b8aa4598 8768 check_cop1x(ctx);
b6d96bed 8769 {
a7812ae4
PB
8770 TCGv_i32 fp0 = tcg_temp_new_i32();
8771 TCGv_i32 fp1 = tcg_temp_new_i32();
8772 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
8773
8774 gen_load_fpr32(fp0, fs);
8775 gen_load_fpr32(fp1, ft);
8776 gen_load_fpr32(fp2, fr);
895c2d04 8777 gen_helper_float_mulsub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8778 tcg_temp_free_i32(fp0);
8779 tcg_temp_free_i32(fp1);
b6d96bed 8780 gen_store_fpr32(fp2, fd);
a7812ae4 8781 tcg_temp_free_i32(fp2);
b6d96bed 8782 }
5a5012ec
TS
8783 opn = "msub.s";
8784 break;
8785 case OPC_MSUB_D:
b8aa4598
TS
8786 check_cop1x(ctx);
8787 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 8788 {
a7812ae4
PB
8789 TCGv_i64 fp0 = tcg_temp_new_i64();
8790 TCGv_i64 fp1 = tcg_temp_new_i64();
8791 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8792
8793 gen_load_fpr64(ctx, fp0, fs);
8794 gen_load_fpr64(ctx, fp1, ft);
8795 gen_load_fpr64(ctx, fp2, fr);
895c2d04 8796 gen_helper_float_mulsub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8797 tcg_temp_free_i64(fp0);
8798 tcg_temp_free_i64(fp1);
b6d96bed 8799 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8800 tcg_temp_free_i64(fp2);
b6d96bed 8801 }
5a5012ec
TS
8802 opn = "msub.d";
8803 break;
8804 case OPC_MSUB_PS:
b8aa4598 8805 check_cp1_64bitmode(ctx);
b6d96bed 8806 {
a7812ae4
PB
8807 TCGv_i64 fp0 = tcg_temp_new_i64();
8808 TCGv_i64 fp1 = tcg_temp_new_i64();
8809 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8810
8811 gen_load_fpr64(ctx, fp0, fs);
8812 gen_load_fpr64(ctx, fp1, ft);
8813 gen_load_fpr64(ctx, fp2, fr);
895c2d04 8814 gen_helper_float_mulsub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8815 tcg_temp_free_i64(fp0);
8816 tcg_temp_free_i64(fp1);
b6d96bed 8817 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8818 tcg_temp_free_i64(fp2);
b6d96bed 8819 }
5a5012ec
TS
8820 opn = "msub.ps";
8821 break;
8822 case OPC_NMADD_S:
b8aa4598 8823 check_cop1x(ctx);
b6d96bed 8824 {
a7812ae4
PB
8825 TCGv_i32 fp0 = tcg_temp_new_i32();
8826 TCGv_i32 fp1 = tcg_temp_new_i32();
8827 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
8828
8829 gen_load_fpr32(fp0, fs);
8830 gen_load_fpr32(fp1, ft);
8831 gen_load_fpr32(fp2, fr);
895c2d04 8832 gen_helper_float_nmuladd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8833 tcg_temp_free_i32(fp0);
8834 tcg_temp_free_i32(fp1);
b6d96bed 8835 gen_store_fpr32(fp2, fd);
a7812ae4 8836 tcg_temp_free_i32(fp2);
b6d96bed 8837 }
5a5012ec
TS
8838 opn = "nmadd.s";
8839 break;
8840 case OPC_NMADD_D:
b8aa4598
TS
8841 check_cop1x(ctx);
8842 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 8843 {
a7812ae4
PB
8844 TCGv_i64 fp0 = tcg_temp_new_i64();
8845 TCGv_i64 fp1 = tcg_temp_new_i64();
8846 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8847
8848 gen_load_fpr64(ctx, fp0, fs);
8849 gen_load_fpr64(ctx, fp1, ft);
8850 gen_load_fpr64(ctx, fp2, fr);
895c2d04 8851 gen_helper_float_nmuladd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8852 tcg_temp_free_i64(fp0);
8853 tcg_temp_free_i64(fp1);
b6d96bed 8854 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8855 tcg_temp_free_i64(fp2);
b6d96bed 8856 }
5a5012ec
TS
8857 opn = "nmadd.d";
8858 break;
8859 case OPC_NMADD_PS:
b8aa4598 8860 check_cp1_64bitmode(ctx);
b6d96bed 8861 {
a7812ae4
PB
8862 TCGv_i64 fp0 = tcg_temp_new_i64();
8863 TCGv_i64 fp1 = tcg_temp_new_i64();
8864 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8865
8866 gen_load_fpr64(ctx, fp0, fs);
8867 gen_load_fpr64(ctx, fp1, ft);
8868 gen_load_fpr64(ctx, fp2, fr);
895c2d04 8869 gen_helper_float_nmuladd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8870 tcg_temp_free_i64(fp0);
8871 tcg_temp_free_i64(fp1);
b6d96bed 8872 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8873 tcg_temp_free_i64(fp2);
b6d96bed 8874 }
5a5012ec
TS
8875 opn = "nmadd.ps";
8876 break;
8877 case OPC_NMSUB_S:
b8aa4598 8878 check_cop1x(ctx);
b6d96bed 8879 {
a7812ae4
PB
8880 TCGv_i32 fp0 = tcg_temp_new_i32();
8881 TCGv_i32 fp1 = tcg_temp_new_i32();
8882 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
8883
8884 gen_load_fpr32(fp0, fs);
8885 gen_load_fpr32(fp1, ft);
8886 gen_load_fpr32(fp2, fr);
895c2d04 8887 gen_helper_float_nmulsub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8888 tcg_temp_free_i32(fp0);
8889 tcg_temp_free_i32(fp1);
b6d96bed 8890 gen_store_fpr32(fp2, fd);
a7812ae4 8891 tcg_temp_free_i32(fp2);
b6d96bed 8892 }
5a5012ec
TS
8893 opn = "nmsub.s";
8894 break;
8895 case OPC_NMSUB_D:
b8aa4598
TS
8896 check_cop1x(ctx);
8897 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 8898 {
a7812ae4
PB
8899 TCGv_i64 fp0 = tcg_temp_new_i64();
8900 TCGv_i64 fp1 = tcg_temp_new_i64();
8901 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8902
8903 gen_load_fpr64(ctx, fp0, fs);
8904 gen_load_fpr64(ctx, fp1, ft);
8905 gen_load_fpr64(ctx, fp2, fr);
895c2d04 8906 gen_helper_float_nmulsub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8907 tcg_temp_free_i64(fp0);
8908 tcg_temp_free_i64(fp1);
b6d96bed 8909 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8910 tcg_temp_free_i64(fp2);
b6d96bed 8911 }
5a5012ec
TS
8912 opn = "nmsub.d";
8913 break;
8914 case OPC_NMSUB_PS:
b8aa4598 8915 check_cp1_64bitmode(ctx);
b6d96bed 8916 {
a7812ae4
PB
8917 TCGv_i64 fp0 = tcg_temp_new_i64();
8918 TCGv_i64 fp1 = tcg_temp_new_i64();
8919 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8920
8921 gen_load_fpr64(ctx, fp0, fs);
8922 gen_load_fpr64(ctx, fp1, ft);
8923 gen_load_fpr64(ctx, fp2, fr);
895c2d04 8924 gen_helper_float_nmulsub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8925 tcg_temp_free_i64(fp0);
8926 tcg_temp_free_i64(fp1);
b6d96bed 8927 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8928 tcg_temp_free_i64(fp2);
b6d96bed 8929 }
5a5012ec
TS
8930 opn = "nmsub.ps";
8931 break;
923617a3
TS
8932 default:
8933 MIPS_INVAL(opn);
5a5012ec
TS
8934 generate_exception (ctx, EXCP_RI);
8935 return;
8936 }
2abf314d 8937 (void)opn; /* avoid a compiler warning */
5a5012ec
TS
8938 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
8939 fregnames[fs], fregnames[ft]);
7a387fff
TS
8940}
8941
26ebe468 8942static void
7db13fae 8943gen_rdhwr (CPUMIPSState *env, DisasContext *ctx, int rt, int rd)
26ebe468
NF
8944{
8945 TCGv t0;
8946
b3167288
RH
8947#if !defined(CONFIG_USER_ONLY)
8948 /* The Linux kernel will emulate rdhwr if it's not supported natively.
8949 Therefore only check the ISA in system mode. */
26ebe468 8950 check_insn(env, ctx, ISA_MIPS32R2);
b3167288 8951#endif
26ebe468
NF
8952 t0 = tcg_temp_new();
8953
8954 switch (rd) {
8955 case 0:
8956 save_cpu_state(ctx, 1);
895c2d04 8957 gen_helper_rdhwr_cpunum(t0, cpu_env);
26ebe468
NF
8958 gen_store_gpr(t0, rt);
8959 break;
8960 case 1:
8961 save_cpu_state(ctx, 1);
895c2d04 8962 gen_helper_rdhwr_synci_step(t0, cpu_env);
26ebe468
NF
8963 gen_store_gpr(t0, rt);
8964 break;
8965 case 2:
8966 save_cpu_state(ctx, 1);
895c2d04 8967 gen_helper_rdhwr_cc(t0, cpu_env);
26ebe468
NF
8968 gen_store_gpr(t0, rt);
8969 break;
8970 case 3:
8971 save_cpu_state(ctx, 1);
895c2d04 8972 gen_helper_rdhwr_ccres(t0, cpu_env);
26ebe468
NF
8973 gen_store_gpr(t0, rt);
8974 break;
8975 case 29:
8976#if defined(CONFIG_USER_ONLY)
7db13fae 8977 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, tls_value));
26ebe468
NF
8978 gen_store_gpr(t0, rt);
8979 break;
8980#else
8981 /* XXX: Some CPUs implement this in hardware.
8982 Not supported yet. */
8983#endif
8984 default: /* Invalid */
8985 MIPS_INVAL("rdhwr");
8986 generate_exception(ctx, EXCP_RI);
8987 break;
8988 }
8989 tcg_temp_free(t0);
8990}
8991
7db13fae 8992static void handle_delay_slot (CPUMIPSState *env, DisasContext *ctx,
c9602061
NF
8993 int insn_bytes)
8994{
8995 if (ctx->hflags & MIPS_HFLAG_BMASK) {
364d4831 8996 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
c9602061
NF
8997 /* Branches completion */
8998 ctx->hflags &= ~MIPS_HFLAG_BMASK;
8999 ctx->bstate = BS_BRANCH;
9000 save_cpu_state(ctx, 0);
9001 /* FIXME: Need to clear can_do_io. */
364d4831 9002 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
c9602061
NF
9003 case MIPS_HFLAG_B:
9004 /* unconditional branch */
9005 MIPS_DEBUG("unconditional branch");
364d4831
NF
9006 if (proc_hflags & MIPS_HFLAG_BX) {
9007 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
9008 }
c9602061
NF
9009 gen_goto_tb(ctx, 0, ctx->btarget);
9010 break;
9011 case MIPS_HFLAG_BL:
9012 /* blikely taken case */
9013 MIPS_DEBUG("blikely branch taken");
9014 gen_goto_tb(ctx, 0, ctx->btarget);
9015 break;
9016 case MIPS_HFLAG_BC:
9017 /* Conditional branch */
9018 MIPS_DEBUG("conditional branch");
9019 {
9020 int l1 = gen_new_label();
9021
9022 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
9023 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
9024 gen_set_label(l1);
9025 gen_goto_tb(ctx, 0, ctx->btarget);
9026 }
9027 break;
9028 case MIPS_HFLAG_BR:
9029 /* unconditional branch to register */
9030 MIPS_DEBUG("branch to register");
3c824109 9031 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
364d4831
NF
9032 TCGv t0 = tcg_temp_new();
9033 TCGv_i32 t1 = tcg_temp_new_i32();
9034
9035 tcg_gen_andi_tl(t0, btarget, 0x1);
9036 tcg_gen_trunc_tl_i32(t1, t0);
9037 tcg_temp_free(t0);
9038 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
9039 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
9040 tcg_gen_or_i32(hflags, hflags, t1);
9041 tcg_temp_free_i32(t1);
9042
9043 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
9044 } else {
9045 tcg_gen_mov_tl(cpu_PC, btarget);
9046 }
c9602061
NF
9047 if (ctx->singlestep_enabled) {
9048 save_cpu_state(ctx, 0);
895c2d04 9049 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
c9602061
NF
9050 }
9051 tcg_gen_exit_tb(0);
9052 break;
9053 default:
9054 MIPS_DEBUG("unknown branch");
9055 break;
9056 }
9057 }
9058}
9059
7a387fff 9060/* ISA extensions (ASEs) */
6af0bf9c 9061/* MIPS16 extension to MIPS32 */
6ea219d0
NF
9062
9063/* MIPS16 major opcodes */
9064enum {
9065 M16_OPC_ADDIUSP = 0x00,
9066 M16_OPC_ADDIUPC = 0x01,
9067 M16_OPC_B = 0x02,
9068 M16_OPC_JAL = 0x03,
9069 M16_OPC_BEQZ = 0x04,
9070 M16_OPC_BNEQZ = 0x05,
9071 M16_OPC_SHIFT = 0x06,
9072 M16_OPC_LD = 0x07,
9073 M16_OPC_RRIA = 0x08,
9074 M16_OPC_ADDIU8 = 0x09,
9075 M16_OPC_SLTI = 0x0a,
9076 M16_OPC_SLTIU = 0x0b,
9077 M16_OPC_I8 = 0x0c,
9078 M16_OPC_LI = 0x0d,
9079 M16_OPC_CMPI = 0x0e,
9080 M16_OPC_SD = 0x0f,
9081 M16_OPC_LB = 0x10,
9082 M16_OPC_LH = 0x11,
9083 M16_OPC_LWSP = 0x12,
9084 M16_OPC_LW = 0x13,
9085 M16_OPC_LBU = 0x14,
9086 M16_OPC_LHU = 0x15,
9087 M16_OPC_LWPC = 0x16,
9088 M16_OPC_LWU = 0x17,
9089 M16_OPC_SB = 0x18,
9090 M16_OPC_SH = 0x19,
9091 M16_OPC_SWSP = 0x1a,
9092 M16_OPC_SW = 0x1b,
9093 M16_OPC_RRR = 0x1c,
9094 M16_OPC_RR = 0x1d,
9095 M16_OPC_EXTEND = 0x1e,
9096 M16_OPC_I64 = 0x1f
9097};
9098
9099/* I8 funct field */
9100enum {
9101 I8_BTEQZ = 0x0,
9102 I8_BTNEZ = 0x1,
9103 I8_SWRASP = 0x2,
9104 I8_ADJSP = 0x3,
9105 I8_SVRS = 0x4,
9106 I8_MOV32R = 0x5,
9107 I8_MOVR32 = 0x7
9108};
9109
9110/* RRR f field */
9111enum {
9112 RRR_DADDU = 0x0,
9113 RRR_ADDU = 0x1,
9114 RRR_DSUBU = 0x2,
9115 RRR_SUBU = 0x3
9116};
9117
9118/* RR funct field */
9119enum {
9120 RR_JR = 0x00,
9121 RR_SDBBP = 0x01,
9122 RR_SLT = 0x02,
9123 RR_SLTU = 0x03,
9124 RR_SLLV = 0x04,
9125 RR_BREAK = 0x05,
9126 RR_SRLV = 0x06,
9127 RR_SRAV = 0x07,
9128 RR_DSRL = 0x08,
9129 RR_CMP = 0x0a,
9130 RR_NEG = 0x0b,
9131 RR_AND = 0x0c,
9132 RR_OR = 0x0d,
9133 RR_XOR = 0x0e,
9134 RR_NOT = 0x0f,
9135 RR_MFHI = 0x10,
9136 RR_CNVT = 0x11,
9137 RR_MFLO = 0x12,
9138 RR_DSRA = 0x13,
9139 RR_DSLLV = 0x14,
9140 RR_DSRLV = 0x16,
9141 RR_DSRAV = 0x17,
9142 RR_MULT = 0x18,
9143 RR_MULTU = 0x19,
9144 RR_DIV = 0x1a,
9145 RR_DIVU = 0x1b,
9146 RR_DMULT = 0x1c,
9147 RR_DMULTU = 0x1d,
9148 RR_DDIV = 0x1e,
9149 RR_DDIVU = 0x1f
9150};
9151
9152/* I64 funct field */
9153enum {
9154 I64_LDSP = 0x0,
9155 I64_SDSP = 0x1,
9156 I64_SDRASP = 0x2,
9157 I64_DADJSP = 0x3,
9158 I64_LDPC = 0x4,
364d4831 9159 I64_DADDIU5 = 0x5,
6ea219d0
NF
9160 I64_DADDIUPC = 0x6,
9161 I64_DADDIUSP = 0x7
9162};
9163
9164/* RR ry field for CNVT */
9165enum {
9166 RR_RY_CNVT_ZEB = 0x0,
9167 RR_RY_CNVT_ZEH = 0x1,
9168 RR_RY_CNVT_ZEW = 0x2,
9169 RR_RY_CNVT_SEB = 0x4,
9170 RR_RY_CNVT_SEH = 0x5,
9171 RR_RY_CNVT_SEW = 0x6,
9172};
9173
364d4831
NF
9174static int xlat (int r)
9175{
9176 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
9177
9178 return map[r];
9179}
9180
9181static void gen_mips16_save (DisasContext *ctx,
9182 int xsregs, int aregs,
9183 int do_ra, int do_s0, int do_s1,
9184 int framesize)
9185{
9186 TCGv t0 = tcg_temp_new();
9187 TCGv t1 = tcg_temp_new();
9188 int args, astatic;
9189
9190 switch (aregs) {
9191 case 0:
9192 case 1:
9193 case 2:
9194 case 3:
9195 case 11:
9196 args = 0;
9197 break;
9198 case 4:
9199 case 5:
9200 case 6:
9201 case 7:
9202 args = 1;
9203 break;
9204 case 8:
9205 case 9:
9206 case 10:
9207 args = 2;
9208 break;
9209 case 12:
9210 case 13:
9211 args = 3;
9212 break;
9213 case 14:
9214 args = 4;
9215 break;
9216 default:
9217 generate_exception(ctx, EXCP_RI);
9218 return;
9219 }
9220
9221 switch (args) {
9222 case 4:
9223 gen_base_offset_addr(ctx, t0, 29, 12);
9224 gen_load_gpr(t1, 7);
5c13fdfd 9225 op_st_sw(t1, t0, ctx);
364d4831
NF
9226 /* Fall through */
9227 case 3:
9228 gen_base_offset_addr(ctx, t0, 29, 8);
9229 gen_load_gpr(t1, 6);
5c13fdfd 9230 op_st_sw(t1, t0, ctx);
364d4831
NF
9231 /* Fall through */
9232 case 2:
9233 gen_base_offset_addr(ctx, t0, 29, 4);
9234 gen_load_gpr(t1, 5);
5c13fdfd 9235 op_st_sw(t1, t0, ctx);
364d4831
NF
9236 /* Fall through */
9237 case 1:
9238 gen_base_offset_addr(ctx, t0, 29, 0);
9239 gen_load_gpr(t1, 4);
5c13fdfd 9240 op_st_sw(t1, t0, ctx);
364d4831
NF
9241 }
9242
9243 gen_load_gpr(t0, 29);
9244
9245#define DECR_AND_STORE(reg) do { \
9246 tcg_gen_subi_tl(t0, t0, 4); \
9247 gen_load_gpr(t1, reg); \
5c13fdfd 9248 op_st_sw(t1, t0, ctx); \
364d4831
NF
9249 } while (0)
9250
9251 if (do_ra) {
9252 DECR_AND_STORE(31);
9253 }
9254
9255 switch (xsregs) {
9256 case 7:
9257 DECR_AND_STORE(30);
9258 /* Fall through */
9259 case 6:
9260 DECR_AND_STORE(23);
9261 /* Fall through */
9262 case 5:
9263 DECR_AND_STORE(22);
9264 /* Fall through */
9265 case 4:
9266 DECR_AND_STORE(21);
9267 /* Fall through */
9268 case 3:
9269 DECR_AND_STORE(20);
9270 /* Fall through */
9271 case 2:
9272 DECR_AND_STORE(19);
9273 /* Fall through */
9274 case 1:
9275 DECR_AND_STORE(18);
9276 }
9277
9278 if (do_s1) {
9279 DECR_AND_STORE(17);
9280 }
9281 if (do_s0) {
9282 DECR_AND_STORE(16);
9283 }
9284
9285 switch (aregs) {
9286 case 0:
9287 case 4:
9288 case 8:
9289 case 12:
9290 case 14:
9291 astatic = 0;
9292 break;
9293 case 1:
9294 case 5:
9295 case 9:
9296 case 13:
9297 astatic = 1;
9298 break;
9299 case 2:
9300 case 6:
9301 case 10:
9302 astatic = 2;
9303 break;
9304 case 3:
9305 case 7:
9306 astatic = 3;
9307 break;
9308 case 11:
9309 astatic = 4;
9310 break;
9311 default:
9312 generate_exception(ctx, EXCP_RI);
9313 return;
9314 }
9315
9316 if (astatic > 0) {
9317 DECR_AND_STORE(7);
9318 if (astatic > 1) {
9319 DECR_AND_STORE(6);
9320 if (astatic > 2) {
9321 DECR_AND_STORE(5);
9322 if (astatic > 3) {
9323 DECR_AND_STORE(4);
9324 }
9325 }
9326 }
9327 }
9328#undef DECR_AND_STORE
9329
9330 tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
9331 tcg_temp_free(t0);
9332 tcg_temp_free(t1);
9333}
9334
9335static void gen_mips16_restore (DisasContext *ctx,
9336 int xsregs, int aregs,
9337 int do_ra, int do_s0, int do_s1,
9338 int framesize)
9339{
9340 int astatic;
9341 TCGv t0 = tcg_temp_new();
9342 TCGv t1 = tcg_temp_new();
9343
9344 tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
9345
9346#define DECR_AND_LOAD(reg) do { \
9347 tcg_gen_subi_tl(t0, t0, 4); \
5c13fdfd 9348 op_ld_lw(t1, t0, ctx); \
364d4831
NF
9349 gen_store_gpr(t1, reg); \
9350 } while (0)
9351
9352 if (do_ra) {
9353 DECR_AND_LOAD(31);
9354 }
9355
9356 switch (xsregs) {
9357 case 7:
9358 DECR_AND_LOAD(30);
9359 /* Fall through */
9360 case 6:
9361 DECR_AND_LOAD(23);
9362 /* Fall through */
9363 case 5:
9364 DECR_AND_LOAD(22);
9365 /* Fall through */
9366 case 4:
9367 DECR_AND_LOAD(21);
9368 /* Fall through */
9369 case 3:
9370 DECR_AND_LOAD(20);
9371 /* Fall through */
9372 case 2:
9373 DECR_AND_LOAD(19);
9374 /* Fall through */
9375 case 1:
9376 DECR_AND_LOAD(18);
9377 }
9378
9379 if (do_s1) {
9380 DECR_AND_LOAD(17);
9381 }
9382 if (do_s0) {
9383 DECR_AND_LOAD(16);
9384 }
9385
9386 switch (aregs) {
9387 case 0:
9388 case 4:
9389 case 8:
9390 case 12:
9391 case 14:
9392 astatic = 0;
9393 break;
9394 case 1:
9395 case 5:
9396 case 9:
9397 case 13:
9398 astatic = 1;
9399 break;
9400 case 2:
9401 case 6:
9402 case 10:
9403 astatic = 2;
9404 break;
9405 case 3:
9406 case 7:
9407 astatic = 3;
9408 break;
9409 case 11:
9410 astatic = 4;
9411 break;
9412 default:
9413 generate_exception(ctx, EXCP_RI);
9414 return;
9415 }
9416
9417 if (astatic > 0) {
9418 DECR_AND_LOAD(7);
9419 if (astatic > 1) {
9420 DECR_AND_LOAD(6);
9421 if (astatic > 2) {
9422 DECR_AND_LOAD(5);
9423 if (astatic > 3) {
9424 DECR_AND_LOAD(4);
9425 }
9426 }
9427 }
9428 }
9429#undef DECR_AND_LOAD
9430
9431 tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
9432 tcg_temp_free(t0);
9433 tcg_temp_free(t1);
9434}
9435
9436static void gen_addiupc (DisasContext *ctx, int rx, int imm,
9437 int is_64_bit, int extended)
9438{
9439 TCGv t0;
9440
9441 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9442 generate_exception(ctx, EXCP_RI);
9443 return;
9444 }
9445
9446 t0 = tcg_temp_new();
9447
9448 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
9449 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
9450 if (!is_64_bit) {
9451 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9452 }
9453
9454 tcg_temp_free(t0);
9455}
9456
9457#if defined(TARGET_MIPS64)
7db13fae 9458static void decode_i64_mips16 (CPUMIPSState *env, DisasContext *ctx,
364d4831
NF
9459 int ry, int funct, int16_t offset,
9460 int extended)
9461{
9462 switch (funct) {
9463 case I64_LDSP:
9464 check_mips_64(ctx);
9465 offset = extended ? offset : offset << 3;
afa88c3a 9466 gen_ld(env, ctx, OPC_LD, ry, 29, offset);
364d4831
NF
9467 break;
9468 case I64_SDSP:
9469 check_mips_64(ctx);
9470 offset = extended ? offset : offset << 3;
5c13fdfd 9471 gen_st(ctx, OPC_SD, ry, 29, offset);
364d4831
NF
9472 break;
9473 case I64_SDRASP:
9474 check_mips_64(ctx);
9475 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
5c13fdfd 9476 gen_st(ctx, OPC_SD, 31, 29, offset);
364d4831
NF
9477 break;
9478 case I64_DADJSP:
9479 check_mips_64(ctx);
9480 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
9481 gen_arith_imm(env, ctx, OPC_DADDIU, 29, 29, offset);
9482 break;
9483 case I64_LDPC:
9484 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9485 generate_exception(ctx, EXCP_RI);
9486 } else {
9487 offset = extended ? offset : offset << 3;
afa88c3a 9488 gen_ld(env, ctx, OPC_LDPC, ry, 0, offset);
364d4831
NF
9489 }
9490 break;
9491 case I64_DADDIU5:
9492 check_mips_64(ctx);
9493 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
9494 gen_arith_imm(env, ctx, OPC_DADDIU, ry, ry, offset);
9495 break;
9496 case I64_DADDIUPC:
9497 check_mips_64(ctx);
9498 offset = extended ? offset : offset << 2;
9499 gen_addiupc(ctx, ry, offset, 1, extended);
9500 break;
9501 case I64_DADDIUSP:
9502 check_mips_64(ctx);
9503 offset = extended ? offset : offset << 2;
9504 gen_arith_imm(env, ctx, OPC_DADDIU, ry, 29, offset);
9505 break;
9506 }
9507}
9508#endif
9509
7db13fae 9510static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
364d4831
NF
9511 int *is_branch)
9512{
895c2d04 9513 int extend = cpu_lduw_code(env, ctx->pc + 2);
364d4831
NF
9514 int op, rx, ry, funct, sa;
9515 int16_t imm, offset;
9516
9517 ctx->opcode = (ctx->opcode << 16) | extend;
9518 op = (ctx->opcode >> 11) & 0x1f;
9519 sa = (ctx->opcode >> 22) & 0x1f;
9520 funct = (ctx->opcode >> 8) & 0x7;
9521 rx = xlat((ctx->opcode >> 8) & 0x7);
9522 ry = xlat((ctx->opcode >> 5) & 0x7);
9523 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
9524 | ((ctx->opcode >> 21) & 0x3f) << 5
9525 | (ctx->opcode & 0x1f));
9526
9527 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
9528 counterparts. */
9529 switch (op) {
9530 case M16_OPC_ADDIUSP:
9531 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
9532 break;
9533 case M16_OPC_ADDIUPC:
9534 gen_addiupc(ctx, rx, imm, 0, 1);
9535 break;
9536 case M16_OPC_B:
9537 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1);
9538 /* No delay slot, so just process as a normal instruction */
9539 break;
9540 case M16_OPC_BEQZ:
9541 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1);
9542 /* No delay slot, so just process as a normal instruction */
9543 break;
9544 case M16_OPC_BNEQZ:
9545 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1);
9546 /* No delay slot, so just process as a normal instruction */
9547 break;
9548 case M16_OPC_SHIFT:
9549 switch (ctx->opcode & 0x3) {
9550 case 0x0:
9551 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
9552 break;
9553 case 0x1:
9554#if defined(TARGET_MIPS64)
9555 check_mips_64(ctx);
9556 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
9557#else
9558 generate_exception(ctx, EXCP_RI);
9559#endif
9560 break;
9561 case 0x2:
9562 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
9563 break;
9564 case 0x3:
9565 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
9566 break;
9567 }
9568 break;
9569#if defined(TARGET_MIPS64)
9570 case M16_OPC_LD:
9571 check_mips_64(ctx);
afa88c3a 9572 gen_ld(env, ctx, OPC_LD, ry, rx, offset);
364d4831
NF
9573 break;
9574#endif
9575 case M16_OPC_RRIA:
9576 imm = ctx->opcode & 0xf;
9577 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
9578 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
9579 imm = (int16_t) (imm << 1) >> 1;
9580 if ((ctx->opcode >> 4) & 0x1) {
9581#if defined(TARGET_MIPS64)
9582 check_mips_64(ctx);
9583 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
9584#else
9585 generate_exception(ctx, EXCP_RI);
9586#endif
9587 } else {
9588 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
9589 }
9590 break;
9591 case M16_OPC_ADDIU8:
9592 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
9593 break;
9594 case M16_OPC_SLTI:
9fa77488 9595 gen_slt_imm(env, ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
9596 break;
9597 case M16_OPC_SLTIU:
9fa77488 9598 gen_slt_imm(env, ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
9599 break;
9600 case M16_OPC_I8:
9601 switch (funct) {
9602 case I8_BTEQZ:
9603 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1);
9604 break;
9605 case I8_BTNEZ:
9606 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
9607 break;
9608 case I8_SWRASP:
5c13fdfd 9609 gen_st(ctx, OPC_SW, 31, 29, imm);
364d4831
NF
9610 break;
9611 case I8_ADJSP:
9612 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm);
9613 break;
9614 case I8_SVRS:
9615 {
9616 int xsregs = (ctx->opcode >> 24) & 0x7;
9617 int aregs = (ctx->opcode >> 16) & 0xf;
9618 int do_ra = (ctx->opcode >> 6) & 0x1;
9619 int do_s0 = (ctx->opcode >> 5) & 0x1;
9620 int do_s1 = (ctx->opcode >> 4) & 0x1;
9621 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
9622 | (ctx->opcode & 0xf)) << 3;
9623
9624 if (ctx->opcode & (1 << 7)) {
9625 gen_mips16_save(ctx, xsregs, aregs,
9626 do_ra, do_s0, do_s1,
9627 framesize);
9628 } else {
9629 gen_mips16_restore(ctx, xsregs, aregs,
9630 do_ra, do_s0, do_s1,
9631 framesize);
9632 }
9633 }
9634 break;
9635 default:
9636 generate_exception(ctx, EXCP_RI);
9637 break;
9638 }
9639 break;
9640 case M16_OPC_LI:
9641 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
9642 break;
9643 case M16_OPC_CMPI:
9644 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
9645 break;
9646#if defined(TARGET_MIPS64)
9647 case M16_OPC_SD:
5c13fdfd 9648 gen_st(ctx, OPC_SD, ry, rx, offset);
364d4831
NF
9649 break;
9650#endif
9651 case M16_OPC_LB:
afa88c3a 9652 gen_ld(env, ctx, OPC_LB, ry, rx, offset);
364d4831
NF
9653 break;
9654 case M16_OPC_LH:
afa88c3a 9655 gen_ld(env, ctx, OPC_LH, ry, rx, offset);
364d4831
NF
9656 break;
9657 case M16_OPC_LWSP:
afa88c3a 9658 gen_ld(env, ctx, OPC_LW, rx, 29, offset);
364d4831
NF
9659 break;
9660 case M16_OPC_LW:
afa88c3a 9661 gen_ld(env, ctx, OPC_LW, ry, rx, offset);
364d4831
NF
9662 break;
9663 case M16_OPC_LBU:
afa88c3a 9664 gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
9665 break;
9666 case M16_OPC_LHU:
afa88c3a 9667 gen_ld(env, ctx, OPC_LHU, ry, rx, offset);
364d4831
NF
9668 break;
9669 case M16_OPC_LWPC:
afa88c3a 9670 gen_ld(env, ctx, OPC_LWPC, rx, 0, offset);
364d4831
NF
9671 break;
9672#if defined(TARGET_MIPS64)
9673 case M16_OPC_LWU:
afa88c3a 9674 gen_ld(env, ctx, OPC_LWU, ry, rx, offset);
364d4831
NF
9675 break;
9676#endif
9677 case M16_OPC_SB:
5c13fdfd 9678 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
9679 break;
9680 case M16_OPC_SH:
5c13fdfd 9681 gen_st(ctx, OPC_SH, ry, rx, offset);
364d4831
NF
9682 break;
9683 case M16_OPC_SWSP:
5c13fdfd 9684 gen_st(ctx, OPC_SW, rx, 29, offset);
364d4831
NF
9685 break;
9686 case M16_OPC_SW:
5c13fdfd 9687 gen_st(ctx, OPC_SW, ry, rx, offset);
364d4831
NF
9688 break;
9689#if defined(TARGET_MIPS64)
9690 case M16_OPC_I64:
9691 decode_i64_mips16(env, ctx, ry, funct, offset, 1);
9692 break;
9693#endif
9694 default:
9695 generate_exception(ctx, EXCP_RI);
9696 break;
9697 }
9698
9699 return 4;
9700}
9701
7db13fae 9702static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
364d4831
NF
9703 int *is_branch)
9704{
9705 int rx, ry;
9706 int sa;
9707 int op, cnvt_op, op1, offset;
9708 int funct;
9709 int n_bytes;
9710
9711 op = (ctx->opcode >> 11) & 0x1f;
9712 sa = (ctx->opcode >> 2) & 0x7;
9713 sa = sa == 0 ? 8 : sa;
9714 rx = xlat((ctx->opcode >> 8) & 0x7);
9715 cnvt_op = (ctx->opcode >> 5) & 0x7;
9716 ry = xlat((ctx->opcode >> 5) & 0x7);
9717 op1 = offset = ctx->opcode & 0x1f;
9718
9719 n_bytes = 2;
9720
9721 switch (op) {
9722 case M16_OPC_ADDIUSP:
9723 {
9724 int16_t imm = ((uint8_t) ctx->opcode) << 2;
9725
9726 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
9727 }
9728 break;
9729 case M16_OPC_ADDIUPC:
9730 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
9731 break;
9732 case M16_OPC_B:
9733 offset = (ctx->opcode & 0x7ff) << 1;
9734 offset = (int16_t)(offset << 4) >> 4;
9735 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset);
9736 /* No delay slot, so just process as a normal instruction */
9737 break;
9738 case M16_OPC_JAL:
895c2d04 9739 offset = cpu_lduw_code(env, ctx->pc + 2);
364d4831
NF
9740 offset = (((ctx->opcode & 0x1f) << 21)
9741 | ((ctx->opcode >> 5) & 0x1f) << 16
9742 | offset) << 2;
620e48f6 9743 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS;
364d4831
NF
9744 gen_compute_branch(ctx, op, 4, rx, ry, offset);
9745 n_bytes = 4;
9746 *is_branch = 1;
9747 break;
9748 case M16_OPC_BEQZ:
9749 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
9750 /* No delay slot, so just process as a normal instruction */
9751 break;
9752 case M16_OPC_BNEQZ:
9753 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
9754 /* No delay slot, so just process as a normal instruction */
9755 break;
9756 case M16_OPC_SHIFT:
9757 switch (ctx->opcode & 0x3) {
9758 case 0x0:
9759 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
9760 break;
9761 case 0x1:
9762#if defined(TARGET_MIPS64)
9763 check_mips_64(ctx);
9764 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
9765#else
9766 generate_exception(ctx, EXCP_RI);
9767#endif
9768 break;
9769 case 0x2:
9770 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
9771 break;
9772 case 0x3:
9773 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
9774 break;
9775 }
9776 break;
9777#if defined(TARGET_MIPS64)
9778 case M16_OPC_LD:
9779 check_mips_64(ctx);
afa88c3a 9780 gen_ld(env, ctx, OPC_LD, ry, rx, offset << 3);
364d4831
NF
9781 break;
9782#endif
9783 case M16_OPC_RRIA:
9784 {
9785 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
9786
9787 if ((ctx->opcode >> 4) & 1) {
9788#if defined(TARGET_MIPS64)
9789 check_mips_64(ctx);
9790 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
9791#else
9792 generate_exception(ctx, EXCP_RI);
9793#endif
9794 } else {
9795 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
9796 }
9797 }
9798 break;
9799 case M16_OPC_ADDIU8:
9800 {
9801 int16_t imm = (int8_t) ctx->opcode;
9802
9803 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
9804 }
9805 break;
9806 case M16_OPC_SLTI:
9807 {
9808 int16_t imm = (uint8_t) ctx->opcode;
9fa77488 9809 gen_slt_imm(env, ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
9810 }
9811 break;
9812 case M16_OPC_SLTIU:
9813 {
9814 int16_t imm = (uint8_t) ctx->opcode;
9fa77488 9815 gen_slt_imm(env, ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
9816 }
9817 break;
9818 case M16_OPC_I8:
9819 {
9820 int reg32;
9821
9822 funct = (ctx->opcode >> 8) & 0x7;
9823 switch (funct) {
9824 case I8_BTEQZ:
9825 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
9826 ((int8_t)ctx->opcode) << 1);
9827 break;
9828 case I8_BTNEZ:
9829 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
9830 ((int8_t)ctx->opcode) << 1);
9831 break;
9832 case I8_SWRASP:
5c13fdfd 9833 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
364d4831
NF
9834 break;
9835 case I8_ADJSP:
9836 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29,
9837 ((int8_t)ctx->opcode) << 3);
9838 break;
9839 case I8_SVRS:
9840 {
9841 int do_ra = ctx->opcode & (1 << 6);
9842 int do_s0 = ctx->opcode & (1 << 5);
9843 int do_s1 = ctx->opcode & (1 << 4);
9844 int framesize = ctx->opcode & 0xf;
9845
9846 if (framesize == 0) {
9847 framesize = 128;
9848 } else {
9849 framesize = framesize << 3;
9850 }
9851
9852 if (ctx->opcode & (1 << 7)) {
9853 gen_mips16_save(ctx, 0, 0,
9854 do_ra, do_s0, do_s1, framesize);
9855 } else {
9856 gen_mips16_restore(ctx, 0, 0,
9857 do_ra, do_s0, do_s1, framesize);
9858 }
9859 }
9860 break;
9861 case I8_MOV32R:
9862 {
9863 int rz = xlat(ctx->opcode & 0x7);
9864
9865 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
9866 ((ctx->opcode >> 5) & 0x7);
9867 gen_arith(env, ctx, OPC_ADDU, reg32, rz, 0);
9868 }
9869 break;
9870 case I8_MOVR32:
9871 reg32 = ctx->opcode & 0x1f;
9872 gen_arith(env, ctx, OPC_ADDU, ry, reg32, 0);
9873 break;
9874 default:
9875 generate_exception(ctx, EXCP_RI);
9876 break;
9877 }
9878 }
9879 break;
9880 case M16_OPC_LI:
9881 {
9882 int16_t imm = (uint8_t) ctx->opcode;
9883
9884 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 0, imm);
9885 }
9886 break;
9887 case M16_OPC_CMPI:
9888 {
9889 int16_t imm = (uint8_t) ctx->opcode;
9fa77488 9890 gen_logic_imm(env, ctx, OPC_XORI, 24, rx, imm);
364d4831
NF
9891 }
9892 break;
9893#if defined(TARGET_MIPS64)
9894 case M16_OPC_SD:
9895 check_mips_64(ctx);
5c13fdfd 9896 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
364d4831
NF
9897 break;
9898#endif
9899 case M16_OPC_LB:
afa88c3a 9900 gen_ld(env, ctx, OPC_LB, ry, rx, offset);
364d4831
NF
9901 break;
9902 case M16_OPC_LH:
afa88c3a 9903 gen_ld(env, ctx, OPC_LH, ry, rx, offset << 1);
364d4831
NF
9904 break;
9905 case M16_OPC_LWSP:
afa88c3a 9906 gen_ld(env, ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
9907 break;
9908 case M16_OPC_LW:
afa88c3a 9909 gen_ld(env, ctx, OPC_LW, ry, rx, offset << 2);
364d4831
NF
9910 break;
9911 case M16_OPC_LBU:
afa88c3a 9912 gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
9913 break;
9914 case M16_OPC_LHU:
afa88c3a 9915 gen_ld(env, ctx, OPC_LHU, ry, rx, offset << 1);
364d4831
NF
9916 break;
9917 case M16_OPC_LWPC:
afa88c3a 9918 gen_ld(env, ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
9919 break;
9920#if defined (TARGET_MIPS64)
9921 case M16_OPC_LWU:
9922 check_mips_64(ctx);
afa88c3a 9923 gen_ld(env, ctx, OPC_LWU, ry, rx, offset << 2);
364d4831
NF
9924 break;
9925#endif
9926 case M16_OPC_SB:
5c13fdfd 9927 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
9928 break;
9929 case M16_OPC_SH:
5c13fdfd 9930 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
364d4831
NF
9931 break;
9932 case M16_OPC_SWSP:
5c13fdfd 9933 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
9934 break;
9935 case M16_OPC_SW:
5c13fdfd 9936 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
364d4831
NF
9937 break;
9938 case M16_OPC_RRR:
9939 {
9940 int rz = xlat((ctx->opcode >> 2) & 0x7);
9941 int mips32_op;
9942
9943 switch (ctx->opcode & 0x3) {
9944 case RRR_ADDU:
9945 mips32_op = OPC_ADDU;
9946 break;
9947 case RRR_SUBU:
9948 mips32_op = OPC_SUBU;
9949 break;
9950#if defined(TARGET_MIPS64)
9951 case RRR_DADDU:
9952 mips32_op = OPC_DADDU;
9953 check_mips_64(ctx);
9954 break;
9955 case RRR_DSUBU:
9956 mips32_op = OPC_DSUBU;
9957 check_mips_64(ctx);
9958 break;
9959#endif
9960 default:
9961 generate_exception(ctx, EXCP_RI);
9962 goto done;
9963 }
9964
9965 gen_arith(env, ctx, mips32_op, rz, rx, ry);
9966 done:
9967 ;
9968 }
9969 break;
9970 case M16_OPC_RR:
9971 switch (op1) {
9972 case RR_JR:
9973 {
9974 int nd = (ctx->opcode >> 7) & 0x1;
9975 int link = (ctx->opcode >> 6) & 0x1;
9976 int ra = (ctx->opcode >> 5) & 0x1;
9977
9978 if (link) {
620e48f6 9979 op = nd ? OPC_JALRC : OPC_JALRS;
364d4831
NF
9980 } else {
9981 op = OPC_JR;
9982 }
9983
9984 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
9985 if (!nd) {
9986 *is_branch = 1;
9987 }
9988 }
9989 break;
9990 case RR_SDBBP:
9991 /* XXX: not clear which exception should be raised
9992 * when in debug mode...
9993 */
9994 check_insn(env, ctx, ISA_MIPS32);
9995 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9996 generate_exception(ctx, EXCP_DBp);
9997 } else {
9998 generate_exception(ctx, EXCP_DBp);
9999 }
10000 break;
10001 case RR_SLT:
9fa77488 10002 gen_slt(env, ctx, OPC_SLT, 24, rx, ry);
364d4831
NF
10003 break;
10004 case RR_SLTU:
9fa77488 10005 gen_slt(env, ctx, OPC_SLTU, 24, rx, ry);
364d4831
NF
10006 break;
10007 case RR_BREAK:
10008 generate_exception(ctx, EXCP_BREAK);
10009 break;
10010 case RR_SLLV:
10011 gen_shift(env, ctx, OPC_SLLV, ry, rx, ry);
10012 break;
10013 case RR_SRLV:
10014 gen_shift(env, ctx, OPC_SRLV, ry, rx, ry);
10015 break;
10016 case RR_SRAV:
10017 gen_shift(env, ctx, OPC_SRAV, ry, rx, ry);
10018 break;
10019#if defined (TARGET_MIPS64)
10020 case RR_DSRL:
10021 check_mips_64(ctx);
10022 gen_shift_imm(env, ctx, OPC_DSRL, ry, ry, sa);
10023 break;
10024#endif
10025 case RR_CMP:
9fa77488 10026 gen_logic(env, ctx, OPC_XOR, 24, rx, ry);
364d4831
NF
10027 break;
10028 case RR_NEG:
10029 gen_arith(env, ctx, OPC_SUBU, rx, 0, ry);
10030 break;
10031 case RR_AND:
9fa77488 10032 gen_logic(env, ctx, OPC_AND, rx, rx, ry);
364d4831
NF
10033 break;
10034 case RR_OR:
9fa77488 10035 gen_logic(env, ctx, OPC_OR, rx, rx, ry);
364d4831
NF
10036 break;
10037 case RR_XOR:
9fa77488 10038 gen_logic(env, ctx, OPC_XOR, rx, rx, ry);
364d4831
NF
10039 break;
10040 case RR_NOT:
9fa77488 10041 gen_logic(env, ctx, OPC_NOR, rx, ry, 0);
364d4831
NF
10042 break;
10043 case RR_MFHI:
10044 gen_HILO(ctx, OPC_MFHI, rx);
10045 break;
10046 case RR_CNVT:
10047 switch (cnvt_op) {
10048 case RR_RY_CNVT_ZEB:
10049 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
10050 break;
10051 case RR_RY_CNVT_ZEH:
10052 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
10053 break;
10054 case RR_RY_CNVT_SEB:
10055 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
10056 break;
10057 case RR_RY_CNVT_SEH:
10058 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
10059 break;
10060#if defined (TARGET_MIPS64)
10061 case RR_RY_CNVT_ZEW:
10062 check_mips_64(ctx);
10063 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
10064 break;
10065 case RR_RY_CNVT_SEW:
10066 check_mips_64(ctx);
10067 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
10068 break;
10069#endif
10070 default:
10071 generate_exception(ctx, EXCP_RI);
10072 break;
10073 }
10074 break;
10075 case RR_MFLO:
10076 gen_HILO(ctx, OPC_MFLO, rx);
10077 break;
10078#if defined (TARGET_MIPS64)
10079 case RR_DSRA:
10080 check_mips_64(ctx);
10081 gen_shift_imm(env, ctx, OPC_DSRA, ry, ry, sa);
10082 break;
10083 case RR_DSLLV:
10084 check_mips_64(ctx);
10085 gen_shift(env, ctx, OPC_DSLLV, ry, rx, ry);
10086 break;
10087 case RR_DSRLV:
10088 check_mips_64(ctx);
10089 gen_shift(env, ctx, OPC_DSRLV, ry, rx, ry);
10090 break;
10091 case RR_DSRAV:
10092 check_mips_64(ctx);
10093 gen_shift(env, ctx, OPC_DSRAV, ry, rx, ry);
10094 break;
10095#endif
10096 case RR_MULT:
10097 gen_muldiv(ctx, OPC_MULT, rx, ry);
10098 break;
10099 case RR_MULTU:
10100 gen_muldiv(ctx, OPC_MULTU, rx, ry);
10101 break;
10102 case RR_DIV:
10103 gen_muldiv(ctx, OPC_DIV, rx, ry);
10104 break;
10105 case RR_DIVU:
10106 gen_muldiv(ctx, OPC_DIVU, rx, ry);
10107 break;
10108#if defined (TARGET_MIPS64)
10109 case RR_DMULT:
10110 check_mips_64(ctx);
10111 gen_muldiv(ctx, OPC_DMULT, rx, ry);
10112 break;
10113 case RR_DMULTU:
10114 check_mips_64(ctx);
10115 gen_muldiv(ctx, OPC_DMULTU, rx, ry);
10116 break;
10117 case RR_DDIV:
10118 check_mips_64(ctx);
10119 gen_muldiv(ctx, OPC_DDIV, rx, ry);
10120 break;
10121 case RR_DDIVU:
10122 check_mips_64(ctx);
10123 gen_muldiv(ctx, OPC_DDIVU, rx, ry);
10124 break;
10125#endif
10126 default:
10127 generate_exception(ctx, EXCP_RI);
10128 break;
10129 }
10130 break;
10131 case M16_OPC_EXTEND:
10132 decode_extended_mips16_opc(env, ctx, is_branch);
10133 n_bytes = 4;
10134 break;
10135#if defined(TARGET_MIPS64)
10136 case M16_OPC_I64:
10137 funct = (ctx->opcode >> 8) & 0x7;
10138 decode_i64_mips16(env, ctx, ry, funct, offset, 0);
10139 break;
10140#endif
10141 default:
10142 generate_exception(ctx, EXCP_RI);
10143 break;
10144 }
10145
10146 return n_bytes;
10147}
10148
3c824109 10149/* microMIPS extension to MIPS32 */
6af0bf9c 10150
3c824109 10151/* microMIPS32 major opcodes */
6af0bf9c 10152
3c824109
NF
10153enum {
10154 POOL32A = 0x00,
10155 POOL16A = 0x01,
10156 LBU16 = 0x02,
10157 MOVE16 = 0x03,
10158 ADDI32 = 0x04,
10159 LBU32 = 0x05,
10160 SB32 = 0x06,
10161 LB32 = 0x07,
10162
10163 POOL32B = 0x08,
10164 POOL16B = 0x09,
10165 LHU16 = 0x0a,
10166 ANDI16 = 0x0b,
10167 ADDIU32 = 0x0c,
10168 LHU32 = 0x0d,
10169 SH32 = 0x0e,
10170 LH32 = 0x0f,
10171
10172 POOL32I = 0x10,
10173 POOL16C = 0x11,
10174 LWSP16 = 0x12,
10175 POOL16D = 0x13,
10176 ORI32 = 0x14,
10177 POOL32F = 0x15,
10178 POOL32S = 0x16,
10179 DADDIU32 = 0x17,
10180
10181 POOL32C = 0x18,
10182 LWGP16 = 0x19,
10183 LW16 = 0x1a,
10184 POOL16E = 0x1b,
10185 XORI32 = 0x1c,
10186 JALS32 = 0x1d,
10187 ADDIUPC = 0x1e,
10188 POOL48A = 0x1f,
10189
10190 /* 0x20 is reserved */
10191 RES_20 = 0x20,
10192 POOL16F = 0x21,
10193 SB16 = 0x22,
10194 BEQZ16 = 0x23,
10195 SLTI32 = 0x24,
10196 BEQ32 = 0x25,
10197 SWC132 = 0x26,
10198 LWC132 = 0x27,
10199
10200 /* 0x28 and 0x29 are reserved */
10201 RES_28 = 0x28,
10202 RES_29 = 0x29,
10203 SH16 = 0x2a,
10204 BNEZ16 = 0x2b,
10205 SLTIU32 = 0x2c,
10206 BNE32 = 0x2d,
10207 SDC132 = 0x2e,
10208 LDC132 = 0x2f,
10209
10210 /* 0x30 and 0x31 are reserved */
10211 RES_30 = 0x30,
10212 RES_31 = 0x31,
10213 SWSP16 = 0x32,
10214 B16 = 0x33,
10215 ANDI32 = 0x34,
10216 J32 = 0x35,
10217 SD32 = 0x36,
10218 LD32 = 0x37,
10219
10220 /* 0x38 and 0x39 are reserved */
10221 RES_38 = 0x38,
10222 RES_39 = 0x39,
10223 SW16 = 0x3a,
10224 LI16 = 0x3b,
10225 JALX32 = 0x3c,
10226 JAL32 = 0x3d,
10227 SW32 = 0x3e,
10228 LW32 = 0x3f
10229};
10230
10231/* POOL32A encoding of minor opcode field */
10232
10233enum {
10234 /* These opcodes are distinguished only by bits 9..6; those bits are
10235 * what are recorded below. */
10236 SLL32 = 0x0,
10237 SRL32 = 0x1,
10238 SRA = 0x2,
10239 ROTR = 0x3,
10240
10241 SLLV = 0x0,
10242 SRLV = 0x1,
10243 SRAV = 0x2,
10244 ROTRV = 0x3,
10245 ADD = 0x4,
10246 ADDU32 = 0x5,
10247 SUB = 0x6,
10248 SUBU32 = 0x7,
10249 MUL = 0x8,
10250 AND = 0x9,
10251 OR32 = 0xa,
10252 NOR = 0xb,
10253 XOR32 = 0xc,
10254 SLT = 0xd,
10255 SLTU = 0xe,
10256
10257 MOVN = 0x0,
10258 MOVZ = 0x1,
10259 LWXS = 0x4,
10260
10261 /* The following can be distinguished by their lower 6 bits. */
10262 INS = 0x0c,
10263 EXT = 0x2c,
10264 POOL32AXF = 0x3c
10265};
10266
10267/* POOL32AXF encoding of minor opcode field extension */
10268
10269enum {
10270 /* bits 11..6 */
10271 TEQ = 0x00,
10272 TGE = 0x08,
10273 TGEU = 0x10,
10274 TLT = 0x20,
10275 TLTU = 0x28,
10276 TNE = 0x30,
10277
10278 MFC0 = 0x03,
10279 MTC0 = 0x0b,
10280
10281 /* bits 13..12 for 0x01 */
10282 MFHI_ACC = 0x0,
10283 MFLO_ACC = 0x1,
10284 MTHI_ACC = 0x2,
10285 MTLO_ACC = 0x3,
10286
10287 /* bits 13..12 for 0x2a */
10288 MADD_ACC = 0x0,
10289 MADDU_ACC = 0x1,
10290 MSUB_ACC = 0x2,
10291 MSUBU_ACC = 0x3,
10292
10293 /* bits 13..12 for 0x32 */
10294 MULT_ACC = 0x0,
10295 MULTU_ACC = 0x0,
10296
10297 /* bits 15..12 for 0x2c */
10298 SEB = 0x2,
10299 SEH = 0x3,
10300 CLO = 0x4,
10301 CLZ = 0x5,
10302 RDHWR = 0x6,
10303 WSBH = 0x7,
10304 MULT = 0x8,
10305 MULTU = 0x9,
10306 DIV = 0xa,
10307 DIVU = 0xb,
10308 MADD = 0xc,
10309 MADDU = 0xd,
10310 MSUB = 0xe,
10311 MSUBU = 0xf,
10312
10313 /* bits 15..12 for 0x34 */
10314 MFC2 = 0x4,
10315 MTC2 = 0x5,
10316 MFHC2 = 0x8,
10317 MTHC2 = 0x9,
10318 CFC2 = 0xc,
10319 CTC2 = 0xd,
10320
10321 /* bits 15..12 for 0x3c */
10322 JALR = 0x0,
10323 JR = 0x0, /* alias */
10324 JALR_HB = 0x1,
10325 JALRS = 0x4,
10326 JALRS_HB = 0x5,
10327
10328 /* bits 15..12 for 0x05 */
10329 RDPGPR = 0xe,
10330 WRPGPR = 0xf,
10331
10332 /* bits 15..12 for 0x0d */
10333 TLBP = 0x0,
10334 TLBR = 0x1,
10335 TLBWI = 0x2,
10336 TLBWR = 0x3,
10337 WAIT = 0x9,
10338 IRET = 0xd,
10339 DERET = 0xe,
10340 ERET = 0xf,
10341
10342 /* bits 15..12 for 0x15 */
10343 DMT = 0x0,
10344 DVPE = 0x1,
10345 EMT = 0x2,
10346 EVPE = 0x3,
10347
10348 /* bits 15..12 for 0x1d */
10349 DI = 0x4,
10350 EI = 0x5,
10351
10352 /* bits 15..12 for 0x2d */
10353 SYNC = 0x6,
10354 SYSCALL = 0x8,
10355 SDBBP = 0xd,
10356
10357 /* bits 15..12 for 0x35 */
10358 MFHI32 = 0x0,
10359 MFLO32 = 0x1,
10360 MTHI32 = 0x2,
10361 MTLO32 = 0x3,
10362};
10363
10364/* POOL32B encoding of minor opcode field (bits 15..12) */
10365
10366enum {
10367 LWC2 = 0x0,
10368 LWP = 0x1,
10369 LDP = 0x4,
10370 LWM32 = 0x5,
10371 CACHE = 0x6,
10372 LDM = 0x7,
10373 SWC2 = 0x8,
10374 SWP = 0x9,
10375 SDP = 0xc,
10376 SWM32 = 0xd,
10377 SDM = 0xf
10378};
10379
10380/* POOL32C encoding of minor opcode field (bits 15..12) */
10381
10382enum {
10383 LWL = 0x0,
10384 SWL = 0x8,
10385 LWR = 0x1,
10386 SWR = 0x9,
10387 PREF = 0x2,
10388 /* 0xa is reserved */
10389 LL = 0x3,
10390 SC = 0xb,
10391 LDL = 0x4,
10392 SDL = 0xc,
10393 LDR = 0x5,
10394 SDR = 0xd,
10395 /* 0x6 is reserved */
10396 LWU = 0xe,
10397 LLD = 0x7,
10398 SCD = 0xf
10399};
10400
10401/* POOL32F encoding of minor opcode field (bits 5..0) */
10402
10403enum {
10404 /* These are the bit 7..6 values */
10405 ADD_FMT = 0x0,
10406 MOVN_FMT = 0x0,
10407
10408 SUB_FMT = 0x1,
10409 MOVZ_FMT = 0x1,
10410
10411 MUL_FMT = 0x2,
10412
10413 DIV_FMT = 0x3,
10414
10415 /* These are the bit 8..6 values */
10416 RSQRT2_FMT = 0x0,
10417 MOVF_FMT = 0x0,
10418
10419 LWXC1 = 0x1,
10420 MOVT_FMT = 0x1,
10421
10422 PLL_PS = 0x2,
10423 SWXC1 = 0x2,
10424
10425 PLU_PS = 0x3,
10426 LDXC1 = 0x3,
10427
10428 PUL_PS = 0x4,
10429 SDXC1 = 0x4,
10430 RECIP2_FMT = 0x4,
10431
10432 PUU_PS = 0x5,
10433 LUXC1 = 0x5,
10434
10435 CVT_PS_S = 0x6,
10436 SUXC1 = 0x6,
10437 ADDR_PS = 0x6,
10438 PREFX = 0x6,
10439
10440 MULR_PS = 0x7,
10441
10442 MADD_S = 0x01,
10443 MADD_D = 0x09,
10444 MADD_PS = 0x11,
10445 ALNV_PS = 0x19,
10446 MSUB_S = 0x21,
10447 MSUB_D = 0x29,
10448 MSUB_PS = 0x31,
10449
10450 NMADD_S = 0x02,
10451 NMADD_D = 0x0a,
10452 NMADD_PS = 0x12,
10453 NMSUB_S = 0x22,
10454 NMSUB_D = 0x2a,
10455 NMSUB_PS = 0x32,
10456
10457 POOL32FXF = 0x3b,
10458
10459 CABS_COND_FMT = 0x1c, /* MIPS3D */
10460 C_COND_FMT = 0x3c
10461};
10462
10463/* POOL32Fxf encoding of minor opcode extension field */
10464
10465enum {
10466 CVT_L = 0x04,
10467 RSQRT_FMT = 0x08,
10468 FLOOR_L = 0x0c,
10469 CVT_PW_PS = 0x1c,
10470 CVT_W = 0x24,
10471 SQRT_FMT = 0x28,
10472 FLOOR_W = 0x2c,
10473 CVT_PS_PW = 0x3c,
10474 CFC1 = 0x40,
10475 RECIP_FMT = 0x48,
10476 CEIL_L = 0x4c,
10477 CTC1 = 0x60,
10478 CEIL_W = 0x6c,
10479 MFC1 = 0x80,
10480 CVT_S_PL = 0x84,
10481 TRUNC_L = 0x8c,
10482 MTC1 = 0xa0,
10483 CVT_S_PU = 0xa4,
10484 TRUNC_W = 0xac,
10485 MFHC1 = 0xc0,
10486 ROUND_L = 0xcc,
10487 MTHC1 = 0xe0,
10488 ROUND_W = 0xec,
10489
10490 MOV_FMT = 0x01,
10491 MOVF = 0x05,
10492 ABS_FMT = 0x0d,
10493 RSQRT1_FMT = 0x1d,
10494 MOVT = 0x25,
10495 NEG_FMT = 0x2d,
10496 CVT_D = 0x4d,
10497 RECIP1_FMT = 0x5d,
10498 CVT_S = 0x6d
10499};
10500
10501/* POOL32I encoding of minor opcode field (bits 25..21) */
10502
10503enum {
10504 BLTZ = 0x00,
10505 BLTZAL = 0x01,
10506 BGEZ = 0x02,
10507 BGEZAL = 0x03,
10508 BLEZ = 0x04,
10509 BNEZC = 0x05,
10510 BGTZ = 0x06,
10511 BEQZC = 0x07,
10512 TLTI = 0x08,
10513 TGEI = 0x09,
10514 TLTIU = 0x0a,
10515 TGEIU = 0x0b,
10516 TNEI = 0x0c,
10517 LUI = 0x0d,
10518 TEQI = 0x0e,
10519 SYNCI = 0x10,
10520 BLTZALS = 0x11,
10521 BGEZALS = 0x13,
10522 BC2F = 0x14,
10523 BC2T = 0x15,
10524 BPOSGE64 = 0x1a,
10525 BPOSGE32 = 0x1b,
10526 /* These overlap and are distinguished by bit16 of the instruction */
10527 BC1F = 0x1c,
10528 BC1T = 0x1d,
10529 BC1ANY2F = 0x1c,
10530 BC1ANY2T = 0x1d,
10531 BC1ANY4F = 0x1e,
10532 BC1ANY4T = 0x1f
10533};
10534
10535/* POOL16A encoding of minor opcode field */
10536
10537enum {
10538 ADDU16 = 0x0,
10539 SUBU16 = 0x1
10540};
10541
10542/* POOL16B encoding of minor opcode field */
10543
10544enum {
10545 SLL16 = 0x0,
10546 SRL16 = 0x1
10547};
10548
10549/* POOL16C encoding of minor opcode field */
10550
10551enum {
10552 NOT16 = 0x00,
10553 XOR16 = 0x04,
10554 AND16 = 0x08,
10555 OR16 = 0x0c,
10556 LWM16 = 0x10,
10557 SWM16 = 0x14,
10558 JR16 = 0x18,
10559 JRC16 = 0x1a,
10560 JALR16 = 0x1c,
10561 JALR16S = 0x1e,
10562 MFHI16 = 0x20,
10563 MFLO16 = 0x24,
10564 BREAK16 = 0x28,
10565 SDBBP16 = 0x2c,
10566 JRADDIUSP = 0x30
10567};
10568
10569/* POOL16D encoding of minor opcode field */
10570
10571enum {
10572 ADDIUS5 = 0x0,
10573 ADDIUSP = 0x1
10574};
10575
10576/* POOL16E encoding of minor opcode field */
10577
10578enum {
10579 ADDIUR2 = 0x0,
10580 ADDIUR1SP = 0x1
10581};
10582
10583static int mmreg (int r)
10584{
10585 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
10586
10587 return map[r];
10588}
10589
10590/* Used for 16-bit store instructions. */
10591static int mmreg2 (int r)
10592{
10593 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
10594
10595 return map[r];
10596}
10597
10598#define uMIPS_RD(op) ((op >> 7) & 0x7)
10599#define uMIPS_RS(op) ((op >> 4) & 0x7)
10600#define uMIPS_RS2(op) uMIPS_RS(op)
10601#define uMIPS_RS1(op) ((op >> 1) & 0x7)
10602#define uMIPS_RD5(op) ((op >> 5) & 0x1f)
10603#define uMIPS_RS5(op) (op & 0x1f)
10604
10605/* Signed immediate */
10606#define SIMM(op, start, width) \
10607 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
10608 << (32-width)) \
10609 >> (32-width))
10610/* Zero-extended immediate */
10611#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
10612
7db13fae 10613static void gen_addiur1sp (CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
10614{
10615 int rd = mmreg(uMIPS_RD(ctx->opcode));
10616
10617 gen_arith_imm(env, ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
10618}
10619
7db13fae 10620static void gen_addiur2 (CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
10621{
10622 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
10623 int rd = mmreg(uMIPS_RD(ctx->opcode));
10624 int rs = mmreg(uMIPS_RS(ctx->opcode));
10625
10626 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
10627}
10628
7db13fae 10629static void gen_addiusp (CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
10630{
10631 int encoded = ZIMM(ctx->opcode, 1, 9);
10632 int decoded;
10633
10634 if (encoded <= 1) {
10635 decoded = 256 + encoded;
10636 } else if (encoded <= 255) {
10637 decoded = encoded;
10638 } else if (encoded <= 509) {
10639 decoded = encoded - 512;
10640 } else {
10641 decoded = encoded - 768;
10642 }
10643
10644 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, decoded << 2);
10645}
10646
7db13fae 10647static void gen_addius5 (CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
10648{
10649 int imm = SIMM(ctx->opcode, 1, 4);
10650 int rd = (ctx->opcode >> 5) & 0x1f;
10651
10652 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rd, imm);
10653}
10654
7db13fae 10655static void gen_andi16 (CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
10656{
10657 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
10658 31, 32, 63, 64, 255, 32768, 65535 };
10659 int rd = mmreg(uMIPS_RD(ctx->opcode));
10660 int rs = mmreg(uMIPS_RS(ctx->opcode));
10661 int encoded = ZIMM(ctx->opcode, 0, 4);
10662
9fa77488 10663 gen_logic_imm(env, ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
3c824109
NF
10664}
10665
10666static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
10667 int base, int16_t offset)
10668{
e1050a76 10669 const char *opn = "ldst_multiple";
3c824109
NF
10670 TCGv t0, t1;
10671 TCGv_i32 t2;
10672
10673 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10674 generate_exception(ctx, EXCP_RI);
10675 return;
10676 }
10677
10678 t0 = tcg_temp_new();
10679
10680 gen_base_offset_addr(ctx, t0, base, offset);
10681
10682 t1 = tcg_const_tl(reglist);
10683 t2 = tcg_const_i32(ctx->mem_idx);
6af0bf9c 10684
3c824109
NF
10685 save_cpu_state(ctx, 1);
10686 switch (opc) {
10687 case LWM32:
895c2d04 10688 gen_helper_lwm(cpu_env, t0, t1, t2);
e1050a76 10689 opn = "lwm";
3c824109
NF
10690 break;
10691 case SWM32:
895c2d04 10692 gen_helper_swm(cpu_env, t0, t1, t2);
e1050a76 10693 opn = "swm";
3c824109
NF
10694 break;
10695#ifdef TARGET_MIPS64
10696 case LDM:
895c2d04 10697 gen_helper_ldm(cpu_env, t0, t1, t2);
e1050a76 10698 opn = "ldm";
3c824109
NF
10699 break;
10700 case SDM:
895c2d04 10701 gen_helper_sdm(cpu_env, t0, t1, t2);
e1050a76 10702 opn = "sdm";
3c824109 10703 break;
6af0bf9c 10704#endif
3c824109 10705 }
e1050a76 10706 (void)opn;
3c824109
NF
10707 MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
10708 tcg_temp_free(t0);
33087598 10709 tcg_temp_free(t1);
3c824109
NF
10710 tcg_temp_free_i32(t2);
10711}
6af0bf9c 10712
3c824109 10713
7db13fae 10714static void gen_pool16c_insn (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
6af0bf9c 10715{
3c824109
NF
10716 int rd = mmreg((ctx->opcode >> 3) & 0x7);
10717 int rs = mmreg(ctx->opcode & 0x7);
10718 int opc;
6af0bf9c 10719
3c824109
NF
10720 switch (((ctx->opcode) >> 4) & 0x3f) {
10721 case NOT16 + 0:
10722 case NOT16 + 1:
10723 case NOT16 + 2:
10724 case NOT16 + 3:
9fa77488 10725 gen_logic(env, ctx, OPC_NOR, rd, rs, 0);
3c824109
NF
10726 break;
10727 case XOR16 + 0:
10728 case XOR16 + 1:
10729 case XOR16 + 2:
10730 case XOR16 + 3:
9fa77488 10731 gen_logic(env, ctx, OPC_XOR, rd, rd, rs);
3c824109
NF
10732 break;
10733 case AND16 + 0:
10734 case AND16 + 1:
10735 case AND16 + 2:
10736 case AND16 + 3:
9fa77488 10737 gen_logic(env, ctx, OPC_AND, rd, rd, rs);
3c824109
NF
10738 break;
10739 case OR16 + 0:
10740 case OR16 + 1:
10741 case OR16 + 2:
10742 case OR16 + 3:
9fa77488 10743 gen_logic(env, ctx, OPC_OR, rd, rd, rs);
3c824109
NF
10744 break;
10745 case LWM16 + 0:
10746 case LWM16 + 1:
10747 case LWM16 + 2:
10748 case LWM16 + 3:
10749 {
10750 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
10751 int offset = ZIMM(ctx->opcode, 0, 4);
10752
10753 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
10754 29, offset << 2);
10755 }
10756 break;
10757 case SWM16 + 0:
10758 case SWM16 + 1:
10759 case SWM16 + 2:
10760 case SWM16 + 3:
10761 {
10762 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
10763 int offset = ZIMM(ctx->opcode, 0, 4);
10764
10765 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
10766 29, offset << 2);
10767 }
10768 break;
10769 case JR16 + 0:
10770 case JR16 + 1:
10771 {
10772 int reg = ctx->opcode & 0x1f;
10773
10774 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
10775 }
10776 *is_branch = 1;
10777 break;
10778 case JRC16 + 0:
10779 case JRC16 + 1:
10780 {
10781 int reg = ctx->opcode & 0x1f;
10782
10783 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
10784 /* Let normal delay slot handling in our caller take us
10785 to the branch target. */
10786 }
10787 break;
10788 case JALR16 + 0:
10789 case JALR16 + 1:
10790 opc = OPC_JALR;
10791 goto do_jalr;
10792 case JALR16S + 0:
10793 case JALR16S + 1:
10794 opc = OPC_JALRS;
10795 do_jalr:
10796 {
10797 int reg = ctx->opcode & 0x1f;
10798
10799 gen_compute_branch(ctx, opc, 2, reg, 31, 0);
10800 }
10801 *is_branch = 1;
10802 break;
10803 case MFHI16 + 0:
10804 case MFHI16 + 1:
10805 gen_HILO(ctx, OPC_MFHI, uMIPS_RS5(ctx->opcode));
10806 break;
10807 case MFLO16 + 0:
10808 case MFLO16 + 1:
10809 gen_HILO(ctx, OPC_MFLO, uMIPS_RS5(ctx->opcode));
10810 break;
10811 case BREAK16:
10812 generate_exception(ctx, EXCP_BREAK);
10813 break;
10814 case SDBBP16:
10815 /* XXX: not clear which exception should be raised
10816 * when in debug mode...
10817 */
10818 check_insn(env, ctx, ISA_MIPS32);
10819 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10820 generate_exception(ctx, EXCP_DBp);
10821 } else {
10822 generate_exception(ctx, EXCP_DBp);
10823 }
10824 break;
10825 case JRADDIUSP + 0:
10826 case JRADDIUSP + 1:
10827 {
10828 int imm = ZIMM(ctx->opcode, 0, 5);
10829
10830 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0);
10831 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm << 2);
10832 /* Let normal delay slot handling in our caller take us
10833 to the branch target. */
10834 }
10835 break;
10836 default:
10837 generate_exception(ctx, EXCP_RI);
10838 break;
10839 }
10840}
10841
10842static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
10843{
10844 TCGv t0 = tcg_temp_new();
10845 TCGv t1 = tcg_temp_new();
10846
10847 gen_load_gpr(t0, base);
10848
10849 if (index != 0) {
10850 gen_load_gpr(t1, index);
10851 tcg_gen_shli_tl(t1, t1, 2);
10852 gen_op_addr_add(ctx, t0, t1, t0);
10853 }
10854
10855 save_cpu_state(ctx, 0);
5c13fdfd 10856 op_ld_lw(t1, t0, ctx);
3c824109
NF
10857 gen_store_gpr(t1, rd);
10858
10859 tcg_temp_free(t0);
10860 tcg_temp_free(t1);
10861}
10862
10863static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
10864 int base, int16_t offset)
10865{
10866 const char *opn = "ldst_pair";
10867 TCGv t0, t1;
10868
36c6711b 10869 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
3c824109 10870 generate_exception(ctx, EXCP_RI);
d796321b
FB
10871 return;
10872 }
10873
3c824109
NF
10874 t0 = tcg_temp_new();
10875 t1 = tcg_temp_new();
8e9ade68 10876
3c824109
NF
10877 gen_base_offset_addr(ctx, t0, base, offset);
10878
10879 switch (opc) {
10880 case LWP:
36c6711b
EJ
10881 if (rd == base) {
10882 generate_exception(ctx, EXCP_RI);
10883 return;
10884 }
3c824109 10885 save_cpu_state(ctx, 0);
5c13fdfd 10886 op_ld_lw(t1, t0, ctx);
3c824109
NF
10887 gen_store_gpr(t1, rd);
10888 tcg_gen_movi_tl(t1, 4);
10889 gen_op_addr_add(ctx, t0, t0, t1);
5c13fdfd 10890 op_ld_lw(t1, t0, ctx);
3c824109
NF
10891 gen_store_gpr(t1, rd+1);
10892 opn = "lwp";
10893 break;
10894 case SWP:
b835e919 10895 save_cpu_state(ctx, 0);
3c824109 10896 gen_load_gpr(t1, rd);
5c13fdfd 10897 op_st_sw(t1, t0, ctx);
3c824109
NF
10898 tcg_gen_movi_tl(t1, 4);
10899 gen_op_addr_add(ctx, t0, t0, t1);
10900 gen_load_gpr(t1, rd+1);
5c13fdfd 10901 op_st_sw(t1, t0, ctx);
3c824109
NF
10902 opn = "swp";
10903 break;
10904#ifdef TARGET_MIPS64
10905 case LDP:
36c6711b
EJ
10906 if (rd == base) {
10907 generate_exception(ctx, EXCP_RI);
10908 return;
10909 }
3c824109 10910 save_cpu_state(ctx, 0);
5c13fdfd 10911 op_ld_ld(t1, t0, ctx);
3c824109
NF
10912 gen_store_gpr(t1, rd);
10913 tcg_gen_movi_tl(t1, 8);
10914 gen_op_addr_add(ctx, t0, t0, t1);
5c13fdfd 10915 op_ld_ld(t1, t0, ctx);
3c824109
NF
10916 gen_store_gpr(t1, rd+1);
10917 opn = "ldp";
10918 break;
10919 case SDP:
b835e919 10920 save_cpu_state(ctx, 0);
3c824109 10921 gen_load_gpr(t1, rd);
5c13fdfd 10922 op_st_sd(t1, t0, ctx);
3c824109
NF
10923 tcg_gen_movi_tl(t1, 8);
10924 gen_op_addr_add(ctx, t0, t0, t1);
10925 gen_load_gpr(t1, rd+1);
5c13fdfd 10926 op_st_sd(t1, t0, ctx);
3c824109
NF
10927 opn = "sdp";
10928 break;
10929#endif
6af0bf9c 10930 }
2abf314d 10931 (void)opn; /* avoid a compiler warning */
3c824109
NF
10932 MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
10933 tcg_temp_free(t0);
10934 tcg_temp_free(t1);
10935}
618b0fe9 10936
7db13fae 10937static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
3c824109
NF
10938 int *is_branch)
10939{
10940 int extension = (ctx->opcode >> 6) & 0x3f;
10941 int minor = (ctx->opcode >> 12) & 0xf;
10942 uint32_t mips32_op;
10943
10944 switch (extension) {
10945 case TEQ:
10946 mips32_op = OPC_TEQ;
10947 goto do_trap;
10948 case TGE:
10949 mips32_op = OPC_TGE;
10950 goto do_trap;
10951 case TGEU:
10952 mips32_op = OPC_TGEU;
10953 goto do_trap;
10954 case TLT:
10955 mips32_op = OPC_TLT;
10956 goto do_trap;
10957 case TLTU:
10958 mips32_op = OPC_TLTU;
10959 goto do_trap;
10960 case TNE:
10961 mips32_op = OPC_TNE;
10962 do_trap:
10963 gen_trap(ctx, mips32_op, rs, rt, -1);
10964 break;
10965#ifndef CONFIG_USER_ONLY
10966 case MFC0:
10967 case MFC0 + 32:
2e15497c 10968 check_cp0_enabled(ctx);
3c824109
NF
10969 if (rt == 0) {
10970 /* Treat as NOP. */
10971 break;
10972 }
10973 gen_mfc0(env, ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
10974 break;
10975 case MTC0:
10976 case MTC0 + 32:
2e15497c 10977 check_cp0_enabled(ctx);
3c824109
NF
10978 {
10979 TCGv t0 = tcg_temp_new();
618b0fe9 10980
3c824109
NF
10981 gen_load_gpr(t0, rt);
10982 gen_mtc0(env, ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
10983 tcg_temp_free(t0);
10984 }
10985 break;
10986#endif
10987 case 0x2c:
10988 switch (minor) {
10989 case SEB:
10990 gen_bshfl(ctx, OPC_SEB, rs, rt);
10991 break;
10992 case SEH:
10993 gen_bshfl(ctx, OPC_SEH, rs, rt);
10994 break;
10995 case CLO:
10996 mips32_op = OPC_CLO;
10997 goto do_cl;
10998 case CLZ:
10999 mips32_op = OPC_CLZ;
11000 do_cl:
11001 check_insn(env, ctx, ISA_MIPS32);
11002 gen_cl(ctx, mips32_op, rt, rs);
11003 break;
11004 case RDHWR:
11005 gen_rdhwr(env, ctx, rt, rs);
11006 break;
11007 case WSBH:
11008 gen_bshfl(ctx, OPC_WSBH, rs, rt);
11009 break;
11010 case MULT:
11011 mips32_op = OPC_MULT;
11012 goto do_muldiv;
11013 case MULTU:
11014 mips32_op = OPC_MULTU;
11015 goto do_muldiv;
11016 case DIV:
11017 mips32_op = OPC_DIV;
11018 goto do_muldiv;
11019 case DIVU:
11020 mips32_op = OPC_DIVU;
11021 goto do_muldiv;
11022 case MADD:
11023 mips32_op = OPC_MADD;
11024 goto do_muldiv;
11025 case MADDU:
11026 mips32_op = OPC_MADDU;
11027 goto do_muldiv;
11028 case MSUB:
11029 mips32_op = OPC_MSUB;
11030 goto do_muldiv;
11031 case MSUBU:
11032 mips32_op = OPC_MSUBU;
11033 do_muldiv:
11034 check_insn(env, ctx, ISA_MIPS32);
11035 gen_muldiv(ctx, mips32_op, rs, rt);
11036 break;
11037 default:
11038 goto pool32axf_invalid;
11039 }
11040 break;
11041 case 0x34:
11042 switch (minor) {
11043 case MFC2:
11044 case MTC2:
11045 case MFHC2:
11046 case MTHC2:
11047 case CFC2:
11048 case CTC2:
11049 generate_exception_err(ctx, EXCP_CpU, 2);
11050 break;
11051 default:
11052 goto pool32axf_invalid;
11053 }
11054 break;
11055 case 0x3c:
11056 switch (minor) {
11057 case JALR:
11058 case JALR_HB:
11059 gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0);
11060 *is_branch = 1;
11061 break;
11062 case JALRS:
11063 case JALRS_HB:
11064 gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0);
11065 *is_branch = 1;
11066 break;
11067 default:
11068 goto pool32axf_invalid;
11069 }
11070 break;
11071 case 0x05:
11072 switch (minor) {
11073 case RDPGPR:
2e15497c 11074 check_cp0_enabled(ctx);
3c824109
NF
11075 check_insn(env, ctx, ISA_MIPS32R2);
11076 gen_load_srsgpr(rt, rs);
11077 break;
11078 case WRPGPR:
2e15497c 11079 check_cp0_enabled(ctx);
3c824109
NF
11080 check_insn(env, ctx, ISA_MIPS32R2);
11081 gen_store_srsgpr(rt, rs);
11082 break;
11083 default:
11084 goto pool32axf_invalid;
11085 }
11086 break;
11087#ifndef CONFIG_USER_ONLY
11088 case 0x0d:
11089 switch (minor) {
11090 case TLBP:
11091 mips32_op = OPC_TLBP;
11092 goto do_cp0;
11093 case TLBR:
11094 mips32_op = OPC_TLBR;
11095 goto do_cp0;
11096 case TLBWI:
11097 mips32_op = OPC_TLBWI;
11098 goto do_cp0;
11099 case TLBWR:
11100 mips32_op = OPC_TLBWR;
11101 goto do_cp0;
11102 case WAIT:
11103 mips32_op = OPC_WAIT;
11104 goto do_cp0;
11105 case DERET:
11106 mips32_op = OPC_DERET;
11107 goto do_cp0;
11108 case ERET:
11109 mips32_op = OPC_ERET;
11110 do_cp0:
11111 gen_cp0(env, ctx, mips32_op, rt, rs);
11112 break;
11113 default:
11114 goto pool32axf_invalid;
11115 }
11116 break;
11117 case 0x1d:
11118 switch (minor) {
11119 case DI:
2e15497c 11120 check_cp0_enabled(ctx);
3c824109
NF
11121 {
11122 TCGv t0 = tcg_temp_new();
11123
11124 save_cpu_state(ctx, 1);
895c2d04 11125 gen_helper_di(t0, cpu_env);
3c824109
NF
11126 gen_store_gpr(t0, rs);
11127 /* Stop translation as we may have switched the execution mode */
11128 ctx->bstate = BS_STOP;
11129 tcg_temp_free(t0);
11130 }
11131 break;
11132 case EI:
2e15497c 11133 check_cp0_enabled(ctx);
3c824109
NF
11134 {
11135 TCGv t0 = tcg_temp_new();
11136
11137 save_cpu_state(ctx, 1);
895c2d04 11138 gen_helper_ei(t0, cpu_env);
3c824109
NF
11139 gen_store_gpr(t0, rs);
11140 /* Stop translation as we may have switched the execution mode */
11141 ctx->bstate = BS_STOP;
11142 tcg_temp_free(t0);
11143 }
11144 break;
11145 default:
11146 goto pool32axf_invalid;
11147 }
11148 break;
11149#endif
11150 case 0x2d:
11151 switch (minor) {
11152 case SYNC:
11153 /* NOP */
11154 break;
11155 case SYSCALL:
11156 generate_exception(ctx, EXCP_SYSCALL);
11157 ctx->bstate = BS_STOP;
11158 break;
11159 case SDBBP:
11160 check_insn(env, ctx, ISA_MIPS32);
11161 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11162 generate_exception(ctx, EXCP_DBp);
11163 } else {
11164 generate_exception(ctx, EXCP_DBp);
11165 }
11166 break;
11167 default:
11168 goto pool32axf_invalid;
11169 }
11170 break;
11171 case 0x35:
11172 switch (minor) {
11173 case MFHI32:
11174 gen_HILO(ctx, OPC_MFHI, rs);
11175 break;
11176 case MFLO32:
11177 gen_HILO(ctx, OPC_MFLO, rs);
11178 break;
11179 case MTHI32:
11180 gen_HILO(ctx, OPC_MTHI, rs);
11181 break;
11182 case MTLO32:
11183 gen_HILO(ctx, OPC_MTLO, rs);
11184 break;
11185 default:
11186 goto pool32axf_invalid;
11187 }
11188 break;
11189 default:
11190 pool32axf_invalid:
11191 MIPS_INVAL("pool32axf");
11192 generate_exception(ctx, EXCP_RI);
11193 break;
11194 }
11195}
11196
11197/* Values for microMIPS fmt field. Variable-width, depending on which
11198 formats the instruction supports. */
11199
11200enum {
11201 FMT_SD_S = 0,
11202 FMT_SD_D = 1,
11203
11204 FMT_SDPS_S = 0,
11205 FMT_SDPS_D = 1,
11206 FMT_SDPS_PS = 2,
11207
11208 FMT_SWL_S = 0,
11209 FMT_SWL_W = 1,
11210 FMT_SWL_L = 2,
11211
11212 FMT_DWL_D = 0,
11213 FMT_DWL_W = 1,
11214 FMT_DWL_L = 2
11215};
11216
7db13fae 11217static void gen_pool32fxf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
3c824109
NF
11218{
11219 int extension = (ctx->opcode >> 6) & 0x3ff;
11220 uint32_t mips32_op;
11221
11222#define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
11223#define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
11224#define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
11225
11226 switch (extension) {
11227 case FLOAT_1BIT_FMT(CFC1, 0):
11228 mips32_op = OPC_CFC1;
11229 goto do_cp1;
11230 case FLOAT_1BIT_FMT(CTC1, 0):
11231 mips32_op = OPC_CTC1;
11232 goto do_cp1;
11233 case FLOAT_1BIT_FMT(MFC1, 0):
11234 mips32_op = OPC_MFC1;
11235 goto do_cp1;
11236 case FLOAT_1BIT_FMT(MTC1, 0):
11237 mips32_op = OPC_MTC1;
11238 goto do_cp1;
11239 case FLOAT_1BIT_FMT(MFHC1, 0):
11240 mips32_op = OPC_MFHC1;
11241 goto do_cp1;
11242 case FLOAT_1BIT_FMT(MTHC1, 0):
11243 mips32_op = OPC_MTHC1;
11244 do_cp1:
11245 gen_cp1(ctx, mips32_op, rt, rs);
11246 break;
11247
11248 /* Reciprocal square root */
11249 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
11250 mips32_op = OPC_RSQRT_S;
11251 goto do_unaryfp;
11252 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
11253 mips32_op = OPC_RSQRT_D;
11254 goto do_unaryfp;
11255
11256 /* Square root */
11257 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
11258 mips32_op = OPC_SQRT_S;
11259 goto do_unaryfp;
11260 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
11261 mips32_op = OPC_SQRT_D;
11262 goto do_unaryfp;
11263
11264 /* Reciprocal */
11265 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
11266 mips32_op = OPC_RECIP_S;
11267 goto do_unaryfp;
11268 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
11269 mips32_op = OPC_RECIP_D;
11270 goto do_unaryfp;
11271
11272 /* Floor */
11273 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
11274 mips32_op = OPC_FLOOR_L_S;
11275 goto do_unaryfp;
11276 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
11277 mips32_op = OPC_FLOOR_L_D;
11278 goto do_unaryfp;
11279 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
11280 mips32_op = OPC_FLOOR_W_S;
11281 goto do_unaryfp;
11282 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
11283 mips32_op = OPC_FLOOR_W_D;
11284 goto do_unaryfp;
11285
11286 /* Ceiling */
11287 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
11288 mips32_op = OPC_CEIL_L_S;
11289 goto do_unaryfp;
11290 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
11291 mips32_op = OPC_CEIL_L_D;
11292 goto do_unaryfp;
11293 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
11294 mips32_op = OPC_CEIL_W_S;
11295 goto do_unaryfp;
11296 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
11297 mips32_op = OPC_CEIL_W_D;
11298 goto do_unaryfp;
11299
11300 /* Truncation */
11301 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
11302 mips32_op = OPC_TRUNC_L_S;
11303 goto do_unaryfp;
11304 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
11305 mips32_op = OPC_TRUNC_L_D;
11306 goto do_unaryfp;
11307 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
11308 mips32_op = OPC_TRUNC_W_S;
11309 goto do_unaryfp;
11310 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
11311 mips32_op = OPC_TRUNC_W_D;
11312 goto do_unaryfp;
11313
11314 /* Round */
11315 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
11316 mips32_op = OPC_ROUND_L_S;
11317 goto do_unaryfp;
11318 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
11319 mips32_op = OPC_ROUND_L_D;
11320 goto do_unaryfp;
11321 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
11322 mips32_op = OPC_ROUND_W_S;
11323 goto do_unaryfp;
11324 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
11325 mips32_op = OPC_ROUND_W_D;
11326 goto do_unaryfp;
11327
11328 /* Integer to floating-point conversion */
11329 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
11330 mips32_op = OPC_CVT_L_S;
11331 goto do_unaryfp;
11332 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
11333 mips32_op = OPC_CVT_L_D;
11334 goto do_unaryfp;
11335 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
11336 mips32_op = OPC_CVT_W_S;
11337 goto do_unaryfp;
11338 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
11339 mips32_op = OPC_CVT_W_D;
11340 goto do_unaryfp;
11341
11342 /* Paired-foo conversions */
11343 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
11344 mips32_op = OPC_CVT_S_PL;
11345 goto do_unaryfp;
11346 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
11347 mips32_op = OPC_CVT_S_PU;
11348 goto do_unaryfp;
11349 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
11350 mips32_op = OPC_CVT_PW_PS;
11351 goto do_unaryfp;
11352 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
11353 mips32_op = OPC_CVT_PS_PW;
11354 goto do_unaryfp;
11355
11356 /* Floating-point moves */
11357 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
11358 mips32_op = OPC_MOV_S;
11359 goto do_unaryfp;
11360 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
11361 mips32_op = OPC_MOV_D;
11362 goto do_unaryfp;
11363 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
11364 mips32_op = OPC_MOV_PS;
11365 goto do_unaryfp;
11366
11367 /* Absolute value */
11368 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
11369 mips32_op = OPC_ABS_S;
11370 goto do_unaryfp;
11371 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
11372 mips32_op = OPC_ABS_D;
11373 goto do_unaryfp;
11374 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
11375 mips32_op = OPC_ABS_PS;
11376 goto do_unaryfp;
11377
11378 /* Negation */
11379 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
11380 mips32_op = OPC_NEG_S;
11381 goto do_unaryfp;
11382 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
11383 mips32_op = OPC_NEG_D;
11384 goto do_unaryfp;
11385 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
11386 mips32_op = OPC_NEG_PS;
11387 goto do_unaryfp;
11388
11389 /* Reciprocal square root step */
11390 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
11391 mips32_op = OPC_RSQRT1_S;
11392 goto do_unaryfp;
11393 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
11394 mips32_op = OPC_RSQRT1_D;
11395 goto do_unaryfp;
11396 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
11397 mips32_op = OPC_RSQRT1_PS;
11398 goto do_unaryfp;
11399
11400 /* Reciprocal step */
11401 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
11402 mips32_op = OPC_RECIP1_S;
11403 goto do_unaryfp;
11404 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
11405 mips32_op = OPC_RECIP1_S;
11406 goto do_unaryfp;
11407 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
11408 mips32_op = OPC_RECIP1_PS;
11409 goto do_unaryfp;
11410
11411 /* Conversions from double */
11412 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
11413 mips32_op = OPC_CVT_D_S;
11414 goto do_unaryfp;
11415 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
11416 mips32_op = OPC_CVT_D_W;
11417 goto do_unaryfp;
11418 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
11419 mips32_op = OPC_CVT_D_L;
11420 goto do_unaryfp;
11421
11422 /* Conversions from single */
11423 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
11424 mips32_op = OPC_CVT_S_D;
11425 goto do_unaryfp;
11426 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
11427 mips32_op = OPC_CVT_S_W;
11428 goto do_unaryfp;
11429 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
11430 mips32_op = OPC_CVT_S_L;
11431 do_unaryfp:
11432 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
11433 break;
11434
11435 /* Conditional moves on floating-point codes */
11436 case COND_FLOAT_MOV(MOVT, 0):
11437 case COND_FLOAT_MOV(MOVT, 1):
11438 case COND_FLOAT_MOV(MOVT, 2):
11439 case COND_FLOAT_MOV(MOVT, 3):
11440 case COND_FLOAT_MOV(MOVT, 4):
11441 case COND_FLOAT_MOV(MOVT, 5):
11442 case COND_FLOAT_MOV(MOVT, 6):
11443 case COND_FLOAT_MOV(MOVT, 7):
11444 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
11445 break;
11446 case COND_FLOAT_MOV(MOVF, 0):
11447 case COND_FLOAT_MOV(MOVF, 1):
11448 case COND_FLOAT_MOV(MOVF, 2):
11449 case COND_FLOAT_MOV(MOVF, 3):
11450 case COND_FLOAT_MOV(MOVF, 4):
11451 case COND_FLOAT_MOV(MOVF, 5):
11452 case COND_FLOAT_MOV(MOVF, 6):
11453 case COND_FLOAT_MOV(MOVF, 7):
11454 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
11455 break;
11456 default:
11457 MIPS_INVAL("pool32fxf");
11458 generate_exception(ctx, EXCP_RI);
11459 break;
11460 }
11461}
11462
7db13fae 11463static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
3c824109
NF
11464 uint16_t insn_hw1, int *is_branch)
11465{
11466 int32_t offset;
11467 uint16_t insn;
11468 int rt, rs, rd, rr;
11469 int16_t imm;
11470 uint32_t op, minor, mips32_op;
11471 uint32_t cond, fmt, cc;
11472
895c2d04 11473 insn = cpu_lduw_code(env, ctx->pc + 2);
3c824109
NF
11474 ctx->opcode = (ctx->opcode << 16) | insn;
11475
11476 rt = (ctx->opcode >> 21) & 0x1f;
11477 rs = (ctx->opcode >> 16) & 0x1f;
11478 rd = (ctx->opcode >> 11) & 0x1f;
11479 rr = (ctx->opcode >> 6) & 0x1f;
11480 imm = (int16_t) ctx->opcode;
11481
11482 op = (ctx->opcode >> 26) & 0x3f;
11483 switch (op) {
11484 case POOL32A:
11485 minor = ctx->opcode & 0x3f;
11486 switch (minor) {
11487 case 0x00:
11488 minor = (ctx->opcode >> 6) & 0xf;
11489 switch (minor) {
11490 case SLL32:
11491 mips32_op = OPC_SLL;
11492 goto do_shifti;
11493 case SRA:
11494 mips32_op = OPC_SRA;
11495 goto do_shifti;
11496 case SRL32:
11497 mips32_op = OPC_SRL;
11498 goto do_shifti;
11499 case ROTR:
11500 mips32_op = OPC_ROTR;
11501 do_shifti:
11502 gen_shift_imm(env, ctx, mips32_op, rt, rs, rd);
11503 break;
11504 default:
11505 goto pool32a_invalid;
11506 }
11507 break;
11508 case 0x10:
11509 minor = (ctx->opcode >> 6) & 0xf;
11510 switch (minor) {
11511 /* Arithmetic */
11512 case ADD:
11513 mips32_op = OPC_ADD;
11514 goto do_arith;
11515 case ADDU32:
11516 mips32_op = OPC_ADDU;
11517 goto do_arith;
11518 case SUB:
11519 mips32_op = OPC_SUB;
11520 goto do_arith;
11521 case SUBU32:
11522 mips32_op = OPC_SUBU;
11523 goto do_arith;
11524 case MUL:
11525 mips32_op = OPC_MUL;
11526 do_arith:
11527 gen_arith(env, ctx, mips32_op, rd, rs, rt);
11528 break;
11529 /* Shifts */
11530 case SLLV:
11531 mips32_op = OPC_SLLV;
11532 goto do_shift;
11533 case SRLV:
11534 mips32_op = OPC_SRLV;
11535 goto do_shift;
11536 case SRAV:
11537 mips32_op = OPC_SRAV;
11538 goto do_shift;
11539 case ROTRV:
11540 mips32_op = OPC_ROTRV;
11541 do_shift:
11542 gen_shift(env, ctx, mips32_op, rd, rs, rt);
11543 break;
11544 /* Logical operations */
11545 case AND:
11546 mips32_op = OPC_AND;
11547 goto do_logic;
11548 case OR32:
11549 mips32_op = OPC_OR;
11550 goto do_logic;
11551 case NOR:
11552 mips32_op = OPC_NOR;
11553 goto do_logic;
11554 case XOR32:
11555 mips32_op = OPC_XOR;
11556 do_logic:
9fa77488 11557 gen_logic(env, ctx, mips32_op, rd, rs, rt);
3c824109
NF
11558 break;
11559 /* Set less than */
11560 case SLT:
11561 mips32_op = OPC_SLT;
11562 goto do_slt;
11563 case SLTU:
11564 mips32_op = OPC_SLTU;
11565 do_slt:
9fa77488 11566 gen_slt(env, ctx, mips32_op, rd, rs, rt);
3c824109
NF
11567 break;
11568 default:
11569 goto pool32a_invalid;
11570 }
11571 break;
11572 case 0x18:
11573 minor = (ctx->opcode >> 6) & 0xf;
11574 switch (minor) {
11575 /* Conditional moves */
11576 case MOVN:
11577 mips32_op = OPC_MOVN;
11578 goto do_cmov;
11579 case MOVZ:
11580 mips32_op = OPC_MOVZ;
11581 do_cmov:
9fa77488 11582 gen_cond_move(env, ctx, mips32_op, rd, rs, rt);
3c824109
NF
11583 break;
11584 case LWXS:
11585 gen_ldxs(ctx, rs, rt, rd);
11586 break;
11587 default:
11588 goto pool32a_invalid;
11589 }
11590 break;
11591 case INS:
11592 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
11593 return;
11594 case EXT:
11595 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
11596 return;
11597 case POOL32AXF:
11598 gen_pool32axf(env, ctx, rt, rs, is_branch);
11599 break;
11600 case 0x07:
11601 generate_exception(ctx, EXCP_BREAK);
11602 break;
11603 default:
11604 pool32a_invalid:
11605 MIPS_INVAL("pool32a");
11606 generate_exception(ctx, EXCP_RI);
11607 break;
11608 }
11609 break;
11610 case POOL32B:
11611 minor = (ctx->opcode >> 12) & 0xf;
11612 switch (minor) {
11613 case CACHE:
2e15497c 11614 check_cp0_enabled(ctx);
3c824109
NF
11615 /* Treat as no-op. */
11616 break;
11617 case LWC2:
11618 case SWC2:
11619 /* COP2: Not implemented. */
11620 generate_exception_err(ctx, EXCP_CpU, 2);
11621 break;
11622 case LWP:
11623 case SWP:
11624#ifdef TARGET_MIPS64
11625 case LDP:
11626 case SDP:
11627#endif
11628 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
11629 break;
11630 case LWM32:
11631 case SWM32:
11632#ifdef TARGET_MIPS64
11633 case LDM:
11634 case SDM:
11635#endif
11636 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
11637 break;
11638 default:
11639 MIPS_INVAL("pool32b");
11640 generate_exception(ctx, EXCP_RI);
11641 break;
11642 }
11643 break;
11644 case POOL32F:
11645 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
11646 minor = ctx->opcode & 0x3f;
11647 check_cp1_enabled(ctx);
11648 switch (minor) {
11649 case ALNV_PS:
11650 mips32_op = OPC_ALNV_PS;
11651 goto do_madd;
11652 case MADD_S:
11653 mips32_op = OPC_MADD_S;
11654 goto do_madd;
11655 case MADD_D:
11656 mips32_op = OPC_MADD_D;
11657 goto do_madd;
11658 case MADD_PS:
11659 mips32_op = OPC_MADD_PS;
11660 goto do_madd;
11661 case MSUB_S:
11662 mips32_op = OPC_MSUB_S;
11663 goto do_madd;
11664 case MSUB_D:
11665 mips32_op = OPC_MSUB_D;
11666 goto do_madd;
11667 case MSUB_PS:
11668 mips32_op = OPC_MSUB_PS;
11669 goto do_madd;
11670 case NMADD_S:
11671 mips32_op = OPC_NMADD_S;
11672 goto do_madd;
11673 case NMADD_D:
11674 mips32_op = OPC_NMADD_D;
11675 goto do_madd;
11676 case NMADD_PS:
11677 mips32_op = OPC_NMADD_PS;
11678 goto do_madd;
11679 case NMSUB_S:
11680 mips32_op = OPC_NMSUB_S;
11681 goto do_madd;
11682 case NMSUB_D:
11683 mips32_op = OPC_NMSUB_D;
11684 goto do_madd;
11685 case NMSUB_PS:
11686 mips32_op = OPC_NMSUB_PS;
11687 do_madd:
11688 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
11689 break;
11690 case CABS_COND_FMT:
11691 cond = (ctx->opcode >> 6) & 0xf;
11692 cc = (ctx->opcode >> 13) & 0x7;
11693 fmt = (ctx->opcode >> 10) & 0x3;
11694 switch (fmt) {
11695 case 0x0:
11696 gen_cmpabs_s(ctx, cond, rt, rs, cc);
11697 break;
11698 case 0x1:
11699 gen_cmpabs_d(ctx, cond, rt, rs, cc);
11700 break;
11701 case 0x2:
11702 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
11703 break;
11704 default:
11705 goto pool32f_invalid;
11706 }
11707 break;
11708 case C_COND_FMT:
11709 cond = (ctx->opcode >> 6) & 0xf;
11710 cc = (ctx->opcode >> 13) & 0x7;
11711 fmt = (ctx->opcode >> 10) & 0x3;
11712 switch (fmt) {
11713 case 0x0:
11714 gen_cmp_s(ctx, cond, rt, rs, cc);
11715 break;
11716 case 0x1:
11717 gen_cmp_d(ctx, cond, rt, rs, cc);
11718 break;
11719 case 0x2:
11720 gen_cmp_ps(ctx, cond, rt, rs, cc);
11721 break;
11722 default:
11723 goto pool32f_invalid;
11724 }
11725 break;
11726 case POOL32FXF:
11727 gen_pool32fxf(env, ctx, rt, rs);
11728 break;
11729 case 0x00:
11730 /* PLL foo */
11731 switch ((ctx->opcode >> 6) & 0x7) {
11732 case PLL_PS:
11733 mips32_op = OPC_PLL_PS;
11734 goto do_ps;
11735 case PLU_PS:
11736 mips32_op = OPC_PLU_PS;
11737 goto do_ps;
11738 case PUL_PS:
11739 mips32_op = OPC_PUL_PS;
11740 goto do_ps;
11741 case PUU_PS:
11742 mips32_op = OPC_PUU_PS;
11743 goto do_ps;
11744 case CVT_PS_S:
11745 mips32_op = OPC_CVT_PS_S;
11746 do_ps:
11747 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
11748 break;
11749 default:
11750 goto pool32f_invalid;
11751 }
11752 break;
11753 case 0x08:
11754 /* [LS][WDU]XC1 */
11755 switch ((ctx->opcode >> 6) & 0x7) {
11756 case LWXC1:
11757 mips32_op = OPC_LWXC1;
11758 goto do_ldst_cp1;
11759 case SWXC1:
11760 mips32_op = OPC_SWXC1;
11761 goto do_ldst_cp1;
11762 case LDXC1:
11763 mips32_op = OPC_LDXC1;
11764 goto do_ldst_cp1;
11765 case SDXC1:
11766 mips32_op = OPC_SDXC1;
11767 goto do_ldst_cp1;
11768 case LUXC1:
11769 mips32_op = OPC_LUXC1;
11770 goto do_ldst_cp1;
11771 case SUXC1:
11772 mips32_op = OPC_SUXC1;
11773 do_ldst_cp1:
11774 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
11775 break;
11776 default:
11777 goto pool32f_invalid;
11778 }
11779 break;
11780 case 0x18:
11781 /* 3D insns */
11782 fmt = (ctx->opcode >> 9) & 0x3;
11783 switch ((ctx->opcode >> 6) & 0x7) {
11784 case RSQRT2_FMT:
11785 switch (fmt) {
11786 case FMT_SDPS_S:
11787 mips32_op = OPC_RSQRT2_S;
11788 goto do_3d;
11789 case FMT_SDPS_D:
11790 mips32_op = OPC_RSQRT2_D;
11791 goto do_3d;
11792 case FMT_SDPS_PS:
11793 mips32_op = OPC_RSQRT2_PS;
11794 goto do_3d;
11795 default:
11796 goto pool32f_invalid;
11797 }
11798 break;
11799 case RECIP2_FMT:
11800 switch (fmt) {
11801 case FMT_SDPS_S:
11802 mips32_op = OPC_RECIP2_S;
11803 goto do_3d;
11804 case FMT_SDPS_D:
11805 mips32_op = OPC_RECIP2_D;
11806 goto do_3d;
11807 case FMT_SDPS_PS:
11808 mips32_op = OPC_RECIP2_PS;
11809 goto do_3d;
11810 default:
11811 goto pool32f_invalid;
11812 }
11813 break;
11814 case ADDR_PS:
11815 mips32_op = OPC_ADDR_PS;
11816 goto do_3d;
11817 case MULR_PS:
11818 mips32_op = OPC_MULR_PS;
11819 do_3d:
11820 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
11821 break;
11822 default:
11823 goto pool32f_invalid;
11824 }
11825 break;
11826 case 0x20:
11827 /* MOV[FT].fmt and PREFX */
11828 cc = (ctx->opcode >> 13) & 0x7;
11829 fmt = (ctx->opcode >> 9) & 0x3;
11830 switch ((ctx->opcode >> 6) & 0x7) {
11831 case MOVF_FMT:
11832 switch (fmt) {
11833 case FMT_SDPS_S:
11834 gen_movcf_s(rs, rt, cc, 0);
11835 break;
11836 case FMT_SDPS_D:
11837 gen_movcf_d(ctx, rs, rt, cc, 0);
11838 break;
11839 case FMT_SDPS_PS:
11840 gen_movcf_ps(rs, rt, cc, 0);
11841 break;
11842 default:
11843 goto pool32f_invalid;
11844 }
11845 break;
11846 case MOVT_FMT:
11847 switch (fmt) {
11848 case FMT_SDPS_S:
11849 gen_movcf_s(rs, rt, cc, 1);
11850 break;
11851 case FMT_SDPS_D:
11852 gen_movcf_d(ctx, rs, rt, cc, 1);
11853 break;
11854 case FMT_SDPS_PS:
11855 gen_movcf_ps(rs, rt, cc, 1);
11856 break;
11857 default:
11858 goto pool32f_invalid;
11859 }
11860 break;
11861 case PREFX:
11862 break;
11863 default:
11864 goto pool32f_invalid;
11865 }
11866 break;
11867#define FINSN_3ARG_SDPS(prfx) \
11868 switch ((ctx->opcode >> 8) & 0x3) { \
11869 case FMT_SDPS_S: \
11870 mips32_op = OPC_##prfx##_S; \
11871 goto do_fpop; \
11872 case FMT_SDPS_D: \
11873 mips32_op = OPC_##prfx##_D; \
11874 goto do_fpop; \
11875 case FMT_SDPS_PS: \
11876 mips32_op = OPC_##prfx##_PS; \
11877 goto do_fpop; \
11878 default: \
11879 goto pool32f_invalid; \
11880 }
11881 case 0x30:
11882 /* regular FP ops */
11883 switch ((ctx->opcode >> 6) & 0x3) {
11884 case ADD_FMT:
11885 FINSN_3ARG_SDPS(ADD);
11886 break;
11887 case SUB_FMT:
11888 FINSN_3ARG_SDPS(SUB);
11889 break;
11890 case MUL_FMT:
11891 FINSN_3ARG_SDPS(MUL);
11892 break;
11893 case DIV_FMT:
11894 fmt = (ctx->opcode >> 8) & 0x3;
11895 if (fmt == 1) {
11896 mips32_op = OPC_DIV_D;
11897 } else if (fmt == 0) {
11898 mips32_op = OPC_DIV_S;
11899 } else {
11900 goto pool32f_invalid;
11901 }
11902 goto do_fpop;
11903 default:
11904 goto pool32f_invalid;
11905 }
11906 break;
11907 case 0x38:
11908 /* cmovs */
11909 switch ((ctx->opcode >> 6) & 0x3) {
11910 case MOVN_FMT:
11911 FINSN_3ARG_SDPS(MOVN);
11912 break;
11913 case MOVZ_FMT:
11914 FINSN_3ARG_SDPS(MOVZ);
11915 break;
11916 default:
11917 goto pool32f_invalid;
11918 }
11919 break;
11920 do_fpop:
11921 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
11922 break;
11923 default:
11924 pool32f_invalid:
11925 MIPS_INVAL("pool32f");
11926 generate_exception(ctx, EXCP_RI);
11927 break;
11928 }
11929 } else {
11930 generate_exception_err(ctx, EXCP_CpU, 1);
11931 }
11932 break;
11933 case POOL32I:
11934 minor = (ctx->opcode >> 21) & 0x1f;
11935 switch (minor) {
11936 case BLTZ:
11937 mips32_op = OPC_BLTZ;
11938 goto do_branch;
11939 case BLTZAL:
11940 mips32_op = OPC_BLTZAL;
11941 goto do_branch;
11942 case BLTZALS:
11943 mips32_op = OPC_BLTZALS;
11944 goto do_branch;
11945 case BGEZ:
11946 mips32_op = OPC_BGEZ;
11947 goto do_branch;
11948 case BGEZAL:
11949 mips32_op = OPC_BGEZAL;
11950 goto do_branch;
11951 case BGEZALS:
11952 mips32_op = OPC_BGEZALS;
11953 goto do_branch;
11954 case BLEZ:
11955 mips32_op = OPC_BLEZ;
11956 goto do_branch;
11957 case BGTZ:
11958 mips32_op = OPC_BGTZ;
11959 do_branch:
11960 gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1);
11961 *is_branch = 1;
11962 break;
11963
11964 /* Traps */
11965 case TLTI:
11966 mips32_op = OPC_TLTI;
11967 goto do_trapi;
11968 case TGEI:
11969 mips32_op = OPC_TGEI;
11970 goto do_trapi;
11971 case TLTIU:
11972 mips32_op = OPC_TLTIU;
11973 goto do_trapi;
11974 case TGEIU:
11975 mips32_op = OPC_TGEIU;
11976 goto do_trapi;
11977 case TNEI:
11978 mips32_op = OPC_TNEI;
11979 goto do_trapi;
11980 case TEQI:
11981 mips32_op = OPC_TEQI;
11982 do_trapi:
11983 gen_trap(ctx, mips32_op, rs, -1, imm);
11984 break;
11985
11986 case BNEZC:
11987 case BEQZC:
11988 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
11989 4, rs, 0, imm << 1);
11990 /* Compact branches don't have a delay slot, so just let
11991 the normal delay slot handling take us to the branch
11992 target. */
11993 break;
11994 case LUI:
9fa77488 11995 gen_logic_imm(env, ctx, OPC_LUI, rs, -1, imm);
3c824109
NF
11996 break;
11997 case SYNCI:
11998 break;
11999 case BC2F:
12000 case BC2T:
12001 /* COP2: Not implemented. */
12002 generate_exception_err(ctx, EXCP_CpU, 2);
12003 break;
12004 case BC1F:
12005 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
12006 goto do_cp1branch;
12007 case BC1T:
12008 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
12009 goto do_cp1branch;
12010 case BC1ANY4F:
12011 mips32_op = OPC_BC1FANY4;
12012 goto do_cp1mips3d;
12013 case BC1ANY4T:
12014 mips32_op = OPC_BC1TANY4;
12015 do_cp1mips3d:
12016 check_cop1x(ctx);
12017 check_insn(env, ctx, ASE_MIPS3D);
12018 /* Fall through */
12019 do_cp1branch:
12020 gen_compute_branch1(env, ctx, mips32_op,
12021 (ctx->opcode >> 18) & 0x7, imm << 1);
12022 *is_branch = 1;
12023 break;
12024 case BPOSGE64:
12025 case BPOSGE32:
12026 /* MIPS DSP: not implemented */
12027 /* Fall through */
12028 default:
12029 MIPS_INVAL("pool32i");
12030 generate_exception(ctx, EXCP_RI);
12031 break;
12032 }
12033 break;
12034 case POOL32C:
12035 minor = (ctx->opcode >> 12) & 0xf;
12036 switch (minor) {
12037 case LWL:
12038 mips32_op = OPC_LWL;
5c13fdfd 12039 goto do_ld_lr;
3c824109
NF
12040 case SWL:
12041 mips32_op = OPC_SWL;
5c13fdfd 12042 goto do_st_lr;
3c824109
NF
12043 case LWR:
12044 mips32_op = OPC_LWR;
5c13fdfd 12045 goto do_ld_lr;
3c824109
NF
12046 case SWR:
12047 mips32_op = OPC_SWR;
5c13fdfd 12048 goto do_st_lr;
3c824109
NF
12049#if defined(TARGET_MIPS64)
12050 case LDL:
12051 mips32_op = OPC_LDL;
5c13fdfd 12052 goto do_ld_lr;
3c824109
NF
12053 case SDL:
12054 mips32_op = OPC_SDL;
5c13fdfd 12055 goto do_st_lr;
3c824109
NF
12056 case LDR:
12057 mips32_op = OPC_LDR;
5c13fdfd 12058 goto do_ld_lr;
3c824109
NF
12059 case SDR:
12060 mips32_op = OPC_SDR;
5c13fdfd 12061 goto do_st_lr;
3c824109
NF
12062 case LWU:
12063 mips32_op = OPC_LWU;
5c13fdfd 12064 goto do_ld_lr;
3c824109
NF
12065 case LLD:
12066 mips32_op = OPC_LLD;
5c13fdfd 12067 goto do_ld_lr;
3c824109
NF
12068#endif
12069 case LL:
12070 mips32_op = OPC_LL;
5c13fdfd
AJ
12071 goto do_ld_lr;
12072 do_ld_lr:
afa88c3a 12073 gen_ld(env, ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
5c13fdfd
AJ
12074 break;
12075 do_st_lr:
12076 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
3c824109
NF
12077 break;
12078 case SC:
12079 gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
12080 break;
12081#if defined(TARGET_MIPS64)
12082 case SCD:
12083 gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
12084 break;
12085#endif
12086 case PREF:
12087 /* Treat as no-op */
12088 break;
12089 default:
12090 MIPS_INVAL("pool32c");
12091 generate_exception(ctx, EXCP_RI);
12092 break;
12093 }
12094 break;
12095 case ADDI32:
12096 mips32_op = OPC_ADDI;
12097 goto do_addi;
12098 case ADDIU32:
12099 mips32_op = OPC_ADDIU;
12100 do_addi:
12101 gen_arith_imm(env, ctx, mips32_op, rt, rs, imm);
12102 break;
12103
12104 /* Logical operations */
12105 case ORI32:
12106 mips32_op = OPC_ORI;
12107 goto do_logici;
12108 case XORI32:
12109 mips32_op = OPC_XORI;
12110 goto do_logici;
12111 case ANDI32:
12112 mips32_op = OPC_ANDI;
12113 do_logici:
9fa77488 12114 gen_logic_imm(env, ctx, mips32_op, rt, rs, imm);
3c824109
NF
12115 break;
12116
12117 /* Set less than immediate */
12118 case SLTI32:
12119 mips32_op = OPC_SLTI;
12120 goto do_slti;
12121 case SLTIU32:
12122 mips32_op = OPC_SLTIU;
12123 do_slti:
9fa77488 12124 gen_slt_imm(env, ctx, mips32_op, rt, rs, imm);
3c824109
NF
12125 break;
12126 case JALX32:
12127 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
12128 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset);
12129 *is_branch = 1;
12130 break;
12131 case JALS32:
12132 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
12133 gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset);
12134 *is_branch = 1;
12135 break;
12136 case BEQ32:
12137 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1);
12138 *is_branch = 1;
12139 break;
12140 case BNE32:
12141 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1);
12142 *is_branch = 1;
12143 break;
12144 case J32:
12145 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
12146 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
12147 *is_branch = 1;
12148 break;
12149 case JAL32:
12150 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
12151 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
12152 *is_branch = 1;
12153 break;
12154 /* Floating point (COP1) */
12155 case LWC132:
12156 mips32_op = OPC_LWC1;
12157 goto do_cop1;
12158 case LDC132:
12159 mips32_op = OPC_LDC1;
12160 goto do_cop1;
12161 case SWC132:
12162 mips32_op = OPC_SWC1;
12163 goto do_cop1;
12164 case SDC132:
12165 mips32_op = OPC_SDC1;
12166 do_cop1:
12167 gen_cop1_ldst(env, ctx, mips32_op, rt, rs, imm);
12168 break;
12169 case ADDIUPC:
12170 {
12171 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
12172 int offset = SIMM(ctx->opcode, 0, 23) << 2;
12173
12174 gen_addiupc(ctx, reg, offset, 0, 0);
12175 }
12176 break;
12177 /* Loads and stores */
12178 case LB32:
12179 mips32_op = OPC_LB;
5c13fdfd 12180 goto do_ld;
3c824109
NF
12181 case LBU32:
12182 mips32_op = OPC_LBU;
5c13fdfd 12183 goto do_ld;
3c824109
NF
12184 case LH32:
12185 mips32_op = OPC_LH;
5c13fdfd 12186 goto do_ld;
3c824109
NF
12187 case LHU32:
12188 mips32_op = OPC_LHU;
5c13fdfd 12189 goto do_ld;
3c824109
NF
12190 case LW32:
12191 mips32_op = OPC_LW;
5c13fdfd 12192 goto do_ld;
3c824109
NF
12193#ifdef TARGET_MIPS64
12194 case LD32:
12195 mips32_op = OPC_LD;
5c13fdfd 12196 goto do_ld;
3c824109
NF
12197 case SD32:
12198 mips32_op = OPC_SD;
5c13fdfd 12199 goto do_st;
3c824109
NF
12200#endif
12201 case SB32:
12202 mips32_op = OPC_SB;
5c13fdfd 12203 goto do_st;
3c824109
NF
12204 case SH32:
12205 mips32_op = OPC_SH;
5c13fdfd 12206 goto do_st;
3c824109
NF
12207 case SW32:
12208 mips32_op = OPC_SW;
5c13fdfd
AJ
12209 goto do_st;
12210 do_ld:
afa88c3a 12211 gen_ld(env, ctx, mips32_op, rt, rs, imm);
5c13fdfd
AJ
12212 break;
12213 do_st:
12214 gen_st(ctx, mips32_op, rt, rs, imm);
3c824109
NF
12215 break;
12216 default:
12217 generate_exception(ctx, EXCP_RI);
12218 break;
12219 }
12220}
12221
7db13fae 12222static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
3c824109
NF
12223{
12224 uint32_t op;
12225
12226 /* make sure instructions are on a halfword boundary */
12227 if (ctx->pc & 0x1) {
12228 env->CP0_BadVAddr = ctx->pc;
12229 generate_exception(ctx, EXCP_AdEL);
12230 ctx->bstate = BS_STOP;
12231 return 2;
12232 }
12233
12234 op = (ctx->opcode >> 10) & 0x3f;
12235 /* Enforce properly-sized instructions in a delay slot */
12236 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12237 int bits = ctx->hflags & MIPS_HFLAG_BMASK_EXT;
12238
12239 switch (op) {
12240 case POOL32A:
12241 case POOL32B:
12242 case POOL32I:
12243 case POOL32C:
12244 case ADDI32:
12245 case ADDIU32:
12246 case ORI32:
12247 case XORI32:
12248 case SLTI32:
12249 case SLTIU32:
12250 case ANDI32:
12251 case JALX32:
12252 case LBU32:
12253 case LHU32:
12254 case POOL32F:
12255 case JALS32:
12256 case BEQ32:
12257 case BNE32:
12258 case J32:
12259 case JAL32:
12260 case SB32:
12261 case SH32:
12262 case POOL32S:
12263 case ADDIUPC:
12264 case SWC132:
12265 case SDC132:
12266 case SD32:
12267 case SW32:
12268 case LB32:
12269 case LH32:
12270 case DADDIU32:
12271 case POOL48A: /* ??? */
12272 case LWC132:
12273 case LDC132:
12274 case LD32:
12275 case LW32:
12276 if (bits & MIPS_HFLAG_BDS16) {
12277 generate_exception(ctx, EXCP_RI);
12278 /* Just stop translation; the user is confused. */
12279 ctx->bstate = BS_STOP;
12280 return 2;
12281 }
12282 break;
12283 case POOL16A:
12284 case POOL16B:
12285 case POOL16C:
12286 case LWGP16:
12287 case POOL16F:
12288 case LBU16:
12289 case LHU16:
12290 case LWSP16:
12291 case LW16:
12292 case SB16:
12293 case SH16:
12294 case SWSP16:
12295 case SW16:
12296 case MOVE16:
12297 case ANDI16:
12298 case POOL16D:
12299 case POOL16E:
12300 case BEQZ16:
12301 case BNEZ16:
12302 case B16:
12303 case LI16:
12304 if (bits & MIPS_HFLAG_BDS32) {
12305 generate_exception(ctx, EXCP_RI);
12306 /* Just stop translation; the user is confused. */
12307 ctx->bstate = BS_STOP;
12308 return 2;
12309 }
12310 break;
12311 default:
12312 break;
12313 }
12314 }
12315 switch (op) {
12316 case POOL16A:
12317 {
12318 int rd = mmreg(uMIPS_RD(ctx->opcode));
12319 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
12320 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
12321 uint32_t opc = 0;
12322
12323 switch (ctx->opcode & 0x1) {
12324 case ADDU16:
12325 opc = OPC_ADDU;
12326 break;
12327 case SUBU16:
12328 opc = OPC_SUBU;
12329 break;
12330 }
12331
12332 gen_arith(env, ctx, opc, rd, rs1, rs2);
12333 }
12334 break;
12335 case POOL16B:
12336 {
12337 int rd = mmreg(uMIPS_RD(ctx->opcode));
12338 int rs = mmreg(uMIPS_RS(ctx->opcode));
12339 int amount = (ctx->opcode >> 1) & 0x7;
12340 uint32_t opc = 0;
12341 amount = amount == 0 ? 8 : amount;
12342
12343 switch (ctx->opcode & 0x1) {
12344 case SLL16:
12345 opc = OPC_SLL;
12346 break;
12347 case SRL16:
12348 opc = OPC_SRL;
12349 break;
12350 }
12351
12352 gen_shift_imm(env, ctx, opc, rd, rs, amount);
12353 }
12354 break;
12355 case POOL16C:
12356 gen_pool16c_insn(env, ctx, is_branch);
12357 break;
12358 case LWGP16:
12359 {
12360 int rd = mmreg(uMIPS_RD(ctx->opcode));
12361 int rb = 28; /* GP */
12362 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
12363
afa88c3a 12364 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
3c824109
NF
12365 }
12366 break;
12367 case POOL16F:
12368 if (ctx->opcode & 1) {
12369 generate_exception(ctx, EXCP_RI);
12370 } else {
12371 /* MOVEP */
12372 int enc_dest = uMIPS_RD(ctx->opcode);
12373 int enc_rt = uMIPS_RS2(ctx->opcode);
12374 int enc_rs = uMIPS_RS1(ctx->opcode);
12375 int rd, rs, re, rt;
12376 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
12377 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
12378 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
12379
12380 rd = rd_enc[enc_dest];
12381 re = re_enc[enc_dest];
12382 rs = rs_rt_enc[enc_rs];
12383 rt = rs_rt_enc[enc_rt];
12384
12385 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
12386 gen_arith_imm(env, ctx, OPC_ADDIU, re, rt, 0);
12387 }
12388 break;
12389 case LBU16:
12390 {
12391 int rd = mmreg(uMIPS_RD(ctx->opcode));
12392 int rb = mmreg(uMIPS_RS(ctx->opcode));
12393 int16_t offset = ZIMM(ctx->opcode, 0, 4);
12394 offset = (offset == 0xf ? -1 : offset);
12395
afa88c3a 12396 gen_ld(env, ctx, OPC_LBU, rd, rb, offset);
3c824109
NF
12397 }
12398 break;
12399 case LHU16:
12400 {
12401 int rd = mmreg(uMIPS_RD(ctx->opcode));
12402 int rb = mmreg(uMIPS_RS(ctx->opcode));
12403 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
12404
afa88c3a 12405 gen_ld(env, ctx, OPC_LHU, rd, rb, offset);
3c824109
NF
12406 }
12407 break;
12408 case LWSP16:
12409 {
12410 int rd = (ctx->opcode >> 5) & 0x1f;
12411 int rb = 29; /* SP */
12412 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
12413
afa88c3a 12414 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
3c824109
NF
12415 }
12416 break;
12417 case LW16:
12418 {
12419 int rd = mmreg(uMIPS_RD(ctx->opcode));
12420 int rb = mmreg(uMIPS_RS(ctx->opcode));
12421 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
12422
afa88c3a 12423 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
3c824109
NF
12424 }
12425 break;
12426 case SB16:
12427 {
12428 int rd = mmreg2(uMIPS_RD(ctx->opcode));
12429 int rb = mmreg(uMIPS_RS(ctx->opcode));
12430 int16_t offset = ZIMM(ctx->opcode, 0, 4);
12431
5c13fdfd 12432 gen_st(ctx, OPC_SB, rd, rb, offset);
3c824109
NF
12433 }
12434 break;
12435 case SH16:
12436 {
12437 int rd = mmreg2(uMIPS_RD(ctx->opcode));
12438 int rb = mmreg(uMIPS_RS(ctx->opcode));
12439 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
12440
5c13fdfd 12441 gen_st(ctx, OPC_SH, rd, rb, offset);
3c824109
NF
12442 }
12443 break;
12444 case SWSP16:
12445 {
12446 int rd = (ctx->opcode >> 5) & 0x1f;
12447 int rb = 29; /* SP */
12448 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
12449
5c13fdfd 12450 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
12451 }
12452 break;
12453 case SW16:
12454 {
12455 int rd = mmreg2(uMIPS_RD(ctx->opcode));
12456 int rb = mmreg(uMIPS_RS(ctx->opcode));
12457 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
12458
5c13fdfd 12459 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
12460 }
12461 break;
12462 case MOVE16:
12463 {
12464 int rd = uMIPS_RD5(ctx->opcode);
12465 int rs = uMIPS_RS5(ctx->opcode);
12466
12467 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
12468 }
12469 break;
12470 case ANDI16:
12471 gen_andi16(env, ctx);
12472 break;
12473 case POOL16D:
12474 switch (ctx->opcode & 0x1) {
12475 case ADDIUS5:
12476 gen_addius5(env, ctx);
12477 break;
12478 case ADDIUSP:
12479 gen_addiusp(env, ctx);
12480 break;
12481 }
12482 break;
12483 case POOL16E:
12484 switch (ctx->opcode & 0x1) {
12485 case ADDIUR2:
12486 gen_addiur2(env, ctx);
12487 break;
12488 case ADDIUR1SP:
12489 gen_addiur1sp(env, ctx);
12490 break;
12491 }
12492 break;
12493 case B16:
12494 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
12495 SIMM(ctx->opcode, 0, 10) << 1);
12496 *is_branch = 1;
12497 break;
12498 case BNEZ16:
12499 case BEQZ16:
12500 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
12501 mmreg(uMIPS_RD(ctx->opcode)),
12502 0, SIMM(ctx->opcode, 0, 7) << 1);
12503 *is_branch = 1;
12504 break;
12505 case LI16:
12506 {
12507 int reg = mmreg(uMIPS_RD(ctx->opcode));
12508 int imm = ZIMM(ctx->opcode, 0, 7);
12509
12510 imm = (imm == 0x7f ? -1 : imm);
12511 tcg_gen_movi_tl(cpu_gpr[reg], imm);
12512 }
12513 break;
12514 case RES_20:
12515 case RES_28:
12516 case RES_29:
12517 case RES_30:
12518 case RES_31:
12519 case RES_38:
12520 case RES_39:
12521 generate_exception(ctx, EXCP_RI);
12522 break;
12523 default:
12524 decode_micromips32_opc (env, ctx, op, is_branch);
12525 return 4;
12526 }
12527
12528 return 2;
12529}
12530
12531/* SmartMIPS extension to MIPS32 */
12532
12533#if defined(TARGET_MIPS64)
12534
12535/* MDMX extension to MIPS64 */
12536
12537#endif
12538
9b1a1d68
JL
12539/* MIPSDSP functions. */
12540static void gen_mipsdsp_ld(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
12541 int rd, int base, int offset)
12542{
12543 const char *opn = "ldx";
12544 TCGv t0;
12545
12546 if (rd == 0) {
12547 MIPS_DEBUG("NOP");
12548 return;
12549 }
12550
12551 check_dsp(ctx);
12552 t0 = tcg_temp_new();
12553
12554 if (base == 0) {
12555 gen_load_gpr(t0, offset);
12556 } else if (offset == 0) {
12557 gen_load_gpr(t0, base);
12558 } else {
12559 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
12560 }
12561
12562 save_cpu_state(ctx, 0);
12563 switch (opc) {
12564 case OPC_LBUX:
12565 op_ld_lbu(t0, t0, ctx);
12566 gen_store_gpr(t0, rd);
12567 opn = "lbux";
12568 break;
12569 case OPC_LHX:
12570 op_ld_lh(t0, t0, ctx);
12571 gen_store_gpr(t0, rd);
12572 opn = "lhx";
12573 break;
12574 case OPC_LWX:
12575 op_ld_lw(t0, t0, ctx);
12576 gen_store_gpr(t0, rd);
12577 opn = "lwx";
12578 break;
12579#if defined(TARGET_MIPS64)
12580 case OPC_LDX:
12581 op_ld_ld(t0, t0, ctx);
12582 gen_store_gpr(t0, rd);
12583 opn = "ldx";
12584 break;
12585#endif
12586 }
12587 (void)opn; /* avoid a compiler warning */
12588 MIPS_DEBUG("%s %s, %s(%s)", opn,
12589 regnames[rd], regnames[offset], regnames[base]);
12590 tcg_temp_free(t0);
12591}
12592
461c08df
JL
12593static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
12594 int ret, int v1, int v2)
12595{
12596 const char *opn = "mipsdsp arith";
12597 TCGv v1_t;
12598 TCGv v2_t;
12599
12600 if (ret == 0) {
12601 /* Treat as NOP. */
12602 MIPS_DEBUG("NOP");
12603 return;
12604 }
12605
12606 v1_t = tcg_temp_new();
12607 v2_t = tcg_temp_new();
12608
12609 gen_load_gpr(v1_t, v1);
12610 gen_load_gpr(v2_t, v2);
12611
12612 switch (op1) {
12613 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
12614 case OPC_MULT_G_2E:
12615 check_dspr2(ctx);
12616 switch (op2) {
12617 case OPC_ADDUH_QB:
12618 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
12619 break;
12620 case OPC_ADDUH_R_QB:
12621 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
12622 break;
12623 case OPC_ADDQH_PH:
12624 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
12625 break;
12626 case OPC_ADDQH_R_PH:
12627 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
12628 break;
12629 case OPC_ADDQH_W:
12630 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
12631 break;
12632 case OPC_ADDQH_R_W:
12633 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
12634 break;
12635 case OPC_SUBUH_QB:
12636 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
12637 break;
12638 case OPC_SUBUH_R_QB:
12639 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
12640 break;
12641 case OPC_SUBQH_PH:
12642 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
12643 break;
12644 case OPC_SUBQH_R_PH:
12645 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
12646 break;
12647 case OPC_SUBQH_W:
12648 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
12649 break;
12650 case OPC_SUBQH_R_W:
12651 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
12652 break;
12653 }
12654 break;
12655 case OPC_ABSQ_S_PH_DSP:
12656 switch (op2) {
12657 case OPC_ABSQ_S_QB:
12658 check_dspr2(ctx);
12659 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
12660 break;
12661 case OPC_ABSQ_S_PH:
12662 check_dsp(ctx);
12663 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
12664 break;
12665 case OPC_ABSQ_S_W:
12666 check_dsp(ctx);
12667 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
12668 break;
12669 case OPC_PRECEQ_W_PHL:
12670 check_dsp(ctx);
12671 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
12672 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
12673 break;
12674 case OPC_PRECEQ_W_PHR:
12675 check_dsp(ctx);
12676 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
12677 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
12678 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
12679 break;
12680 case OPC_PRECEQU_PH_QBL:
12681 check_dsp(ctx);
12682 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
12683 break;
12684 case OPC_PRECEQU_PH_QBR:
12685 check_dsp(ctx);
12686 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
12687 break;
12688 case OPC_PRECEQU_PH_QBLA:
12689 check_dsp(ctx);
12690 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
12691 break;
12692 case OPC_PRECEQU_PH_QBRA:
12693 check_dsp(ctx);
12694 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
12695 break;
12696 case OPC_PRECEU_PH_QBL:
12697 check_dsp(ctx);
12698 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
12699 break;
12700 case OPC_PRECEU_PH_QBR:
12701 check_dsp(ctx);
12702 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
12703 break;
12704 case OPC_PRECEU_PH_QBLA:
12705 check_dsp(ctx);
12706 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
12707 break;
12708 case OPC_PRECEU_PH_QBRA:
12709 check_dsp(ctx);
12710 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
12711 break;
12712 }
12713 break;
12714 case OPC_ADDU_QB_DSP:
12715 switch (op2) {
12716 case OPC_ADDQ_PH:
12717 check_dsp(ctx);
12718 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12719 break;
12720 case OPC_ADDQ_S_PH:
12721 check_dsp(ctx);
12722 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12723 break;
12724 case OPC_ADDQ_S_W:
12725 check_dsp(ctx);
12726 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12727 break;
12728 case OPC_ADDU_QB:
12729 check_dsp(ctx);
12730 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12731 break;
12732 case OPC_ADDU_S_QB:
12733 check_dsp(ctx);
12734 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12735 break;
12736 case OPC_ADDU_PH:
12737 check_dspr2(ctx);
12738 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12739 break;
12740 case OPC_ADDU_S_PH:
12741 check_dspr2(ctx);
12742 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12743 break;
12744 case OPC_SUBQ_PH:
12745 check_dsp(ctx);
12746 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12747 break;
12748 case OPC_SUBQ_S_PH:
12749 check_dsp(ctx);
12750 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12751 break;
12752 case OPC_SUBQ_S_W:
12753 check_dsp(ctx);
12754 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12755 break;
12756 case OPC_SUBU_QB:
12757 check_dsp(ctx);
12758 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12759 break;
12760 case OPC_SUBU_S_QB:
12761 check_dsp(ctx);
12762 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12763 break;
12764 case OPC_SUBU_PH:
12765 check_dspr2(ctx);
12766 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12767 break;
12768 case OPC_SUBU_S_PH:
12769 check_dspr2(ctx);
12770 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12771 break;
12772 case OPC_ADDSC:
12773 check_dsp(ctx);
12774 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12775 break;
12776 case OPC_ADDWC:
12777 check_dsp(ctx);
12778 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12779 break;
12780 case OPC_MODSUB:
12781 check_dsp(ctx);
12782 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
12783 break;
12784 case OPC_RADDU_W_QB:
12785 check_dsp(ctx);
12786 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
12787 break;
12788 }
12789 break;
12790 case OPC_CMPU_EQ_QB_DSP:
12791 switch (op2) {
12792 case OPC_PRECR_QB_PH:
12793 check_dspr2(ctx);
12794 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
12795 break;
12796 case OPC_PRECRQ_QB_PH:
12797 check_dsp(ctx);
12798 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
12799 break;
12800 case OPC_PRECR_SRA_PH_W:
12801 check_dspr2(ctx);
12802 {
12803 TCGv_i32 sa_t = tcg_const_i32(v2);
12804 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
12805 cpu_gpr[ret]);
12806 tcg_temp_free_i32(sa_t);
12807 break;
12808 }
12809 case OPC_PRECR_SRA_R_PH_W:
12810 check_dspr2(ctx);
12811 {
12812 TCGv_i32 sa_t = tcg_const_i32(v2);
12813 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
12814 cpu_gpr[ret]);
12815 tcg_temp_free_i32(sa_t);
12816 break;
12817 }
12818 case OPC_PRECRQ_PH_W:
12819 check_dsp(ctx);
12820 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
12821 break;
12822 case OPC_PRECRQ_RS_PH_W:
12823 check_dsp(ctx);
12824 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12825 break;
12826 case OPC_PRECRQU_S_QB_PH:
12827 check_dsp(ctx);
12828 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12829 break;
12830 }
12831 break;
12832#ifdef TARGET_MIPS64
12833 case OPC_ABSQ_S_QH_DSP:
12834 switch (op2) {
12835 case OPC_PRECEQ_L_PWL:
12836 check_dsp(ctx);
12837 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
12838 break;
12839 case OPC_PRECEQ_L_PWR:
12840 check_dsp(ctx);
12841 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
12842 break;
12843 case OPC_PRECEQ_PW_QHL:
12844 check_dsp(ctx);
12845 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
12846 break;
12847 case OPC_PRECEQ_PW_QHR:
12848 check_dsp(ctx);
12849 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
12850 break;
12851 case OPC_PRECEQ_PW_QHLA:
12852 check_dsp(ctx);
12853 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
12854 break;
12855 case OPC_PRECEQ_PW_QHRA:
12856 check_dsp(ctx);
12857 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
12858 break;
12859 case OPC_PRECEQU_QH_OBL:
12860 check_dsp(ctx);
12861 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
12862 break;
12863 case OPC_PRECEQU_QH_OBR:
12864 check_dsp(ctx);
12865 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
12866 break;
12867 case OPC_PRECEQU_QH_OBLA:
12868 check_dsp(ctx);
12869 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
12870 break;
12871 case OPC_PRECEQU_QH_OBRA:
12872 check_dsp(ctx);
12873 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
12874 break;
12875 case OPC_PRECEU_QH_OBL:
12876 check_dsp(ctx);
12877 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
12878 break;
12879 case OPC_PRECEU_QH_OBR:
12880 check_dsp(ctx);
12881 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
12882 break;
12883 case OPC_PRECEU_QH_OBLA:
12884 check_dsp(ctx);
12885 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
12886 break;
12887 case OPC_PRECEU_QH_OBRA:
12888 check_dsp(ctx);
12889 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
12890 break;
12891 case OPC_ABSQ_S_OB:
12892 check_dspr2(ctx);
12893 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
12894 break;
12895 case OPC_ABSQ_S_PW:
12896 check_dsp(ctx);
12897 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
12898 break;
12899 case OPC_ABSQ_S_QH:
12900 check_dsp(ctx);
12901 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
12902 break;
12903 }
12904 break;
12905 case OPC_ADDU_OB_DSP:
12906 switch (op2) {
12907 case OPC_RADDU_L_OB:
12908 check_dsp(ctx);
12909 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
12910 break;
12911 case OPC_SUBQ_PW:
12912 check_dsp(ctx);
12913 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12914 break;
12915 case OPC_SUBQ_S_PW:
12916 check_dsp(ctx);
12917 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12918 break;
12919 case OPC_SUBQ_QH:
12920 check_dsp(ctx);
12921 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12922 break;
12923 case OPC_SUBQ_S_QH:
12924 check_dsp(ctx);
12925 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12926 break;
12927 case OPC_SUBU_OB:
12928 check_dsp(ctx);
12929 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12930 break;
12931 case OPC_SUBU_S_OB:
12932 check_dsp(ctx);
12933 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12934 break;
12935 case OPC_SUBU_QH:
12936 check_dspr2(ctx);
12937 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12938 break;
12939 case OPC_SUBU_S_QH:
12940 check_dspr2(ctx);
12941 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12942 break;
12943 case OPC_SUBUH_OB:
12944 check_dspr2(ctx);
12945 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
12946 break;
12947 case OPC_SUBUH_R_OB:
12948 check_dspr2(ctx);
12949 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
12950 break;
12951 case OPC_ADDQ_PW:
12952 check_dsp(ctx);
12953 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12954 break;
12955 case OPC_ADDQ_S_PW:
12956 check_dsp(ctx);
12957 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12958 break;
12959 case OPC_ADDQ_QH:
12960 check_dsp(ctx);
12961 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12962 break;
12963 case OPC_ADDQ_S_QH:
12964 check_dsp(ctx);
12965 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12966 break;
12967 case OPC_ADDU_OB:
12968 check_dsp(ctx);
12969 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12970 break;
12971 case OPC_ADDU_S_OB:
12972 check_dsp(ctx);
12973 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12974 break;
12975 case OPC_ADDU_QH:
12976 check_dspr2(ctx);
12977 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12978 break;
12979 case OPC_ADDU_S_QH:
12980 check_dspr2(ctx);
12981 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12982 break;
12983 case OPC_ADDUH_OB:
12984 check_dspr2(ctx);
12985 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
12986 break;
12987 case OPC_ADDUH_R_OB:
12988 check_dspr2(ctx);
12989 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
12990 break;
12991 }
12992 break;
12993 case OPC_CMPU_EQ_OB_DSP:
12994 switch (op2) {
12995 case OPC_PRECR_OB_QH:
12996 check_dspr2(ctx);
12997 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
12998 break;
12999 case OPC_PRECR_SRA_QH_PW:
13000 check_dspr2(ctx);
13001 {
13002 TCGv_i32 ret_t = tcg_const_i32(ret);
13003 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
13004 tcg_temp_free_i32(ret_t);
13005 break;
13006 }
13007 case OPC_PRECR_SRA_R_QH_PW:
13008 check_dspr2(ctx);
13009 {
13010 TCGv_i32 sa_v = tcg_const_i32(ret);
13011 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
13012 tcg_temp_free_i32(sa_v);
13013 break;
13014 }
13015 case OPC_PRECRQ_OB_QH:
13016 check_dsp(ctx);
13017 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
13018 break;
13019 case OPC_PRECRQ_PW_L:
13020 check_dsp(ctx);
13021 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
13022 break;
13023 case OPC_PRECRQ_QH_PW:
13024 check_dsp(ctx);
13025 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
13026 break;
13027 case OPC_PRECRQ_RS_QH_PW:
13028 check_dsp(ctx);
13029 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13030 break;
13031 case OPC_PRECRQU_S_OB_QH:
13032 check_dsp(ctx);
13033 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13034 break;
13035 }
13036 break;
13037#endif
13038 }
13039
13040 tcg_temp_free(v1_t);
13041 tcg_temp_free(v2_t);
13042
13043 (void)opn; /* avoid a compiler warning */
13044 MIPS_DEBUG("%s", opn);
13045}
9b1a1d68 13046
77c5fa8b
JL
13047static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
13048 int ret, int v1, int v2)
13049{
13050 uint32_t op2;
13051 const char *opn = "mipsdsp shift";
13052 TCGv t0;
13053 TCGv v1_t;
13054 TCGv v2_t;
13055
13056 if (ret == 0) {
13057 /* Treat as NOP. */
13058 MIPS_DEBUG("NOP");
13059 return;
13060 }
13061
13062 t0 = tcg_temp_new();
13063 v1_t = tcg_temp_new();
13064 v2_t = tcg_temp_new();
13065
13066 tcg_gen_movi_tl(t0, v1);
13067 gen_load_gpr(v1_t, v1);
13068 gen_load_gpr(v2_t, v2);
13069
13070 switch (opc) {
13071 case OPC_SHLL_QB_DSP:
13072 {
13073 op2 = MASK_SHLL_QB(ctx->opcode);
13074 switch (op2) {
13075 case OPC_SHLL_QB:
13076 check_dsp(ctx);
13077 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
13078 break;
13079 case OPC_SHLLV_QB:
13080 check_dsp(ctx);
13081 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13082 break;
13083 case OPC_SHLL_PH:
13084 check_dsp(ctx);
13085 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
13086 break;
13087 case OPC_SHLLV_PH:
13088 check_dsp(ctx);
13089 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13090 break;
13091 case OPC_SHLL_S_PH:
13092 check_dsp(ctx);
13093 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
13094 break;
13095 case OPC_SHLLV_S_PH:
13096 check_dsp(ctx);
13097 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13098 break;
13099 case OPC_SHLL_S_W:
13100 check_dsp(ctx);
13101 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
13102 break;
13103 case OPC_SHLLV_S_W:
13104 check_dsp(ctx);
13105 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13106 break;
13107 case OPC_SHRL_QB:
13108 check_dsp(ctx);
13109 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
13110 break;
13111 case OPC_SHRLV_QB:
13112 check_dsp(ctx);
13113 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
13114 break;
13115 case OPC_SHRL_PH:
13116 check_dspr2(ctx);
13117 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
13118 break;
13119 case OPC_SHRLV_PH:
13120 check_dspr2(ctx);
13121 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
13122 break;
13123 case OPC_SHRA_QB:
13124 check_dspr2(ctx);
13125 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
13126 break;
13127 case OPC_SHRA_R_QB:
13128 check_dspr2(ctx);
13129 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
13130 break;
13131 case OPC_SHRAV_QB:
13132 check_dspr2(ctx);
13133 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
13134 break;
13135 case OPC_SHRAV_R_QB:
13136 check_dspr2(ctx);
13137 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
13138 break;
13139 case OPC_SHRA_PH:
13140 check_dsp(ctx);
13141 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
13142 break;
13143 case OPC_SHRA_R_PH:
13144 check_dsp(ctx);
13145 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
13146 break;
13147 case OPC_SHRAV_PH:
13148 check_dsp(ctx);
13149 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
13150 break;
13151 case OPC_SHRAV_R_PH:
13152 check_dsp(ctx);
13153 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
13154 break;
13155 case OPC_SHRA_R_W:
13156 check_dsp(ctx);
13157 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
13158 break;
13159 case OPC_SHRAV_R_W:
13160 check_dsp(ctx);
13161 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
13162 break;
13163 default: /* Invalid */
13164 MIPS_INVAL("MASK SHLL.QB");
13165 generate_exception(ctx, EXCP_RI);
13166 break;
13167 }
13168 break;
13169 }
13170#ifdef TARGET_MIPS64
13171 case OPC_SHLL_OB_DSP:
13172 op2 = MASK_SHLL_OB(ctx->opcode);
13173 switch (op2) {
13174 case OPC_SHLL_PW:
13175 check_dsp(ctx);
13176 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
13177 break;
13178 case OPC_SHLLV_PW:
13179 check_dsp(ctx);
13180 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
13181 break;
13182 case OPC_SHLL_S_PW:
13183 check_dsp(ctx);
13184 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
13185 break;
13186 case OPC_SHLLV_S_PW:
13187 check_dsp(ctx);
13188 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
13189 break;
13190 case OPC_SHLL_OB:
13191 check_dsp(ctx);
13192 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
13193 break;
13194 case OPC_SHLLV_OB:
13195 check_dsp(ctx);
13196 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
13197 break;
13198 case OPC_SHLL_QH:
13199 check_dsp(ctx);
13200 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
13201 break;
13202 case OPC_SHLLV_QH:
13203 check_dsp(ctx);
13204 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
13205 break;
13206 case OPC_SHLL_S_QH:
13207 check_dsp(ctx);
13208 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
13209 break;
13210 case OPC_SHLLV_S_QH:
13211 check_dsp(ctx);
13212 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
13213 break;
13214 case OPC_SHRA_OB:
13215 check_dspr2(ctx);
13216 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
13217 break;
13218 case OPC_SHRAV_OB:
13219 check_dspr2(ctx);
13220 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
13221 break;
13222 case OPC_SHRA_R_OB:
13223 check_dspr2(ctx);
13224 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
13225 break;
13226 case OPC_SHRAV_R_OB:
13227 check_dspr2(ctx);
13228 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
13229 break;
13230 case OPC_SHRA_PW:
13231 check_dsp(ctx);
13232 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
13233 break;
13234 case OPC_SHRAV_PW:
13235 check_dsp(ctx);
13236 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
13237 break;
13238 case OPC_SHRA_R_PW:
13239 check_dsp(ctx);
13240 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
13241 break;
13242 case OPC_SHRAV_R_PW:
13243 check_dsp(ctx);
13244 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
13245 break;
13246 case OPC_SHRA_QH:
13247 check_dsp(ctx);
13248 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
13249 break;
13250 case OPC_SHRAV_QH:
13251 check_dsp(ctx);
13252 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
13253 break;
13254 case OPC_SHRA_R_QH:
13255 check_dsp(ctx);
13256 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
13257 break;
13258 case OPC_SHRAV_R_QH:
13259 check_dsp(ctx);
13260 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
13261 break;
13262 case OPC_SHRL_OB:
13263 check_dsp(ctx);
13264 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
13265 break;
13266 case OPC_SHRLV_OB:
13267 check_dsp(ctx);
13268 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
13269 break;
13270 case OPC_SHRL_QH:
13271 check_dspr2(ctx);
13272 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
13273 break;
13274 case OPC_SHRLV_QH:
13275 check_dspr2(ctx);
13276 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
13277 break;
13278 default: /* Invalid */
13279 MIPS_INVAL("MASK SHLL.OB");
13280 generate_exception(ctx, EXCP_RI);
13281 break;
13282 }
13283 break;
13284#endif
13285 }
13286
13287 tcg_temp_free(t0);
13288 tcg_temp_free(v1_t);
13289 tcg_temp_free(v2_t);
13290 (void)opn; /* avoid a compiler warning */
13291 MIPS_DEBUG("%s", opn);
13292}
13293
a22260ae
JL
13294static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
13295 int ret, int v1, int v2, int check_ret)
13296{
13297 const char *opn = "mipsdsp multiply";
13298 TCGv_i32 t0;
13299 TCGv v1_t;
13300 TCGv v2_t;
13301
13302 if ((ret == 0) && (check_ret == 1)) {
13303 /* Treat as NOP. */
13304 MIPS_DEBUG("NOP");
13305 return;
13306 }
13307
13308 t0 = tcg_temp_new_i32();
13309 v1_t = tcg_temp_new();
13310 v2_t = tcg_temp_new();
13311
13312 tcg_gen_movi_i32(t0, ret);
13313 gen_load_gpr(v1_t, v1);
13314 gen_load_gpr(v2_t, v2);
13315
13316 switch (op1) {
13317 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
13318 * the same mask and op1. */
13319 case OPC_MULT_G_2E:
13320 switch (op2) {
13321 case OPC_MUL_PH:
13322 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13323 break;
13324 case OPC_MUL_S_PH:
13325 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13326 break;
13327 case OPC_MULQ_S_W:
13328 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13329 break;
13330 case OPC_MULQ_RS_W:
13331 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13332 break;
13333 }
13334 break;
13335 case OPC_DPA_W_PH_DSP:
13336 switch (op2) {
13337 case OPC_DPAU_H_QBL:
13338 check_dsp(ctx);
13339 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
13340 break;
13341 case OPC_DPAU_H_QBR:
13342 check_dsp(ctx);
13343 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
13344 break;
13345 case OPC_DPSU_H_QBL:
13346 check_dsp(ctx);
13347 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
13348 break;
13349 case OPC_DPSU_H_QBR:
13350 check_dsp(ctx);
13351 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
13352 break;
13353 case OPC_DPA_W_PH:
13354 check_dspr2(ctx);
13355 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
13356 break;
13357 case OPC_DPAX_W_PH:
13358 check_dspr2(ctx);
13359 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
13360 break;
13361 case OPC_DPAQ_S_W_PH:
13362 check_dsp(ctx);
13363 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
13364 break;
13365 case OPC_DPAQX_S_W_PH:
13366 check_dspr2(ctx);
13367 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
13368 break;
13369 case OPC_DPAQX_SA_W_PH:
13370 check_dspr2(ctx);
13371 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
13372 break;
13373 case OPC_DPS_W_PH:
13374 check_dspr2(ctx);
13375 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
13376 break;
13377 case OPC_DPSX_W_PH:
13378 check_dspr2(ctx);
13379 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
13380 break;
13381 case OPC_DPSQ_S_W_PH:
13382 check_dsp(ctx);
13383 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
13384 break;
13385 case OPC_DPSQX_S_W_PH:
13386 check_dspr2(ctx);
13387 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
13388 break;
13389 case OPC_DPSQX_SA_W_PH:
13390 check_dspr2(ctx);
13391 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
13392 break;
13393 case OPC_MULSAQ_S_W_PH:
13394 check_dsp(ctx);
13395 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
13396 break;
13397 case OPC_DPAQ_SA_L_W:
13398 check_dsp(ctx);
13399 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
13400 break;
13401 case OPC_DPSQ_SA_L_W:
13402 check_dsp(ctx);
13403 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
13404 break;
13405 case OPC_MAQ_S_W_PHL:
13406 check_dsp(ctx);
13407 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
13408 break;
13409 case OPC_MAQ_S_W_PHR:
13410 check_dsp(ctx);
13411 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
13412 break;
13413 case OPC_MAQ_SA_W_PHL:
13414 check_dsp(ctx);
13415 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
13416 break;
13417 case OPC_MAQ_SA_W_PHR:
13418 check_dsp(ctx);
13419 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
13420 break;
13421 case OPC_MULSA_W_PH:
13422 check_dspr2(ctx);
13423 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
13424 break;
13425 }
13426 break;
13427#ifdef TARGET_MIPS64
13428 case OPC_DPAQ_W_QH_DSP:
13429 {
13430 int ac = ret & 0x03;
13431 tcg_gen_movi_i32(t0, ac);
13432
13433 switch (op2) {
13434 case OPC_DMADD:
13435 check_dsp(ctx);
13436 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
13437 break;
13438 case OPC_DMADDU:
13439 check_dsp(ctx);
13440 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
13441 break;
13442 case OPC_DMSUB:
13443 check_dsp(ctx);
13444 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
13445 break;
13446 case OPC_DMSUBU:
13447 check_dsp(ctx);
13448 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
13449 break;
13450 case OPC_DPA_W_QH:
13451 check_dspr2(ctx);
13452 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
13453 break;
13454 case OPC_DPAQ_S_W_QH:
13455 check_dsp(ctx);
13456 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
13457 break;
13458 case OPC_DPAQ_SA_L_PW:
13459 check_dsp(ctx);
13460 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
13461 break;
13462 case OPC_DPAU_H_OBL:
13463 check_dsp(ctx);
13464 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
13465 break;
13466 case OPC_DPAU_H_OBR:
13467 check_dsp(ctx);
13468 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
13469 break;
13470 case OPC_DPS_W_QH:
13471 check_dspr2(ctx);
13472 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
13473 break;
13474 case OPC_DPSQ_S_W_QH:
13475 check_dsp(ctx);
13476 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
13477 break;
13478 case OPC_DPSQ_SA_L_PW:
13479 check_dsp(ctx);
13480 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
13481 break;
13482 case OPC_DPSU_H_OBL:
13483 check_dsp(ctx);
13484 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
13485 break;
13486 case OPC_DPSU_H_OBR:
13487 check_dsp(ctx);
13488 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
13489 break;
13490 case OPC_MAQ_S_L_PWL:
13491 check_dsp(ctx);
13492 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
13493 break;
13494 case OPC_MAQ_S_L_PWR:
13495 check_dsp(ctx);
13496 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
13497 break;
13498 case OPC_MAQ_S_W_QHLL:
13499 check_dsp(ctx);
13500 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
13501 break;
13502 case OPC_MAQ_SA_W_QHLL:
13503 check_dsp(ctx);
13504 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
13505 break;
13506 case OPC_MAQ_S_W_QHLR:
13507 check_dsp(ctx);
13508 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
13509 break;
13510 case OPC_MAQ_SA_W_QHLR:
13511 check_dsp(ctx);
13512 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
13513 break;
13514 case OPC_MAQ_S_W_QHRL:
13515 check_dsp(ctx);
13516 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
13517 break;
13518 case OPC_MAQ_SA_W_QHRL:
13519 check_dsp(ctx);
13520 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
13521 break;
13522 case OPC_MAQ_S_W_QHRR:
13523 check_dsp(ctx);
13524 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
13525 break;
13526 case OPC_MAQ_SA_W_QHRR:
13527 check_dsp(ctx);
13528 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
13529 break;
13530 case OPC_MULSAQ_S_L_PW:
13531 check_dsp(ctx);
13532 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
13533 break;
13534 case OPC_MULSAQ_S_W_QH:
13535 check_dsp(ctx);
13536 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
13537 break;
13538 }
13539 }
13540 break;
13541#endif
13542 case OPC_ADDU_QB_DSP:
13543 switch (op2) {
13544 case OPC_MULEU_S_PH_QBL:
13545 check_dsp(ctx);
13546 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13547 break;
13548 case OPC_MULEU_S_PH_QBR:
13549 check_dsp(ctx);
13550 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13551 break;
13552 case OPC_MULQ_RS_PH:
13553 check_dsp(ctx);
13554 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13555 break;
13556 case OPC_MULEQ_S_W_PHL:
13557 check_dsp(ctx);
13558 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13559 break;
13560 case OPC_MULEQ_S_W_PHR:
13561 check_dsp(ctx);
13562 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13563 break;
13564 case OPC_MULQ_S_PH:
13565 check_dspr2(ctx);
13566 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13567 break;
13568 }
13569 break;
13570#ifdef TARGET_MIPS64
13571 case OPC_ADDU_OB_DSP:
13572 switch (op2) {
13573 case OPC_MULEQ_S_PW_QHL:
13574 check_dsp(ctx);
13575 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13576 break;
13577 case OPC_MULEQ_S_PW_QHR:
13578 check_dsp(ctx);
13579 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13580 break;
13581 case OPC_MULEU_S_QH_OBL:
13582 check_dsp(ctx);
13583 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13584 break;
13585 case OPC_MULEU_S_QH_OBR:
13586 check_dsp(ctx);
13587 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13588 break;
13589 case OPC_MULQ_RS_QH:
13590 check_dsp(ctx);
13591 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13592 break;
13593 }
13594 break;
13595#endif
13596 }
13597
13598 tcg_temp_free_i32(t0);
13599 tcg_temp_free(v1_t);
13600 tcg_temp_free(v2_t);
13601
13602 (void)opn; /* avoid a compiler warning */
13603 MIPS_DEBUG("%s", opn);
13604
13605}
13606
9b1a1d68
JL
13607/* End MIPSDSP functions. */
13608
7db13fae 13609static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
3c824109
NF
13610{
13611 int32_t offset;
13612 int rs, rt, rd, sa;
13613 uint32_t op, op1, op2;
13614 int16_t imm;
13615
13616 /* make sure instructions are on a word boundary */
13617 if (ctx->pc & 0x3) {
13618 env->CP0_BadVAddr = ctx->pc;
13619 generate_exception(ctx, EXCP_AdEL);
13620 return;
13621 }
13622
13623 /* Handle blikely not taken case */
13624 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
13625 int l1 = gen_new_label();
13626
13627 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
13628 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
13629 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
13630 gen_goto_tb(ctx, 1, ctx->pc + 4);
13631 gen_set_label(l1);
13632 }
13633
fdefe51c 13634 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
3c824109 13635 tcg_gen_debug_insn_start(ctx->pc);
fdefe51c 13636 }
3c824109
NF
13637
13638 op = MASK_OP_MAJOR(ctx->opcode);
13639 rs = (ctx->opcode >> 21) & 0x1f;
13640 rt = (ctx->opcode >> 16) & 0x1f;
13641 rd = (ctx->opcode >> 11) & 0x1f;
13642 sa = (ctx->opcode >> 6) & 0x1f;
13643 imm = (int16_t)ctx->opcode;
13644 switch (op) {
7a387fff
TS
13645 case OPC_SPECIAL:
13646 op1 = MASK_SPECIAL(ctx->opcode);
6af0bf9c 13647 switch (op1) {
324d9e32
AJ
13648 case OPC_SLL: /* Shift with immediate */
13649 case OPC_SRA:
324d9e32 13650 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7a387fff 13651 break;
ea63e2c3
NF
13652 case OPC_SRL:
13653 switch ((ctx->opcode >> 21) & 0x1f) {
13654 case 1:
13655 /* rotr is decoded as srl on non-R2 CPUs */
13656 if (env->insn_flags & ISA_MIPS32R2) {
13657 op1 = OPC_ROTR;
13658 }
13659 /* Fallthrough */
13660 case 0:
13661 gen_shift_imm(env, ctx, op1, rd, rt, sa);
13662 break;
13663 default:
13664 generate_exception(ctx, EXCP_RI);
13665 break;
13666 }
13667 break;
460f00c4
AJ
13668 case OPC_MOVN: /* Conditional move */
13669 case OPC_MOVZ:
aa8f4009
AJ
13670 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32 |
13671 INSN_LOONGSON2E | INSN_LOONGSON2F);
9fa77488 13672 gen_cond_move(env, ctx, op1, rd, rs, rt);
460f00c4
AJ
13673 break;
13674 case OPC_ADD ... OPC_SUBU:
e189e748 13675 gen_arith(env, ctx, op1, rd, rs, rt);
7a387fff 13676 break;
460f00c4 13677 case OPC_SLLV: /* Shifts */
460f00c4
AJ
13678 case OPC_SRAV:
13679 gen_shift(env, ctx, op1, rd, rs, rt);
13680 break;
ea63e2c3
NF
13681 case OPC_SRLV:
13682 switch ((ctx->opcode >> 6) & 0x1f) {
13683 case 1:
13684 /* rotrv is decoded as srlv on non-R2 CPUs */
13685 if (env->insn_flags & ISA_MIPS32R2) {
13686 op1 = OPC_ROTRV;
13687 }
13688 /* Fallthrough */
13689 case 0:
13690 gen_shift(env, ctx, op1, rd, rs, rt);
13691 break;
13692 default:
13693 generate_exception(ctx, EXCP_RI);
13694 break;
13695 }
13696 break;
460f00c4
AJ
13697 case OPC_SLT: /* Set on less than */
13698 case OPC_SLTU:
9fa77488 13699 gen_slt(env, ctx, op1, rd, rs, rt);
460f00c4
AJ
13700 break;
13701 case OPC_AND: /* Logic*/
13702 case OPC_OR:
13703 case OPC_NOR:
13704 case OPC_XOR:
9fa77488 13705 gen_logic(env, ctx, op1, rd, rs, rt);
460f00c4 13706 break;
7a387fff 13707 case OPC_MULT ... OPC_DIVU:
e9c71dd1
TS
13708 if (sa) {
13709 check_insn(env, ctx, INSN_VR54XX);
13710 op1 = MASK_MUL_VR54XX(ctx->opcode);
13711 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
13712 } else
13713 gen_muldiv(ctx, op1, rs, rt);
7a387fff
TS
13714 break;
13715 case OPC_JR ... OPC_JALR:
7dca4ad0 13716 gen_compute_branch(ctx, op1, 4, rs, rd, sa);
c9602061
NF
13717 *is_branch = 1;
13718 break;
7a387fff
TS
13719 case OPC_TGE ... OPC_TEQ: /* Traps */
13720 case OPC_TNE:
13721 gen_trap(ctx, op1, rs, rt, -1);
6af0bf9c 13722 break;
7a387fff
TS
13723 case OPC_MFHI: /* Move from HI/LO */
13724 case OPC_MFLO:
13725 gen_HILO(ctx, op1, rd);
6af0bf9c 13726 break;
7a387fff
TS
13727 case OPC_MTHI:
13728 case OPC_MTLO: /* Move to HI/LO */
13729 gen_HILO(ctx, op1, rs);
6af0bf9c 13730 break;
b48cfdff
TS
13731 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
13732#ifdef MIPS_STRICT_STANDARD
13733 MIPS_INVAL("PMON / selsl");
13734 generate_exception(ctx, EXCP_RI);
13735#else
895c2d04 13736 gen_helper_0e0i(pmon, sa);
b48cfdff 13737#endif
7a387fff
TS
13738 break;
13739 case OPC_SYSCALL:
6af0bf9c 13740 generate_exception(ctx, EXCP_SYSCALL);
8e0f950d 13741 ctx->bstate = BS_STOP;
6af0bf9c 13742 break;
7a387fff 13743 case OPC_BREAK:
6af0bf9c
FB
13744 generate_exception(ctx, EXCP_BREAK);
13745 break;
b48cfdff
TS
13746 case OPC_SPIM:
13747#ifdef MIPS_STRICT_STANDARD
13748 MIPS_INVAL("SPIM");
13749 generate_exception(ctx, EXCP_RI);
13750#else
7a387fff
TS
13751 /* Implemented as RI exception for now. */
13752 MIPS_INVAL("spim (unofficial)");
13753 generate_exception(ctx, EXCP_RI);
b48cfdff 13754#endif
6af0bf9c 13755 break;
7a387fff 13756 case OPC_SYNC:
ead9360e 13757 /* Treat as NOP. */
6af0bf9c 13758 break;
4ad40f36 13759
7a387fff 13760 case OPC_MOVCI:
e189e748 13761 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
36d23958 13762 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 13763 check_cp1_enabled(ctx);
36d23958
TS
13764 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
13765 (ctx->opcode >> 16) & 1);
13766 } else {
e397ee33 13767 generate_exception_err(ctx, EXCP_CpU, 1);
36d23958 13768 }
4ad40f36
FB
13769 break;
13770
d26bc211 13771#if defined(TARGET_MIPS64)
7a387fff
TS
13772 /* MIPS64 specific opcodes */
13773 case OPC_DSLL:
324d9e32 13774 case OPC_DSRA:
7a387fff 13775 case OPC_DSLL32:
324d9e32 13776 case OPC_DSRA32:
e189e748
TS
13777 check_insn(env, ctx, ISA_MIPS3);
13778 check_mips_64(ctx);
324d9e32 13779 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7a387fff 13780 break;
ea63e2c3
NF
13781 case OPC_DSRL:
13782 switch ((ctx->opcode >> 21) & 0x1f) {
13783 case 1:
13784 /* drotr is decoded as dsrl on non-R2 CPUs */
13785 if (env->insn_flags & ISA_MIPS32R2) {
13786 op1 = OPC_DROTR;
13787 }
13788 /* Fallthrough */
13789 case 0:
13790 check_insn(env, ctx, ISA_MIPS3);
13791 check_mips_64(ctx);
13792 gen_shift_imm(env, ctx, op1, rd, rt, sa);
13793 break;
13794 default:
13795 generate_exception(ctx, EXCP_RI);
13796 break;
13797 }
13798 break;
13799 case OPC_DSRL32:
13800 switch ((ctx->opcode >> 21) & 0x1f) {
13801 case 1:
13802 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
13803 if (env->insn_flags & ISA_MIPS32R2) {
13804 op1 = OPC_DROTR32;
13805 }
13806 /* Fallthrough */
13807 case 0:
13808 check_insn(env, ctx, ISA_MIPS3);
13809 check_mips_64(ctx);
13810 gen_shift_imm(env, ctx, op1, rd, rt, sa);
13811 break;
13812 default:
13813 generate_exception(ctx, EXCP_RI);
13814 break;
13815 }
13816 break;
7a387fff 13817 case OPC_DADD ... OPC_DSUBU:
e189e748
TS
13818 check_insn(env, ctx, ISA_MIPS3);
13819 check_mips_64(ctx);
13820 gen_arith(env, ctx, op1, rd, rs, rt);
7a387fff 13821 break;
460f00c4
AJ
13822 case OPC_DSLLV:
13823 case OPC_DSRAV:
460f00c4
AJ
13824 check_insn(env, ctx, ISA_MIPS3);
13825 check_mips_64(ctx);
13826 gen_shift(env, ctx, op1, rd, rs, rt);
13827 break;
ea63e2c3
NF
13828 case OPC_DSRLV:
13829 switch ((ctx->opcode >> 6) & 0x1f) {
13830 case 1:
13831 /* drotrv is decoded as dsrlv on non-R2 CPUs */
13832 if (env->insn_flags & ISA_MIPS32R2) {
13833 op1 = OPC_DROTRV;
13834 }
13835 /* Fallthrough */
13836 case 0:
13837 check_insn(env, ctx, ISA_MIPS3);
13838 check_mips_64(ctx);
13839 gen_shift(env, ctx, op1, rd, rs, rt);
13840 break;
13841 default:
13842 generate_exception(ctx, EXCP_RI);
13843 break;
13844 }
13845 break;
7a387fff 13846 case OPC_DMULT ... OPC_DDIVU:
e189e748
TS
13847 check_insn(env, ctx, ISA_MIPS3);
13848 check_mips_64(ctx);
7a387fff
TS
13849 gen_muldiv(ctx, op1, rs, rt);
13850 break;
6af0bf9c
FB
13851#endif
13852 default: /* Invalid */
13853 MIPS_INVAL("special");
13854 generate_exception(ctx, EXCP_RI);
13855 break;
13856 }
13857 break;
7a387fff
TS
13858 case OPC_SPECIAL2:
13859 op1 = MASK_SPECIAL2(ctx->opcode);
6af0bf9c 13860 switch (op1) {
7a387fff
TS
13861 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
13862 case OPC_MSUB ... OPC_MSUBU:
e189e748 13863 check_insn(env, ctx, ISA_MIPS32);
7a387fff 13864 gen_muldiv(ctx, op1, rs, rt);
6af0bf9c 13865 break;
7a387fff 13866 case OPC_MUL:
e189e748 13867 gen_arith(env, ctx, op1, rd, rs, rt);
6af0bf9c 13868 break;
20e1fb52
AJ
13869 case OPC_CLO:
13870 case OPC_CLZ:
e189e748 13871 check_insn(env, ctx, ISA_MIPS32);
7a387fff 13872 gen_cl(ctx, op1, rd, rs);
6af0bf9c 13873 break;
7a387fff 13874 case OPC_SDBBP:
6af0bf9c
FB
13875 /* XXX: not clear which exception should be raised
13876 * when in debug mode...
13877 */
e189e748 13878 check_insn(env, ctx, ISA_MIPS32);
6af0bf9c
FB
13879 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
13880 generate_exception(ctx, EXCP_DBp);
13881 } else {
13882 generate_exception(ctx, EXCP_DBp);
13883 }
ead9360e 13884 /* Treat as NOP. */
6af0bf9c 13885 break;
161f85e6
AJ
13886 case OPC_DIV_G_2F:
13887 case OPC_DIVU_G_2F:
13888 case OPC_MULT_G_2F:
13889 case OPC_MULTU_G_2F:
13890 case OPC_MOD_G_2F:
13891 case OPC_MODU_G_2F:
13892 check_insn(env, ctx, INSN_LOONGSON2F);
13893 gen_loongson_integer(ctx, op1, rd, rs, rt);
13894 break;
d26bc211 13895#if defined(TARGET_MIPS64)
20e1fb52
AJ
13896 case OPC_DCLO:
13897 case OPC_DCLZ:
e189e748
TS
13898 check_insn(env, ctx, ISA_MIPS64);
13899 check_mips_64(ctx);
7a387fff
TS
13900 gen_cl(ctx, op1, rd, rs);
13901 break;
161f85e6
AJ
13902 case OPC_DMULT_G_2F:
13903 case OPC_DMULTU_G_2F:
13904 case OPC_DDIV_G_2F:
13905 case OPC_DDIVU_G_2F:
13906 case OPC_DMOD_G_2F:
13907 case OPC_DMODU_G_2F:
13908 check_insn(env, ctx, INSN_LOONGSON2F);
13909 gen_loongson_integer(ctx, op1, rd, rs, rt);
13910 break;
7a387fff 13911#endif
6af0bf9c
FB
13912 default: /* Invalid */
13913 MIPS_INVAL("special2");
13914 generate_exception(ctx, EXCP_RI);
13915 break;
13916 }
13917 break;
7a387fff 13918 case OPC_SPECIAL3:
2b0233ab
TS
13919 op1 = MASK_SPECIAL3(ctx->opcode);
13920 switch (op1) {
13921 case OPC_EXT:
13922 case OPC_INS:
13923 check_insn(env, ctx, ISA_MIPS32R2);
13924 gen_bitops(ctx, op1, rt, rs, sa, rd);
13925 break;
13926 case OPC_BSHFL:
13927 check_insn(env, ctx, ISA_MIPS32R2);
13928 op2 = MASK_BSHFL(ctx->opcode);
49bcf33c 13929 gen_bshfl(ctx, op2, rt, rd);
7a387fff 13930 break;
1579a72e 13931 case OPC_RDHWR:
26ebe468 13932 gen_rdhwr(env, ctx, rt, rd);
1579a72e 13933 break;
ead9360e 13934 case OPC_FORK:
7385ac0b 13935 check_insn(env, ctx, ASE_MT);
6c5c1e20 13936 {
35fbce2c
AJ
13937 TCGv t0 = tcg_temp_new();
13938 TCGv t1 = tcg_temp_new();
6c5c1e20
TS
13939
13940 gen_load_gpr(t0, rt);
13941 gen_load_gpr(t1, rs);
a7812ae4 13942 gen_helper_fork(t0, t1);
6c5c1e20
TS
13943 tcg_temp_free(t0);
13944 tcg_temp_free(t1);
13945 }
ead9360e
TS
13946 break;
13947 case OPC_YIELD:
7385ac0b 13948 check_insn(env, ctx, ASE_MT);
6c5c1e20 13949 {
35fbce2c 13950 TCGv t0 = tcg_temp_new();
6c5c1e20 13951
35fbce2c 13952 save_cpu_state(ctx, 1);
6c5c1e20 13953 gen_load_gpr(t0, rs);
895c2d04 13954 gen_helper_yield(t0, cpu_env, t0);
6c5c1e20
TS
13955 gen_store_gpr(t0, rd);
13956 tcg_temp_free(t0);
13957 }
ead9360e 13958 break;
161f85e6 13959 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
161f85e6 13960 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
461c08df
JL
13961 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
13962 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
13963 * the same mask and op1. */
13964 if ((env->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
13965 op2 = MASK_ADDUH_QB(ctx->opcode);
13966 switch (op2) {
13967 case OPC_ADDUH_QB:
13968 case OPC_ADDUH_R_QB:
13969 case OPC_ADDQH_PH:
13970 case OPC_ADDQH_R_PH:
13971 case OPC_ADDQH_W:
13972 case OPC_ADDQH_R_W:
13973 case OPC_SUBUH_QB:
13974 case OPC_SUBUH_R_QB:
13975 case OPC_SUBQH_PH:
13976 case OPC_SUBQH_R_PH:
13977 case OPC_SUBQH_W:
13978 case OPC_SUBQH_R_W:
13979 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
13980 break;
a22260ae
JL
13981 case OPC_MUL_PH:
13982 case OPC_MUL_S_PH:
13983 case OPC_MULQ_S_W:
13984 case OPC_MULQ_RS_W:
13985 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
13986 break;
461c08df
JL
13987 default:
13988 MIPS_INVAL("MASK ADDUH.QB");
13989 generate_exception(ctx, EXCP_RI);
13990 break;
13991 }
13992 } else if (env->insn_flags & INSN_LOONGSON2E) {
13993 gen_loongson_integer(ctx, op1, rd, rs, rt);
13994 } else {
13995 generate_exception(ctx, EXCP_RI);
13996 }
161f85e6 13997 break;
9b1a1d68
JL
13998 case OPC_LX_DSP:
13999 op2 = MASK_LX(ctx->opcode);
14000 switch (op2) {
14001#if defined(TARGET_MIPS64)
14002 case OPC_LDX:
14003#endif
14004 case OPC_LBUX:
14005 case OPC_LHX:
14006 case OPC_LWX:
14007 gen_mipsdsp_ld(env, ctx, op2, rd, rs, rt);
14008 break;
14009 default: /* Invalid */
14010 MIPS_INVAL("MASK LX");
14011 generate_exception(ctx, EXCP_RI);
14012 break;
14013 }
14014 break;
461c08df
JL
14015 case OPC_ABSQ_S_PH_DSP:
14016 op2 = MASK_ABSQ_S_PH(ctx->opcode);
14017 switch (op2) {
14018 case OPC_ABSQ_S_QB:
14019 case OPC_ABSQ_S_PH:
14020 case OPC_ABSQ_S_W:
14021 case OPC_PRECEQ_W_PHL:
14022 case OPC_PRECEQ_W_PHR:
14023 case OPC_PRECEQU_PH_QBL:
14024 case OPC_PRECEQU_PH_QBR:
14025 case OPC_PRECEQU_PH_QBLA:
14026 case OPC_PRECEQU_PH_QBRA:
14027 case OPC_PRECEU_PH_QBL:
14028 case OPC_PRECEU_PH_QBR:
14029 case OPC_PRECEU_PH_QBLA:
14030 case OPC_PRECEU_PH_QBRA:
14031 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14032 break;
14033 default:
14034 MIPS_INVAL("MASK ABSQ_S.PH");
14035 generate_exception(ctx, EXCP_RI);
14036 break;
14037 }
14038 break;
14039 case OPC_ADDU_QB_DSP:
14040 op2 = MASK_ADDU_QB(ctx->opcode);
14041 switch (op2) {
14042 case OPC_ADDQ_PH:
14043 case OPC_ADDQ_S_PH:
14044 case OPC_ADDQ_S_W:
14045 case OPC_ADDU_QB:
14046 case OPC_ADDU_S_QB:
14047 case OPC_ADDU_PH:
14048 case OPC_ADDU_S_PH:
14049 case OPC_SUBQ_PH:
14050 case OPC_SUBQ_S_PH:
14051 case OPC_SUBQ_S_W:
14052 case OPC_SUBU_QB:
14053 case OPC_SUBU_S_QB:
14054 case OPC_SUBU_PH:
14055 case OPC_SUBU_S_PH:
14056 case OPC_ADDSC:
14057 case OPC_ADDWC:
14058 case OPC_MODSUB:
14059 case OPC_RADDU_W_QB:
14060 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14061 break;
a22260ae
JL
14062 case OPC_MULEU_S_PH_QBL:
14063 case OPC_MULEU_S_PH_QBR:
14064 case OPC_MULQ_RS_PH:
14065 case OPC_MULEQ_S_W_PHL:
14066 case OPC_MULEQ_S_W_PHR:
14067 case OPC_MULQ_S_PH:
14068 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
14069 break;
461c08df
JL
14070 default: /* Invalid */
14071 MIPS_INVAL("MASK ADDU.QB");
14072 generate_exception(ctx, EXCP_RI);
14073 break;
14074
14075 }
14076 break;
14077 case OPC_CMPU_EQ_QB_DSP:
14078 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
14079 switch (op2) {
14080 case OPC_PRECR_SRA_PH_W:
14081 case OPC_PRECR_SRA_R_PH_W:
14082 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
14083 break;
14084 case OPC_PRECR_QB_PH:
14085 case OPC_PRECRQ_QB_PH:
14086 case OPC_PRECRQ_PH_W:
14087 case OPC_PRECRQ_RS_PH_W:
14088 case OPC_PRECRQU_S_QB_PH:
14089 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14090 break;
14091 default: /* Invalid */
14092 MIPS_INVAL("MASK CMPU.EQ.QB");
14093 generate_exception(ctx, EXCP_RI);
14094 break;
14095 }
14096 break;
77c5fa8b
JL
14097 case OPC_SHLL_QB_DSP:
14098 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
14099 break;
a22260ae
JL
14100 case OPC_DPA_W_PH_DSP:
14101 op2 = MASK_DPA_W_PH(ctx->opcode);
14102 switch (op2) {
14103 case OPC_DPAU_H_QBL:
14104 case OPC_DPAU_H_QBR:
14105 case OPC_DPSU_H_QBL:
14106 case OPC_DPSU_H_QBR:
14107 case OPC_DPA_W_PH:
14108 case OPC_DPAX_W_PH:
14109 case OPC_DPAQ_S_W_PH:
14110 case OPC_DPAQX_S_W_PH:
14111 case OPC_DPAQX_SA_W_PH:
14112 case OPC_DPS_W_PH:
14113 case OPC_DPSX_W_PH:
14114 case OPC_DPSQ_S_W_PH:
14115 case OPC_DPSQX_S_W_PH:
14116 case OPC_DPSQX_SA_W_PH:
14117 case OPC_MULSAQ_S_W_PH:
14118 case OPC_DPAQ_SA_L_W:
14119 case OPC_DPSQ_SA_L_W:
14120 case OPC_MAQ_S_W_PHL:
14121 case OPC_MAQ_S_W_PHR:
14122 case OPC_MAQ_SA_W_PHL:
14123 case OPC_MAQ_SA_W_PHR:
14124 case OPC_MULSA_W_PH:
14125 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
14126 break;
14127 default: /* Invalid */
14128 MIPS_INVAL("MASK DPAW.PH");
14129 generate_exception(ctx, EXCP_RI);
14130 break;
14131 }
14132 break;
d26bc211 14133#if defined(TARGET_MIPS64)
1579a72e
TS
14134 case OPC_DEXTM ... OPC_DEXT:
14135 case OPC_DINSM ... OPC_DINS:
e189e748
TS
14136 check_insn(env, ctx, ISA_MIPS64R2);
14137 check_mips_64(ctx);
1579a72e 14138 gen_bitops(ctx, op1, rt, rs, sa, rd);
7a387fff 14139 break;
1579a72e 14140 case OPC_DBSHFL:
e189e748
TS
14141 check_insn(env, ctx, ISA_MIPS64R2);
14142 check_mips_64(ctx);
1579a72e 14143 op2 = MASK_DBSHFL(ctx->opcode);
49bcf33c 14144 gen_bshfl(ctx, op2, rt, rd);
c6d6dd7c 14145 break;
161f85e6
AJ
14146 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
14147 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
14148 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
14149 check_insn(env, ctx, INSN_LOONGSON2E);
14150 gen_loongson_integer(ctx, op1, rd, rs, rt);
14151 break;
461c08df
JL
14152 case OPC_ABSQ_S_QH_DSP:
14153 op2 = MASK_ABSQ_S_QH(ctx->opcode);
14154 switch (op2) {
14155 case OPC_PRECEQ_L_PWL:
14156 case OPC_PRECEQ_L_PWR:
14157 case OPC_PRECEQ_PW_QHL:
14158 case OPC_PRECEQ_PW_QHR:
14159 case OPC_PRECEQ_PW_QHLA:
14160 case OPC_PRECEQ_PW_QHRA:
14161 case OPC_PRECEQU_QH_OBL:
14162 case OPC_PRECEQU_QH_OBR:
14163 case OPC_PRECEQU_QH_OBLA:
14164 case OPC_PRECEQU_QH_OBRA:
14165 case OPC_PRECEU_QH_OBL:
14166 case OPC_PRECEU_QH_OBR:
14167 case OPC_PRECEU_QH_OBLA:
14168 case OPC_PRECEU_QH_OBRA:
14169 case OPC_ABSQ_S_OB:
14170 case OPC_ABSQ_S_PW:
14171 case OPC_ABSQ_S_QH:
14172 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14173 break;
14174 default: /* Invalid */
14175 MIPS_INVAL("MASK ABSQ_S.QH");
14176 generate_exception(ctx, EXCP_RI);
14177 break;
14178 }
14179 break;
14180 case OPC_ADDU_OB_DSP:
14181 op2 = MASK_ADDU_OB(ctx->opcode);
14182 switch (op2) {
14183 case OPC_RADDU_L_OB:
14184 case OPC_SUBQ_PW:
14185 case OPC_SUBQ_S_PW:
14186 case OPC_SUBQ_QH:
14187 case OPC_SUBQ_S_QH:
14188 case OPC_SUBU_OB:
14189 case OPC_SUBU_S_OB:
14190 case OPC_SUBU_QH:
14191 case OPC_SUBU_S_QH:
14192 case OPC_SUBUH_OB:
14193 case OPC_SUBUH_R_OB:
14194 case OPC_ADDQ_PW:
14195 case OPC_ADDQ_S_PW:
14196 case OPC_ADDQ_QH:
14197 case OPC_ADDQ_S_QH:
14198 case OPC_ADDU_OB:
14199 case OPC_ADDU_S_OB:
14200 case OPC_ADDU_QH:
14201 case OPC_ADDU_S_QH:
14202 case OPC_ADDUH_OB:
14203 case OPC_ADDUH_R_OB:
14204 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14205 break;
a22260ae
JL
14206 case OPC_MULEQ_S_PW_QHL:
14207 case OPC_MULEQ_S_PW_QHR:
14208 case OPC_MULEU_S_QH_OBL:
14209 case OPC_MULEU_S_QH_OBR:
14210 case OPC_MULQ_RS_QH:
14211 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
14212 break;
461c08df
JL
14213 default: /* Invalid */
14214 MIPS_INVAL("MASK ADDU.OB");
14215 generate_exception(ctx, EXCP_RI);
14216 break;
14217 }
14218 break;
14219 case OPC_CMPU_EQ_OB_DSP:
14220 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
14221 switch (op2) {
14222 case OPC_PRECR_SRA_QH_PW:
14223 case OPC_PRECR_SRA_R_QH_PW:
14224 /* Return value is rt. */
14225 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
14226 break;
14227 case OPC_PRECR_OB_QH:
14228 case OPC_PRECRQ_OB_QH:
14229 case OPC_PRECRQ_PW_L:
14230 case OPC_PRECRQ_QH_PW:
14231 case OPC_PRECRQ_RS_QH_PW:
14232 case OPC_PRECRQU_S_OB_QH:
14233 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14234 break;
14235 default: /* Invalid */
14236 MIPS_INVAL("MASK CMPU_EQ.OB");
14237 generate_exception(ctx, EXCP_RI);
14238 break;
14239 }
14240 break;
a22260ae
JL
14241 case OPC_DPAQ_W_QH_DSP:
14242 op2 = MASK_DPAQ_W_QH(ctx->opcode);
14243 switch (op2) {
14244 case OPC_DPAU_H_OBL:
14245 case OPC_DPAU_H_OBR:
14246 case OPC_DPSU_H_OBL:
14247 case OPC_DPSU_H_OBR:
14248 case OPC_DPA_W_QH:
14249 case OPC_DPAQ_S_W_QH:
14250 case OPC_DPS_W_QH:
14251 case OPC_DPSQ_S_W_QH:
14252 case OPC_MULSAQ_S_W_QH:
14253 case OPC_DPAQ_SA_L_PW:
14254 case OPC_DPSQ_SA_L_PW:
14255 case OPC_MULSAQ_S_L_PW:
14256 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
14257 break;
14258 case OPC_MAQ_S_W_QHLL:
14259 case OPC_MAQ_S_W_QHLR:
14260 case OPC_MAQ_S_W_QHRL:
14261 case OPC_MAQ_S_W_QHRR:
14262 case OPC_MAQ_SA_W_QHLL:
14263 case OPC_MAQ_SA_W_QHLR:
14264 case OPC_MAQ_SA_W_QHRL:
14265 case OPC_MAQ_SA_W_QHRR:
14266 case OPC_MAQ_S_L_PWL:
14267 case OPC_MAQ_S_L_PWR:
14268 case OPC_DMADD:
14269 case OPC_DMADDU:
14270 case OPC_DMSUB:
14271 case OPC_DMSUBU:
14272 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
14273 break;
14274 default: /* Invalid */
14275 MIPS_INVAL("MASK DPAQ.W.QH");
14276 generate_exception(ctx, EXCP_RI);
14277 break;
14278 }
14279 break;
77c5fa8b
JL
14280 case OPC_SHLL_OB_DSP:
14281 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
14282 break;
7a387fff
TS
14283#endif
14284 default: /* Invalid */
14285 MIPS_INVAL("special3");
14286 generate_exception(ctx, EXCP_RI);
14287 break;
14288 }
14289 break;
14290 case OPC_REGIMM:
14291 op1 = MASK_REGIMM(ctx->opcode);
14292 switch (op1) {
14293 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
14294 case OPC_BLTZAL ... OPC_BGEZALL:
7dca4ad0 14295 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
c9602061
NF
14296 *is_branch = 1;
14297 break;
7a387fff
TS
14298 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
14299 case OPC_TNEI:
14300 gen_trap(ctx, op1, rs, -1, imm);
14301 break;
14302 case OPC_SYNCI:
e189e748 14303 check_insn(env, ctx, ISA_MIPS32R2);
ead9360e 14304 /* Treat as NOP. */
6af0bf9c 14305 break;
e45a93e2
JL
14306 case OPC_BPOSGE32: /* MIPS DSP branch */
14307#if defined(TARGET_MIPS64)
14308 case OPC_BPOSGE64:
14309#endif
14310 check_dsp(ctx);
14311 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2);
14312 *is_branch = 1;
14313 break;
6af0bf9c 14314 default: /* Invalid */
923617a3 14315 MIPS_INVAL("regimm");
6af0bf9c
FB
14316 generate_exception(ctx, EXCP_RI);
14317 break;
14318 }
14319 break;
7a387fff 14320 case OPC_CP0:
387a8fe5 14321 check_cp0_enabled(ctx);
7a387fff 14322 op1 = MASK_CP0(ctx->opcode);
6af0bf9c 14323 switch (op1) {
7a387fff
TS
14324 case OPC_MFC0:
14325 case OPC_MTC0:
ead9360e
TS
14326 case OPC_MFTR:
14327 case OPC_MTTR:
d26bc211 14328#if defined(TARGET_MIPS64)
7a387fff
TS
14329 case OPC_DMFC0:
14330 case OPC_DMTC0:
14331#endif
f1aa6320 14332#ifndef CONFIG_USER_ONLY
932e71cd 14333 gen_cp0(env, ctx, op1, rt, rd);
0eaef5aa 14334#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
14335 break;
14336 case OPC_C0_FIRST ... OPC_C0_LAST:
f1aa6320 14337#ifndef CONFIG_USER_ONLY
932e71cd 14338 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
0eaef5aa 14339#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
14340 break;
14341 case OPC_MFMC0:
8706c382 14342#ifndef CONFIG_USER_ONLY
932e71cd 14343 {
35fbce2c 14344 TCGv t0 = tcg_temp_new();
6c5c1e20 14345
0eaef5aa 14346 op2 = MASK_MFMC0(ctx->opcode);
6c5c1e20
TS
14347 switch (op2) {
14348 case OPC_DMT:
14349 check_insn(env, ctx, ASE_MT);
9ed5726c 14350 gen_helper_dmt(t0);
35fbce2c 14351 gen_store_gpr(t0, rt);
6c5c1e20
TS
14352 break;
14353 case OPC_EMT:
14354 check_insn(env, ctx, ASE_MT);
9ed5726c 14355 gen_helper_emt(t0);
35fbce2c 14356 gen_store_gpr(t0, rt);
da80682b 14357 break;
6c5c1e20
TS
14358 case OPC_DVPE:
14359 check_insn(env, ctx, ASE_MT);
895c2d04 14360 gen_helper_dvpe(t0, cpu_env);
35fbce2c 14361 gen_store_gpr(t0, rt);
6c5c1e20
TS
14362 break;
14363 case OPC_EVPE:
14364 check_insn(env, ctx, ASE_MT);
895c2d04 14365 gen_helper_evpe(t0, cpu_env);
35fbce2c 14366 gen_store_gpr(t0, rt);
6c5c1e20
TS
14367 break;
14368 case OPC_DI:
14369 check_insn(env, ctx, ISA_MIPS32R2);
867abc7e 14370 save_cpu_state(ctx, 1);
895c2d04 14371 gen_helper_di(t0, cpu_env);
35fbce2c 14372 gen_store_gpr(t0, rt);
6c5c1e20
TS
14373 /* Stop translation as we may have switched the execution mode */
14374 ctx->bstate = BS_STOP;
14375 break;
14376 case OPC_EI:
14377 check_insn(env, ctx, ISA_MIPS32R2);
867abc7e 14378 save_cpu_state(ctx, 1);
895c2d04 14379 gen_helper_ei(t0, cpu_env);
35fbce2c 14380 gen_store_gpr(t0, rt);
6c5c1e20
TS
14381 /* Stop translation as we may have switched the execution mode */
14382 ctx->bstate = BS_STOP;
14383 break;
14384 default: /* Invalid */
14385 MIPS_INVAL("mfmc0");
14386 generate_exception(ctx, EXCP_RI);
14387 break;
14388 }
6c5c1e20 14389 tcg_temp_free(t0);
7a387fff 14390 }
0eaef5aa 14391#endif /* !CONFIG_USER_ONLY */
6af0bf9c 14392 break;
7a387fff 14393 case OPC_RDPGPR:
e189e748 14394 check_insn(env, ctx, ISA_MIPS32R2);
be24bb4f 14395 gen_load_srsgpr(rt, rd);
ead9360e 14396 break;
7a387fff 14397 case OPC_WRPGPR:
e189e748 14398 check_insn(env, ctx, ISA_MIPS32R2);
be24bb4f 14399 gen_store_srsgpr(rt, rd);
38121543 14400 break;
6af0bf9c 14401 default:
923617a3 14402 MIPS_INVAL("cp0");
7a387fff 14403 generate_exception(ctx, EXCP_RI);
6af0bf9c
FB
14404 break;
14405 }
14406 break;
324d9e32
AJ
14407 case OPC_ADDI: /* Arithmetic with immediate opcode */
14408 case OPC_ADDIU:
e189e748 14409 gen_arith_imm(env, ctx, op, rt, rs, imm);
7a387fff 14410 break;
324d9e32
AJ
14411 case OPC_SLTI: /* Set on less than with immediate opcode */
14412 case OPC_SLTIU:
9fa77488 14413 gen_slt_imm(env, ctx, op, rt, rs, imm);
324d9e32
AJ
14414 break;
14415 case OPC_ANDI: /* Arithmetic with immediate opcode */
14416 case OPC_LUI:
14417 case OPC_ORI:
14418 case OPC_XORI:
9fa77488 14419 gen_logic_imm(env, ctx, op, rt, rs, imm);
324d9e32 14420 break;
7a387fff
TS
14421 case OPC_J ... OPC_JAL: /* Jump */
14422 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
7dca4ad0 14423 gen_compute_branch(ctx, op, 4, rs, rt, offset);
c9602061
NF
14424 *is_branch = 1;
14425 break;
7a387fff
TS
14426 case OPC_BEQ ... OPC_BGTZ: /* Branch */
14427 case OPC_BEQL ... OPC_BGTZL:
7dca4ad0 14428 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
c9602061
NF
14429 *is_branch = 1;
14430 break;
7a387fff 14431 case OPC_LB ... OPC_LWR: /* Load and stores */
5c13fdfd 14432 case OPC_LL:
afa88c3a 14433 gen_ld(env, ctx, op, rt, rs, imm);
5c13fdfd 14434 break;
7a387fff
TS
14435 case OPC_SB ... OPC_SW:
14436 case OPC_SWR:
5c13fdfd 14437 gen_st(ctx, op, rt, rs, imm);
7a387fff 14438 break;
d66c7132
AJ
14439 case OPC_SC:
14440 gen_st_cond(ctx, op, rt, rs, imm);
14441 break;
7a387fff 14442 case OPC_CACHE:
2e15497c 14443 check_cp0_enabled(ctx);
e189e748 14444 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
ead9360e 14445 /* Treat as NOP. */
34ae7b51 14446 break;
7a387fff 14447 case OPC_PREF:
e189e748 14448 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
ead9360e 14449 /* Treat as NOP. */
6af0bf9c 14450 break;
4ad40f36 14451
923617a3 14452 /* Floating point (COP1). */
7a387fff
TS
14453 case OPC_LWC1:
14454 case OPC_LDC1:
14455 case OPC_SWC1:
14456 case OPC_SDC1:
26ebe468 14457 gen_cop1_ldst(env, ctx, op, rt, rs, imm);
6ea83fed
FB
14458 break;
14459
7a387fff 14460 case OPC_CP1:
36d23958 14461 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 14462 check_cp1_enabled(ctx);
36d23958
TS
14463 op1 = MASK_CP1(ctx->opcode);
14464 switch (op1) {
3a95e3a7
TS
14465 case OPC_MFHC1:
14466 case OPC_MTHC1:
e189e748 14467 check_insn(env, ctx, ISA_MIPS32R2);
36d23958
TS
14468 case OPC_MFC1:
14469 case OPC_CFC1:
14470 case OPC_MTC1:
14471 case OPC_CTC1:
e189e748
TS
14472 gen_cp1(ctx, op1, rt, rd);
14473 break;
d26bc211 14474#if defined(TARGET_MIPS64)
36d23958
TS
14475 case OPC_DMFC1:
14476 case OPC_DMTC1:
e189e748 14477 check_insn(env, ctx, ISA_MIPS3);
36d23958
TS
14478 gen_cp1(ctx, op1, rt, rd);
14479 break;
e189e748 14480#endif
fbcc6828
TS
14481 case OPC_BC1ANY2:
14482 case OPC_BC1ANY4:
b8aa4598 14483 check_cop1x(ctx);
7385ac0b 14484 check_insn(env, ctx, ASE_MIPS3D);
d8a5950a
TS
14485 /* fall through */
14486 case OPC_BC1:
e189e748 14487 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
5a5012ec 14488 (rt >> 2) & 0x7, imm << 2);
c9602061
NF
14489 *is_branch = 1;
14490 break;
36d23958
TS
14491 case OPC_S_FMT:
14492 case OPC_D_FMT:
14493 case OPC_W_FMT:
14494 case OPC_L_FMT:
5a5012ec 14495 case OPC_PS_FMT:
bf4120ad 14496 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
5a5012ec 14497 (imm >> 8) & 0x7);
36d23958
TS
14498 break;
14499 default:
923617a3 14500 MIPS_INVAL("cp1");
e397ee33 14501 generate_exception (ctx, EXCP_RI);
36d23958
TS
14502 break;
14503 }
14504 } else {
14505 generate_exception_err(ctx, EXCP_CpU, 1);
6ea83fed 14506 }
4ad40f36
FB
14507 break;
14508
14509 /* COP2. */
7a387fff
TS
14510 case OPC_LWC2:
14511 case OPC_LDC2:
14512 case OPC_SWC2:
14513 case OPC_SDC2:
7a387fff 14514 /* COP2: Not implemented. */
4ad40f36
FB
14515 generate_exception_err(ctx, EXCP_CpU, 2);
14516 break;
bd277fa1
RH
14517 case OPC_CP2:
14518 check_insn(env, ctx, INSN_LOONGSON2F);
14519 /* Note that these instructions use different fields. */
14520 gen_loongson_multimedia(ctx, sa, rd, rt);
14521 break;
4ad40f36 14522
7a387fff 14523 case OPC_CP3:
36d23958 14524 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 14525 check_cp1_enabled(ctx);
36d23958
TS
14526 op1 = MASK_CP3(ctx->opcode);
14527 switch (op1) {
5a5012ec
TS
14528 case OPC_LWXC1:
14529 case OPC_LDXC1:
14530 case OPC_LUXC1:
14531 case OPC_SWXC1:
14532 case OPC_SDXC1:
14533 case OPC_SUXC1:
93b12ccc 14534 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
5a5012ec 14535 break;
e0c84da7 14536 case OPC_PREFX:
ead9360e 14537 /* Treat as NOP. */
e0c84da7 14538 break;
5a5012ec
TS
14539 case OPC_ALNV_PS:
14540 case OPC_MADD_S:
14541 case OPC_MADD_D:
14542 case OPC_MADD_PS:
14543 case OPC_MSUB_S:
14544 case OPC_MSUB_D:
14545 case OPC_MSUB_PS:
14546 case OPC_NMADD_S:
14547 case OPC_NMADD_D:
14548 case OPC_NMADD_PS:
14549 case OPC_NMSUB_S:
14550 case OPC_NMSUB_D:
14551 case OPC_NMSUB_PS:
14552 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
14553 break;
36d23958 14554 default:
923617a3 14555 MIPS_INVAL("cp3");
e397ee33 14556 generate_exception (ctx, EXCP_RI);
36d23958
TS
14557 break;
14558 }
14559 } else {
e397ee33 14560 generate_exception_err(ctx, EXCP_CpU, 1);
7a387fff 14561 }
4ad40f36
FB
14562 break;
14563
d26bc211 14564#if defined(TARGET_MIPS64)
7a387fff
TS
14565 /* MIPS64 opcodes */
14566 case OPC_LWU:
14567 case OPC_LDL ... OPC_LDR:
7a387fff
TS
14568 case OPC_LLD:
14569 case OPC_LD:
5c13fdfd
AJ
14570 check_insn(env, ctx, ISA_MIPS3);
14571 check_mips_64(ctx);
afa88c3a 14572 gen_ld(env, ctx, op, rt, rs, imm);
5c13fdfd
AJ
14573 break;
14574 case OPC_SDL ... OPC_SDR:
7a387fff 14575 case OPC_SD:
e189e748
TS
14576 check_insn(env, ctx, ISA_MIPS3);
14577 check_mips_64(ctx);
5c13fdfd 14578 gen_st(ctx, op, rt, rs, imm);
7a387fff 14579 break;
d66c7132
AJ
14580 case OPC_SCD:
14581 check_insn(env, ctx, ISA_MIPS3);
14582 check_mips_64(ctx);
14583 gen_st_cond(ctx, op, rt, rs, imm);
14584 break;
324d9e32
AJ
14585 case OPC_DADDI:
14586 case OPC_DADDIU:
e189e748
TS
14587 check_insn(env, ctx, ISA_MIPS3);
14588 check_mips_64(ctx);
14589 gen_arith_imm(env, ctx, op, rt, rs, imm);
7a387fff 14590 break;
6af0bf9c 14591#endif
7a387fff 14592 case OPC_JALX:
3c824109 14593 check_insn(env, ctx, ASE_MIPS16 | ASE_MICROMIPS);
364d4831
NF
14594 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
14595 gen_compute_branch(ctx, op, 4, rs, rt, offset);
14596 *is_branch = 1;
14597 break;
7a387fff 14598 case OPC_MDMX:
e189e748 14599 check_insn(env, ctx, ASE_MDMX);
7a387fff 14600 /* MDMX: Not implemented. */
6af0bf9c 14601 default: /* Invalid */
923617a3 14602 MIPS_INVAL("major opcode");
6af0bf9c
FB
14603 generate_exception(ctx, EXCP_RI);
14604 break;
14605 }
6af0bf9c
FB
14606}
14607
2cfc5f17 14608static inline void
7db13fae 14609gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
820e00f2 14610 int search_pc)
6af0bf9c 14611{
278d0702 14612 DisasContext ctx;
6af0bf9c
FB
14613 target_ulong pc_start;
14614 uint16_t *gen_opc_end;
a1d1bb31 14615 CPUBreakpoint *bp;
6af0bf9c 14616 int j, lj = -1;
2e70f6ef
PB
14617 int num_insns;
14618 int max_insns;
c9602061
NF
14619 int insn_bytes;
14620 int is_branch;
6af0bf9c 14621
93fcfe39
AL
14622 if (search_pc)
14623 qemu_log("search pc %d\n", search_pc);
4ad40f36 14624
6af0bf9c 14625 pc_start = tb->pc;
d42320c2 14626 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6af0bf9c 14627 ctx.pc = pc_start;
4ad40f36 14628 ctx.saved_pc = -1;
7b270ef2 14629 ctx.singlestep_enabled = env->singlestep_enabled;
6af0bf9c
FB
14630 ctx.tb = tb;
14631 ctx.bstate = BS_NONE;
4ad40f36 14632 /* Restore delay slot state from the tb context. */
c068688b 14633 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
fd4a04eb 14634 restore_cpu_state(env, &ctx);
932e71cd 14635#ifdef CONFIG_USER_ONLY
0eaef5aa 14636 ctx.mem_idx = MIPS_HFLAG_UM;
932e71cd 14637#else
0eaef5aa 14638 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
932e71cd 14639#endif
2e70f6ef
PB
14640 num_insns = 0;
14641 max_insns = tb->cflags & CF_COUNT_MASK;
14642 if (max_insns == 0)
14643 max_insns = CF_COUNT_MASK;
d12d51d5 14644 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
2e70f6ef 14645 gen_icount_start();
faf7aaa9 14646 while (ctx.bstate == BS_NONE) {
72cf2d4f
BS
14647 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
14648 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
a1d1bb31 14649 if (bp->pc == ctx.pc) {
278d0702 14650 save_cpu_state(&ctx, 1);
4ad40f36 14651 ctx.bstate = BS_BRANCH;
895c2d04 14652 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
ce62e5ba
TS
14653 /* Include the breakpoint location or the tb won't
14654 * be flushed when it must be. */
14655 ctx.pc += 4;
4ad40f36
FB
14656 goto done_generating;
14657 }
14658 }
14659 }
14660
6af0bf9c
FB
14661 if (search_pc) {
14662 j = gen_opc_ptr - gen_opc_buf;
6af0bf9c
FB
14663 if (lj < j) {
14664 lj++;
14665 while (lj < j)
14666 gen_opc_instr_start[lj++] = 0;
6af0bf9c 14667 }
4ad40f36
FB
14668 gen_opc_pc[lj] = ctx.pc;
14669 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
14670 gen_opc_instr_start[lj] = 1;
2e70f6ef 14671 gen_opc_icount[lj] = num_insns;
6af0bf9c 14672 }
2e70f6ef
PB
14673 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
14674 gen_io_start();
c9602061
NF
14675
14676 is_branch = 0;
364d4831 14677 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
895c2d04 14678 ctx.opcode = cpu_ldl_code(env, ctx.pc);
c9602061
NF
14679 insn_bytes = 4;
14680 decode_opc(env, &ctx, &is_branch);
3c824109 14681 } else if (env->insn_flags & ASE_MICROMIPS) {
895c2d04 14682 ctx.opcode = cpu_lduw_code(env, ctx.pc);
3c824109 14683 insn_bytes = decode_micromips_opc(env, &ctx, &is_branch);
364d4831 14684 } else if (env->insn_flags & ASE_MIPS16) {
895c2d04 14685 ctx.opcode = cpu_lduw_code(env, ctx.pc);
364d4831 14686 insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
c9602061
NF
14687 } else {
14688 generate_exception(&ctx, EXCP_RI);
3c824109 14689 ctx.bstate = BS_STOP;
c9602061
NF
14690 break;
14691 }
14692 if (!is_branch) {
14693 handle_delay_slot(env, &ctx, insn_bytes);
14694 }
14695 ctx.pc += insn_bytes;
14696
2e70f6ef 14697 num_insns++;
4ad40f36 14698
7b270ef2
NF
14699 /* Execute a branch and its delay slot as a single instruction.
14700 This is what GDB expects and is consistent with what the
14701 hardware does (e.g. if a delay slot instruction faults, the
14702 reported PC is the PC of the branch). */
14703 if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
4ad40f36
FB
14704 break;
14705
6af0bf9c
FB
14706 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
14707 break;
4ad40f36 14708
faf7aaa9
TS
14709 if (gen_opc_ptr >= gen_opc_end)
14710 break;
14711
2e70f6ef
PB
14712 if (num_insns >= max_insns)
14713 break;
1b530a6d
AJ
14714
14715 if (singlestep)
14716 break;
6af0bf9c 14717 }
2e70f6ef
PB
14718 if (tb->cflags & CF_LAST_IO)
14719 gen_io_end();
7b270ef2 14720 if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) {
278d0702 14721 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
895c2d04 14722 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
16c00cb2 14723 } else {
6958549d 14724 switch (ctx.bstate) {
16c00cb2 14725 case BS_STOP:
df1561e2
TS
14726 gen_goto_tb(&ctx, 0, ctx.pc);
14727 break;
16c00cb2 14728 case BS_NONE:
278d0702 14729 save_cpu_state(&ctx, 0);
16c00cb2
TS
14730 gen_goto_tb(&ctx, 0, ctx.pc);
14731 break;
5a5012ec 14732 case BS_EXCP:
57fec1fe 14733 tcg_gen_exit_tb(0);
16c00cb2 14734 break;
5a5012ec
TS
14735 case BS_BRANCH:
14736 default:
14737 break;
6958549d 14738 }
6af0bf9c 14739 }
4ad40f36 14740done_generating:
2e70f6ef 14741 gen_icount_end(tb, num_insns);
6af0bf9c
FB
14742 *gen_opc_ptr = INDEX_op_end;
14743 if (search_pc) {
14744 j = gen_opc_ptr - gen_opc_buf;
14745 lj++;
14746 while (lj <= j)
14747 gen_opc_instr_start[lj++] = 0;
6af0bf9c
FB
14748 } else {
14749 tb->size = ctx.pc - pc_start;
2e70f6ef 14750 tb->icount = num_insns;
6af0bf9c
FB
14751 }
14752#ifdef DEBUG_DISAS
d12d51d5 14753 LOG_DISAS("\n");
8fec2b8c 14754 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
93fcfe39
AL
14755 qemu_log("IN: %s\n", lookup_symbol(pc_start));
14756 log_target_disas(pc_start, ctx.pc - pc_start, 0);
14757 qemu_log("\n");
6af0bf9c
FB
14758 }
14759#endif
6af0bf9c
FB
14760}
14761
7db13fae 14762void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
6af0bf9c 14763{
2cfc5f17 14764 gen_intermediate_code_internal(env, tb, 0);
6af0bf9c
FB
14765}
14766
7db13fae 14767void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
6af0bf9c 14768{
2cfc5f17 14769 gen_intermediate_code_internal(env, tb, 1);
6af0bf9c
FB
14770}
14771
7db13fae 14772static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
8706c382 14773 int flags)
6ea83fed
FB
14774{
14775 int i;
5e755519 14776 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
5a5012ec 14777
2a5612e6
SW
14778#define printfpr(fp) \
14779 do { \
14780 if (is_fpu64) \
14781 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
14782 " fd:%13g fs:%13g psu: %13g\n", \
14783 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
14784 (double)(fp)->fd, \
14785 (double)(fp)->fs[FP_ENDIAN_IDX], \
14786 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
14787 else { \
14788 fpr_t tmp; \
14789 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
14790 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
14791 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
14792 " fd:%13g fs:%13g psu:%13g\n", \
14793 tmp.w[FP_ENDIAN_IDX], tmp.d, \
14794 (double)tmp.fd, \
14795 (double)tmp.fs[FP_ENDIAN_IDX], \
14796 (double)tmp.fs[!FP_ENDIAN_IDX]); \
14797 } \
6ea83fed
FB
14798 } while(0)
14799
5a5012ec 14800
9a78eead
SW
14801 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
14802 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
f01be154 14803 get_float_exception_flags(&env->active_fpu.fp_status));
5a5012ec
TS
14804 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
14805 fpu_fprintf(f, "%3s: ", fregnames[i]);
f01be154 14806 printfpr(&env->active_fpu.fpr[i]);
6ea83fed
FB
14807 }
14808
14809#undef printfpr
14810}
14811
d26bc211 14812#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16 14813/* Debug help: The architecture requires 32bit code to maintain proper
c7e8a937 14814 sign-extended values on 64bit machines. */
c570fd16
TS
14815
14816#define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
14817
8706c382 14818static void
7db13fae 14819cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f,
9a78eead 14820 fprintf_function cpu_fprintf,
8706c382 14821 int flags)
c570fd16
TS
14822{
14823 int i;
14824
b5dc7732
TS
14825 if (!SIGN_EXT_P(env->active_tc.PC))
14826 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
14827 if (!SIGN_EXT_P(env->active_tc.HI[0]))
14828 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
14829 if (!SIGN_EXT_P(env->active_tc.LO[0]))
14830 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
c570fd16 14831 if (!SIGN_EXT_P(env->btarget))
3594c774 14832 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
c570fd16
TS
14833
14834 for (i = 0; i < 32; i++) {
b5dc7732
TS
14835 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
14836 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
c570fd16
TS
14837 }
14838
14839 if (!SIGN_EXT_P(env->CP0_EPC))
3594c774 14840 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
5499b6ff
AJ
14841 if (!SIGN_EXT_P(env->lladdr))
14842 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
c570fd16
TS
14843}
14844#endif
14845
7db13fae 14846void cpu_dump_state (CPUMIPSState *env, FILE *f, fprintf_function cpu_fprintf,
6af0bf9c
FB
14847 int flags)
14848{
14849 int i;
3b46e624 14850
a7200c9f
SW
14851 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
14852 " LO=0x" TARGET_FMT_lx " ds %04x "
14853 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
3d5be870
TS
14854 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
14855 env->hflags, env->btarget, env->bcond);
6af0bf9c
FB
14856 for (i = 0; i < 32; i++) {
14857 if ((i & 3) == 0)
14858 cpu_fprintf(f, "GPR%02d:", i);
b5dc7732 14859 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
6af0bf9c
FB
14860 if ((i & 3) == 3)
14861 cpu_fprintf(f, "\n");
14862 }
568b600d 14863
3594c774 14864 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
5e755519 14865 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
3594c774 14866 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
5499b6ff 14867 env->CP0_Config0, env->CP0_Config1, env->lladdr);
5e755519 14868 if (env->hflags & MIPS_HFLAG_FPU)
7a387fff 14869 fpu_dump_state(env, f, cpu_fprintf, flags);
d26bc211 14870#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16
TS
14871 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
14872#endif
6af0bf9c
FB
14873}
14874
39454628
TS
14875static void mips_tcg_init(void)
14876{
f01be154 14877 int i;
39454628
TS
14878 static int inited;
14879
14880 /* Initialize various static tables. */
14881 if (inited)
6958549d 14882 return;
39454628 14883
a7812ae4 14884 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
f2c94b92 14885 TCGV_UNUSED(cpu_gpr[0]);
bb928dbe 14886 for (i = 1; i < 32; i++)
a7812ae4 14887 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
7db13fae 14888 offsetof(CPUMIPSState, active_tc.gpr[i]),
4b2eb8d2 14889 regnames[i]);
d73ee8a2
RH
14890
14891 for (i = 0; i < 32; i++) {
14892 int off = offsetof(CPUMIPSState, active_fpu.fpr[i]);
14893 fpu_f64[i] = tcg_global_mem_new_i64(TCG_AREG0, off, fregnames[i]);
14894 }
14895
a7812ae4 14896 cpu_PC = tcg_global_mem_new(TCG_AREG0,
7db13fae 14897 offsetof(CPUMIPSState, active_tc.PC), "PC");
4b2eb8d2 14898 for (i = 0; i < MIPS_DSP_ACC; i++) {
a7812ae4 14899 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
7db13fae 14900 offsetof(CPUMIPSState, active_tc.HI[i]),
4b2eb8d2 14901 regnames_HI[i]);
a7812ae4 14902 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
7db13fae 14903 offsetof(CPUMIPSState, active_tc.LO[i]),
4b2eb8d2 14904 regnames_LO[i]);
a7812ae4 14905 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
7db13fae 14906 offsetof(CPUMIPSState, active_tc.ACX[i]),
4b2eb8d2
TS
14907 regnames_ACX[i]);
14908 }
a7812ae4 14909 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
7db13fae 14910 offsetof(CPUMIPSState, active_tc.DSPControl),
4b2eb8d2 14911 "DSPControl");
1ba74fb8 14912 bcond = tcg_global_mem_new(TCG_AREG0,
7db13fae 14913 offsetof(CPUMIPSState, bcond), "bcond");
a7812ae4 14914 btarget = tcg_global_mem_new(TCG_AREG0,
7db13fae 14915 offsetof(CPUMIPSState, btarget), "btarget");
41db4607 14916 hflags = tcg_global_mem_new_i32(TCG_AREG0,
7db13fae 14917 offsetof(CPUMIPSState, hflags), "hflags");
41db4607 14918
a7812ae4 14919 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
7db13fae 14920 offsetof(CPUMIPSState, active_fpu.fcr0),
a7812ae4
PB
14921 "fcr0");
14922 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
7db13fae 14923 offsetof(CPUMIPSState, active_fpu.fcr31),
a7812ae4 14924 "fcr31");
39454628 14925
7dd9e556 14926 /* register helpers */
a7812ae4 14927#define GEN_HELPER 2
7dd9e556
TS
14928#include "helper.h"
14929
39454628
TS
14930 inited = 1;
14931}
14932
aaed909a
FB
14933#include "translate_init.c"
14934
30bf942d 14935MIPSCPU *cpu_mips_init(const char *cpu_model)
6af0bf9c 14936{
0f71a709 14937 MIPSCPU *cpu;
6af0bf9c 14938 CPUMIPSState *env;
c227f099 14939 const mips_def_t *def;
6af0bf9c 14940
aaed909a
FB
14941 def = cpu_mips_find_by_name(cpu_model);
14942 if (!def)
14943 return NULL;
0f71a709
AF
14944 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
14945 env = &cpu->env;
aaed909a 14946 env->cpu_model = def;
51cc2e78 14947 env->cpu_model_str = cpu_model;
aaed909a 14948
51cc2e78
BS
14949#ifndef CONFIG_USER_ONLY
14950 mmu_init(env, def);
14951#endif
14952 fpu_init(env, def);
14953 mvp_init(env, def);
39454628 14954 mips_tcg_init();
3bd4122e 14955 cpu_reset(CPU(cpu));
0bf46a40 14956 qemu_init_vcpu(env);
30bf942d 14957 return cpu;
6ae81775
TS
14958}
14959
1bba0dc9 14960void cpu_state_reset(CPUMIPSState *env)
6ae81775 14961{
eca1bdf4
AL
14962 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
14963 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
14964 log_cpu_state(env, 0);
14965 }
14966
6ae81775 14967 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
6af0bf9c 14968 tlb_flush(env, 1);
6ae81775 14969
51cc2e78
BS
14970 /* Reset registers to their default values */
14971 env->CP0_PRid = env->cpu_model->CP0_PRid;
14972 env->CP0_Config0 = env->cpu_model->CP0_Config0;
14973#ifdef TARGET_WORDS_BIGENDIAN
14974 env->CP0_Config0 |= (1 << CP0C0_BE);
14975#endif
14976 env->CP0_Config1 = env->cpu_model->CP0_Config1;
14977 env->CP0_Config2 = env->cpu_model->CP0_Config2;
14978 env->CP0_Config3 = env->cpu_model->CP0_Config3;
14979 env->CP0_Config6 = env->cpu_model->CP0_Config6;
14980 env->CP0_Config7 = env->cpu_model->CP0_Config7;
2a6e32dd
AJ
14981 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
14982 << env->cpu_model->CP0_LLAddr_shift;
14983 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
51cc2e78
BS
14984 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
14985 env->CCRes = env->cpu_model->CCRes;
14986 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
14987 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
14988 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
14989 env->current_tc = 0;
14990 env->SEGBITS = env->cpu_model->SEGBITS;
14991 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
14992#if defined(TARGET_MIPS64)
14993 if (env->cpu_model->insn_flags & ISA_MIPS3) {
14994 env->SEGMask |= 3ULL << 62;
14995 }
14996#endif
14997 env->PABITS = env->cpu_model->PABITS;
14998 env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
14999 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
15000 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
15001 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
15002 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
15003 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
15004 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
15005 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
15006 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
15007 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
15008 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
f1cb0951 15009 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
51cc2e78
BS
15010 env->insn_flags = env->cpu_model->insn_flags;
15011
0eaef5aa 15012#if defined(CONFIG_USER_ONLY)
03e6e501 15013 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
94159135
MI
15014 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
15015 hardware registers. */
15016 env->CP0_HWREna |= 0x0000000F;
91a75935 15017 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
03e6e501 15018 env->CP0_Status |= (1 << CP0St_CU1);
91a75935 15019 }
853c3240
JL
15020 if (env->cpu_model->insn_flags & ASE_DSPR2) {
15021 env->hflags |= MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2;
15022 } else if (env->cpu_model->insn_flags & ASE_DSP) {
15023 env->hflags |= MIPS_HFLAG_DSP;
15024 }
932e71cd
AJ
15025#else
15026 if (env->hflags & MIPS_HFLAG_BMASK) {
15027 /* If the exception was raised from a delay slot,
15028 come back to the jump. */
15029 env->CP0_ErrorEPC = env->active_tc.PC - 4;
aa328add 15030 } else {
932e71cd
AJ
15031 env->CP0_ErrorEPC = env->active_tc.PC;
15032 }
15033 env->active_tc.PC = (int32_t)0xBFC00000;
51cc2e78
BS
15034 env->CP0_Random = env->tlb->nb_tlb - 1;
15035 env->tlb->tlb_in_use = env->tlb->nb_tlb;
932e71cd 15036 env->CP0_Wired = 0;
671b0f36 15037 env->CP0_EBase = 0x80000000 | (env->cpu_index & 0x3FF);
932e71cd
AJ
15038 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
15039 /* vectored interrupts not implemented, timer on int 7,
15040 no performance counters. */
15041 env->CP0_IntCtl = 0xe0000000;
15042 {
15043 int i;
15044
15045 for (i = 0; i < 7; i++) {
15046 env->CP0_WatchLo[i] = 0;
15047 env->CP0_WatchHi[i] = 0x80000000;
fd88b6ab 15048 }
932e71cd
AJ
15049 env->CP0_WatchLo[7] = 0;
15050 env->CP0_WatchHi[7] = 0;
fd88b6ab 15051 }
932e71cd
AJ
15052 /* Count register increments in debug mode, EJTAG version 1 */
15053 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
9e56e756
EI
15054
15055 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
15056 int i;
15057
15058 /* Only TC0 on VPE 0 starts as active. */
15059 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
15060 env->tcs[i].CP0_TCBind = env->cpu_index << CP0TCBd_CurVPE;
15061 env->tcs[i].CP0_TCHalt = 1;
15062 }
15063 env->active_tc.CP0_TCHalt = 1;
15064 env->halted = 1;
15065
15066 if (!env->cpu_index) {
15067 /* VPE0 starts up enabled. */
15068 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
15069 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
15070
15071 /* TC0 starts up unhalted. */
15072 env->halted = 0;
15073 env->active_tc.CP0_TCHalt = 0;
15074 env->tcs[0].CP0_TCHalt = 0;
15075 /* With thread 0 active. */
15076 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
15077 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
15078 }
15079 }
51cc2e78 15080#endif
03e6e501 15081 compute_hflags(env);
6af0bf9c 15082 env->exception_index = EXCP_NONE;
6af0bf9c 15083}
d2856f1a 15084
7db13fae 15085void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
d2856f1a 15086{
b5dc7732 15087 env->active_tc.PC = gen_opc_pc[pc_pos];
d2856f1a
AJ
15088 env->hflags &= ~MIPS_HFLAG_BMASK;
15089 env->hflags |= gen_opc_hflags[pc_pos];
15090}