]> git.proxmox.com Git - qemu.git/blame - target-mips/translate.c
target-mips: Add ASE DSP arithmetic instructions
[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,
333#endif
e37e863f
FB
334};
335
7a387fff
TS
336/* BSHFL opcodes */
337#define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
338
e37e863f 339enum {
7a387fff
TS
340 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
341 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
342 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
e37e863f
FB
343};
344
7a387fff
TS
345/* DBSHFL opcodes */
346#define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
347
e37e863f 348enum {
7a387fff
TS
349 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
350 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
e37e863f
FB
351};
352
e45a93e2
JL
353/* MIPS DSP REGIMM opcodes */
354enum {
355 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
356#if defined(TARGET_MIPS64)
357 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
358#endif
359};
360
9b1a1d68
JL
361#define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
362/* MIPS DSP Load */
363enum {
364 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
365 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
366 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
367#if defined(TARGET_MIPS64)
368 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
369#endif
370};
371
461c08df
JL
372#define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
373enum {
374 /* MIPS DSP Arithmetic Sub-class */
375 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
376 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
377 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
378 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
379 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
380 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
381 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
382 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
383 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
384 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
385 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
386 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
387 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
388 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
389 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
390 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
391 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
392 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
393};
394
395#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
396#define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
397enum {
398 /* MIPS DSP Arithmetic Sub-class */
399 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
400 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
401 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
402 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
403 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
404 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
405 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
406 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
407 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
408 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
409 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
410 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
411};
412
413#define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
414enum {
415 /* MIPS DSP Arithmetic Sub-class */
416 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
417 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
418 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
419 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
420 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
421 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
422 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
423 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
424 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
425 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
426 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
427 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
428 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
429};
430
431#define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
432enum {
433 /* MIPS DSP Arithmetic Sub-class */
434 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
435 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
436 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
437 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
438 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
439 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
440 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
441};
442
443#if defined(TARGET_MIPS64)
444#define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
445enum {
446 /* MIPS DSP Arithmetic Sub-class */
447 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
448 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
449 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
450 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
451 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
452 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
453 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
454 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
455 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
456 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
457 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
458 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
459 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
460 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
461 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
462 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
463 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
464};
465#endif
466
467#if defined(TARGET_MIPS64)
468#define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
469enum {
470 /* MIPS DSP Arithmetic Sub-class */
471 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
472 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
473 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
474 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
475 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
476 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
477 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
478 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
479 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
480 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
481 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
482 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
483 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
484 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
485 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
486 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
487 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
488 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
489 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
490 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
491 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
492};
493#endif
494
495#if defined(TARGET_MIPS64)
496#define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
497enum {
498 /* MIPS DSP Arithmetic Sub-class */
499 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
500 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
501 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
502 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
503 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
504 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
505 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
506 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
507};
508#endif
509
7a387fff
TS
510/* Coprocessor 0 (rs field) */
511#define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
512
6ea83fed 513enum {
7a387fff
TS
514 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
515 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
516 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
517 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
ead9360e 518 OPC_MFTR = (0x08 << 21) | OPC_CP0,
7a387fff
TS
519 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
520 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
ead9360e 521 OPC_MTTR = (0x0C << 21) | OPC_CP0,
7a387fff
TS
522 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
523 OPC_C0 = (0x10 << 21) | OPC_CP0,
524 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
525 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
6ea83fed 526};
7a387fff
TS
527
528/* MFMC0 opcodes */
b48cfdff 529#define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
7a387fff
TS
530
531enum {
ead9360e
TS
532 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
533 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
534 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
535 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
7a387fff
TS
536 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
537 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
538};
539
540/* Coprocessor 0 (with rs == C0) */
541#define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
542
543enum {
544 OPC_TLBR = 0x01 | OPC_C0,
545 OPC_TLBWI = 0x02 | OPC_C0,
546 OPC_TLBWR = 0x06 | OPC_C0,
547 OPC_TLBP = 0x08 | OPC_C0,
548 OPC_RFE = 0x10 | OPC_C0,
549 OPC_ERET = 0x18 | OPC_C0,
550 OPC_DERET = 0x1F | OPC_C0,
551 OPC_WAIT = 0x20 | OPC_C0,
552};
553
554/* Coprocessor 1 (rs field) */
555#define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
556
bf4120ad
NF
557/* Values for the fmt field in FP instructions */
558enum {
559 /* 0 - 15 are reserved */
e459440a
AJ
560 FMT_S = 16, /* single fp */
561 FMT_D = 17, /* double fp */
562 FMT_E = 18, /* extended fp */
563 FMT_Q = 19, /* quad fp */
564 FMT_W = 20, /* 32-bit fixed */
565 FMT_L = 21, /* 64-bit fixed */
566 FMT_PS = 22, /* paired single fp */
bf4120ad
NF
567 /* 23 - 31 are reserved */
568};
569
7a387fff
TS
570enum {
571 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
572 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
573 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
5a5012ec 574 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
7a387fff
TS
575 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
576 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
577 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
5a5012ec 578 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
7a387fff 579 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
5a5012ec
TS
580 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
581 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
e459440a
AJ
582 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
583 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
584 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
585 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
586 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
587 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
588 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
7a387fff
TS
589};
590
5a5012ec
TS
591#define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
592#define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
593
7a387fff
TS
594enum {
595 OPC_BC1F = (0x00 << 16) | OPC_BC1,
596 OPC_BC1T = (0x01 << 16) | OPC_BC1,
597 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
598 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
599};
600
5a5012ec
TS
601enum {
602 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
603 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
604};
605
606enum {
607 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
608 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
609};
7a387fff
TS
610
611#define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
e0c84da7
TS
612
613enum {
614 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
615 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
616 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
617 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
618 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
619 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
620 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
621 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
622 OPC_BC2 = (0x08 << 21) | OPC_CP2,
623};
624
bd277fa1
RH
625#define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
626
627enum {
628 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
629 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
630 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
631 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
632 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
633 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
634 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
635 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
636
637 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
638 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
639 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
640 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
641 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
642 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
643 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
644 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
645
646 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
647 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
648 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
649 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
650 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
651 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
652 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
653 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
654
655 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
656 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
657 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
658 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
659 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
660 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
661 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
662 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
663
664 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
665 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
666 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
667 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
668 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
669 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
670
671 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
672 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
673 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
674 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
675 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
676 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
677
678 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
679 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
680 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
681 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
682 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
683 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
684
685 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
686 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
687 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
688 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
689 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
690 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
691
692 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
693 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
694 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
695 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
696 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
697 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
698
699 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
700 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
701 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
702 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
703 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
704 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
705
706 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
707 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
708 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
709 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
710 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
711 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
712
713 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
714 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
715 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
716 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
717 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
718 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
719};
720
721
e0c84da7
TS
722#define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
723
724enum {
725 OPC_LWXC1 = 0x00 | OPC_CP3,
726 OPC_LDXC1 = 0x01 | OPC_CP3,
727 OPC_LUXC1 = 0x05 | OPC_CP3,
728 OPC_SWXC1 = 0x08 | OPC_CP3,
729 OPC_SDXC1 = 0x09 | OPC_CP3,
730 OPC_SUXC1 = 0x0D | OPC_CP3,
731 OPC_PREFX = 0x0F | OPC_CP3,
732 OPC_ALNV_PS = 0x1E | OPC_CP3,
733 OPC_MADD_S = 0x20 | OPC_CP3,
734 OPC_MADD_D = 0x21 | OPC_CP3,
735 OPC_MADD_PS = 0x26 | OPC_CP3,
736 OPC_MSUB_S = 0x28 | OPC_CP3,
737 OPC_MSUB_D = 0x29 | OPC_CP3,
738 OPC_MSUB_PS = 0x2E | OPC_CP3,
739 OPC_NMADD_S = 0x30 | OPC_CP3,
fbcc6828 740 OPC_NMADD_D = 0x31 | OPC_CP3,
e0c84da7
TS
741 OPC_NMADD_PS= 0x36 | OPC_CP3,
742 OPC_NMSUB_S = 0x38 | OPC_CP3,
743 OPC_NMSUB_D = 0x39 | OPC_CP3,
744 OPC_NMSUB_PS= 0x3E | OPC_CP3,
745};
746
39454628 747/* global register indices */
a7812ae4
PB
748static TCGv_ptr cpu_env;
749static TCGv cpu_gpr[32], cpu_PC;
4b2eb8d2 750static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
41db4607
AJ
751static TCGv cpu_dspctrl, btarget, bcond;
752static TCGv_i32 hflags;
a7812ae4 753static TCGv_i32 fpu_fcr0, fpu_fcr31;
d73ee8a2 754static TCGv_i64 fpu_f64[32];
aa0bf00b 755
1a7ff922
PB
756static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
757
2e70f6ef
PB
758#include "gen-icount.h"
759
895c2d04 760#define gen_helper_0e0i(name, arg) do { \
a7812ae4 761 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
895c2d04 762 gen_helper_##name(cpu_env, helper_tmp); \
a7812ae4
PB
763 tcg_temp_free_i32(helper_tmp); \
764 } while(0)
be24bb4f 765
895c2d04 766#define gen_helper_0e1i(name, arg1, arg2) do { \
a7812ae4 767 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
895c2d04 768 gen_helper_##name(cpu_env, arg1, helper_tmp); \
a7812ae4
PB
769 tcg_temp_free_i32(helper_tmp); \
770 } while(0)
be24bb4f 771
895c2d04
BS
772#define gen_helper_1e0i(name, ret, arg1) do { \
773 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
774 gen_helper_##name(ret, cpu_env, helper_tmp); \
775 tcg_temp_free_i32(helper_tmp); \
776 } while(0)
777
778#define gen_helper_1e1i(name, ret, arg1, arg2) do { \
779 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
780 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
781 tcg_temp_free_i32(helper_tmp); \
782 } while(0)
783
784#define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
785 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
786 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
787 tcg_temp_free_i32(helper_tmp); \
788 } while(0)
789
790#define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
a7812ae4 791 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
895c2d04 792 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
a7812ae4
PB
793 tcg_temp_free_i32(helper_tmp); \
794 } while(0)
be24bb4f 795
895c2d04 796#define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
a7812ae4 797 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
895c2d04 798 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
a7812ae4
PB
799 tcg_temp_free_i32(helper_tmp); \
800 } while(0)
c239529e 801
8e9ade68
TS
802typedef struct DisasContext {
803 struct TranslationBlock *tb;
804 target_ulong pc, saved_pc;
805 uint32_t opcode;
7b270ef2 806 int singlestep_enabled;
8e9ade68
TS
807 /* Routine used to access memory */
808 int mem_idx;
809 uint32_t hflags, saved_hflags;
810 int bstate;
811 target_ulong btarget;
812} DisasContext;
813
814enum {
815 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
d077b6f7 816 * exception condition */
8e9ade68
TS
817 BS_STOP = 1, /* We want to stop translation for any reason */
818 BS_BRANCH = 2, /* We reached a branch condition */
819 BS_EXCP = 3, /* We reached an exception condition */
820};
821
d73ee8a2
RH
822static const char * const regnames[] = {
823 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
824 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
825 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
826 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
827};
6af0bf9c 828
d73ee8a2
RH
829static const char * const regnames_HI[] = {
830 "HI0", "HI1", "HI2", "HI3",
831};
4b2eb8d2 832
d73ee8a2
RH
833static const char * const regnames_LO[] = {
834 "LO0", "LO1", "LO2", "LO3",
835};
4b2eb8d2 836
d73ee8a2
RH
837static const char * const regnames_ACX[] = {
838 "ACX0", "ACX1", "ACX2", "ACX3",
839};
4b2eb8d2 840
d73ee8a2
RH
841static const char * const fregnames[] = {
842 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
843 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
844 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
845 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
846};
958fb4a9 847
fb7729e2
RH
848#define MIPS_DEBUG(fmt, ...) \
849 do { \
850 if (MIPS_DEBUG_DISAS) { \
851 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
852 TARGET_FMT_lx ": %08x " fmt "\n", \
853 ctx->pc, ctx->opcode , ## __VA_ARGS__); \
854 } \
855 } while (0)
856
857#define LOG_DISAS(...) \
858 do { \
859 if (MIPS_DEBUG_DISAS) { \
860 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
861 } \
862 } while (0)
958fb4a9 863
8e9ade68 864#define MIPS_INVAL(op) \
8e9ade68 865 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
fb7729e2 866 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F))
ead9360e 867
8e9ade68
TS
868/* General purpose registers moves. */
869static inline void gen_load_gpr (TCGv t, int reg)
aaa9128a 870{
8e9ade68
TS
871 if (reg == 0)
872 tcg_gen_movi_tl(t, 0);
873 else
4b2eb8d2 874 tcg_gen_mov_tl(t, cpu_gpr[reg]);
aaa9128a
TS
875}
876
8e9ade68 877static inline void gen_store_gpr (TCGv t, int reg)
aaa9128a 878{
8e9ade68 879 if (reg != 0)
4b2eb8d2 880 tcg_gen_mov_tl(cpu_gpr[reg], t);
aaa9128a
TS
881}
882
b10fa3c9 883/* Moves to/from ACX register. */
4b2eb8d2 884static inline void gen_load_ACX (TCGv t, int reg)
893f9865 885{
4b2eb8d2 886 tcg_gen_mov_tl(t, cpu_ACX[reg]);
893f9865
TS
887}
888
4b2eb8d2 889static inline void gen_store_ACX (TCGv t, int reg)
893f9865 890{
4b2eb8d2 891 tcg_gen_mov_tl(cpu_ACX[reg], t);
893f9865
TS
892}
893
8e9ade68 894/* Moves to/from shadow registers. */
be24bb4f 895static inline void gen_load_srsgpr (int from, int to)
aaa9128a 896{
d9bea114 897 TCGv t0 = tcg_temp_new();
be24bb4f
TS
898
899 if (from == 0)
d9bea114 900 tcg_gen_movi_tl(t0, 0);
8e9ade68 901 else {
d9bea114 902 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 903 TCGv_ptr addr = tcg_temp_new_ptr();
aaa9128a 904
7db13fae 905 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
906 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
907 tcg_gen_andi_i32(t2, t2, 0xf);
908 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
909 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 910 tcg_gen_add_ptr(addr, cpu_env, addr);
aaa9128a 911
d9bea114 912 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
a7812ae4 913 tcg_temp_free_ptr(addr);
d9bea114 914 tcg_temp_free_i32(t2);
8e9ade68 915 }
d9bea114
AJ
916 gen_store_gpr(t0, to);
917 tcg_temp_free(t0);
aaa9128a
TS
918}
919
be24bb4f 920static inline void gen_store_srsgpr (int from, int to)
aaa9128a 921{
be24bb4f 922 if (to != 0) {
d9bea114
AJ
923 TCGv t0 = tcg_temp_new();
924 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 925 TCGv_ptr addr = tcg_temp_new_ptr();
be24bb4f 926
d9bea114 927 gen_load_gpr(t0, from);
7db13fae 928 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
929 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
930 tcg_gen_andi_i32(t2, t2, 0xf);
931 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
932 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 933 tcg_gen_add_ptr(addr, cpu_env, addr);
be24bb4f 934
d9bea114 935 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
a7812ae4 936 tcg_temp_free_ptr(addr);
d9bea114
AJ
937 tcg_temp_free_i32(t2);
938 tcg_temp_free(t0);
8e9ade68 939 }
aaa9128a
TS
940}
941
aaa9128a 942/* Floating point register moves. */
d73ee8a2 943static void gen_load_fpr32(TCGv_i32 t, int reg)
aa0bf00b 944{
d73ee8a2 945 tcg_gen_trunc_i64_i32(t, fpu_f64[reg]);
6ea83fed
FB
946}
947
d73ee8a2 948static void gen_store_fpr32(TCGv_i32 t, int reg)
aa0bf00b 949{
d73ee8a2
RH
950 TCGv_i64 t64 = tcg_temp_new_i64();
951 tcg_gen_extu_i32_i64(t64, t);
952 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
953 tcg_temp_free_i64(t64);
6d066274
AJ
954}
955
d73ee8a2 956static void gen_load_fpr32h(TCGv_i32 t, int reg)
6d066274 957{
d73ee8a2
RH
958 TCGv_i64 t64 = tcg_temp_new_i64();
959 tcg_gen_shri_i64(t64, fpu_f64[reg], 32);
960 tcg_gen_trunc_i64_i32(t, t64);
961 tcg_temp_free_i64(t64);
6d066274
AJ
962}
963
d73ee8a2 964static void gen_store_fpr32h(TCGv_i32 t, int reg)
6d066274 965{
d73ee8a2
RH
966 TCGv_i64 t64 = tcg_temp_new_i64();
967 tcg_gen_extu_i32_i64(t64, t);
968 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
969 tcg_temp_free_i64(t64);
aa0bf00b 970}
6ea83fed 971
d73ee8a2 972static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 973{
f364515c 974 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 975 tcg_gen_mov_i64(t, fpu_f64[reg]);
f364515c 976 } else {
d73ee8a2 977 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
aa0bf00b
TS
978 }
979}
6ea83fed 980
d73ee8a2 981static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 982{
f364515c 983 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 984 tcg_gen_mov_i64(fpu_f64[reg], t);
f364515c 985 } else {
d73ee8a2
RH
986 TCGv_i64 t0;
987 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
988 t0 = tcg_temp_new_i64();
6d066274 989 tcg_gen_shri_i64(t0, t, 32);
d73ee8a2 990 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
6d066274 991 tcg_temp_free_i64(t0);
aa0bf00b
TS
992 }
993}
6ea83fed 994
d94536f4 995static inline int get_fp_bit (int cc)
a16336e4 996{
d94536f4
AJ
997 if (cc)
998 return 24 + cc;
999 else
1000 return 23;
a16336e4
TS
1001}
1002
30898801 1003/* Tests */
8e9ade68
TS
1004static inline void gen_save_pc(target_ulong pc)
1005{
1eb75d4a 1006 tcg_gen_movi_tl(cpu_PC, pc);
8e9ade68 1007}
30898801 1008
356265ae 1009static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
6af0bf9c 1010{
d12d51d5 1011 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
6af0bf9c 1012 if (do_save_pc && ctx->pc != ctx->saved_pc) {
9b9e4393 1013 gen_save_pc(ctx->pc);
6af0bf9c
FB
1014 ctx->saved_pc = ctx->pc;
1015 }
1016 if (ctx->hflags != ctx->saved_hflags) {
41db4607 1017 tcg_gen_movi_i32(hflags, ctx->hflags);
6af0bf9c 1018 ctx->saved_hflags = ctx->hflags;
364d4831 1019 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
5a5012ec 1020 case MIPS_HFLAG_BR:
5a5012ec
TS
1021 break;
1022 case MIPS_HFLAG_BC:
5a5012ec 1023 case MIPS_HFLAG_BL:
5a5012ec 1024 case MIPS_HFLAG_B:
d077b6f7 1025 tcg_gen_movi_tl(btarget, ctx->btarget);
5a5012ec 1026 break;
6af0bf9c
FB
1027 }
1028 }
1029}
1030
7db13fae 1031static inline void restore_cpu_state (CPUMIPSState *env, DisasContext *ctx)
5a5012ec 1032{
fd4a04eb 1033 ctx->saved_hflags = ctx->hflags;
364d4831 1034 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
fd4a04eb 1035 case MIPS_HFLAG_BR:
fd4a04eb
TS
1036 break;
1037 case MIPS_HFLAG_BC:
1038 case MIPS_HFLAG_BL:
39454628 1039 case MIPS_HFLAG_B:
fd4a04eb 1040 ctx->btarget = env->btarget;
fd4a04eb 1041 break;
5a5012ec
TS
1042 }
1043}
1044
356265ae 1045static inline void
48d38ca5 1046generate_exception_err (DisasContext *ctx, int excp, int err)
aaa9128a 1047{
a7812ae4
PB
1048 TCGv_i32 texcp = tcg_const_i32(excp);
1049 TCGv_i32 terr = tcg_const_i32(err);
aaa9128a 1050 save_cpu_state(ctx, 1);
895c2d04 1051 gen_helper_raise_exception_err(cpu_env, texcp, terr);
a7812ae4
PB
1052 tcg_temp_free_i32(terr);
1053 tcg_temp_free_i32(texcp);
aaa9128a
TS
1054}
1055
356265ae 1056static inline void
48d38ca5 1057generate_exception (DisasContext *ctx, int excp)
aaa9128a 1058{
6af0bf9c 1059 save_cpu_state(ctx, 1);
895c2d04 1060 gen_helper_0e0i(raise_exception, excp);
6af0bf9c
FB
1061}
1062
48d38ca5 1063/* Addresses computation */
941694d0 1064static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
4ad40f36 1065{
941694d0 1066 tcg_gen_add_tl(ret, arg0, arg1);
48d38ca5
TS
1067
1068#if defined(TARGET_MIPS64)
1069 /* For compatibility with 32-bit code, data reference in user mode
1070 with Status_UX = 0 should be casted to 32-bit and sign extended.
1071 See the MIPS64 PRA manual, section 4.10. */
2623c1ec
AJ
1072 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
1073 !(ctx->hflags & MIPS_HFLAG_UX)) {
941694d0 1074 tcg_gen_ext32s_i64(ret, ret);
48d38ca5
TS
1075 }
1076#endif
4ad40f36
FB
1077}
1078
356265ae 1079static inline void check_cp0_enabled(DisasContext *ctx)
387a8fe5 1080{
fe253235 1081 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
c2c65dab 1082 generate_exception_err(ctx, EXCP_CpU, 0);
387a8fe5
TS
1083}
1084
356265ae 1085static inline void check_cp1_enabled(DisasContext *ctx)
5e755519 1086{
fe253235 1087 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
5e755519
TS
1088 generate_exception_err(ctx, EXCP_CpU, 1);
1089}
1090
b8aa4598
TS
1091/* Verify that the processor is running with COP1X instructions enabled.
1092 This is associated with the nabla symbol in the MIPS32 and MIPS64
1093 opcode tables. */
1094
356265ae 1095static inline void check_cop1x(DisasContext *ctx)
b8aa4598
TS
1096{
1097 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
1098 generate_exception(ctx, EXCP_RI);
1099}
1100
1101/* Verify that the processor is running with 64-bit floating-point
1102 operations enabled. */
1103
356265ae 1104static inline void check_cp1_64bitmode(DisasContext *ctx)
5e755519 1105{
b8aa4598 1106 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
5e755519
TS
1107 generate_exception(ctx, EXCP_RI);
1108}
1109
1110/*
1111 * Verify if floating point register is valid; an operation is not defined
1112 * if bit 0 of any register specification is set and the FR bit in the
1113 * Status register equals zero, since the register numbers specify an
1114 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1115 * in the Status register equals one, both even and odd register numbers
1116 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1117 *
1118 * Multiple 64 bit wide registers can be checked by calling
1119 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1120 */
356265ae 1121static inline void check_cp1_registers(DisasContext *ctx, int regs)
5e755519 1122{
fe253235 1123 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
5e755519
TS
1124 generate_exception(ctx, EXCP_RI);
1125}
1126
853c3240
JL
1127/* Verify that the processor is running with DSP instructions enabled.
1128 This is enabled by CP0 Status register MX(24) bit.
1129 */
1130
1131static inline void check_dsp(DisasContext *ctx)
1132{
1133 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1134 generate_exception(ctx, EXCP_DSPDIS);
1135 }
1136}
1137
1138static inline void check_dspr2(DisasContext *ctx)
1139{
1140 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
1141 generate_exception(ctx, EXCP_DSPDIS);
1142 }
1143}
1144
3a95e3a7 1145/* This code generates a "reserved instruction" exception if the
e189e748 1146 CPU does not support the instruction set corresponding to flags. */
7db13fae 1147static inline void check_insn(CPUMIPSState *env, DisasContext *ctx, int flags)
3a95e3a7 1148{
e189e748 1149 if (unlikely(!(env->insn_flags & flags)))
3a95e3a7
TS
1150 generate_exception(ctx, EXCP_RI);
1151}
1152
e189e748
TS
1153/* This code generates a "reserved instruction" exception if 64-bit
1154 instructions are not enabled. */
356265ae 1155static inline void check_mips_64(DisasContext *ctx)
e189e748 1156{
fe253235 1157 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
e189e748
TS
1158 generate_exception(ctx, EXCP_RI);
1159}
1160
8153667c
NF
1161/* Define small wrappers for gen_load_fpr* so that we have a uniform
1162 calling interface for 32 and 64-bit FPRs. No sense in changing
1163 all callers for gen_load_fpr32 when we need the CTX parameter for
1164 this one use. */
1165#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y)
1166#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1167#define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1168static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1169 int ft, int fs, int cc) \
1170{ \
1171 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
1172 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
1173 switch (ifmt) { \
1174 case FMT_PS: \
1175 check_cp1_64bitmode(ctx); \
1176 break; \
1177 case FMT_D: \
1178 if (abs) { \
1179 check_cop1x(ctx); \
1180 } \
1181 check_cp1_registers(ctx, fs | ft); \
1182 break; \
1183 case FMT_S: \
1184 if (abs) { \
1185 check_cop1x(ctx); \
1186 } \
1187 break; \
1188 } \
1189 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
1190 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
1191 switch (n) { \
895c2d04
BS
1192 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
1193 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
1194 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
1195 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
1196 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
1197 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
1198 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
1199 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
1200 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
1201 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
1202 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
1203 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
1204 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
1205 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
1206 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
1207 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
8153667c
NF
1208 default: abort(); \
1209 } \
1210 tcg_temp_free_i##bits (fp0); \
1211 tcg_temp_free_i##bits (fp1); \
1212}
1213
1214FOP_CONDS(, 0, d, FMT_D, 64)
1215FOP_CONDS(abs, 1, d, FMT_D, 64)
1216FOP_CONDS(, 0, s, FMT_S, 32)
1217FOP_CONDS(abs, 1, s, FMT_S, 32)
1218FOP_CONDS(, 0, ps, FMT_PS, 64)
1219FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1220#undef FOP_CONDS
1221#undef gen_ldcmp_fpr32
1222#undef gen_ldcmp_fpr64
1223
958fb4a9 1224/* load/store instructions. */
d9bea114 1225#define OP_LD(insn,fname) \
5c13fdfd 1226static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
d9bea114
AJ
1227{ \
1228 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
aaa9128a
TS
1229}
1230OP_LD(lb,ld8s);
1231OP_LD(lbu,ld8u);
1232OP_LD(lh,ld16s);
1233OP_LD(lhu,ld16u);
1234OP_LD(lw,ld32s);
1235#if defined(TARGET_MIPS64)
1236OP_LD(lwu,ld32u);
1237OP_LD(ld,ld64);
1238#endif
1239#undef OP_LD
1240
d9bea114 1241#define OP_ST(insn,fname) \
5c13fdfd 1242static inline void op_st_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \
d9bea114
AJ
1243{ \
1244 tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
aaa9128a
TS
1245}
1246OP_ST(sb,st8);
1247OP_ST(sh,st16);
1248OP_ST(sw,st32);
1249#if defined(TARGET_MIPS64)
1250OP_ST(sd,st64);
1251#endif
1252#undef OP_ST
1253
e7139c44 1254#ifdef CONFIG_USER_ONLY
d9bea114 1255#define OP_LD_ATOMIC(insn,fname) \
5c13fdfd 1256static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
d9bea114
AJ
1257{ \
1258 TCGv t0 = tcg_temp_new(); \
1259 tcg_gen_mov_tl(t0, arg1); \
1260 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
7db13fae
AF
1261 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
1262 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
d9bea114 1263 tcg_temp_free(t0); \
aaa9128a 1264}
e7139c44
AJ
1265#else
1266#define OP_LD_ATOMIC(insn,fname) \
5c13fdfd 1267static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
e7139c44 1268{ \
895c2d04 1269 gen_helper_1e1i(insn, ret, arg1, ctx->mem_idx); \
e7139c44
AJ
1270}
1271#endif
aaa9128a
TS
1272OP_LD_ATOMIC(ll,ld32s);
1273#if defined(TARGET_MIPS64)
1274OP_LD_ATOMIC(lld,ld64);
1275#endif
1276#undef OP_LD_ATOMIC
1277
590bc601
PB
1278#ifdef CONFIG_USER_ONLY
1279#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
5c13fdfd 1280static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
590bc601
PB
1281{ \
1282 TCGv t0 = tcg_temp_new(); \
1283 int l1 = gen_new_label(); \
1284 int l2 = gen_new_label(); \
1285 \
1286 tcg_gen_andi_tl(t0, arg2, almask); \
1287 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
7db13fae 1288 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
590bc601
PB
1289 generate_exception(ctx, EXCP_AdES); \
1290 gen_set_label(l1); \
7db13fae 1291 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
590bc601
PB
1292 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
1293 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
7db13fae
AF
1294 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
1295 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
895c2d04 1296 gen_helper_0e0i(raise_exception, EXCP_SC); \
590bc601
PB
1297 gen_set_label(l2); \
1298 tcg_gen_movi_tl(t0, 0); \
1299 gen_store_gpr(t0, rt); \
1300 tcg_temp_free(t0); \
1301}
1302#else
1303#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
5c13fdfd 1304static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
590bc601
PB
1305{ \
1306 TCGv t0 = tcg_temp_new(); \
895c2d04 1307 gen_helper_1e2i(insn, t0, arg1, arg2, ctx->mem_idx); \
590bc601 1308 gen_store_gpr(t0, rt); \
590bc601
PB
1309 tcg_temp_free(t0); \
1310}
1311#endif
590bc601 1312OP_ST_ATOMIC(sc,st32,ld32s,0x3);
aaa9128a 1313#if defined(TARGET_MIPS64)
590bc601 1314OP_ST_ATOMIC(scd,st64,ld64,0x7);
aaa9128a
TS
1315#endif
1316#undef OP_ST_ATOMIC
1317
662d7485
NF
1318static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
1319 int base, int16_t offset)
1320{
1321 if (base == 0) {
1322 tcg_gen_movi_tl(addr, offset);
1323 } else if (offset == 0) {
1324 gen_load_gpr(addr, base);
1325 } else {
1326 tcg_gen_movi_tl(addr, offset);
1327 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
1328 }
1329}
1330
364d4831
NF
1331static target_ulong pc_relative_pc (DisasContext *ctx)
1332{
1333 target_ulong pc = ctx->pc;
1334
1335 if (ctx->hflags & MIPS_HFLAG_BMASK) {
1336 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
1337
1338 pc -= branch_bytes;
1339 }
1340
1341 pc &= ~(target_ulong)3;
1342 return pc;
1343}
1344
5c13fdfd 1345/* Load */
7db13fae 1346static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
afa88c3a 1347 int rt, int base, int16_t offset)
6af0bf9c 1348{
5c13fdfd 1349 const char *opn = "ld";
afa88c3a
AJ
1350 TCGv t0, t1;
1351
1352 if (rt == 0 && env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
1353 /* Loongson CPU uses a load to zero register for prefetch.
1354 We emulate it as a NOP. On other CPU we must perform the
1355 actual memory access. */
1356 MIPS_DEBUG("NOP");
1357 return;
1358 }
6af0bf9c 1359
afa88c3a
AJ
1360 t0 = tcg_temp_new();
1361 t1 = tcg_temp_new();
662d7485 1362 gen_base_offset_addr(ctx, t0, base, offset);
afa88c3a 1363
6af0bf9c 1364 switch (opc) {
d26bc211 1365#if defined(TARGET_MIPS64)
6e473128 1366 case OPC_LWU:
d66c7132 1367 save_cpu_state(ctx, 0);
5c13fdfd 1368 op_ld_lwu(t0, t0, ctx);
78723684 1369 gen_store_gpr(t0, rt);
6e473128
TS
1370 opn = "lwu";
1371 break;
6af0bf9c 1372 case OPC_LD:
d66c7132 1373 save_cpu_state(ctx, 0);
5c13fdfd 1374 op_ld_ld(t0, t0, ctx);
78723684 1375 gen_store_gpr(t0, rt);
6af0bf9c
FB
1376 opn = "ld";
1377 break;
7a387fff 1378 case OPC_LLD:
b835e919 1379 save_cpu_state(ctx, 1);
5c13fdfd 1380 op_ld_lld(t0, t0, ctx);
78723684 1381 gen_store_gpr(t0, rt);
7a387fff
TS
1382 opn = "lld";
1383 break;
6af0bf9c 1384 case OPC_LDL:
c8c2227e 1385 save_cpu_state(ctx, 1);
78723684 1386 gen_load_gpr(t1, rt);
895c2d04 1387 gen_helper_1e2i(ldl, t1, t1, t0, ctx->mem_idx);
78723684 1388 gen_store_gpr(t1, rt);
6af0bf9c
FB
1389 opn = "ldl";
1390 break;
6af0bf9c 1391 case OPC_LDR:
c8c2227e 1392 save_cpu_state(ctx, 1);
78723684 1393 gen_load_gpr(t1, rt);
895c2d04 1394 gen_helper_1e2i(ldr, t1, t1, t0, ctx->mem_idx);
78723684 1395 gen_store_gpr(t1, rt);
6af0bf9c
FB
1396 opn = "ldr";
1397 break;
364d4831 1398 case OPC_LDPC:
b835e919 1399 save_cpu_state(ctx, 0);
364d4831
NF
1400 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1401 gen_op_addr_add(ctx, t0, t0, t1);
5c13fdfd 1402 op_ld_ld(t0, t0, ctx);
364d4831 1403 gen_store_gpr(t0, rt);
5c13fdfd 1404 opn = "ldpc";
364d4831 1405 break;
6af0bf9c 1406#endif
364d4831 1407 case OPC_LWPC:
b835e919 1408 save_cpu_state(ctx, 0);
364d4831
NF
1409 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1410 gen_op_addr_add(ctx, t0, t0, t1);
5c13fdfd 1411 op_ld_lw(t0, t0, ctx);
364d4831 1412 gen_store_gpr(t0, rt);
5c13fdfd 1413 opn = "lwpc";
364d4831 1414 break;
6af0bf9c 1415 case OPC_LW:
d66c7132 1416 save_cpu_state(ctx, 0);
5c13fdfd 1417 op_ld_lw(t0, t0, ctx);
78723684 1418 gen_store_gpr(t0, rt);
6af0bf9c
FB
1419 opn = "lw";
1420 break;
6af0bf9c 1421 case OPC_LH:
d66c7132 1422 save_cpu_state(ctx, 0);
5c13fdfd 1423 op_ld_lh(t0, t0, ctx);
78723684 1424 gen_store_gpr(t0, rt);
6af0bf9c
FB
1425 opn = "lh";
1426 break;
6af0bf9c 1427 case OPC_LHU:
d66c7132 1428 save_cpu_state(ctx, 0);
5c13fdfd 1429 op_ld_lhu(t0, t0, ctx);
78723684 1430 gen_store_gpr(t0, rt);
6af0bf9c
FB
1431 opn = "lhu";
1432 break;
1433 case OPC_LB:
d66c7132 1434 save_cpu_state(ctx, 0);
5c13fdfd 1435 op_ld_lb(t0, t0, ctx);
78723684 1436 gen_store_gpr(t0, rt);
6af0bf9c
FB
1437 opn = "lb";
1438 break;
6af0bf9c 1439 case OPC_LBU:
d66c7132 1440 save_cpu_state(ctx, 0);
5c13fdfd 1441 op_ld_lbu(t0, t0, ctx);
78723684 1442 gen_store_gpr(t0, rt);
6af0bf9c
FB
1443 opn = "lbu";
1444 break;
1445 case OPC_LWL:
c8c2227e 1446 save_cpu_state(ctx, 1);
6958549d 1447 gen_load_gpr(t1, rt);
895c2d04 1448 gen_helper_1e2i(lwl, t1, t1, t0, ctx->mem_idx);
78723684 1449 gen_store_gpr(t1, rt);
6af0bf9c
FB
1450 opn = "lwl";
1451 break;
6af0bf9c 1452 case OPC_LWR:
c8c2227e 1453 save_cpu_state(ctx, 1);
6958549d 1454 gen_load_gpr(t1, rt);
895c2d04 1455 gen_helper_1e2i(lwr, t1, t1, t0, ctx->mem_idx);
78723684 1456 gen_store_gpr(t1, rt);
6af0bf9c
FB
1457 opn = "lwr";
1458 break;
6af0bf9c 1459 case OPC_LL:
e7139c44 1460 save_cpu_state(ctx, 1);
5c13fdfd 1461 op_ld_ll(t0, t0, ctx);
78723684 1462 gen_store_gpr(t0, rt);
6af0bf9c
FB
1463 opn = "ll";
1464 break;
d66c7132 1465 }
2abf314d 1466 (void)opn; /* avoid a compiler warning */
d66c7132
AJ
1467 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1468 tcg_temp_free(t0);
1469 tcg_temp_free(t1);
1470}
1471
5c13fdfd
AJ
1472/* Store */
1473static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
1474 int base, int16_t offset)
1475{
1476 const char *opn = "st";
1477 TCGv t0 = tcg_temp_new();
1478 TCGv t1 = tcg_temp_new();
1479
1480 gen_base_offset_addr(ctx, t0, base, offset);
1481 gen_load_gpr(t1, rt);
1482 switch (opc) {
1483#if defined(TARGET_MIPS64)
1484 case OPC_SD:
1485 save_cpu_state(ctx, 0);
1486 op_st_sd(t1, t0, ctx);
1487 opn = "sd";
1488 break;
1489 case OPC_SDL:
1490 save_cpu_state(ctx, 1);
895c2d04 1491 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
5c13fdfd
AJ
1492 opn = "sdl";
1493 break;
1494 case OPC_SDR:
1495 save_cpu_state(ctx, 1);
895c2d04 1496 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
5c13fdfd
AJ
1497 opn = "sdr";
1498 break;
1499#endif
1500 case OPC_SW:
1501 save_cpu_state(ctx, 0);
1502 op_st_sw(t1, t0, ctx);
1503 opn = "sw";
1504 break;
1505 case OPC_SH:
1506 save_cpu_state(ctx, 0);
1507 op_st_sh(t1, t0, ctx);
1508 opn = "sh";
1509 break;
1510 case OPC_SB:
1511 save_cpu_state(ctx, 0);
1512 op_st_sb(t1, t0, ctx);
1513 opn = "sb";
1514 break;
1515 case OPC_SWL:
1516 save_cpu_state(ctx, 1);
895c2d04 1517 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
5c13fdfd
AJ
1518 opn = "swl";
1519 break;
1520 case OPC_SWR:
1521 save_cpu_state(ctx, 1);
895c2d04 1522 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
5c13fdfd
AJ
1523 opn = "swr";
1524 break;
1525 }
2abf314d 1526 (void)opn; /* avoid a compiler warning */
5c13fdfd
AJ
1527 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1528 tcg_temp_free(t0);
1529 tcg_temp_free(t1);
1530}
1531
1532
d66c7132
AJ
1533/* Store conditional */
1534static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1535 int base, int16_t offset)
1536{
1537 const char *opn = "st_cond";
1538 TCGv t0, t1;
1539
1540 t0 = tcg_temp_local_new();
1541
662d7485 1542 gen_base_offset_addr(ctx, t0, base, offset);
d66c7132
AJ
1543 /* Don't do NOP if destination is zero: we must perform the actual
1544 memory access. */
1545
1546 t1 = tcg_temp_local_new();
1547 gen_load_gpr(t1, rt);
1548 switch (opc) {
1549#if defined(TARGET_MIPS64)
1550 case OPC_SCD:
b835e919 1551 save_cpu_state(ctx, 1);
5c13fdfd 1552 op_st_scd(t1, t0, rt, ctx);
d66c7132
AJ
1553 opn = "scd";
1554 break;
1555#endif
6af0bf9c 1556 case OPC_SC:
e7139c44 1557 save_cpu_state(ctx, 1);
5c13fdfd 1558 op_st_sc(t1, t0, rt, ctx);
6af0bf9c
FB
1559 opn = "sc";
1560 break;
6af0bf9c 1561 }
2abf314d 1562 (void)opn; /* avoid a compiler warning */
6af0bf9c 1563 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
78723684 1564 tcg_temp_free(t1);
d66c7132 1565 tcg_temp_free(t0);
6af0bf9c
FB
1566}
1567
6ea83fed 1568/* Load and store */
7a387fff 1569static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
356265ae 1570 int base, int16_t offset)
6ea83fed 1571{
923617a3 1572 const char *opn = "flt_ldst";
4e2474d6 1573 TCGv t0 = tcg_temp_new();
6ea83fed 1574
662d7485 1575 gen_base_offset_addr(ctx, t0, base, offset);
6ea83fed 1576 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 1577 memory access. */
6ea83fed
FB
1578 switch (opc) {
1579 case OPC_LWC1:
b6d96bed 1580 {
a7812ae4 1581 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 1582
c407df81
AJ
1583 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
1584 tcg_gen_trunc_tl_i32(fp0, t0);
b6d96bed 1585 gen_store_fpr32(fp0, ft);
a7812ae4 1586 tcg_temp_free_i32(fp0);
b6d96bed 1587 }
6ea83fed
FB
1588 opn = "lwc1";
1589 break;
1590 case OPC_SWC1:
b6d96bed 1591 {
a7812ae4
PB
1592 TCGv_i32 fp0 = tcg_temp_new_i32();
1593 TCGv t1 = tcg_temp_new();
b6d96bed
TS
1594
1595 gen_load_fpr32(fp0, ft);
a7812ae4
PB
1596 tcg_gen_extu_i32_tl(t1, fp0);
1597 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1598 tcg_temp_free(t1);
1599 tcg_temp_free_i32(fp0);
b6d96bed 1600 }
6ea83fed
FB
1601 opn = "swc1";
1602 break;
1603 case OPC_LDC1:
b6d96bed 1604 {
a7812ae4 1605 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
1606
1607 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1608 gen_store_fpr64(ctx, fp0, ft);
a7812ae4 1609 tcg_temp_free_i64(fp0);
b6d96bed 1610 }
6ea83fed
FB
1611 opn = "ldc1";
1612 break;
1613 case OPC_SDC1:
b6d96bed 1614 {
a7812ae4 1615 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
1616
1617 gen_load_fpr64(ctx, fp0, ft);
1618 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 1619 tcg_temp_free_i64(fp0);
b6d96bed 1620 }
6ea83fed
FB
1621 opn = "sdc1";
1622 break;
1623 default:
923617a3 1624 MIPS_INVAL(opn);
e397ee33 1625 generate_exception(ctx, EXCP_RI);
78723684 1626 goto out;
6ea83fed 1627 }
2abf314d 1628 (void)opn; /* avoid a compiler warning */
6ea83fed 1629 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
78723684
TS
1630 out:
1631 tcg_temp_free(t0);
6ea83fed 1632}
6ea83fed 1633
7db13fae 1634static void gen_cop1_ldst(CPUMIPSState *env, DisasContext *ctx,
26ebe468
NF
1635 uint32_t op, int rt, int rs, int16_t imm)
1636{
1637 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
1638 check_cp1_enabled(ctx);
1639 gen_flt_ldst(ctx, op, rt, rs, imm);
1640 } else {
1641 generate_exception_err(ctx, EXCP_CpU, 1);
1642 }
1643}
1644
6af0bf9c 1645/* Arithmetic with immediate operand */
7db13fae 1646static void gen_arith_imm (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
e189e748 1647 int rt, int rs, int16_t imm)
6af0bf9c 1648{
324d9e32 1649 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
923617a3 1650 const char *opn = "imm arith";
6af0bf9c 1651
7a387fff 1652 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
ead9360e
TS
1653 /* If no destination, treat it as a NOP.
1654 For addi, we must generate the overflow exception when needed. */
6af0bf9c 1655 MIPS_DEBUG("NOP");
324d9e32 1656 return;
6af0bf9c
FB
1657 }
1658 switch (opc) {
1659 case OPC_ADDI:
48d38ca5 1660 {
324d9e32
AJ
1661 TCGv t0 = tcg_temp_local_new();
1662 TCGv t1 = tcg_temp_new();
1663 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1664 int l1 = gen_new_label();
1665
324d9e32
AJ
1666 gen_load_gpr(t1, rs);
1667 tcg_gen_addi_tl(t0, t1, uimm);
1668 tcg_gen_ext32s_tl(t0, t0);
48d38ca5 1669
324d9e32
AJ
1670 tcg_gen_xori_tl(t1, t1, ~uimm);
1671 tcg_gen_xori_tl(t2, t0, uimm);
1672 tcg_gen_and_tl(t1, t1, t2);
1673 tcg_temp_free(t2);
1674 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1675 tcg_temp_free(t1);
48d38ca5
TS
1676 /* operands of same sign, result different sign */
1677 generate_exception(ctx, EXCP_OVERFLOW);
1678 gen_set_label(l1);
78723684 1679 tcg_gen_ext32s_tl(t0, t0);
324d9e32
AJ
1680 gen_store_gpr(t0, rt);
1681 tcg_temp_free(t0);
48d38ca5 1682 }
6af0bf9c
FB
1683 opn = "addi";
1684 break;
1685 case OPC_ADDIU:
324d9e32
AJ
1686 if (rs != 0) {
1687 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1688 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1689 } else {
1690 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1691 }
6af0bf9c
FB
1692 opn = "addiu";
1693 break;
d26bc211 1694#if defined(TARGET_MIPS64)
7a387fff 1695 case OPC_DADDI:
48d38ca5 1696 {
324d9e32
AJ
1697 TCGv t0 = tcg_temp_local_new();
1698 TCGv t1 = tcg_temp_new();
1699 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1700 int l1 = gen_new_label();
1701
324d9e32
AJ
1702 gen_load_gpr(t1, rs);
1703 tcg_gen_addi_tl(t0, t1, uimm);
48d38ca5 1704
324d9e32
AJ
1705 tcg_gen_xori_tl(t1, t1, ~uimm);
1706 tcg_gen_xori_tl(t2, t0, uimm);
1707 tcg_gen_and_tl(t1, t1, t2);
1708 tcg_temp_free(t2);
1709 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1710 tcg_temp_free(t1);
48d38ca5
TS
1711 /* operands of same sign, result different sign */
1712 generate_exception(ctx, EXCP_OVERFLOW);
1713 gen_set_label(l1);
324d9e32
AJ
1714 gen_store_gpr(t0, rt);
1715 tcg_temp_free(t0);
48d38ca5 1716 }
7a387fff
TS
1717 opn = "daddi";
1718 break;
1719 case OPC_DADDIU:
324d9e32
AJ
1720 if (rs != 0) {
1721 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1722 } else {
1723 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1724 }
7a387fff
TS
1725 opn = "daddiu";
1726 break;
1727#endif
324d9e32 1728 }
2abf314d 1729 (void)opn; /* avoid a compiler warning */
324d9e32
AJ
1730 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1731}
1732
1733/* Logic with immediate operand */
9fa77488
RH
1734static void gen_logic_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1735 int rt, int rs, int16_t imm)
324d9e32
AJ
1736{
1737 target_ulong uimm;
1738 const char *opn = "imm logic";
1739
1740 if (rt == 0) {
1741 /* If no destination, treat it as a NOP. */
1742 MIPS_DEBUG("NOP");
1743 return;
1744 }
1745 uimm = (uint16_t)imm;
1746 switch (opc) {
6af0bf9c 1747 case OPC_ANDI:
324d9e32
AJ
1748 if (likely(rs != 0))
1749 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1750 else
1751 tcg_gen_movi_tl(cpu_gpr[rt], 0);
6af0bf9c
FB
1752 opn = "andi";
1753 break;
1754 case OPC_ORI:
324d9e32
AJ
1755 if (rs != 0)
1756 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1757 else
1758 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
6af0bf9c
FB
1759 opn = "ori";
1760 break;
1761 case OPC_XORI:
324d9e32
AJ
1762 if (likely(rs != 0))
1763 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1764 else
1765 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
6af0bf9c
FB
1766 opn = "xori";
1767 break;
1768 case OPC_LUI:
324d9e32 1769 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
6af0bf9c
FB
1770 opn = "lui";
1771 break;
324d9e32 1772 }
2abf314d 1773 (void)opn; /* avoid a compiler warning */
324d9e32
AJ
1774 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1775}
1776
1777/* Set on less than with immediate operand */
9fa77488
RH
1778static void gen_slt_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1779 int rt, int rs, int16_t imm)
324d9e32
AJ
1780{
1781 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1782 const char *opn = "imm arith";
1783 TCGv t0;
1784
1785 if (rt == 0) {
1786 /* If no destination, treat it as a NOP. */
1787 MIPS_DEBUG("NOP");
1788 return;
1789 }
1790 t0 = tcg_temp_new();
1791 gen_load_gpr(t0, rs);
1792 switch (opc) {
1793 case OPC_SLTI:
e68dd28f 1794 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
1795 opn = "slti";
1796 break;
1797 case OPC_SLTIU:
e68dd28f 1798 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
1799 opn = "sltiu";
1800 break;
1801 }
2abf314d 1802 (void)opn; /* avoid a compiler warning */
324d9e32
AJ
1803 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1804 tcg_temp_free(t0);
1805}
1806
1807/* Shifts with immediate operand */
7db13fae 1808static void gen_shift_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
324d9e32
AJ
1809 int rt, int rs, int16_t imm)
1810{
1811 target_ulong uimm = ((uint16_t)imm) & 0x1f;
1812 const char *opn = "imm shift";
1813 TCGv t0;
1814
1815 if (rt == 0) {
1816 /* If no destination, treat it as a NOP. */
1817 MIPS_DEBUG("NOP");
1818 return;
1819 }
1820
1821 t0 = tcg_temp_new();
1822 gen_load_gpr(t0, rs);
1823 switch (opc) {
6af0bf9c 1824 case OPC_SLL:
78723684 1825 tcg_gen_shli_tl(t0, t0, uimm);
324d9e32 1826 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
6af0bf9c
FB
1827 opn = "sll";
1828 break;
1829 case OPC_SRA:
324d9e32 1830 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
6af0bf9c
FB
1831 opn = "sra";
1832 break;
1833 case OPC_SRL:
ea63e2c3
NF
1834 if (uimm != 0) {
1835 tcg_gen_ext32u_tl(t0, t0);
1836 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1837 } else {
1838 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
5a63bcb2 1839 }
ea63e2c3
NF
1840 opn = "srl";
1841 break;
1842 case OPC_ROTR:
1843 if (uimm != 0) {
1844 TCGv_i32 t1 = tcg_temp_new_i32();
1845
1846 tcg_gen_trunc_tl_i32(t1, t0);
1847 tcg_gen_rotri_i32(t1, t1, uimm);
1848 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
1849 tcg_temp_free_i32(t1);
3399e30f
NF
1850 } else {
1851 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
ea63e2c3
NF
1852 }
1853 opn = "rotr";
7a387fff 1854 break;
d26bc211 1855#if defined(TARGET_MIPS64)
7a387fff 1856 case OPC_DSLL:
324d9e32 1857 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
1858 opn = "dsll";
1859 break;
1860 case OPC_DSRA:
324d9e32 1861 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
1862 opn = "dsra";
1863 break;
1864 case OPC_DSRL:
ea63e2c3
NF
1865 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1866 opn = "dsrl";
1867 break;
1868 case OPC_DROTR:
1869 if (uimm != 0) {
1870 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3399e30f
NF
1871 } else {
1872 tcg_gen_mov_tl(cpu_gpr[rt], t0);
5a63bcb2 1873 }
ea63e2c3 1874 opn = "drotr";
7a387fff
TS
1875 break;
1876 case OPC_DSLL32:
324d9e32 1877 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
1878 opn = "dsll32";
1879 break;
1880 case OPC_DSRA32:
324d9e32 1881 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
1882 opn = "dsra32";
1883 break;
1884 case OPC_DSRL32:
ea63e2c3
NF
1885 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1886 opn = "dsrl32";
1887 break;
1888 case OPC_DROTR32:
1889 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
1890 opn = "drotr32";
6af0bf9c 1891 break;
7a387fff 1892#endif
6af0bf9c 1893 }
2abf314d 1894 (void)opn; /* avoid a compiler warning */
93b12ccc 1895 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
78723684 1896 tcg_temp_free(t0);
6af0bf9c
FB
1897}
1898
1899/* Arithmetic */
7db13fae 1900static void gen_arith (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
1901 int rd, int rs, int rt)
1902{
923617a3 1903 const char *opn = "arith";
6af0bf9c 1904
7a387fff
TS
1905 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1906 && opc != OPC_DADD && opc != OPC_DSUB) {
ead9360e
TS
1907 /* If no destination, treat it as a NOP.
1908 For add & sub, we must generate the overflow exception when needed. */
6af0bf9c 1909 MIPS_DEBUG("NOP");
460f00c4 1910 return;
185f0762 1911 }
460f00c4 1912
6af0bf9c
FB
1913 switch (opc) {
1914 case OPC_ADD:
48d38ca5 1915 {
460f00c4
AJ
1916 TCGv t0 = tcg_temp_local_new();
1917 TCGv t1 = tcg_temp_new();
1918 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1919 int l1 = gen_new_label();
1920
460f00c4
AJ
1921 gen_load_gpr(t1, rs);
1922 gen_load_gpr(t2, rt);
1923 tcg_gen_add_tl(t0, t1, t2);
1924 tcg_gen_ext32s_tl(t0, t0);
1925 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 1926 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 1927 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
1928 tcg_temp_free(t2);
1929 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1930 tcg_temp_free(t1);
48d38ca5
TS
1931 /* operands of same sign, result different sign */
1932 generate_exception(ctx, EXCP_OVERFLOW);
1933 gen_set_label(l1);
460f00c4
AJ
1934 gen_store_gpr(t0, rd);
1935 tcg_temp_free(t0);
48d38ca5 1936 }
6af0bf9c
FB
1937 opn = "add";
1938 break;
1939 case OPC_ADDU:
460f00c4
AJ
1940 if (rs != 0 && rt != 0) {
1941 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1942 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1943 } else if (rs == 0 && rt != 0) {
1944 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1945 } else if (rs != 0 && rt == 0) {
1946 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1947 } else {
1948 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1949 }
6af0bf9c
FB
1950 opn = "addu";
1951 break;
1952 case OPC_SUB:
48d38ca5 1953 {
460f00c4
AJ
1954 TCGv t0 = tcg_temp_local_new();
1955 TCGv t1 = tcg_temp_new();
1956 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1957 int l1 = gen_new_label();
1958
460f00c4
AJ
1959 gen_load_gpr(t1, rs);
1960 gen_load_gpr(t2, rt);
1961 tcg_gen_sub_tl(t0, t1, t2);
1962 tcg_gen_ext32s_tl(t0, t0);
1963 tcg_gen_xor_tl(t2, t1, t2);
1964 tcg_gen_xor_tl(t1, t0, t1);
1965 tcg_gen_and_tl(t1, t1, t2);
1966 tcg_temp_free(t2);
1967 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1968 tcg_temp_free(t1);
31e3104f 1969 /* operands of different sign, first operand and result different sign */
48d38ca5
TS
1970 generate_exception(ctx, EXCP_OVERFLOW);
1971 gen_set_label(l1);
460f00c4
AJ
1972 gen_store_gpr(t0, rd);
1973 tcg_temp_free(t0);
48d38ca5 1974 }
6af0bf9c
FB
1975 opn = "sub";
1976 break;
1977 case OPC_SUBU:
460f00c4
AJ
1978 if (rs != 0 && rt != 0) {
1979 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1980 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1981 } else if (rs == 0 && rt != 0) {
1982 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
6bb72b18 1983 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
460f00c4
AJ
1984 } else if (rs != 0 && rt == 0) {
1985 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1986 } else {
1987 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1988 }
6af0bf9c
FB
1989 opn = "subu";
1990 break;
d26bc211 1991#if defined(TARGET_MIPS64)
7a387fff 1992 case OPC_DADD:
48d38ca5 1993 {
460f00c4
AJ
1994 TCGv t0 = tcg_temp_local_new();
1995 TCGv t1 = tcg_temp_new();
1996 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1997 int l1 = gen_new_label();
1998
460f00c4
AJ
1999 gen_load_gpr(t1, rs);
2000 gen_load_gpr(t2, rt);
2001 tcg_gen_add_tl(t0, t1, t2);
2002 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 2003 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 2004 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
2005 tcg_temp_free(t2);
2006 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2007 tcg_temp_free(t1);
48d38ca5
TS
2008 /* operands of same sign, result different sign */
2009 generate_exception(ctx, EXCP_OVERFLOW);
2010 gen_set_label(l1);
460f00c4
AJ
2011 gen_store_gpr(t0, rd);
2012 tcg_temp_free(t0);
48d38ca5 2013 }
7a387fff
TS
2014 opn = "dadd";
2015 break;
2016 case OPC_DADDU:
460f00c4
AJ
2017 if (rs != 0 && rt != 0) {
2018 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2019 } else if (rs == 0 && rt != 0) {
2020 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2021 } else if (rs != 0 && rt == 0) {
2022 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2023 } else {
2024 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2025 }
7a387fff
TS
2026 opn = "daddu";
2027 break;
2028 case OPC_DSUB:
48d38ca5 2029 {
460f00c4
AJ
2030 TCGv t0 = tcg_temp_local_new();
2031 TCGv t1 = tcg_temp_new();
2032 TCGv t2 = tcg_temp_new();
48d38ca5
TS
2033 int l1 = gen_new_label();
2034
460f00c4
AJ
2035 gen_load_gpr(t1, rs);
2036 gen_load_gpr(t2, rt);
2037 tcg_gen_sub_tl(t0, t1, t2);
2038 tcg_gen_xor_tl(t2, t1, t2);
2039 tcg_gen_xor_tl(t1, t0, t1);
2040 tcg_gen_and_tl(t1, t1, t2);
2041 tcg_temp_free(t2);
2042 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2043 tcg_temp_free(t1);
31e3104f 2044 /* operands of different sign, first operand and result different sign */
48d38ca5
TS
2045 generate_exception(ctx, EXCP_OVERFLOW);
2046 gen_set_label(l1);
460f00c4
AJ
2047 gen_store_gpr(t0, rd);
2048 tcg_temp_free(t0);
48d38ca5 2049 }
7a387fff
TS
2050 opn = "dsub";
2051 break;
2052 case OPC_DSUBU:
460f00c4
AJ
2053 if (rs != 0 && rt != 0) {
2054 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2055 } else if (rs == 0 && rt != 0) {
2056 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2057 } else if (rs != 0 && rt == 0) {
2058 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2059 } else {
2060 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2061 }
7a387fff
TS
2062 opn = "dsubu";
2063 break;
2064#endif
460f00c4
AJ
2065 case OPC_MUL:
2066 if (likely(rs != 0 && rt != 0)) {
2067 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2068 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2069 } else {
2070 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2071 }
2072 opn = "mul";
6af0bf9c 2073 break;
460f00c4 2074 }
2abf314d 2075 (void)opn; /* avoid a compiler warning */
460f00c4
AJ
2076 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2077}
2078
2079/* Conditional move */
9fa77488
RH
2080static void gen_cond_move(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
2081 int rd, int rs, int rt)
460f00c4
AJ
2082{
2083 const char *opn = "cond move";
2084 int l1;
2085
2086 if (rd == 0) {
2087 /* If no destination, treat it as a NOP.
2088 For add & sub, we must generate the overflow exception when needed. */
2089 MIPS_DEBUG("NOP");
2090 return;
2091 }
2092
2093 l1 = gen_new_label();
2094 switch (opc) {
2095 case OPC_MOVN:
2096 if (likely(rt != 0))
2097 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1);
2098 else
2099 tcg_gen_br(l1);
2100 opn = "movn";
6af0bf9c 2101 break;
460f00c4
AJ
2102 case OPC_MOVZ:
2103 if (likely(rt != 0))
2104 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1);
2105 opn = "movz";
2106 break;
2107 }
2108 if (rs != 0)
2109 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2110 else
2111 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2112 gen_set_label(l1);
2113
2abf314d 2114 (void)opn; /* avoid a compiler warning */
460f00c4
AJ
2115 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2116}
2117
2118/* Logic */
9fa77488
RH
2119static void gen_logic(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
2120 int rd, int rs, int rt)
460f00c4
AJ
2121{
2122 const char *opn = "logic";
2123
2124 if (rd == 0) {
2125 /* If no destination, treat it as a NOP. */
2126 MIPS_DEBUG("NOP");
2127 return;
2128 }
2129
2130 switch (opc) {
6af0bf9c 2131 case OPC_AND:
460f00c4
AJ
2132 if (likely(rs != 0 && rt != 0)) {
2133 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2134 } else {
2135 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2136 }
6af0bf9c
FB
2137 opn = "and";
2138 break;
2139 case OPC_NOR:
460f00c4
AJ
2140 if (rs != 0 && rt != 0) {
2141 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2142 } else if (rs == 0 && rt != 0) {
2143 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2144 } else if (rs != 0 && rt == 0) {
2145 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2146 } else {
2147 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2148 }
6af0bf9c
FB
2149 opn = "nor";
2150 break;
2151 case OPC_OR:
460f00c4
AJ
2152 if (likely(rs != 0 && rt != 0)) {
2153 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2154 } else if (rs == 0 && rt != 0) {
2155 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2156 } else if (rs != 0 && rt == 0) {
2157 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2158 } else {
2159 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2160 }
6af0bf9c
FB
2161 opn = "or";
2162 break;
2163 case OPC_XOR:
460f00c4
AJ
2164 if (likely(rs != 0 && rt != 0)) {
2165 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2166 } else if (rs == 0 && rt != 0) {
2167 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2168 } else if (rs != 0 && rt == 0) {
2169 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2170 } else {
2171 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2172 }
6af0bf9c
FB
2173 opn = "xor";
2174 break;
460f00c4 2175 }
2abf314d 2176 (void)opn; /* avoid a compiler warning */
460f00c4
AJ
2177 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2178}
2179
2180/* Set on lower than */
9fa77488
RH
2181static void gen_slt(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
2182 int rd, int rs, int rt)
460f00c4
AJ
2183{
2184 const char *opn = "slt";
2185 TCGv t0, t1;
2186
2187 if (rd == 0) {
2188 /* If no destination, treat it as a NOP. */
2189 MIPS_DEBUG("NOP");
2190 return;
2191 }
2192
2193 t0 = tcg_temp_new();
2194 t1 = tcg_temp_new();
2195 gen_load_gpr(t0, rs);
2196 gen_load_gpr(t1, rt);
2197 switch (opc) {
2198 case OPC_SLT:
e68dd28f 2199 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
460f00c4 2200 opn = "slt";
6af0bf9c 2201 break;
460f00c4 2202 case OPC_SLTU:
e68dd28f 2203 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
460f00c4
AJ
2204 opn = "sltu";
2205 break;
2206 }
2abf314d 2207 (void)opn; /* avoid a compiler warning */
460f00c4
AJ
2208 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2209 tcg_temp_free(t0);
2210 tcg_temp_free(t1);
2211}
20c4c97c 2212
460f00c4 2213/* Shifts */
7db13fae 2214static void gen_shift (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
460f00c4
AJ
2215 int rd, int rs, int rt)
2216{
2217 const char *opn = "shifts";
2218 TCGv t0, t1;
20c4c97c 2219
460f00c4
AJ
2220 if (rd == 0) {
2221 /* If no destination, treat it as a NOP.
2222 For add & sub, we must generate the overflow exception when needed. */
2223 MIPS_DEBUG("NOP");
2224 return;
2225 }
2226
2227 t0 = tcg_temp_new();
2228 t1 = tcg_temp_new();
2229 gen_load_gpr(t0, rs);
2230 gen_load_gpr(t1, rt);
2231 switch (opc) {
6af0bf9c 2232 case OPC_SLLV:
78723684
TS
2233 tcg_gen_andi_tl(t0, t0, 0x1f);
2234 tcg_gen_shl_tl(t0, t1, t0);
460f00c4 2235 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6af0bf9c
FB
2236 opn = "sllv";
2237 break;
2238 case OPC_SRAV:
78723684 2239 tcg_gen_andi_tl(t0, t0, 0x1f);
460f00c4 2240 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
6af0bf9c
FB
2241 opn = "srav";
2242 break;
2243 case OPC_SRLV:
ea63e2c3
NF
2244 tcg_gen_ext32u_tl(t1, t1);
2245 tcg_gen_andi_tl(t0, t0, 0x1f);
2246 tcg_gen_shr_tl(t0, t1, t0);
2247 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2248 opn = "srlv";
2249 break;
2250 case OPC_ROTRV:
2251 {
2252 TCGv_i32 t2 = tcg_temp_new_i32();
2253 TCGv_i32 t3 = tcg_temp_new_i32();
2254
2255 tcg_gen_trunc_tl_i32(t2, t0);
2256 tcg_gen_trunc_tl_i32(t3, t1);
2257 tcg_gen_andi_i32(t2, t2, 0x1f);
2258 tcg_gen_rotr_i32(t2, t3, t2);
2259 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
2260 tcg_temp_free_i32(t2);
2261 tcg_temp_free_i32(t3);
2262 opn = "rotrv";
5a63bcb2 2263 }
7a387fff 2264 break;
d26bc211 2265#if defined(TARGET_MIPS64)
7a387fff 2266 case OPC_DSLLV:
78723684 2267 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 2268 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
2269 opn = "dsllv";
2270 break;
2271 case OPC_DSRAV:
78723684 2272 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 2273 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
2274 opn = "dsrav";
2275 break;
2276 case OPC_DSRLV:
ea63e2c3
NF
2277 tcg_gen_andi_tl(t0, t0, 0x3f);
2278 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
2279 opn = "dsrlv";
2280 break;
2281 case OPC_DROTRV:
2282 tcg_gen_andi_tl(t0, t0, 0x3f);
2283 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
2284 opn = "drotrv";
6af0bf9c 2285 break;
7a387fff 2286#endif
6af0bf9c 2287 }
2abf314d 2288 (void)opn; /* avoid a compiler warning */
6af0bf9c 2289 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
78723684
TS
2290 tcg_temp_free(t0);
2291 tcg_temp_free(t1);
6af0bf9c
FB
2292}
2293
2294/* Arithmetic on HI/LO registers */
7a387fff 2295static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
6af0bf9c 2296{
923617a3 2297 const char *opn = "hilo";
4133498f 2298 unsigned int acc;
6af0bf9c
FB
2299
2300 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
ead9360e 2301 /* Treat as NOP. */
6af0bf9c 2302 MIPS_DEBUG("NOP");
a1f6684d 2303 return;
6af0bf9c 2304 }
4133498f
JL
2305
2306 if (opc == OPC_MFHI || opc == OPC_MFLO) {
2307 acc = ((ctx->opcode) >> 21) & 0x03;
2308 } else {
2309 acc = ((ctx->opcode) >> 11) & 0x03;
2310 }
2311
2312 if (acc != 0) {
2313 check_dsp(ctx);
2314 }
2315
6af0bf9c
FB
2316 switch (opc) {
2317 case OPC_MFHI:
4133498f
JL
2318#if defined(TARGET_MIPS64)
2319 if (acc != 0) {
2320 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
2321 } else
2322#endif
2323 {
2324 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
2325 }
6af0bf9c
FB
2326 opn = "mfhi";
2327 break;
2328 case OPC_MFLO:
4133498f
JL
2329#if defined(TARGET_MIPS64)
2330 if (acc != 0) {
2331 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
2332 } else
2333#endif
2334 {
2335 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
2336 }
6af0bf9c
FB
2337 opn = "mflo";
2338 break;
2339 case OPC_MTHI:
4133498f
JL
2340 if (reg != 0) {
2341#if defined(TARGET_MIPS64)
2342 if (acc != 0) {
2343 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
2344 } else
2345#endif
2346 {
2347 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
2348 }
2349 } else {
2350 tcg_gen_movi_tl(cpu_HI[acc], 0);
2351 }
6af0bf9c
FB
2352 opn = "mthi";
2353 break;
2354 case OPC_MTLO:
4133498f
JL
2355 if (reg != 0) {
2356#if defined(TARGET_MIPS64)
2357 if (acc != 0) {
2358 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
2359 } else
2360#endif
2361 {
2362 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
2363 }
2364 } else {
2365 tcg_gen_movi_tl(cpu_LO[acc], 0);
2366 }
6af0bf9c
FB
2367 opn = "mtlo";
2368 break;
6af0bf9c 2369 }
2abf314d 2370 (void)opn; /* avoid a compiler warning */
6af0bf9c
FB
2371 MIPS_DEBUG("%s %s", opn, regnames[reg]);
2372}
2373
7a387fff 2374static void gen_muldiv (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
2375 int rs, int rt)
2376{
923617a3 2377 const char *opn = "mul/div";
d45f89f4 2378 TCGv t0, t1;
4133498f 2379 unsigned int acc;
d45f89f4
AJ
2380
2381 switch (opc) {
2382 case OPC_DIV:
2383 case OPC_DIVU:
2384#if defined(TARGET_MIPS64)
2385 case OPC_DDIV:
2386 case OPC_DDIVU:
2387#endif
2388 t0 = tcg_temp_local_new();
2389 t1 = tcg_temp_local_new();
2390 break;
2391 default:
2392 t0 = tcg_temp_new();
2393 t1 = tcg_temp_new();
2394 break;
2395 }
6af0bf9c 2396
78723684
TS
2397 gen_load_gpr(t0, rs);
2398 gen_load_gpr(t1, rt);
6af0bf9c
FB
2399 switch (opc) {
2400 case OPC_DIV:
48d38ca5
TS
2401 {
2402 int l1 = gen_new_label();
d45f89f4 2403 int l2 = gen_new_label();
48d38ca5 2404
d45f89f4
AJ
2405 tcg_gen_ext32s_tl(t0, t0);
2406 tcg_gen_ext32s_tl(t1, t1);
78723684 2407 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
d45f89f4
AJ
2408 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2409 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2410
2411 tcg_gen_mov_tl(cpu_LO[0], t0);
2412 tcg_gen_movi_tl(cpu_HI[0], 0);
2413 tcg_gen_br(l1);
2414 gen_set_label(l2);
2415 tcg_gen_div_tl(cpu_LO[0], t0, t1);
2416 tcg_gen_rem_tl(cpu_HI[0], t0, t1);
2417 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2418 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
48d38ca5
TS
2419 gen_set_label(l1);
2420 }
6af0bf9c
FB
2421 opn = "div";
2422 break;
2423 case OPC_DIVU:
48d38ca5
TS
2424 {
2425 int l1 = gen_new_label();
2426
0c0ed03b
AJ
2427 tcg_gen_ext32u_tl(t0, t0);
2428 tcg_gen_ext32u_tl(t1, t1);
78723684 2429 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
d45f89f4
AJ
2430 tcg_gen_divu_tl(cpu_LO[0], t0, t1);
2431 tcg_gen_remu_tl(cpu_HI[0], t0, t1);
2432 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2433 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
48d38ca5
TS
2434 gen_set_label(l1);
2435 }
6af0bf9c
FB
2436 opn = "divu";
2437 break;
2438 case OPC_MULT:
214c465f 2439 {
d45f89f4
AJ
2440 TCGv_i64 t2 = tcg_temp_new_i64();
2441 TCGv_i64 t3 = tcg_temp_new_i64();
4133498f
JL
2442 acc = ((ctx->opcode) >> 11) & 0x03;
2443 if (acc != 0) {
2444 check_dsp(ctx);
2445 }
d45f89f4
AJ
2446
2447 tcg_gen_ext_tl_i64(t2, t0);
2448 tcg_gen_ext_tl_i64(t3, t1);
2449 tcg_gen_mul_i64(t2, t2, t3);
2450 tcg_temp_free_i64(t3);
2451 tcg_gen_trunc_i64_tl(t0, t2);
2452 tcg_gen_shri_i64(t2, t2, 32);
2453 tcg_gen_trunc_i64_tl(t1, t2);
2454 tcg_temp_free_i64(t2);
4133498f
JL
2455 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2456 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
214c465f 2457 }
6af0bf9c
FB
2458 opn = "mult";
2459 break;
2460 case OPC_MULTU:
214c465f 2461 {
d45f89f4
AJ
2462 TCGv_i64 t2 = tcg_temp_new_i64();
2463 TCGv_i64 t3 = tcg_temp_new_i64();
4133498f
JL
2464 acc = ((ctx->opcode) >> 11) & 0x03;
2465 if (acc != 0) {
2466 check_dsp(ctx);
2467 }
214c465f 2468
78723684
TS
2469 tcg_gen_ext32u_tl(t0, t0);
2470 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
2471 tcg_gen_extu_tl_i64(t2, t0);
2472 tcg_gen_extu_tl_i64(t3, t1);
2473 tcg_gen_mul_i64(t2, t2, t3);
2474 tcg_temp_free_i64(t3);
2475 tcg_gen_trunc_i64_tl(t0, t2);
2476 tcg_gen_shri_i64(t2, t2, 32);
2477 tcg_gen_trunc_i64_tl(t1, t2);
2478 tcg_temp_free_i64(t2);
4133498f
JL
2479 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2480 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
214c465f 2481 }
6af0bf9c
FB
2482 opn = "multu";
2483 break;
d26bc211 2484#if defined(TARGET_MIPS64)
7a387fff 2485 case OPC_DDIV:
48d38ca5
TS
2486 {
2487 int l1 = gen_new_label();
d45f89f4 2488 int l2 = gen_new_label();
48d38ca5 2489
78723684 2490 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
d45f89f4
AJ
2491 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2492 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2493 tcg_gen_mov_tl(cpu_LO[0], t0);
2494 tcg_gen_movi_tl(cpu_HI[0], 0);
2495 tcg_gen_br(l1);
2496 gen_set_label(l2);
2497 tcg_gen_div_i64(cpu_LO[0], t0, t1);
2498 tcg_gen_rem_i64(cpu_HI[0], t0, t1);
48d38ca5
TS
2499 gen_set_label(l1);
2500 }
7a387fff
TS
2501 opn = "ddiv";
2502 break;
2503 case OPC_DDIVU:
48d38ca5
TS
2504 {
2505 int l1 = gen_new_label();
2506
78723684 2507 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
b10fa3c9
AJ
2508 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2509 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
48d38ca5
TS
2510 gen_set_label(l1);
2511 }
7a387fff
TS
2512 opn = "ddivu";
2513 break;
2514 case OPC_DMULT:
895c2d04 2515 gen_helper_dmult(cpu_env, t0, t1);
7a387fff
TS
2516 opn = "dmult";
2517 break;
2518 case OPC_DMULTU:
895c2d04 2519 gen_helper_dmultu(cpu_env, t0, t1);
7a387fff
TS
2520 opn = "dmultu";
2521 break;
2522#endif
6af0bf9c 2523 case OPC_MADD:
214c465f 2524 {
d45f89f4
AJ
2525 TCGv_i64 t2 = tcg_temp_new_i64();
2526 TCGv_i64 t3 = tcg_temp_new_i64();
4133498f
JL
2527 acc = ((ctx->opcode) >> 11) & 0x03;
2528 if (acc != 0) {
2529 check_dsp(ctx);
2530 }
d45f89f4
AJ
2531
2532 tcg_gen_ext_tl_i64(t2, t0);
2533 tcg_gen_ext_tl_i64(t3, t1);
2534 tcg_gen_mul_i64(t2, t2, t3);
4133498f 2535 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
2536 tcg_gen_add_i64(t2, t2, t3);
2537 tcg_temp_free_i64(t3);
2538 tcg_gen_trunc_i64_tl(t0, t2);
2539 tcg_gen_shri_i64(t2, t2, 32);
2540 tcg_gen_trunc_i64_tl(t1, t2);
2541 tcg_temp_free_i64(t2);
4133498f
JL
2542 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2543 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
214c465f 2544 }
6af0bf9c
FB
2545 opn = "madd";
2546 break;
2547 case OPC_MADDU:
4133498f 2548 {
d45f89f4
AJ
2549 TCGv_i64 t2 = tcg_temp_new_i64();
2550 TCGv_i64 t3 = tcg_temp_new_i64();
4133498f
JL
2551 acc = ((ctx->opcode) >> 11) & 0x03;
2552 if (acc != 0) {
2553 check_dsp(ctx);
2554 }
214c465f 2555
78723684
TS
2556 tcg_gen_ext32u_tl(t0, t0);
2557 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
2558 tcg_gen_extu_tl_i64(t2, t0);
2559 tcg_gen_extu_tl_i64(t3, t1);
2560 tcg_gen_mul_i64(t2, t2, t3);
4133498f 2561 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
2562 tcg_gen_add_i64(t2, t2, t3);
2563 tcg_temp_free_i64(t3);
2564 tcg_gen_trunc_i64_tl(t0, t2);
2565 tcg_gen_shri_i64(t2, t2, 32);
2566 tcg_gen_trunc_i64_tl(t1, t2);
2567 tcg_temp_free_i64(t2);
4133498f
JL
2568 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2569 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
214c465f 2570 }
6af0bf9c
FB
2571 opn = "maddu";
2572 break;
2573 case OPC_MSUB:
214c465f 2574 {
d45f89f4
AJ
2575 TCGv_i64 t2 = tcg_temp_new_i64();
2576 TCGv_i64 t3 = tcg_temp_new_i64();
4133498f
JL
2577 acc = ((ctx->opcode) >> 11) & 0x03;
2578 if (acc != 0) {
2579 check_dsp(ctx);
2580 }
d45f89f4
AJ
2581
2582 tcg_gen_ext_tl_i64(t2, t0);
2583 tcg_gen_ext_tl_i64(t3, t1);
2584 tcg_gen_mul_i64(t2, t2, t3);
4133498f 2585 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 2586 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4
AJ
2587 tcg_temp_free_i64(t3);
2588 tcg_gen_trunc_i64_tl(t0, t2);
2589 tcg_gen_shri_i64(t2, t2, 32);
2590 tcg_gen_trunc_i64_tl(t1, t2);
2591 tcg_temp_free_i64(t2);
4133498f
JL
2592 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2593 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
214c465f 2594 }
6af0bf9c
FB
2595 opn = "msub";
2596 break;
2597 case OPC_MSUBU:
214c465f 2598 {
d45f89f4
AJ
2599 TCGv_i64 t2 = tcg_temp_new_i64();
2600 TCGv_i64 t3 = tcg_temp_new_i64();
4133498f
JL
2601 acc = ((ctx->opcode) >> 11) & 0x03;
2602 if (acc != 0) {
2603 check_dsp(ctx);
2604 }
214c465f 2605
78723684
TS
2606 tcg_gen_ext32u_tl(t0, t0);
2607 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
2608 tcg_gen_extu_tl_i64(t2, t0);
2609 tcg_gen_extu_tl_i64(t3, t1);
2610 tcg_gen_mul_i64(t2, t2, t3);
4133498f 2611 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 2612 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4
AJ
2613 tcg_temp_free_i64(t3);
2614 tcg_gen_trunc_i64_tl(t0, t2);
2615 tcg_gen_shri_i64(t2, t2, 32);
2616 tcg_gen_trunc_i64_tl(t1, t2);
2617 tcg_temp_free_i64(t2);
4133498f
JL
2618 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2619 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
214c465f 2620 }
6af0bf9c
FB
2621 opn = "msubu";
2622 break;
2623 default:
923617a3 2624 MIPS_INVAL(opn);
6af0bf9c 2625 generate_exception(ctx, EXCP_RI);
78723684 2626 goto out;
6af0bf9c 2627 }
2abf314d 2628 (void)opn; /* avoid a compiler warning */
6af0bf9c 2629 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
78723684
TS
2630 out:
2631 tcg_temp_free(t0);
2632 tcg_temp_free(t1);
6af0bf9c
FB
2633}
2634
e9c71dd1
TS
2635static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2636 int rd, int rs, int rt)
2637{
2638 const char *opn = "mul vr54xx";
f157bfe1
AJ
2639 TCGv t0 = tcg_temp_new();
2640 TCGv t1 = tcg_temp_new();
e9c71dd1 2641
6c5c1e20
TS
2642 gen_load_gpr(t0, rs);
2643 gen_load_gpr(t1, rt);
e9c71dd1
TS
2644
2645 switch (opc) {
2646 case OPC_VR54XX_MULS:
895c2d04 2647 gen_helper_muls(t0, cpu_env, t0, t1);
e9c71dd1 2648 opn = "muls";
6958549d 2649 break;
e9c71dd1 2650 case OPC_VR54XX_MULSU:
895c2d04 2651 gen_helper_mulsu(t0, cpu_env, t0, t1);
e9c71dd1 2652 opn = "mulsu";
6958549d 2653 break;
e9c71dd1 2654 case OPC_VR54XX_MACC:
895c2d04 2655 gen_helper_macc(t0, cpu_env, t0, t1);
e9c71dd1 2656 opn = "macc";
6958549d 2657 break;
e9c71dd1 2658 case OPC_VR54XX_MACCU:
895c2d04 2659 gen_helper_maccu(t0, cpu_env, t0, t1);
e9c71dd1 2660 opn = "maccu";
6958549d 2661 break;
e9c71dd1 2662 case OPC_VR54XX_MSAC:
895c2d04 2663 gen_helper_msac(t0, cpu_env, t0, t1);
e9c71dd1 2664 opn = "msac";
6958549d 2665 break;
e9c71dd1 2666 case OPC_VR54XX_MSACU:
895c2d04 2667 gen_helper_msacu(t0, cpu_env, t0, t1);
e9c71dd1 2668 opn = "msacu";
6958549d 2669 break;
e9c71dd1 2670 case OPC_VR54XX_MULHI:
895c2d04 2671 gen_helper_mulhi(t0, cpu_env, t0, t1);
e9c71dd1 2672 opn = "mulhi";
6958549d 2673 break;
e9c71dd1 2674 case OPC_VR54XX_MULHIU:
895c2d04 2675 gen_helper_mulhiu(t0, cpu_env, t0, t1);
e9c71dd1 2676 opn = "mulhiu";
6958549d 2677 break;
e9c71dd1 2678 case OPC_VR54XX_MULSHI:
895c2d04 2679 gen_helper_mulshi(t0, cpu_env, t0, t1);
e9c71dd1 2680 opn = "mulshi";
6958549d 2681 break;
e9c71dd1 2682 case OPC_VR54XX_MULSHIU:
895c2d04 2683 gen_helper_mulshiu(t0, cpu_env, t0, t1);
e9c71dd1 2684 opn = "mulshiu";
6958549d 2685 break;
e9c71dd1 2686 case OPC_VR54XX_MACCHI:
895c2d04 2687 gen_helper_macchi(t0, cpu_env, t0, t1);
e9c71dd1 2688 opn = "macchi";
6958549d 2689 break;
e9c71dd1 2690 case OPC_VR54XX_MACCHIU:
895c2d04 2691 gen_helper_macchiu(t0, cpu_env, t0, t1);
e9c71dd1 2692 opn = "macchiu";
6958549d 2693 break;
e9c71dd1 2694 case OPC_VR54XX_MSACHI:
895c2d04 2695 gen_helper_msachi(t0, cpu_env, t0, t1);
e9c71dd1 2696 opn = "msachi";
6958549d 2697 break;
e9c71dd1 2698 case OPC_VR54XX_MSACHIU:
895c2d04 2699 gen_helper_msachiu(t0, cpu_env, t0, t1);
e9c71dd1 2700 opn = "msachiu";
6958549d 2701 break;
e9c71dd1
TS
2702 default:
2703 MIPS_INVAL("mul vr54xx");
2704 generate_exception(ctx, EXCP_RI);
6c5c1e20 2705 goto out;
e9c71dd1 2706 }
6c5c1e20 2707 gen_store_gpr(t0, rd);
2abf314d 2708 (void)opn; /* avoid a compiler warning */
e9c71dd1 2709 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
6c5c1e20
TS
2710
2711 out:
2712 tcg_temp_free(t0);
2713 tcg_temp_free(t1);
e9c71dd1
TS
2714}
2715
7a387fff 2716static void gen_cl (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
2717 int rd, int rs)
2718{
923617a3 2719 const char *opn = "CLx";
20e1fb52 2720 TCGv t0;
6c5c1e20 2721
6af0bf9c 2722 if (rd == 0) {
ead9360e 2723 /* Treat as NOP. */
6af0bf9c 2724 MIPS_DEBUG("NOP");
20e1fb52 2725 return;
6af0bf9c 2726 }
20e1fb52 2727 t0 = tcg_temp_new();
6c5c1e20 2728 gen_load_gpr(t0, rs);
6af0bf9c
FB
2729 switch (opc) {
2730 case OPC_CLO:
20e1fb52 2731 gen_helper_clo(cpu_gpr[rd], t0);
6af0bf9c
FB
2732 opn = "clo";
2733 break;
2734 case OPC_CLZ:
20e1fb52 2735 gen_helper_clz(cpu_gpr[rd], t0);
6af0bf9c
FB
2736 opn = "clz";
2737 break;
d26bc211 2738#if defined(TARGET_MIPS64)
7a387fff 2739 case OPC_DCLO:
20e1fb52 2740 gen_helper_dclo(cpu_gpr[rd], t0);
7a387fff
TS
2741 opn = "dclo";
2742 break;
2743 case OPC_DCLZ:
20e1fb52 2744 gen_helper_dclz(cpu_gpr[rd], t0);
7a387fff
TS
2745 opn = "dclz";
2746 break;
2747#endif
6af0bf9c 2748 }
2abf314d 2749 (void)opn; /* avoid a compiler warning */
6af0bf9c 2750 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
6c5c1e20 2751 tcg_temp_free(t0);
6af0bf9c
FB
2752}
2753
161f85e6 2754/* Godson integer instructions */
bd277fa1
RH
2755static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
2756 int rd, int rs, int rt)
161f85e6
AJ
2757{
2758 const char *opn = "loongson";
2759 TCGv t0, t1;
2760
2761 if (rd == 0) {
2762 /* Treat as NOP. */
2763 MIPS_DEBUG("NOP");
2764 return;
2765 }
2766
2767 switch (opc) {
2768 case OPC_MULT_G_2E:
2769 case OPC_MULT_G_2F:
2770 case OPC_MULTU_G_2E:
2771 case OPC_MULTU_G_2F:
2772#if defined(TARGET_MIPS64)
2773 case OPC_DMULT_G_2E:
2774 case OPC_DMULT_G_2F:
2775 case OPC_DMULTU_G_2E:
2776 case OPC_DMULTU_G_2F:
2777#endif
2778 t0 = tcg_temp_new();
2779 t1 = tcg_temp_new();
2780 break;
2781 default:
2782 t0 = tcg_temp_local_new();
2783 t1 = tcg_temp_local_new();
2784 break;
2785 }
2786
2787 gen_load_gpr(t0, rs);
2788 gen_load_gpr(t1, rt);
2789
2790 switch (opc) {
2791 case OPC_MULT_G_2E:
2792 case OPC_MULT_G_2F:
2793 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2794 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2795 opn = "mult.g";
2796 break;
2797 case OPC_MULTU_G_2E:
2798 case OPC_MULTU_G_2F:
2799 tcg_gen_ext32u_tl(t0, t0);
2800 tcg_gen_ext32u_tl(t1, t1);
2801 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2802 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2803 opn = "multu.g";
2804 break;
2805 case OPC_DIV_G_2E:
2806 case OPC_DIV_G_2F:
2807 {
2808 int l1 = gen_new_label();
2809 int l2 = gen_new_label();
2810 int l3 = gen_new_label();
2811 tcg_gen_ext32s_tl(t0, t0);
2812 tcg_gen_ext32s_tl(t1, t1);
2813 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2814 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2815 tcg_gen_br(l3);
2816 gen_set_label(l1);
2817 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2818 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2819 tcg_gen_mov_tl(cpu_gpr[rd], t0);
2820 tcg_gen_br(l3);
2821 gen_set_label(l2);
2822 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2823 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2824 gen_set_label(l3);
2825 }
2826 opn = "div.g";
2827 break;
2828 case OPC_DIVU_G_2E:
2829 case OPC_DIVU_G_2F:
2830 {
2831 int l1 = gen_new_label();
2832 int l2 = gen_new_label();
2833 tcg_gen_ext32u_tl(t0, t0);
2834 tcg_gen_ext32u_tl(t1, t1);
2835 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2836 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2837 tcg_gen_br(l2);
2838 gen_set_label(l1);
2839 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
2840 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2841 gen_set_label(l2);
2842 }
2843 opn = "divu.g";
2844 break;
2845 case OPC_MOD_G_2E:
2846 case OPC_MOD_G_2F:
2847 {
2848 int l1 = gen_new_label();
2849 int l2 = gen_new_label();
2850 int l3 = gen_new_label();
2851 tcg_gen_ext32u_tl(t0, t0);
2852 tcg_gen_ext32u_tl(t1, t1);
2853 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2854 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2855 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2856 gen_set_label(l1);
2857 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2858 tcg_gen_br(l3);
2859 gen_set_label(l2);
2860 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
2861 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2862 gen_set_label(l3);
2863 }
2864 opn = "mod.g";
2865 break;
2866 case OPC_MODU_G_2E:
2867 case OPC_MODU_G_2F:
2868 {
2869 int l1 = gen_new_label();
2870 int l2 = gen_new_label();
2871 tcg_gen_ext32u_tl(t0, t0);
2872 tcg_gen_ext32u_tl(t1, t1);
2873 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2874 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2875 tcg_gen_br(l2);
2876 gen_set_label(l1);
2877 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
2878 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2879 gen_set_label(l2);
2880 }
2881 opn = "modu.g";
2882 break;
2883#if defined(TARGET_MIPS64)
2884 case OPC_DMULT_G_2E:
2885 case OPC_DMULT_G_2F:
2886 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2887 opn = "dmult.g";
2888 break;
2889 case OPC_DMULTU_G_2E:
2890 case OPC_DMULTU_G_2F:
2891 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2892 opn = "dmultu.g";
2893 break;
2894 case OPC_DDIV_G_2E:
2895 case OPC_DDIV_G_2F:
2896 {
2897 int l1 = gen_new_label();
2898 int l2 = gen_new_label();
2899 int l3 = gen_new_label();
2900 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2901 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2902 tcg_gen_br(l3);
2903 gen_set_label(l1);
2904 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2905 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2906 tcg_gen_mov_tl(cpu_gpr[rd], t0);
2907 tcg_gen_br(l3);
2908 gen_set_label(l2);
2909 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2910 gen_set_label(l3);
2911 }
2912 opn = "ddiv.g";
2913 break;
2914 case OPC_DDIVU_G_2E:
2915 case OPC_DDIVU_G_2F:
2916 {
2917 int l1 = gen_new_label();
2918 int l2 = gen_new_label();
2919 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2920 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2921 tcg_gen_br(l2);
2922 gen_set_label(l1);
2923 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
2924 gen_set_label(l2);
2925 }
2926 opn = "ddivu.g";
2927 break;
2928 case OPC_DMOD_G_2E:
2929 case OPC_DMOD_G_2F:
2930 {
2931 int l1 = gen_new_label();
2932 int l2 = gen_new_label();
2933 int l3 = gen_new_label();
2934 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2935 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2936 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2937 gen_set_label(l1);
2938 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2939 tcg_gen_br(l3);
2940 gen_set_label(l2);
2941 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
2942 gen_set_label(l3);
2943 }
2944 opn = "dmod.g";
2945 break;
2946 case OPC_DMODU_G_2E:
2947 case OPC_DMODU_G_2F:
2948 {
2949 int l1 = gen_new_label();
2950 int l2 = gen_new_label();
2951 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2952 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2953 tcg_gen_br(l2);
2954 gen_set_label(l1);
2955 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
2956 gen_set_label(l2);
2957 }
2958 opn = "dmodu.g";
2959 break;
2960#endif
2961 }
2962
2abf314d 2963 (void)opn; /* avoid a compiler warning */
161f85e6
AJ
2964 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2965 tcg_temp_free(t0);
2966 tcg_temp_free(t1);
2967}
2968
bd277fa1
RH
2969/* Loongson multimedia instructions */
2970static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
2971{
2972 const char *opn = "loongson_cp2";
2973 uint32_t opc, shift_max;
2974 TCGv_i64 t0, t1;
2975
2976 opc = MASK_LMI(ctx->opcode);
2977 switch (opc) {
2978 case OPC_ADD_CP2:
2979 case OPC_SUB_CP2:
2980 case OPC_DADD_CP2:
2981 case OPC_DSUB_CP2:
2982 t0 = tcg_temp_local_new_i64();
2983 t1 = tcg_temp_local_new_i64();
2984 break;
2985 default:
2986 t0 = tcg_temp_new_i64();
2987 t1 = tcg_temp_new_i64();
2988 break;
2989 }
2990
2991 gen_load_fpr64(ctx, t0, rs);
2992 gen_load_fpr64(ctx, t1, rt);
2993
2994#define LMI_HELPER(UP, LO) \
2995 case OPC_##UP: gen_helper_##LO(t0, t0, t1); opn = #LO; break
2996#define LMI_HELPER_1(UP, LO) \
2997 case OPC_##UP: gen_helper_##LO(t0, t0); opn = #LO; break
2998#define LMI_DIRECT(UP, LO, OP) \
2999 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); opn = #LO; break
3000
3001 switch (opc) {
3002 LMI_HELPER(PADDSH, paddsh);
3003 LMI_HELPER(PADDUSH, paddush);
3004 LMI_HELPER(PADDH, paddh);
3005 LMI_HELPER(PADDW, paddw);
3006 LMI_HELPER(PADDSB, paddsb);
3007 LMI_HELPER(PADDUSB, paddusb);
3008 LMI_HELPER(PADDB, paddb);
3009
3010 LMI_HELPER(PSUBSH, psubsh);
3011 LMI_HELPER(PSUBUSH, psubush);
3012 LMI_HELPER(PSUBH, psubh);
3013 LMI_HELPER(PSUBW, psubw);
3014 LMI_HELPER(PSUBSB, psubsb);
3015 LMI_HELPER(PSUBUSB, psubusb);
3016 LMI_HELPER(PSUBB, psubb);
3017
3018 LMI_HELPER(PSHUFH, pshufh);
3019 LMI_HELPER(PACKSSWH, packsswh);
3020 LMI_HELPER(PACKSSHB, packsshb);
3021 LMI_HELPER(PACKUSHB, packushb);
3022
3023 LMI_HELPER(PUNPCKLHW, punpcklhw);
3024 LMI_HELPER(PUNPCKHHW, punpckhhw);
3025 LMI_HELPER(PUNPCKLBH, punpcklbh);
3026 LMI_HELPER(PUNPCKHBH, punpckhbh);
3027 LMI_HELPER(PUNPCKLWD, punpcklwd);
3028 LMI_HELPER(PUNPCKHWD, punpckhwd);
3029
3030 LMI_HELPER(PAVGH, pavgh);
3031 LMI_HELPER(PAVGB, pavgb);
3032 LMI_HELPER(PMAXSH, pmaxsh);
3033 LMI_HELPER(PMINSH, pminsh);
3034 LMI_HELPER(PMAXUB, pmaxub);
3035 LMI_HELPER(PMINUB, pminub);
3036
3037 LMI_HELPER(PCMPEQW, pcmpeqw);
3038 LMI_HELPER(PCMPGTW, pcmpgtw);
3039 LMI_HELPER(PCMPEQH, pcmpeqh);
3040 LMI_HELPER(PCMPGTH, pcmpgth);
3041 LMI_HELPER(PCMPEQB, pcmpeqb);
3042 LMI_HELPER(PCMPGTB, pcmpgtb);
3043
3044 LMI_HELPER(PSLLW, psllw);
3045 LMI_HELPER(PSLLH, psllh);
3046 LMI_HELPER(PSRLW, psrlw);
3047 LMI_HELPER(PSRLH, psrlh);
3048 LMI_HELPER(PSRAW, psraw);
3049 LMI_HELPER(PSRAH, psrah);
3050
3051 LMI_HELPER(PMULLH, pmullh);
3052 LMI_HELPER(PMULHH, pmulhh);
3053 LMI_HELPER(PMULHUH, pmulhuh);
3054 LMI_HELPER(PMADDHW, pmaddhw);
3055
3056 LMI_HELPER(PASUBUB, pasubub);
3057 LMI_HELPER_1(BIADD, biadd);
3058 LMI_HELPER_1(PMOVMSKB, pmovmskb);
3059
3060 LMI_DIRECT(PADDD, paddd, add);
3061 LMI_DIRECT(PSUBD, psubd, sub);
3062 LMI_DIRECT(XOR_CP2, xor, xor);
3063 LMI_DIRECT(NOR_CP2, nor, nor);
3064 LMI_DIRECT(AND_CP2, and, and);
3065 LMI_DIRECT(PANDN, pandn, andc);
3066 LMI_DIRECT(OR, or, or);
3067
3068 case OPC_PINSRH_0:
3069 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
3070 opn = "pinsrh_0";
3071 break;
3072 case OPC_PINSRH_1:
3073 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
3074 opn = "pinsrh_1";
3075 break;
3076 case OPC_PINSRH_2:
3077 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
3078 opn = "pinsrh_2";
3079 break;
3080 case OPC_PINSRH_3:
3081 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
3082 opn = "pinsrh_3";
3083 break;
3084
3085 case OPC_PEXTRH:
3086 tcg_gen_andi_i64(t1, t1, 3);
3087 tcg_gen_shli_i64(t1, t1, 4);
3088 tcg_gen_shr_i64(t0, t0, t1);
3089 tcg_gen_ext16u_i64(t0, t0);
3090 opn = "pextrh";
3091 break;
3092
3093 case OPC_ADDU_CP2:
3094 tcg_gen_add_i64(t0, t0, t1);
3095 tcg_gen_ext32s_i64(t0, t0);
3096 opn = "addu";
3097 break;
3098 case OPC_SUBU_CP2:
3099 tcg_gen_sub_i64(t0, t0, t1);
3100 tcg_gen_ext32s_i64(t0, t0);
3101 opn = "addu";
3102 break;
3103
3104 case OPC_SLL_CP2:
3105 opn = "sll";
3106 shift_max = 32;
3107 goto do_shift;
3108 case OPC_SRL_CP2:
3109 opn = "srl";
3110 shift_max = 32;
3111 goto do_shift;
3112 case OPC_SRA_CP2:
3113 opn = "sra";
3114 shift_max = 32;
3115 goto do_shift;
3116 case OPC_DSLL_CP2:
3117 opn = "dsll";
3118 shift_max = 64;
3119 goto do_shift;
3120 case OPC_DSRL_CP2:
3121 opn = "dsrl";
3122 shift_max = 64;
3123 goto do_shift;
3124 case OPC_DSRA_CP2:
3125 opn = "dsra";
3126 shift_max = 64;
3127 goto do_shift;
3128 do_shift:
3129 /* Make sure shift count isn't TCG undefined behaviour. */
3130 tcg_gen_andi_i64(t1, t1, shift_max - 1);
3131
3132 switch (opc) {
3133 case OPC_SLL_CP2:
3134 case OPC_DSLL_CP2:
3135 tcg_gen_shl_i64(t0, t0, t1);
3136 break;
3137 case OPC_SRA_CP2:
3138 case OPC_DSRA_CP2:
3139 /* Since SRA is UndefinedResult without sign-extended inputs,
3140 we can treat SRA and DSRA the same. */
3141 tcg_gen_sar_i64(t0, t0, t1);
3142 break;
3143 case OPC_SRL_CP2:
3144 /* We want to shift in zeros for SRL; zero-extend first. */
3145 tcg_gen_ext32u_i64(t0, t0);
3146 /* FALLTHRU */
3147 case OPC_DSRL_CP2:
3148 tcg_gen_shr_i64(t0, t0, t1);
3149 break;
3150 }
3151
3152 if (shift_max == 32) {
3153 tcg_gen_ext32s_i64(t0, t0);
3154 }
3155
3156 /* Shifts larger than MAX produce zero. */
3157 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
3158 tcg_gen_neg_i64(t1, t1);
3159 tcg_gen_and_i64(t0, t0, t1);
3160 break;
3161
3162 case OPC_ADD_CP2:
3163 case OPC_DADD_CP2:
3164 {
3165 TCGv_i64 t2 = tcg_temp_new_i64();
3166 int lab = gen_new_label();
3167
3168 tcg_gen_mov_i64(t2, t0);
3169 tcg_gen_add_i64(t0, t1, t2);
3170 if (opc == OPC_ADD_CP2) {
3171 tcg_gen_ext32s_i64(t0, t0);
3172 }
3173 tcg_gen_xor_i64(t1, t1, t2);
3174 tcg_gen_xor_i64(t2, t2, t0);
3175 tcg_gen_andc_i64(t1, t2, t1);
3176 tcg_temp_free_i64(t2);
3177 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
3178 generate_exception(ctx, EXCP_OVERFLOW);
3179 gen_set_label(lab);
3180
3181 opn = (opc == OPC_ADD_CP2 ? "add" : "dadd");
3182 break;
3183 }
3184
3185 case OPC_SUB_CP2:
3186 case OPC_DSUB_CP2:
3187 {
3188 TCGv_i64 t2 = tcg_temp_new_i64();
3189 int lab = gen_new_label();
3190
3191 tcg_gen_mov_i64(t2, t0);
3192 tcg_gen_sub_i64(t0, t1, t2);
3193 if (opc == OPC_SUB_CP2) {
3194 tcg_gen_ext32s_i64(t0, t0);
3195 }
3196 tcg_gen_xor_i64(t1, t1, t2);
3197 tcg_gen_xor_i64(t2, t2, t0);
3198 tcg_gen_and_i64(t1, t1, t2);
3199 tcg_temp_free_i64(t2);
3200 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
3201 generate_exception(ctx, EXCP_OVERFLOW);
3202 gen_set_label(lab);
3203
3204 opn = (opc == OPC_SUB_CP2 ? "sub" : "dsub");
3205 break;
3206 }
3207
3208 case OPC_PMULUW:
3209 tcg_gen_ext32u_i64(t0, t0);
3210 tcg_gen_ext32u_i64(t1, t1);
3211 tcg_gen_mul_i64(t0, t0, t1);
3212 opn = "pmuluw";
3213 break;
3214
3215 case OPC_SEQU_CP2:
3216 case OPC_SEQ_CP2:
3217 case OPC_SLTU_CP2:
3218 case OPC_SLT_CP2:
3219 case OPC_SLEU_CP2:
3220 case OPC_SLE_CP2:
3221 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
3222 FD field is the CC field? */
3223 default:
3224 MIPS_INVAL(opn);
3225 generate_exception(ctx, EXCP_RI);
3226 return;
3227 }
3228
3229#undef LMI_HELPER
3230#undef LMI_DIRECT
3231
3232 gen_store_fpr64(ctx, t0, rd);
3233
3234 (void)opn; /* avoid a compiler warning */
3235 MIPS_DEBUG("%s %s, %s, %s", opn,
3236 fregnames[rd], fregnames[rs], fregnames[rt]);
3237 tcg_temp_free_i64(t0);
3238 tcg_temp_free_i64(t1);
3239}
3240
6af0bf9c 3241/* Traps */
7a387fff 3242static void gen_trap (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
3243 int rs, int rt, int16_t imm)
3244{
3245 int cond;
cdc0faa6 3246 TCGv t0 = tcg_temp_new();
1ba74fb8 3247 TCGv t1 = tcg_temp_new();
6af0bf9c
FB
3248
3249 cond = 0;
3250 /* Load needed operands */
3251 switch (opc) {
3252 case OPC_TEQ:
3253 case OPC_TGE:
3254 case OPC_TGEU:
3255 case OPC_TLT:
3256 case OPC_TLTU:
3257 case OPC_TNE:
3258 /* Compare two registers */
3259 if (rs != rt) {
be24bb4f
TS
3260 gen_load_gpr(t0, rs);
3261 gen_load_gpr(t1, rt);
6af0bf9c
FB
3262 cond = 1;
3263 }
179e32bb 3264 break;
6af0bf9c
FB
3265 case OPC_TEQI:
3266 case OPC_TGEI:
3267 case OPC_TGEIU:
3268 case OPC_TLTI:
3269 case OPC_TLTIU:
3270 case OPC_TNEI:
3271 /* Compare register to immediate */
3272 if (rs != 0 || imm != 0) {
be24bb4f
TS
3273 gen_load_gpr(t0, rs);
3274 tcg_gen_movi_tl(t1, (int32_t)imm);
6af0bf9c
FB
3275 cond = 1;
3276 }
3277 break;
3278 }
3279 if (cond == 0) {
3280 switch (opc) {
3281 case OPC_TEQ: /* rs == rs */
3282 case OPC_TEQI: /* r0 == 0 */
3283 case OPC_TGE: /* rs >= rs */
3284 case OPC_TGEI: /* r0 >= 0 */
3285 case OPC_TGEU: /* rs >= rs unsigned */
3286 case OPC_TGEIU: /* r0 >= 0 unsigned */
3287 /* Always trap */
cdc0faa6 3288 generate_exception(ctx, EXCP_TRAP);
6af0bf9c
FB
3289 break;
3290 case OPC_TLT: /* rs < rs */
3291 case OPC_TLTI: /* r0 < 0 */
3292 case OPC_TLTU: /* rs < rs unsigned */
3293 case OPC_TLTIU: /* r0 < 0 unsigned */
3294 case OPC_TNE: /* rs != rs */
3295 case OPC_TNEI: /* r0 != 0 */
ead9360e 3296 /* Never trap: treat as NOP. */
cdc0faa6 3297 break;
6af0bf9c
FB
3298 }
3299 } else {
cdc0faa6
AJ
3300 int l1 = gen_new_label();
3301
6af0bf9c
FB
3302 switch (opc) {
3303 case OPC_TEQ:
3304 case OPC_TEQI:
cdc0faa6 3305 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6af0bf9c
FB
3306 break;
3307 case OPC_TGE:
3308 case OPC_TGEI:
cdc0faa6 3309 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6af0bf9c
FB
3310 break;
3311 case OPC_TGEU:
3312 case OPC_TGEIU:
cdc0faa6 3313 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6af0bf9c
FB
3314 break;
3315 case OPC_TLT:
3316 case OPC_TLTI:
cdc0faa6 3317 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6af0bf9c
FB
3318 break;
3319 case OPC_TLTU:
3320 case OPC_TLTIU:
cdc0faa6 3321 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6af0bf9c
FB
3322 break;
3323 case OPC_TNE:
3324 case OPC_TNEI:
cdc0faa6 3325 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6af0bf9c 3326 break;
6af0bf9c 3327 }
cdc0faa6 3328 generate_exception(ctx, EXCP_TRAP);
08ba7963
TS
3329 gen_set_label(l1);
3330 }
be24bb4f
TS
3331 tcg_temp_free(t0);
3332 tcg_temp_free(t1);
6af0bf9c
FB
3333}
3334
356265ae 3335static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
c53be334 3336{
6e256c93
FB
3337 TranslationBlock *tb;
3338 tb = ctx->tb;
7b270ef2
NF
3339 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
3340 likely(!ctx->singlestep_enabled)) {
57fec1fe 3341 tcg_gen_goto_tb(n);
9b9e4393 3342 gen_save_pc(dest);
4b4a72e5 3343 tcg_gen_exit_tb((tcg_target_long)tb + n);
6e256c93 3344 } else {
9b9e4393 3345 gen_save_pc(dest);
7b270ef2
NF
3346 if (ctx->singlestep_enabled) {
3347 save_cpu_state(ctx, 0);
895c2d04 3348 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
7b270ef2 3349 }
57fec1fe 3350 tcg_gen_exit_tb(0);
6e256c93 3351 }
c53be334
FB
3352}
3353
6af0bf9c 3354/* Branches (before delay slot) */
7a387fff 3355static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
7dca4ad0 3356 int insn_bytes,
6af0bf9c
FB
3357 int rs, int rt, int32_t offset)
3358{
d077b6f7 3359 target_ulong btgt = -1;
3ad4bb2d 3360 int blink = 0;
2fdbad25 3361 int bcond_compute = 0;
1ba74fb8
AJ
3362 TCGv t0 = tcg_temp_new();
3363 TCGv t1 = tcg_temp_new();
3ad4bb2d
TS
3364
3365 if (ctx->hflags & MIPS_HFLAG_BMASK) {
923617a3 3366#ifdef MIPS_DEBUG_DISAS
d12d51d5 3367 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
923617a3 3368#endif
3ad4bb2d 3369 generate_exception(ctx, EXCP_RI);
6c5c1e20 3370 goto out;
3ad4bb2d 3371 }
6af0bf9c 3372
6af0bf9c
FB
3373 /* Load needed operands */
3374 switch (opc) {
3375 case OPC_BEQ:
3376 case OPC_BEQL:
3377 case OPC_BNE:
3378 case OPC_BNEL:
3379 /* Compare two registers */
3380 if (rs != rt) {
6c5c1e20
TS
3381 gen_load_gpr(t0, rs);
3382 gen_load_gpr(t1, rt);
2fdbad25 3383 bcond_compute = 1;
6af0bf9c 3384 }
7dca4ad0 3385 btgt = ctx->pc + insn_bytes + offset;
6af0bf9c
FB
3386 break;
3387 case OPC_BGEZ:
3388 case OPC_BGEZAL:
3c824109 3389 case OPC_BGEZALS:
6af0bf9c
FB
3390 case OPC_BGEZALL:
3391 case OPC_BGEZL:
3392 case OPC_BGTZ:
3393 case OPC_BGTZL:
3394 case OPC_BLEZ:
3395 case OPC_BLEZL:
3396 case OPC_BLTZ:
3397 case OPC_BLTZAL:
3c824109 3398 case OPC_BLTZALS:
6af0bf9c
FB
3399 case OPC_BLTZALL:
3400 case OPC_BLTZL:
3401 /* Compare to zero */
3402 if (rs != 0) {
6c5c1e20 3403 gen_load_gpr(t0, rs);
2fdbad25 3404 bcond_compute = 1;
6af0bf9c 3405 }
7dca4ad0 3406 btgt = ctx->pc + insn_bytes + offset;
6af0bf9c 3407 break;
e45a93e2
JL
3408 case OPC_BPOSGE32:
3409#if defined(TARGET_MIPS64)
3410 case OPC_BPOSGE64:
3411 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
3412#else
3413 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
3414#endif
3415 bcond_compute = 1;
3416 btgt = ctx->pc + insn_bytes + offset;
3417 break;
6af0bf9c
FB
3418 case OPC_J:
3419 case OPC_JAL:
364d4831 3420 case OPC_JALX:
620e48f6
NF
3421 case OPC_JALS:
3422 case OPC_JALXS:
6af0bf9c 3423 /* Jump to immediate */
7dca4ad0 3424 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
6af0bf9c
FB
3425 break;
3426 case OPC_JR:
3427 case OPC_JALR:
364d4831 3428 case OPC_JALRC:
620e48f6 3429 case OPC_JALRS:
6af0bf9c 3430 /* Jump to register */
7a387fff
TS
3431 if (offset != 0 && offset != 16) {
3432 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
cbeb0857 3433 others are reserved. */
923617a3 3434 MIPS_INVAL("jump hint");
6af0bf9c 3435 generate_exception(ctx, EXCP_RI);
6c5c1e20 3436 goto out;
6af0bf9c 3437 }
d077b6f7 3438 gen_load_gpr(btarget, rs);
6af0bf9c
FB
3439 break;
3440 default:
3441 MIPS_INVAL("branch/jump");
3442 generate_exception(ctx, EXCP_RI);
6c5c1e20 3443 goto out;
6af0bf9c 3444 }
2fdbad25 3445 if (bcond_compute == 0) {
6af0bf9c
FB
3446 /* No condition to be computed */
3447 switch (opc) {
3448 case OPC_BEQ: /* rx == rx */
3449 case OPC_BEQL: /* rx == rx likely */
3450 case OPC_BGEZ: /* 0 >= 0 */
3451 case OPC_BGEZL: /* 0 >= 0 likely */
3452 case OPC_BLEZ: /* 0 <= 0 */
3453 case OPC_BLEZL: /* 0 <= 0 likely */
3454 /* Always take */
4ad40f36 3455 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
3456 MIPS_DEBUG("balways");
3457 break;
3c824109 3458 case OPC_BGEZALS:
6af0bf9c
FB
3459 case OPC_BGEZAL: /* 0 >= 0 */
3460 case OPC_BGEZALL: /* 0 >= 0 likely */
3c824109
NF
3461 ctx->hflags |= (opc == OPC_BGEZALS
3462 ? MIPS_HFLAG_BDS16
3463 : MIPS_HFLAG_BDS32);
6af0bf9c
FB
3464 /* Always take and link */
3465 blink = 31;
4ad40f36 3466 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
3467 MIPS_DEBUG("balways and link");
3468 break;
3469 case OPC_BNE: /* rx != rx */
3470 case OPC_BGTZ: /* 0 > 0 */
3471 case OPC_BLTZ: /* 0 < 0 */
ead9360e 3472 /* Treat as NOP. */
6af0bf9c 3473 MIPS_DEBUG("bnever (NOP)");
6c5c1e20 3474 goto out;
3c824109 3475 case OPC_BLTZALS:
eeef26cd 3476 case OPC_BLTZAL: /* 0 < 0 */
3c824109
NF
3477 ctx->hflags |= (opc == OPC_BLTZALS
3478 ? MIPS_HFLAG_BDS16
3479 : MIPS_HFLAG_BDS32);
3480 /* Handle as an unconditional branch to get correct delay
3481 slot checking. */
3482 blink = 31;
3483 btgt = ctx->pc + (opc == OPC_BLTZALS ? 6 : 8);
3484 ctx->hflags |= MIPS_HFLAG_B;
9898128f 3485 MIPS_DEBUG("bnever and link");
3c824109 3486 break;
eeef26cd 3487 case OPC_BLTZALL: /* 0 < 0 likely */
1ba74fb8 3488 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
9898128f
TS
3489 /* Skip the instruction in the delay slot */
3490 MIPS_DEBUG("bnever, link and skip");
3491 ctx->pc += 4;
6c5c1e20 3492 goto out;
6af0bf9c
FB
3493 case OPC_BNEL: /* rx != rx likely */
3494 case OPC_BGTZL: /* 0 > 0 likely */
6af0bf9c
FB
3495 case OPC_BLTZL: /* 0 < 0 likely */
3496 /* Skip the instruction in the delay slot */
3497 MIPS_DEBUG("bnever and skip");
9898128f 3498 ctx->pc += 4;
6c5c1e20 3499 goto out;
6af0bf9c 3500 case OPC_J:
4ad40f36 3501 ctx->hflags |= MIPS_HFLAG_B;
d077b6f7 3502 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
6af0bf9c 3503 break;
620e48f6 3504 case OPC_JALXS:
364d4831
NF
3505 case OPC_JALX:
3506 ctx->hflags |= MIPS_HFLAG_BX;
3507 /* Fallthrough */
620e48f6 3508 case OPC_JALS:
6af0bf9c
FB
3509 case OPC_JAL:
3510 blink = 31;
4ad40f36 3511 ctx->hflags |= MIPS_HFLAG_B;
620e48f6 3512 ctx->hflags |= ((opc == OPC_JALS || opc == OPC_JALXS)
364d4831
NF
3513 ? MIPS_HFLAG_BDS16
3514 : MIPS_HFLAG_BDS32);
d077b6f7 3515 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
6af0bf9c
FB
3516 break;
3517 case OPC_JR:
4ad40f36 3518 ctx->hflags |= MIPS_HFLAG_BR;
620e48f6
NF
3519 if (insn_bytes == 4)
3520 ctx->hflags |= MIPS_HFLAG_BDS32;
6af0bf9c
FB
3521 MIPS_DEBUG("jr %s", regnames[rs]);
3522 break;
620e48f6 3523 case OPC_JALRS:
6af0bf9c 3524 case OPC_JALR:
364d4831 3525 case OPC_JALRC:
6af0bf9c 3526 blink = rt;
4ad40f36 3527 ctx->hflags |= MIPS_HFLAG_BR;
620e48f6
NF
3528 ctx->hflags |= (opc == OPC_JALRS
3529 ? MIPS_HFLAG_BDS16
3530 : MIPS_HFLAG_BDS32);
6af0bf9c
FB
3531 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
3532 break;
3533 default:
3534 MIPS_INVAL("branch/jump");
3535 generate_exception(ctx, EXCP_RI);
6c5c1e20 3536 goto out;
6af0bf9c
FB
3537 }
3538 } else {
3539 switch (opc) {
3540 case OPC_BEQ:
e68dd28f 3541 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
923617a3 3542 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
d077b6f7 3543 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
3544 goto not_likely;
3545 case OPC_BEQL:
e68dd28f 3546 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
923617a3 3547 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
d077b6f7 3548 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
3549 goto likely;
3550 case OPC_BNE:
e68dd28f 3551 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
923617a3 3552 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
d077b6f7 3553 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
3554 goto not_likely;
3555 case OPC_BNEL:
e68dd28f 3556 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
923617a3 3557 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
d077b6f7 3558 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
3559 goto likely;
3560 case OPC_BGEZ:
e68dd28f 3561 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
d077b6f7 3562 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
3563 goto not_likely;
3564 case OPC_BGEZL:
e68dd28f 3565 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
d077b6f7 3566 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 3567 goto likely;
3c824109 3568 case OPC_BGEZALS:
6af0bf9c 3569 case OPC_BGEZAL:
3c824109
NF
3570 ctx->hflags |= (opc == OPC_BGEZALS
3571 ? MIPS_HFLAG_BDS16
3572 : MIPS_HFLAG_BDS32);
e68dd28f 3573 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
d077b6f7 3574 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
3575 blink = 31;
3576 goto not_likely;
3577 case OPC_BGEZALL:
e68dd28f 3578 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c 3579 blink = 31;
d077b6f7 3580 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
3581 goto likely;
3582 case OPC_BGTZ:
e68dd28f 3583 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
d077b6f7 3584 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
3585 goto not_likely;
3586 case OPC_BGTZL:
e68dd28f 3587 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
d077b6f7 3588 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
3589 goto likely;
3590 case OPC_BLEZ:
e68dd28f 3591 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
d077b6f7 3592 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
3593 goto not_likely;
3594 case OPC_BLEZL:
e68dd28f 3595 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
d077b6f7 3596 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
3597 goto likely;
3598 case OPC_BLTZ:
e68dd28f 3599 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
d077b6f7 3600 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
3601 goto not_likely;
3602 case OPC_BLTZL:
e68dd28f 3603 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
d077b6f7 3604 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 3605 goto likely;
e45a93e2
JL
3606 case OPC_BPOSGE32:
3607 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
3608 MIPS_DEBUG("bposge32 " TARGET_FMT_lx, btgt);
3609 goto not_likely;
3610#if defined(TARGET_MIPS64)
3611 case OPC_BPOSGE64:
3612 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
3613 MIPS_DEBUG("bposge64 " TARGET_FMT_lx, btgt);
3614 goto not_likely;
3615#endif
3c824109 3616 case OPC_BLTZALS:
6af0bf9c 3617 case OPC_BLTZAL:
3c824109
NF
3618 ctx->hflags |= (opc == OPC_BLTZALS
3619 ? MIPS_HFLAG_BDS16
3620 : MIPS_HFLAG_BDS32);
e68dd28f 3621 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 3622 blink = 31;
d077b6f7 3623 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 3624 not_likely:
4ad40f36 3625 ctx->hflags |= MIPS_HFLAG_BC;
6af0bf9c
FB
3626 break;
3627 case OPC_BLTZALL:
e68dd28f 3628 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 3629 blink = 31;
d077b6f7 3630 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 3631 likely:
4ad40f36 3632 ctx->hflags |= MIPS_HFLAG_BL;
6af0bf9c 3633 break;
c53f4a62
TS
3634 default:
3635 MIPS_INVAL("conditional branch/jump");
3636 generate_exception(ctx, EXCP_RI);
6c5c1e20 3637 goto out;
6af0bf9c 3638 }
6af0bf9c 3639 }
923617a3 3640 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
d077b6f7 3641 blink, ctx->hflags, btgt);
9b9e4393 3642
d077b6f7 3643 ctx->btarget = btgt;
6af0bf9c 3644 if (blink > 0) {
364d4831
NF
3645 int post_delay = insn_bytes;
3646 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
3647
3648 if (opc != OPC_JALRC)
3649 post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4);
3650
3651 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
6af0bf9c 3652 }
6c5c1e20
TS
3653
3654 out:
364d4831
NF
3655 if (insn_bytes == 2)
3656 ctx->hflags |= MIPS_HFLAG_B16;
6c5c1e20
TS
3657 tcg_temp_free(t0);
3658 tcg_temp_free(t1);
6af0bf9c
FB
3659}
3660
7a387fff
TS
3661/* special3 bitfield operations */
3662static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
356265ae 3663 int rs, int lsb, int msb)
7a387fff 3664{
a7812ae4
PB
3665 TCGv t0 = tcg_temp_new();
3666 TCGv t1 = tcg_temp_new();
505ad7c2 3667 target_ulong mask;
6c5c1e20
TS
3668
3669 gen_load_gpr(t1, rs);
7a387fff
TS
3670 switch (opc) {
3671 case OPC_EXT:
3672 if (lsb + msb > 31)
3673 goto fail;
505ad7c2
AJ
3674 tcg_gen_shri_tl(t0, t1, lsb);
3675 if (msb != 31) {
3676 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
3677 } else {
3678 tcg_gen_ext32s_tl(t0, t0);
3679 }
7a387fff 3680 break;
c6d6dd7c 3681#if defined(TARGET_MIPS64)
7a387fff 3682 case OPC_DEXTM:
505ad7c2
AJ
3683 tcg_gen_shri_tl(t0, t1, lsb);
3684 if (msb != 31) {
3685 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
3686 }
7a387fff
TS
3687 break;
3688 case OPC_DEXTU:
505ad7c2
AJ
3689 tcg_gen_shri_tl(t0, t1, lsb + 32);
3690 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
7a387fff
TS
3691 break;
3692 case OPC_DEXT:
505ad7c2
AJ
3693 tcg_gen_shri_tl(t0, t1, lsb);
3694 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
7a387fff 3695 break;
c6d6dd7c 3696#endif
7a387fff
TS
3697 case OPC_INS:
3698 if (lsb > msb)
3699 goto fail;
505ad7c2 3700 mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
6c5c1e20 3701 gen_load_gpr(t0, rt);
505ad7c2
AJ
3702 tcg_gen_andi_tl(t0, t0, ~mask);
3703 tcg_gen_shli_tl(t1, t1, lsb);
3704 tcg_gen_andi_tl(t1, t1, mask);
3705 tcg_gen_or_tl(t0, t0, t1);
3706 tcg_gen_ext32s_tl(t0, t0);
7a387fff 3707 break;
c6d6dd7c 3708#if defined(TARGET_MIPS64)
7a387fff
TS
3709 case OPC_DINSM:
3710 if (lsb > msb)
3711 goto fail;
505ad7c2 3712 mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
6c5c1e20 3713 gen_load_gpr(t0, rt);
505ad7c2
AJ
3714 tcg_gen_andi_tl(t0, t0, ~mask);
3715 tcg_gen_shli_tl(t1, t1, lsb);
3716 tcg_gen_andi_tl(t1, t1, mask);
3717 tcg_gen_or_tl(t0, t0, t1);
7a387fff
TS
3718 break;
3719 case OPC_DINSU:
3720 if (lsb > msb)
3721 goto fail;
6fbab869 3722 mask = ((1ULL << (msb - lsb + 1)) - 1) << (lsb + 32);
6c5c1e20 3723 gen_load_gpr(t0, rt);
505ad7c2
AJ
3724 tcg_gen_andi_tl(t0, t0, ~mask);
3725 tcg_gen_shli_tl(t1, t1, lsb + 32);
3726 tcg_gen_andi_tl(t1, t1, mask);
3727 tcg_gen_or_tl(t0, t0, t1);
7a387fff
TS
3728 break;
3729 case OPC_DINS:
3730 if (lsb > msb)
3731 goto fail;
6c5c1e20 3732 gen_load_gpr(t0, rt);
505ad7c2
AJ
3733 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
3734 gen_load_gpr(t0, rt);
3735 tcg_gen_andi_tl(t0, t0, ~mask);
3736 tcg_gen_shli_tl(t1, t1, lsb);
3737 tcg_gen_andi_tl(t1, t1, mask);
3738 tcg_gen_or_tl(t0, t0, t1);
7a387fff 3739 break;
c6d6dd7c 3740#endif
7a387fff
TS
3741 default:
3742fail:
3743 MIPS_INVAL("bitops");
3744 generate_exception(ctx, EXCP_RI);
6c5c1e20
TS
3745 tcg_temp_free(t0);
3746 tcg_temp_free(t1);
7a387fff
TS
3747 return;
3748 }
6c5c1e20
TS
3749 gen_store_gpr(t0, rt);
3750 tcg_temp_free(t0);
3751 tcg_temp_free(t1);
7a387fff
TS
3752}
3753
49bcf33c
AJ
3754static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
3755{
3a55fa47 3756 TCGv t0;
49bcf33c 3757
3a55fa47
AJ
3758 if (rd == 0) {
3759 /* If no destination, treat it as a NOP. */
3760 MIPS_DEBUG("NOP");
3761 return;
3762 }
3763
3764 t0 = tcg_temp_new();
3765 gen_load_gpr(t0, rt);
49bcf33c
AJ
3766 switch (op2) {
3767 case OPC_WSBH:
3a55fa47
AJ
3768 {
3769 TCGv t1 = tcg_temp_new();
3770
3771 tcg_gen_shri_tl(t1, t0, 8);
3772 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
3773 tcg_gen_shli_tl(t0, t0, 8);
3774 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
3775 tcg_gen_or_tl(t0, t0, t1);
3776 tcg_temp_free(t1);
3777 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3778 }
49bcf33c
AJ
3779 break;
3780 case OPC_SEB:
3a55fa47 3781 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
3782 break;
3783 case OPC_SEH:
3a55fa47 3784 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
3785 break;
3786#if defined(TARGET_MIPS64)
3787 case OPC_DSBH:
3a55fa47
AJ
3788 {
3789 TCGv t1 = tcg_temp_new();
3790
3791 tcg_gen_shri_tl(t1, t0, 8);
3792 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
3793 tcg_gen_shli_tl(t0, t0, 8);
3794 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
3795 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3796 tcg_temp_free(t1);
3797 }
49bcf33c
AJ
3798 break;
3799 case OPC_DSHD:
3a55fa47
AJ
3800 {
3801 TCGv t1 = tcg_temp_new();
3802
3803 tcg_gen_shri_tl(t1, t0, 16);
3804 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
3805 tcg_gen_shli_tl(t0, t0, 16);
3806 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
3807 tcg_gen_or_tl(t0, t0, t1);
3808 tcg_gen_shri_tl(t1, t0, 32);
3809 tcg_gen_shli_tl(t0, t0, 32);
3810 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3811 tcg_temp_free(t1);
3812 }
49bcf33c
AJ
3813 break;
3814#endif
3815 default:
3816 MIPS_INVAL("bsfhl");
3817 generate_exception(ctx, EXCP_RI);
3818 tcg_temp_free(t0);
49bcf33c
AJ
3819 return;
3820 }
49bcf33c 3821 tcg_temp_free(t0);
49bcf33c
AJ
3822}
3823
f1aa6320 3824#ifndef CONFIG_USER_ONLY
0eaef5aa 3825/* CP0 (MMU and control) */
d9bea114 3826static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
4f57689a 3827{
d9bea114 3828 TCGv_i32 t0 = tcg_temp_new_i32();
4f57689a 3829
d9bea114
AJ
3830 tcg_gen_ld_i32(t0, cpu_env, off);
3831 tcg_gen_ext_i32_tl(arg, t0);
3832 tcg_temp_free_i32(t0);
4f57689a
TS
3833}
3834
d9bea114 3835static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
4f57689a 3836{
d9bea114
AJ
3837 tcg_gen_ld_tl(arg, cpu_env, off);
3838 tcg_gen_ext32s_tl(arg, arg);
4f57689a
TS
3839}
3840
d9bea114 3841static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
f1aa6320 3842{
d9bea114 3843 TCGv_i32 t0 = tcg_temp_new_i32();
f1aa6320 3844
d9bea114
AJ
3845 tcg_gen_trunc_tl_i32(t0, arg);
3846 tcg_gen_st_i32(t0, cpu_env, off);
3847 tcg_temp_free_i32(t0);
f1aa6320
TS
3848}
3849
d9bea114 3850static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
f1aa6320 3851{
d9bea114
AJ
3852 tcg_gen_ext32s_tl(arg, arg);
3853 tcg_gen_st_tl(arg, cpu_env, off);
f1aa6320
TS
3854}
3855
7db13fae 3856static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
873eb012 3857{
7a387fff 3858 const char *rn = "invalid";
873eb012 3859
e189e748
TS
3860 if (sel != 0)
3861 check_insn(env, ctx, ISA_MIPS32);
3862
873eb012
TS
3863 switch (reg) {
3864 case 0:
7a387fff
TS
3865 switch (sel) {
3866 case 0:
7db13fae 3867 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7a387fff
TS
3868 rn = "Index";
3869 break;
3870 case 1:
7385ac0b 3871 check_insn(env, ctx, ASE_MT);
895c2d04 3872 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7a387fff 3873 rn = "MVPControl";
ead9360e 3874 break;
7a387fff 3875 case 2:
7385ac0b 3876 check_insn(env, ctx, ASE_MT);
895c2d04 3877 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7a387fff 3878 rn = "MVPConf0";
ead9360e 3879 break;
7a387fff 3880 case 3:
7385ac0b 3881 check_insn(env, ctx, ASE_MT);
895c2d04 3882 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7a387fff 3883 rn = "MVPConf1";
ead9360e 3884 break;
7a387fff
TS
3885 default:
3886 goto die;
3887 }
873eb012
TS
3888 break;
3889 case 1:
7a387fff
TS
3890 switch (sel) {
3891 case 0:
895c2d04 3892 gen_helper_mfc0_random(arg, cpu_env);
7a387fff 3893 rn = "Random";
2423f660 3894 break;
7a387fff 3895 case 1:
7385ac0b 3896 check_insn(env, ctx, ASE_MT);
7db13fae 3897 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7a387fff 3898 rn = "VPEControl";
ead9360e 3899 break;
7a387fff 3900 case 2:
7385ac0b 3901 check_insn(env, ctx, ASE_MT);
7db13fae 3902 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7a387fff 3903 rn = "VPEConf0";
ead9360e 3904 break;
7a387fff 3905 case 3:
7385ac0b 3906 check_insn(env, ctx, ASE_MT);
7db13fae 3907 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7a387fff 3908 rn = "VPEConf1";
ead9360e 3909 break;
7a387fff 3910 case 4:
7385ac0b 3911 check_insn(env, ctx, ASE_MT);
7db13fae 3912 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
7a387fff 3913 rn = "YQMask";
ead9360e 3914 break;
7a387fff 3915 case 5:
7385ac0b 3916 check_insn(env, ctx, ASE_MT);
7db13fae 3917 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
7a387fff 3918 rn = "VPESchedule";
ead9360e 3919 break;
7a387fff 3920 case 6:
7385ac0b 3921 check_insn(env, ctx, ASE_MT);
7db13fae 3922 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7a387fff 3923 rn = "VPEScheFBack";
ead9360e 3924 break;
7a387fff 3925 case 7:
7385ac0b 3926 check_insn(env, ctx, ASE_MT);
7db13fae 3927 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7a387fff 3928 rn = "VPEOpt";
ead9360e 3929 break;
7a387fff
TS
3930 default:
3931 goto die;
3932 }
873eb012
TS
3933 break;
3934 case 2:
7a387fff
TS
3935 switch (sel) {
3936 case 0:
7db13fae 3937 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
d9bea114 3938 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3939 rn = "EntryLo0";
3940 break;
7a387fff 3941 case 1:
7385ac0b 3942 check_insn(env, ctx, ASE_MT);
895c2d04 3943 gen_helper_mfc0_tcstatus(arg, cpu_env);
2423f660 3944 rn = "TCStatus";
ead9360e 3945 break;
7a387fff 3946 case 2:
7385ac0b 3947 check_insn(env, ctx, ASE_MT);
895c2d04 3948 gen_helper_mfc0_tcbind(arg, cpu_env);
2423f660 3949 rn = "TCBind";
ead9360e 3950 break;
7a387fff 3951 case 3:
7385ac0b 3952 check_insn(env, ctx, ASE_MT);
895c2d04 3953 gen_helper_mfc0_tcrestart(arg, cpu_env);
2423f660 3954 rn = "TCRestart";
ead9360e 3955 break;
7a387fff 3956 case 4:
7385ac0b 3957 check_insn(env, ctx, ASE_MT);
895c2d04 3958 gen_helper_mfc0_tchalt(arg, cpu_env);
2423f660 3959 rn = "TCHalt";
ead9360e 3960 break;
7a387fff 3961 case 5:
7385ac0b 3962 check_insn(env, ctx, ASE_MT);
895c2d04 3963 gen_helper_mfc0_tccontext(arg, cpu_env);
2423f660 3964 rn = "TCContext";
ead9360e 3965 break;
7a387fff 3966 case 6:
7385ac0b 3967 check_insn(env, ctx, ASE_MT);
895c2d04 3968 gen_helper_mfc0_tcschedule(arg, cpu_env);
2423f660 3969 rn = "TCSchedule";
ead9360e 3970 break;
7a387fff 3971 case 7:
7385ac0b 3972 check_insn(env, ctx, ASE_MT);
895c2d04 3973 gen_helper_mfc0_tcschefback(arg, cpu_env);
2423f660 3974 rn = "TCScheFBack";
ead9360e 3975 break;
7a387fff
TS
3976 default:
3977 goto die;
3978 }
873eb012
TS
3979 break;
3980 case 3:
7a387fff
TS
3981 switch (sel) {
3982 case 0:
7db13fae 3983 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
d9bea114 3984 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3985 rn = "EntryLo1";
3986 break;
7a387fff
TS
3987 default:
3988 goto die;
1579a72e 3989 }
873eb012
TS
3990 break;
3991 case 4:
7a387fff
TS
3992 switch (sel) {
3993 case 0:
7db13fae 3994 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
d9bea114 3995 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3996 rn = "Context";
3997 break;
7a387fff 3998 case 1:
d9bea114 3999// gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
2423f660
TS
4000 rn = "ContextConfig";
4001// break;
7a387fff
TS
4002 default:
4003 goto die;
1579a72e 4004 }
873eb012
TS
4005 break;
4006 case 5:
7a387fff
TS
4007 switch (sel) {
4008 case 0:
7db13fae 4009 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
2423f660
TS
4010 rn = "PageMask";
4011 break;
7a387fff 4012 case 1:
e189e748 4013 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4014 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
2423f660
TS
4015 rn = "PageGrain";
4016 break;
7a387fff
TS
4017 default:
4018 goto die;
1579a72e 4019 }
873eb012
TS
4020 break;
4021 case 6:
7a387fff
TS
4022 switch (sel) {
4023 case 0:
7db13fae 4024 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
2423f660
TS
4025 rn = "Wired";
4026 break;
7a387fff 4027 case 1:
e189e748 4028 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4029 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
2423f660 4030 rn = "SRSConf0";
ead9360e 4031 break;
7a387fff 4032 case 2:
e189e748 4033 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4034 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
2423f660 4035 rn = "SRSConf1";
ead9360e 4036 break;
7a387fff 4037 case 3:
e189e748 4038 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4039 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
2423f660 4040 rn = "SRSConf2";
ead9360e 4041 break;
7a387fff 4042 case 4:
e189e748 4043 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4044 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
2423f660 4045 rn = "SRSConf3";
ead9360e 4046 break;
7a387fff 4047 case 5:
e189e748 4048 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4049 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
2423f660 4050 rn = "SRSConf4";
ead9360e 4051 break;
7a387fff
TS
4052 default:
4053 goto die;
1579a72e 4054 }
873eb012 4055 break;
8c0fdd85 4056 case 7:
7a387fff
TS
4057 switch (sel) {
4058 case 0:
e189e748 4059 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4060 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
2423f660
TS
4061 rn = "HWREna";
4062 break;
7a387fff
TS
4063 default:
4064 goto die;
1579a72e 4065 }
8c0fdd85 4066 break;
873eb012 4067 case 8:
7a387fff
TS
4068 switch (sel) {
4069 case 0:
7db13fae 4070 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
d9bea114 4071 tcg_gen_ext32s_tl(arg, arg);
f0b3f3ae 4072 rn = "BadVAddr";
2423f660 4073 break;
7a387fff
TS
4074 default:
4075 goto die;
4076 }
873eb012
TS
4077 break;
4078 case 9:
7a387fff
TS
4079 switch (sel) {
4080 case 0:
2e70f6ef
PB
4081 /* Mark as an IO operation because we read the time. */
4082 if (use_icount)
4083 gen_io_start();
895c2d04 4084 gen_helper_mfc0_count(arg, cpu_env);
2e70f6ef
PB
4085 if (use_icount) {
4086 gen_io_end();
2e70f6ef 4087 }
55807224
EI
4088 /* Break the TB to be able to take timer interrupts immediately
4089 after reading count. */
4090 ctx->bstate = BS_STOP;
2423f660
TS
4091 rn = "Count";
4092 break;
4093 /* 6,7 are implementation dependent */
7a387fff
TS
4094 default:
4095 goto die;
2423f660 4096 }
873eb012
TS
4097 break;
4098 case 10:
7a387fff
TS
4099 switch (sel) {
4100 case 0:
7db13fae 4101 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
d9bea114 4102 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
4103 rn = "EntryHi";
4104 break;
7a387fff
TS
4105 default:
4106 goto die;
1579a72e 4107 }
873eb012
TS
4108 break;
4109 case 11:
7a387fff
TS
4110 switch (sel) {
4111 case 0:
7db13fae 4112 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
2423f660
TS
4113 rn = "Compare";
4114 break;
4115 /* 6,7 are implementation dependent */
7a387fff
TS
4116 default:
4117 goto die;
2423f660 4118 }
873eb012
TS
4119 break;
4120 case 12:
7a387fff
TS
4121 switch (sel) {
4122 case 0:
7db13fae 4123 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
2423f660
TS
4124 rn = "Status";
4125 break;
7a387fff 4126 case 1:
e189e748 4127 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4128 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
2423f660
TS
4129 rn = "IntCtl";
4130 break;
7a387fff 4131 case 2:
e189e748 4132 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4133 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
2423f660
TS
4134 rn = "SRSCtl";
4135 break;
7a387fff 4136 case 3:
e189e748 4137 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4138 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
2423f660 4139 rn = "SRSMap";
fd88b6ab 4140 break;
7a387fff
TS
4141 default:
4142 goto die;
4143 }
873eb012
TS
4144 break;
4145 case 13:
7a387fff
TS
4146 switch (sel) {
4147 case 0:
7db13fae 4148 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
2423f660
TS
4149 rn = "Cause";
4150 break;
7a387fff
TS
4151 default:
4152 goto die;
4153 }
873eb012
TS
4154 break;
4155 case 14:
7a387fff
TS
4156 switch (sel) {
4157 case 0:
7db13fae 4158 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
d9bea114 4159 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
4160 rn = "EPC";
4161 break;
7a387fff
TS
4162 default:
4163 goto die;
1579a72e 4164 }
873eb012
TS
4165 break;
4166 case 15:
7a387fff
TS
4167 switch (sel) {
4168 case 0:
7db13fae 4169 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
2423f660
TS
4170 rn = "PRid";
4171 break;
7a387fff 4172 case 1:
e189e748 4173 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4174 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
2423f660
TS
4175 rn = "EBase";
4176 break;
7a387fff
TS
4177 default:
4178 goto die;
4179 }
873eb012
TS
4180 break;
4181 case 16:
4182 switch (sel) {
4183 case 0:
7db13fae 4184 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
873eb012
TS
4185 rn = "Config";
4186 break;
4187 case 1:
7db13fae 4188 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
873eb012
TS
4189 rn = "Config1";
4190 break;
7a387fff 4191 case 2:
7db13fae 4192 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7a387fff
TS
4193 rn = "Config2";
4194 break;
4195 case 3:
7db13fae 4196 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7a387fff
TS
4197 rn = "Config3";
4198 break;
e397ee33
TS
4199 /* 4,5 are reserved */
4200 /* 6,7 are implementation dependent */
4201 case 6:
7db13fae 4202 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
e397ee33
TS
4203 rn = "Config6";
4204 break;
4205 case 7:
7db13fae 4206 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
e397ee33
TS
4207 rn = "Config7";
4208 break;
873eb012 4209 default:
873eb012
TS
4210 goto die;
4211 }
4212 break;
4213 case 17:
7a387fff
TS
4214 switch (sel) {
4215 case 0:
895c2d04 4216 gen_helper_mfc0_lladdr(arg, cpu_env);
2423f660
TS
4217 rn = "LLAddr";
4218 break;
7a387fff
TS
4219 default:
4220 goto die;
4221 }
873eb012
TS
4222 break;
4223 case 18:
7a387fff 4224 switch (sel) {
fd88b6ab 4225 case 0 ... 7:
895c2d04 4226 gen_helper_1e0i(mfc0_watchlo, arg, sel);
2423f660
TS
4227 rn = "WatchLo";
4228 break;
7a387fff
TS
4229 default:
4230 goto die;
4231 }
873eb012
TS
4232 break;
4233 case 19:
7a387fff 4234 switch (sel) {
fd88b6ab 4235 case 0 ...7:
895c2d04 4236 gen_helper_1e0i(mfc0_watchhi, arg, sel);
2423f660
TS
4237 rn = "WatchHi";
4238 break;
7a387fff
TS
4239 default:
4240 goto die;
4241 }
873eb012 4242 break;
8c0fdd85 4243 case 20:
7a387fff
TS
4244 switch (sel) {
4245 case 0:
d26bc211 4246#if defined(TARGET_MIPS64)
e189e748 4247 check_insn(env, ctx, ISA_MIPS3);
7db13fae 4248 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
d9bea114 4249 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
4250 rn = "XContext";
4251 break;
703eaf37 4252#endif
7a387fff
TS
4253 default:
4254 goto die;
4255 }
8c0fdd85
TS
4256 break;
4257 case 21:
7a387fff
TS
4258 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4259 switch (sel) {
4260 case 0:
7db13fae 4261 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
2423f660
TS
4262 rn = "Framemask";
4263 break;
7a387fff
TS
4264 default:
4265 goto die;
4266 }
8c0fdd85
TS
4267 break;
4268 case 22:
d9bea114 4269 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
4270 rn = "'Diagnostic"; /* implementation dependent */
4271 break;
873eb012 4272 case 23:
7a387fff
TS
4273 switch (sel) {
4274 case 0:
895c2d04 4275 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
2423f660
TS
4276 rn = "Debug";
4277 break;
7a387fff 4278 case 1:
d9bea114 4279// gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
2423f660
TS
4280 rn = "TraceControl";
4281// break;
7a387fff 4282 case 2:
d9bea114 4283// gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
2423f660
TS
4284 rn = "TraceControl2";
4285// break;
7a387fff 4286 case 3:
d9bea114 4287// gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
2423f660
TS
4288 rn = "UserTraceData";
4289// break;
7a387fff 4290 case 4:
d9bea114 4291// gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
2423f660
TS
4292 rn = "TraceBPC";
4293// break;
7a387fff
TS
4294 default:
4295 goto die;
4296 }
873eb012
TS
4297 break;
4298 case 24:
7a387fff
TS
4299 switch (sel) {
4300 case 0:
f0b3f3ae 4301 /* EJTAG support */
7db13fae 4302 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
d9bea114 4303 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
4304 rn = "DEPC";
4305 break;
7a387fff
TS
4306 default:
4307 goto die;
4308 }
873eb012 4309 break;
8c0fdd85 4310 case 25:
7a387fff
TS
4311 switch (sel) {
4312 case 0:
7db13fae 4313 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
2423f660 4314 rn = "Performance0";
7a387fff
TS
4315 break;
4316 case 1:
d9bea114 4317// gen_helper_mfc0_performance1(arg);
2423f660
TS
4318 rn = "Performance1";
4319// break;
7a387fff 4320 case 2:
d9bea114 4321// gen_helper_mfc0_performance2(arg);
2423f660
TS
4322 rn = "Performance2";
4323// break;
7a387fff 4324 case 3:
d9bea114 4325// gen_helper_mfc0_performance3(arg);
2423f660
TS
4326 rn = "Performance3";
4327// break;
7a387fff 4328 case 4:
d9bea114 4329// gen_helper_mfc0_performance4(arg);
2423f660
TS
4330 rn = "Performance4";
4331// break;
7a387fff 4332 case 5:
d9bea114 4333// gen_helper_mfc0_performance5(arg);
2423f660
TS
4334 rn = "Performance5";
4335// break;
7a387fff 4336 case 6:
d9bea114 4337// gen_helper_mfc0_performance6(arg);
2423f660
TS
4338 rn = "Performance6";
4339// break;
7a387fff 4340 case 7:
d9bea114 4341// gen_helper_mfc0_performance7(arg);
2423f660
TS
4342 rn = "Performance7";
4343// break;
7a387fff
TS
4344 default:
4345 goto die;
4346 }
8c0fdd85
TS
4347 break;
4348 case 26:
d9bea114 4349 tcg_gen_movi_tl(arg, 0); /* unimplemented */
da80682b
AJ
4350 rn = "ECC";
4351 break;
8c0fdd85 4352 case 27:
7a387fff 4353 switch (sel) {
7a387fff 4354 case 0 ... 3:
d9bea114 4355 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
4356 rn = "CacheErr";
4357 break;
7a387fff
TS
4358 default:
4359 goto die;
4360 }
8c0fdd85 4361 break;
873eb012
TS
4362 case 28:
4363 switch (sel) {
4364 case 0:
7a387fff
TS
4365 case 2:
4366 case 4:
4367 case 6:
7db13fae 4368 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
873eb012
TS
4369 rn = "TagLo";
4370 break;
4371 case 1:
7a387fff
TS
4372 case 3:
4373 case 5:
4374 case 7:
7db13fae 4375 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
873eb012
TS
4376 rn = "DataLo";
4377 break;
4378 default:
873eb012
TS
4379 goto die;
4380 }
4381 break;
8c0fdd85 4382 case 29:
7a387fff
TS
4383 switch (sel) {
4384 case 0:
4385 case 2:
4386 case 4:
4387 case 6:
7db13fae 4388 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7a387fff
TS
4389 rn = "TagHi";
4390 break;
4391 case 1:
4392 case 3:
4393 case 5:
4394 case 7:
7db13fae 4395 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7a387fff
TS
4396 rn = "DataHi";
4397 break;
4398 default:
4399 goto die;
4400 }
8c0fdd85 4401 break;
873eb012 4402 case 30:
7a387fff
TS
4403 switch (sel) {
4404 case 0:
7db13fae 4405 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
d9bea114 4406 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
4407 rn = "ErrorEPC";
4408 break;
7a387fff
TS
4409 default:
4410 goto die;
4411 }
873eb012
TS
4412 break;
4413 case 31:
7a387fff
TS
4414 switch (sel) {
4415 case 0:
f0b3f3ae 4416 /* EJTAG support */
7db13fae 4417 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
4418 rn = "DESAVE";
4419 break;
7a387fff
TS
4420 default:
4421 goto die;
4422 }
873eb012
TS
4423 break;
4424 default:
873eb012
TS
4425 goto die;
4426 }
2abf314d 4427 (void)rn; /* avoid a compiler warning */
d12d51d5 4428 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
873eb012
TS
4429 return;
4430
4431die:
d12d51d5 4432 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
873eb012
TS
4433 generate_exception(ctx, EXCP_RI);
4434}
4435
7db13fae 4436static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
8c0fdd85 4437{
7a387fff
TS
4438 const char *rn = "invalid";
4439
e189e748
TS
4440 if (sel != 0)
4441 check_insn(env, ctx, ISA_MIPS32);
4442
2e70f6ef
PB
4443 if (use_icount)
4444 gen_io_start();
4445
8c0fdd85
TS
4446 switch (reg) {
4447 case 0:
7a387fff
TS
4448 switch (sel) {
4449 case 0:
895c2d04 4450 gen_helper_mtc0_index(cpu_env, arg);
7a387fff
TS
4451 rn = "Index";
4452 break;
4453 case 1:
7385ac0b 4454 check_insn(env, ctx, ASE_MT);
895c2d04 4455 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7a387fff 4456 rn = "MVPControl";
ead9360e 4457 break;
7a387fff 4458 case 2:
7385ac0b 4459 check_insn(env, ctx, ASE_MT);
ead9360e 4460 /* ignored */
7a387fff 4461 rn = "MVPConf0";
ead9360e 4462 break;
7a387fff 4463 case 3:
7385ac0b 4464 check_insn(env, ctx, ASE_MT);
ead9360e 4465 /* ignored */
7a387fff 4466 rn = "MVPConf1";
ead9360e 4467 break;
7a387fff
TS
4468 default:
4469 goto die;
4470 }
8c0fdd85
TS
4471 break;
4472 case 1:
7a387fff
TS
4473 switch (sel) {
4474 case 0:
2423f660 4475 /* ignored */
7a387fff 4476 rn = "Random";
2423f660 4477 break;
7a387fff 4478 case 1:
7385ac0b 4479 check_insn(env, ctx, ASE_MT);
895c2d04 4480 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7a387fff 4481 rn = "VPEControl";
ead9360e 4482 break;
7a387fff 4483 case 2:
7385ac0b 4484 check_insn(env, ctx, ASE_MT);
895c2d04 4485 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7a387fff 4486 rn = "VPEConf0";
ead9360e 4487 break;
7a387fff 4488 case 3:
7385ac0b 4489 check_insn(env, ctx, ASE_MT);
895c2d04 4490 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7a387fff 4491 rn = "VPEConf1";
ead9360e 4492 break;
7a387fff 4493 case 4:
7385ac0b 4494 check_insn(env, ctx, ASE_MT);
895c2d04 4495 gen_helper_mtc0_yqmask(cpu_env, arg);
7a387fff 4496 rn = "YQMask";
ead9360e 4497 break;
7a387fff 4498 case 5:
7385ac0b 4499 check_insn(env, ctx, ASE_MT);
7db13fae 4500 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
7a387fff 4501 rn = "VPESchedule";
ead9360e 4502 break;
7a387fff 4503 case 6:
7385ac0b 4504 check_insn(env, ctx, ASE_MT);
7db13fae 4505 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7a387fff 4506 rn = "VPEScheFBack";
ead9360e 4507 break;
7a387fff 4508 case 7:
7385ac0b 4509 check_insn(env, ctx, ASE_MT);
895c2d04 4510 gen_helper_mtc0_vpeopt(cpu_env, arg);
7a387fff 4511 rn = "VPEOpt";
ead9360e 4512 break;
7a387fff
TS
4513 default:
4514 goto die;
4515 }
8c0fdd85
TS
4516 break;
4517 case 2:
7a387fff
TS
4518 switch (sel) {
4519 case 0:
895c2d04 4520 gen_helper_mtc0_entrylo0(cpu_env, arg);
2423f660
TS
4521 rn = "EntryLo0";
4522 break;
7a387fff 4523 case 1:
7385ac0b 4524 check_insn(env, ctx, ASE_MT);
895c2d04 4525 gen_helper_mtc0_tcstatus(cpu_env, arg);
2423f660 4526 rn = "TCStatus";
ead9360e 4527 break;
7a387fff 4528 case 2:
7385ac0b 4529 check_insn(env, ctx, ASE_MT);
895c2d04 4530 gen_helper_mtc0_tcbind(cpu_env, arg);
2423f660 4531 rn = "TCBind";
ead9360e 4532 break;
7a387fff 4533 case 3:
7385ac0b 4534 check_insn(env, ctx, ASE_MT);
895c2d04 4535 gen_helper_mtc0_tcrestart(cpu_env, arg);
2423f660 4536 rn = "TCRestart";
ead9360e 4537 break;
7a387fff 4538 case 4:
7385ac0b 4539 check_insn(env, ctx, ASE_MT);
895c2d04 4540 gen_helper_mtc0_tchalt(cpu_env, arg);
2423f660 4541 rn = "TCHalt";
ead9360e 4542 break;
7a387fff 4543 case 5:
7385ac0b 4544 check_insn(env, ctx, ASE_MT);
895c2d04 4545 gen_helper_mtc0_tccontext(cpu_env, arg);
2423f660 4546 rn = "TCContext";
ead9360e 4547 break;
7a387fff 4548 case 6:
7385ac0b 4549 check_insn(env, ctx, ASE_MT);
895c2d04 4550 gen_helper_mtc0_tcschedule(cpu_env, arg);
2423f660 4551 rn = "TCSchedule";
ead9360e 4552 break;
7a387fff 4553 case 7:
7385ac0b 4554 check_insn(env, ctx, ASE_MT);
895c2d04 4555 gen_helper_mtc0_tcschefback(cpu_env, arg);
2423f660 4556 rn = "TCScheFBack";
ead9360e 4557 break;
7a387fff
TS
4558 default:
4559 goto die;
4560 }
8c0fdd85
TS
4561 break;
4562 case 3:
7a387fff
TS
4563 switch (sel) {
4564 case 0:
895c2d04 4565 gen_helper_mtc0_entrylo1(cpu_env, arg);
2423f660
TS
4566 rn = "EntryLo1";
4567 break;
7a387fff
TS
4568 default:
4569 goto die;
876d4b07 4570 }
8c0fdd85
TS
4571 break;
4572 case 4:
7a387fff
TS
4573 switch (sel) {
4574 case 0:
895c2d04 4575 gen_helper_mtc0_context(cpu_env, arg);
2423f660
TS
4576 rn = "Context";
4577 break;
7a387fff 4578 case 1:
895c2d04 4579// gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
2423f660
TS
4580 rn = "ContextConfig";
4581// break;
7a387fff
TS
4582 default:
4583 goto die;
876d4b07 4584 }
8c0fdd85
TS
4585 break;
4586 case 5:
7a387fff
TS
4587 switch (sel) {
4588 case 0:
895c2d04 4589 gen_helper_mtc0_pagemask(cpu_env, arg);
2423f660
TS
4590 rn = "PageMask";
4591 break;
7a387fff 4592 case 1:
e189e748 4593 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4594 gen_helper_mtc0_pagegrain(cpu_env, arg);
2423f660
TS
4595 rn = "PageGrain";
4596 break;
7a387fff
TS
4597 default:
4598 goto die;
876d4b07 4599 }
8c0fdd85
TS
4600 break;
4601 case 6:
7a387fff
TS
4602 switch (sel) {
4603 case 0:
895c2d04 4604 gen_helper_mtc0_wired(cpu_env, arg);
2423f660
TS
4605 rn = "Wired";
4606 break;
7a387fff 4607 case 1:
e189e748 4608 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4609 gen_helper_mtc0_srsconf0(cpu_env, arg);
2423f660 4610 rn = "SRSConf0";
ead9360e 4611 break;
7a387fff 4612 case 2:
e189e748 4613 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4614 gen_helper_mtc0_srsconf1(cpu_env, arg);
2423f660 4615 rn = "SRSConf1";
ead9360e 4616 break;
7a387fff 4617 case 3:
e189e748 4618 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4619 gen_helper_mtc0_srsconf2(cpu_env, arg);
2423f660 4620 rn = "SRSConf2";
ead9360e 4621 break;
7a387fff 4622 case 4:
e189e748 4623 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4624 gen_helper_mtc0_srsconf3(cpu_env, arg);
2423f660 4625 rn = "SRSConf3";
ead9360e 4626 break;
7a387fff 4627 case 5:
e189e748 4628 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4629 gen_helper_mtc0_srsconf4(cpu_env, arg);
2423f660 4630 rn = "SRSConf4";
ead9360e 4631 break;
7a387fff
TS
4632 default:
4633 goto die;
876d4b07 4634 }
8c0fdd85
TS
4635 break;
4636 case 7:
7a387fff
TS
4637 switch (sel) {
4638 case 0:
e189e748 4639 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4640 gen_helper_mtc0_hwrena(cpu_env, arg);
2423f660
TS
4641 rn = "HWREna";
4642 break;
7a387fff
TS
4643 default:
4644 goto die;
876d4b07 4645 }
8c0fdd85
TS
4646 break;
4647 case 8:
7a387fff 4648 /* ignored */
f0b3f3ae 4649 rn = "BadVAddr";
8c0fdd85
TS
4650 break;
4651 case 9:
7a387fff
TS
4652 switch (sel) {
4653 case 0:
895c2d04 4654 gen_helper_mtc0_count(cpu_env, arg);
2423f660
TS
4655 rn = "Count";
4656 break;
876d4b07 4657 /* 6,7 are implementation dependent */
7a387fff
TS
4658 default:
4659 goto die;
876d4b07 4660 }
8c0fdd85
TS
4661 break;
4662 case 10:
7a387fff
TS
4663 switch (sel) {
4664 case 0:
895c2d04 4665 gen_helper_mtc0_entryhi(cpu_env, arg);
2423f660
TS
4666 rn = "EntryHi";
4667 break;
7a387fff
TS
4668 default:
4669 goto die;
876d4b07 4670 }
8c0fdd85
TS
4671 break;
4672 case 11:
7a387fff
TS
4673 switch (sel) {
4674 case 0:
895c2d04 4675 gen_helper_mtc0_compare(cpu_env, arg);
2423f660
TS
4676 rn = "Compare";
4677 break;
4678 /* 6,7 are implementation dependent */
7a387fff
TS
4679 default:
4680 goto die;
876d4b07 4681 }
8c0fdd85
TS
4682 break;
4683 case 12:
7a387fff
TS
4684 switch (sel) {
4685 case 0:
867abc7e 4686 save_cpu_state(ctx, 1);
895c2d04 4687 gen_helper_mtc0_status(cpu_env, arg);
8487327a
TS
4688 /* BS_STOP isn't good enough here, hflags may have changed. */
4689 gen_save_pc(ctx->pc + 4);
4690 ctx->bstate = BS_EXCP;
2423f660
TS
4691 rn = "Status";
4692 break;
7a387fff 4693 case 1:
e189e748 4694 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4695 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a
TS
4696 /* Stop translation as we may have switched the execution mode */
4697 ctx->bstate = BS_STOP;
2423f660
TS
4698 rn = "IntCtl";
4699 break;
7a387fff 4700 case 2:
e189e748 4701 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4702 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a
TS
4703 /* Stop translation as we may have switched the execution mode */
4704 ctx->bstate = BS_STOP;
2423f660
TS
4705 rn = "SRSCtl";
4706 break;
7a387fff 4707 case 3:
e189e748 4708 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 4709 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a
TS
4710 /* Stop translation as we may have switched the execution mode */
4711 ctx->bstate = BS_STOP;
2423f660 4712 rn = "SRSMap";
fd88b6ab 4713 break;
7a387fff
TS
4714 default:
4715 goto die;
876d4b07 4716 }
8c0fdd85
TS
4717 break;
4718 case 13:
7a387fff
TS
4719 switch (sel) {
4720 case 0:
867abc7e 4721 save_cpu_state(ctx, 1);
895c2d04 4722 gen_helper_mtc0_cause(cpu_env, arg);
2423f660
TS
4723 rn = "Cause";
4724 break;
7a387fff
TS
4725 default:
4726 goto die;
876d4b07 4727 }
8c0fdd85
TS
4728 break;
4729 case 14:
7a387fff
TS
4730 switch (sel) {
4731 case 0:
7db13fae 4732 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
2423f660
TS
4733 rn = "EPC";
4734 break;
7a387fff
TS
4735 default:
4736 goto die;
876d4b07 4737 }
8c0fdd85
TS
4738 break;
4739 case 15:
7a387fff
TS
4740 switch (sel) {
4741 case 0:
2423f660
TS
4742 /* ignored */
4743 rn = "PRid";
4744 break;
7a387fff 4745 case 1:
e189e748 4746 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 4747 gen_helper_mtc0_ebase(cpu_env, arg);
2423f660
TS
4748 rn = "EBase";
4749 break;
7a387fff
TS
4750 default:
4751 goto die;
1579a72e 4752 }
8c0fdd85
TS
4753 break;
4754 case 16:
4755 switch (sel) {
4756 case 0:
895c2d04 4757 gen_helper_mtc0_config0(cpu_env, arg);
7a387fff 4758 rn = "Config";
2423f660
TS
4759 /* Stop translation as we may have switched the execution mode */
4760 ctx->bstate = BS_STOP;
7a387fff
TS
4761 break;
4762 case 1:
e397ee33 4763 /* ignored, read only */
7a387fff
TS
4764 rn = "Config1";
4765 break;
4766 case 2:
895c2d04 4767 gen_helper_mtc0_config2(cpu_env, arg);
7a387fff 4768 rn = "Config2";
2423f660
TS
4769 /* Stop translation as we may have switched the execution mode */
4770 ctx->bstate = BS_STOP;
8c0fdd85 4771 break;
7a387fff 4772 case 3:
e397ee33 4773 /* ignored, read only */
7a387fff
TS
4774 rn = "Config3";
4775 break;
e397ee33
TS
4776 /* 4,5 are reserved */
4777 /* 6,7 are implementation dependent */
4778 case 6:
4779 /* ignored */
4780 rn = "Config6";
4781 break;
4782 case 7:
4783 /* ignored */
4784 rn = "Config7";
4785 break;
8c0fdd85
TS
4786 default:
4787 rn = "Invalid config selector";
4788 goto die;
4789 }
4790 break;
4791 case 17:
7a387fff
TS
4792 switch (sel) {
4793 case 0:
895c2d04 4794 gen_helper_mtc0_lladdr(cpu_env, arg);
2423f660
TS
4795 rn = "LLAddr";
4796 break;
7a387fff
TS
4797 default:
4798 goto die;
4799 }
8c0fdd85
TS
4800 break;
4801 case 18:
7a387fff 4802 switch (sel) {
fd88b6ab 4803 case 0 ... 7:
895c2d04 4804 gen_helper_0e1i(mtc0_watchlo, arg, sel);
2423f660
TS
4805 rn = "WatchLo";
4806 break;
7a387fff
TS
4807 default:
4808 goto die;
4809 }
8c0fdd85
TS
4810 break;
4811 case 19:
7a387fff 4812 switch (sel) {
fd88b6ab 4813 case 0 ... 7:
895c2d04 4814 gen_helper_0e1i(mtc0_watchhi, arg, sel);
2423f660
TS
4815 rn = "WatchHi";
4816 break;
7a387fff
TS
4817 default:
4818 goto die;
4819 }
8c0fdd85
TS
4820 break;
4821 case 20:
7a387fff
TS
4822 switch (sel) {
4823 case 0:
d26bc211 4824#if defined(TARGET_MIPS64)
e189e748 4825 check_insn(env, ctx, ISA_MIPS3);
895c2d04 4826 gen_helper_mtc0_xcontext(cpu_env, arg);
2423f660
TS
4827 rn = "XContext";
4828 break;
703eaf37 4829#endif
7a387fff
TS
4830 default:
4831 goto die;
4832 }
8c0fdd85
TS
4833 break;
4834 case 21:
7a387fff
TS
4835 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4836 switch (sel) {
4837 case 0:
895c2d04 4838 gen_helper_mtc0_framemask(cpu_env, arg);
2423f660
TS
4839 rn = "Framemask";
4840 break;
7a387fff
TS
4841 default:
4842 goto die;
4843 }
4844 break;
8c0fdd85 4845 case 22:
7a387fff
TS
4846 /* ignored */
4847 rn = "Diagnostic"; /* implementation dependent */
2423f660 4848 break;
8c0fdd85 4849 case 23:
7a387fff
TS
4850 switch (sel) {
4851 case 0:
895c2d04 4852 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8487327a
TS
4853 /* BS_STOP isn't good enough here, hflags may have changed. */
4854 gen_save_pc(ctx->pc + 4);
4855 ctx->bstate = BS_EXCP;
2423f660
TS
4856 rn = "Debug";
4857 break;
7a387fff 4858 case 1:
895c2d04 4859// gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
2423f660 4860 rn = "TraceControl";
8487327a
TS
4861 /* Stop translation as we may have switched the execution mode */
4862 ctx->bstate = BS_STOP;
2423f660 4863// break;
7a387fff 4864 case 2:
895c2d04 4865// gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
2423f660 4866 rn = "TraceControl2";
8487327a
TS
4867 /* Stop translation as we may have switched the execution mode */
4868 ctx->bstate = BS_STOP;
2423f660 4869// break;
7a387fff 4870 case 3:
8487327a
TS
4871 /* Stop translation as we may have switched the execution mode */
4872 ctx->bstate = BS_STOP;
895c2d04 4873// gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
2423f660 4874 rn = "UserTraceData";
8487327a
TS
4875 /* Stop translation as we may have switched the execution mode */
4876 ctx->bstate = BS_STOP;
2423f660 4877// break;
7a387fff 4878 case 4:
895c2d04 4879// gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
8487327a
TS
4880 /* Stop translation as we may have switched the execution mode */
4881 ctx->bstate = BS_STOP;
2423f660
TS
4882 rn = "TraceBPC";
4883// break;
7a387fff
TS
4884 default:
4885 goto die;
4886 }
8c0fdd85
TS
4887 break;
4888 case 24:
7a387fff
TS
4889 switch (sel) {
4890 case 0:
f1aa6320 4891 /* EJTAG support */
7db13fae 4892 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
2423f660
TS
4893 rn = "DEPC";
4894 break;
7a387fff
TS
4895 default:
4896 goto die;
4897 }
8c0fdd85
TS
4898 break;
4899 case 25:
7a387fff
TS
4900 switch (sel) {
4901 case 0:
895c2d04 4902 gen_helper_mtc0_performance0(cpu_env, arg);
2423f660
TS
4903 rn = "Performance0";
4904 break;
7a387fff 4905 case 1:
d9bea114 4906// gen_helper_mtc0_performance1(arg);
2423f660
TS
4907 rn = "Performance1";
4908// break;
7a387fff 4909 case 2:
d9bea114 4910// gen_helper_mtc0_performance2(arg);
2423f660
TS
4911 rn = "Performance2";
4912// break;
7a387fff 4913 case 3:
d9bea114 4914// gen_helper_mtc0_performance3(arg);
2423f660
TS
4915 rn = "Performance3";
4916// break;
7a387fff 4917 case 4:
d9bea114 4918// gen_helper_mtc0_performance4(arg);
2423f660
TS
4919 rn = "Performance4";
4920// break;
7a387fff 4921 case 5:
d9bea114 4922// gen_helper_mtc0_performance5(arg);
2423f660
TS
4923 rn = "Performance5";
4924// break;
7a387fff 4925 case 6:
d9bea114 4926// gen_helper_mtc0_performance6(arg);
2423f660
TS
4927 rn = "Performance6";
4928// break;
7a387fff 4929 case 7:
d9bea114 4930// gen_helper_mtc0_performance7(arg);
2423f660
TS
4931 rn = "Performance7";
4932// break;
7a387fff
TS
4933 default:
4934 goto die;
4935 }
8c0fdd85
TS
4936 break;
4937 case 26:
2423f660 4938 /* ignored */
8c0fdd85 4939 rn = "ECC";
2423f660 4940 break;
8c0fdd85 4941 case 27:
7a387fff
TS
4942 switch (sel) {
4943 case 0 ... 3:
2423f660
TS
4944 /* ignored */
4945 rn = "CacheErr";
4946 break;
7a387fff
TS
4947 default:
4948 goto die;
4949 }
8c0fdd85
TS
4950 break;
4951 case 28:
4952 switch (sel) {
4953 case 0:
7a387fff
TS
4954 case 2:
4955 case 4:
4956 case 6:
895c2d04 4957 gen_helper_mtc0_taglo(cpu_env, arg);
8c0fdd85
TS
4958 rn = "TagLo";
4959 break;
7a387fff
TS
4960 case 1:
4961 case 3:
4962 case 5:
4963 case 7:
895c2d04 4964 gen_helper_mtc0_datalo(cpu_env, arg);
7a387fff
TS
4965 rn = "DataLo";
4966 break;
8c0fdd85 4967 default:
8c0fdd85
TS
4968 goto die;
4969 }
4970 break;
4971 case 29:
7a387fff
TS
4972 switch (sel) {
4973 case 0:
4974 case 2:
4975 case 4:
4976 case 6:
895c2d04 4977 gen_helper_mtc0_taghi(cpu_env, arg);
7a387fff
TS
4978 rn = "TagHi";
4979 break;
4980 case 1:
4981 case 3:
4982 case 5:
4983 case 7:
895c2d04 4984 gen_helper_mtc0_datahi(cpu_env, arg);
7a387fff
TS
4985 rn = "DataHi";
4986 break;
4987 default:
4988 rn = "invalid sel";
4989 goto die;
4990 }
8c0fdd85
TS
4991 break;
4992 case 30:
7a387fff
TS
4993 switch (sel) {
4994 case 0:
7db13fae 4995 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
2423f660
TS
4996 rn = "ErrorEPC";
4997 break;
7a387fff
TS
4998 default:
4999 goto die;
5000 }
8c0fdd85
TS
5001 break;
5002 case 31:
7a387fff
TS
5003 switch (sel) {
5004 case 0:
f1aa6320 5005 /* EJTAG support */
7db13fae 5006 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
5007 rn = "DESAVE";
5008 break;
7a387fff
TS
5009 default:
5010 goto die;
5011 }
2423f660
TS
5012 /* Stop translation as we may have switched the execution mode */
5013 ctx->bstate = BS_STOP;
8c0fdd85
TS
5014 break;
5015 default:
8c0fdd85
TS
5016 goto die;
5017 }
2abf314d 5018 (void)rn; /* avoid a compiler warning */
d12d51d5 5019 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
bf20dc07 5020 /* For simplicity assume that all writes can cause interrupts. */
2e70f6ef
PB
5021 if (use_icount) {
5022 gen_io_end();
5023 ctx->bstate = BS_STOP;
5024 }
8c0fdd85
TS
5025 return;
5026
5027die:
d12d51d5 5028 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
8c0fdd85
TS
5029 generate_exception(ctx, EXCP_RI);
5030}
5031
d26bc211 5032#if defined(TARGET_MIPS64)
7db13fae 5033static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8
TS
5034{
5035 const char *rn = "invalid";
5036
e189e748
TS
5037 if (sel != 0)
5038 check_insn(env, ctx, ISA_MIPS64);
5039
9c2149c8
TS
5040 switch (reg) {
5041 case 0:
5042 switch (sel) {
5043 case 0:
7db13fae 5044 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
9c2149c8
TS
5045 rn = "Index";
5046 break;
5047 case 1:
7385ac0b 5048 check_insn(env, ctx, ASE_MT);
895c2d04 5049 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
9c2149c8 5050 rn = "MVPControl";
ead9360e 5051 break;
9c2149c8 5052 case 2:
7385ac0b 5053 check_insn(env, ctx, ASE_MT);
895c2d04 5054 gen_helper_mfc0_mvpconf0(arg, cpu_env);
9c2149c8 5055 rn = "MVPConf0";
ead9360e 5056 break;
9c2149c8 5057 case 3:
7385ac0b 5058 check_insn(env, ctx, ASE_MT);
895c2d04 5059 gen_helper_mfc0_mvpconf1(arg, cpu_env);
9c2149c8 5060 rn = "MVPConf1";
ead9360e 5061 break;
9c2149c8
TS
5062 default:
5063 goto die;
5064 }
5065 break;
5066 case 1:
5067 switch (sel) {
5068 case 0:
895c2d04 5069 gen_helper_mfc0_random(arg, cpu_env);
9c2149c8 5070 rn = "Random";
2423f660 5071 break;
9c2149c8 5072 case 1:
7385ac0b 5073 check_insn(env, ctx, ASE_MT);
7db13fae 5074 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
9c2149c8 5075 rn = "VPEControl";
ead9360e 5076 break;
9c2149c8 5077 case 2:
7385ac0b 5078 check_insn(env, ctx, ASE_MT);
7db13fae 5079 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
9c2149c8 5080 rn = "VPEConf0";
ead9360e 5081 break;
9c2149c8 5082 case 3:
7385ac0b 5083 check_insn(env, ctx, ASE_MT);
7db13fae 5084 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
9c2149c8 5085 rn = "VPEConf1";
ead9360e 5086 break;
9c2149c8 5087 case 4:
7385ac0b 5088 check_insn(env, ctx, ASE_MT);
7db13fae 5089 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
9c2149c8 5090 rn = "YQMask";
ead9360e 5091 break;
9c2149c8 5092 case 5:
7385ac0b 5093 check_insn(env, ctx, ASE_MT);
7db13fae 5094 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
9c2149c8 5095 rn = "VPESchedule";
ead9360e 5096 break;
9c2149c8 5097 case 6:
7385ac0b 5098 check_insn(env, ctx, ASE_MT);
7db13fae 5099 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
9c2149c8 5100 rn = "VPEScheFBack";
ead9360e 5101 break;
9c2149c8 5102 case 7:
7385ac0b 5103 check_insn(env, ctx, ASE_MT);
7db13fae 5104 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
9c2149c8 5105 rn = "VPEOpt";
ead9360e 5106 break;
9c2149c8
TS
5107 default:
5108 goto die;
5109 }
5110 break;
5111 case 2:
5112 switch (sel) {
5113 case 0:
7db13fae 5114 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
2423f660
TS
5115 rn = "EntryLo0";
5116 break;
9c2149c8 5117 case 1:
7385ac0b 5118 check_insn(env, ctx, ASE_MT);
895c2d04 5119 gen_helper_mfc0_tcstatus(arg, cpu_env);
2423f660 5120 rn = "TCStatus";
ead9360e 5121 break;
9c2149c8 5122 case 2:
7385ac0b 5123 check_insn(env, ctx, ASE_MT);
895c2d04 5124 gen_helper_mfc0_tcbind(arg, cpu_env);
2423f660 5125 rn = "TCBind";
ead9360e 5126 break;
9c2149c8 5127 case 3:
7385ac0b 5128 check_insn(env, ctx, ASE_MT);
895c2d04 5129 gen_helper_dmfc0_tcrestart(arg, cpu_env);
2423f660 5130 rn = "TCRestart";
ead9360e 5131 break;
9c2149c8 5132 case 4:
7385ac0b 5133 check_insn(env, ctx, ASE_MT);
895c2d04 5134 gen_helper_dmfc0_tchalt(arg, cpu_env);
2423f660 5135 rn = "TCHalt";
ead9360e 5136 break;
9c2149c8 5137 case 5:
7385ac0b 5138 check_insn(env, ctx, ASE_MT);
895c2d04 5139 gen_helper_dmfc0_tccontext(arg, cpu_env);
2423f660 5140 rn = "TCContext";
ead9360e 5141 break;
9c2149c8 5142 case 6:
7385ac0b 5143 check_insn(env, ctx, ASE_MT);
895c2d04 5144 gen_helper_dmfc0_tcschedule(arg, cpu_env);
2423f660 5145 rn = "TCSchedule";
ead9360e 5146 break;
9c2149c8 5147 case 7:
7385ac0b 5148 check_insn(env, ctx, ASE_MT);
895c2d04 5149 gen_helper_dmfc0_tcschefback(arg, cpu_env);
2423f660 5150 rn = "TCScheFBack";
ead9360e 5151 break;
9c2149c8
TS
5152 default:
5153 goto die;
5154 }
5155 break;
5156 case 3:
5157 switch (sel) {
5158 case 0:
7db13fae 5159 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
2423f660
TS
5160 rn = "EntryLo1";
5161 break;
9c2149c8
TS
5162 default:
5163 goto die;
1579a72e 5164 }
9c2149c8
TS
5165 break;
5166 case 4:
5167 switch (sel) {
5168 case 0:
7db13fae 5169 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
2423f660
TS
5170 rn = "Context";
5171 break;
9c2149c8 5172 case 1:
d9bea114 5173// gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
2423f660
TS
5174 rn = "ContextConfig";
5175// break;
9c2149c8
TS
5176 default:
5177 goto die;
876d4b07 5178 }
9c2149c8
TS
5179 break;
5180 case 5:
5181 switch (sel) {
5182 case 0:
7db13fae 5183 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
2423f660
TS
5184 rn = "PageMask";
5185 break;
9c2149c8 5186 case 1:
e189e748 5187 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5188 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
2423f660
TS
5189 rn = "PageGrain";
5190 break;
9c2149c8
TS
5191 default:
5192 goto die;
876d4b07 5193 }
9c2149c8
TS
5194 break;
5195 case 6:
5196 switch (sel) {
5197 case 0:
7db13fae 5198 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
2423f660
TS
5199 rn = "Wired";
5200 break;
9c2149c8 5201 case 1:
e189e748 5202 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5203 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
2423f660 5204 rn = "SRSConf0";
ead9360e 5205 break;
9c2149c8 5206 case 2:
e189e748 5207 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5208 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
2423f660 5209 rn = "SRSConf1";
ead9360e 5210 break;
9c2149c8 5211 case 3:
e189e748 5212 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5213 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
2423f660 5214 rn = "SRSConf2";
ead9360e 5215 break;
9c2149c8 5216 case 4:
e189e748 5217 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5218 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
2423f660 5219 rn = "SRSConf3";
ead9360e 5220 break;
9c2149c8 5221 case 5:
e189e748 5222 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5223 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
2423f660 5224 rn = "SRSConf4";
ead9360e 5225 break;
9c2149c8
TS
5226 default:
5227 goto die;
876d4b07 5228 }
9c2149c8
TS
5229 break;
5230 case 7:
5231 switch (sel) {
5232 case 0:
e189e748 5233 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5234 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
2423f660
TS
5235 rn = "HWREna";
5236 break;
9c2149c8
TS
5237 default:
5238 goto die;
876d4b07 5239 }
9c2149c8
TS
5240 break;
5241 case 8:
5242 switch (sel) {
5243 case 0:
7db13fae 5244 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
f0b3f3ae 5245 rn = "BadVAddr";
2423f660 5246 break;
9c2149c8
TS
5247 default:
5248 goto die;
876d4b07 5249 }
9c2149c8
TS
5250 break;
5251 case 9:
5252 switch (sel) {
5253 case 0:
2e70f6ef
PB
5254 /* Mark as an IO operation because we read the time. */
5255 if (use_icount)
5256 gen_io_start();
895c2d04 5257 gen_helper_mfc0_count(arg, cpu_env);
2e70f6ef
PB
5258 if (use_icount) {
5259 gen_io_end();
2e70f6ef 5260 }
55807224
EI
5261 /* Break the TB to be able to take timer interrupts immediately
5262 after reading count. */
5263 ctx->bstate = BS_STOP;
2423f660
TS
5264 rn = "Count";
5265 break;
5266 /* 6,7 are implementation dependent */
9c2149c8
TS
5267 default:
5268 goto die;
876d4b07 5269 }
9c2149c8
TS
5270 break;
5271 case 10:
5272 switch (sel) {
5273 case 0:
7db13fae 5274 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
2423f660
TS
5275 rn = "EntryHi";
5276 break;
9c2149c8
TS
5277 default:
5278 goto die;
876d4b07 5279 }
9c2149c8
TS
5280 break;
5281 case 11:
5282 switch (sel) {
5283 case 0:
7db13fae 5284 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
2423f660
TS
5285 rn = "Compare";
5286 break;
876d4b07 5287 /* 6,7 are implementation dependent */
9c2149c8
TS
5288 default:
5289 goto die;
876d4b07 5290 }
9c2149c8
TS
5291 break;
5292 case 12:
5293 switch (sel) {
5294 case 0:
7db13fae 5295 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
2423f660
TS
5296 rn = "Status";
5297 break;
9c2149c8 5298 case 1:
e189e748 5299 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5300 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
2423f660
TS
5301 rn = "IntCtl";
5302 break;
9c2149c8 5303 case 2:
e189e748 5304 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5305 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
2423f660
TS
5306 rn = "SRSCtl";
5307 break;
9c2149c8 5308 case 3:
e189e748 5309 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5310 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
2423f660
TS
5311 rn = "SRSMap";
5312 break;
9c2149c8
TS
5313 default:
5314 goto die;
876d4b07 5315 }
9c2149c8
TS
5316 break;
5317 case 13:
5318 switch (sel) {
5319 case 0:
7db13fae 5320 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
2423f660
TS
5321 rn = "Cause";
5322 break;
9c2149c8
TS
5323 default:
5324 goto die;
876d4b07 5325 }
9c2149c8
TS
5326 break;
5327 case 14:
5328 switch (sel) {
5329 case 0:
7db13fae 5330 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
2423f660
TS
5331 rn = "EPC";
5332 break;
9c2149c8
TS
5333 default:
5334 goto die;
876d4b07 5335 }
9c2149c8
TS
5336 break;
5337 case 15:
5338 switch (sel) {
5339 case 0:
7db13fae 5340 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
2423f660
TS
5341 rn = "PRid";
5342 break;
9c2149c8 5343 case 1:
e189e748 5344 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5345 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
2423f660
TS
5346 rn = "EBase";
5347 break;
9c2149c8
TS
5348 default:
5349 goto die;
876d4b07 5350 }
9c2149c8
TS
5351 break;
5352 case 16:
5353 switch (sel) {
5354 case 0:
7db13fae 5355 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
9c2149c8
TS
5356 rn = "Config";
5357 break;
5358 case 1:
7db13fae 5359 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
9c2149c8
TS
5360 rn = "Config1";
5361 break;
5362 case 2:
7db13fae 5363 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
9c2149c8
TS
5364 rn = "Config2";
5365 break;
5366 case 3:
7db13fae 5367 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
9c2149c8
TS
5368 rn = "Config3";
5369 break;
5370 /* 6,7 are implementation dependent */
f0b3f3ae 5371 case 6:
7db13fae 5372 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
f0b3f3ae
TS
5373 rn = "Config6";
5374 break;
5375 case 7:
7db13fae 5376 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
f0b3f3ae
TS
5377 rn = "Config7";
5378 break;
9c2149c8
TS
5379 default:
5380 goto die;
5381 }
5382 break;
5383 case 17:
5384 switch (sel) {
5385 case 0:
895c2d04 5386 gen_helper_dmfc0_lladdr(arg, cpu_env);
2423f660
TS
5387 rn = "LLAddr";
5388 break;
9c2149c8
TS
5389 default:
5390 goto die;
5391 }
5392 break;
5393 case 18:
5394 switch (sel) {
fd88b6ab 5395 case 0 ... 7:
895c2d04 5396 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
2423f660
TS
5397 rn = "WatchLo";
5398 break;
9c2149c8
TS
5399 default:
5400 goto die;
5401 }
5402 break;
5403 case 19:
5404 switch (sel) {
fd88b6ab 5405 case 0 ... 7:
895c2d04 5406 gen_helper_1e0i(mfc0_watchhi, arg, sel);
2423f660
TS
5407 rn = "WatchHi";
5408 break;
9c2149c8
TS
5409 default:
5410 goto die;
5411 }
5412 break;
5413 case 20:
5414 switch (sel) {
5415 case 0:
e189e748 5416 check_insn(env, ctx, ISA_MIPS3);
7db13fae 5417 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
2423f660
TS
5418 rn = "XContext";
5419 break;
9c2149c8
TS
5420 default:
5421 goto die;
5422 }
5423 break;
5424 case 21:
5425 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5426 switch (sel) {
5427 case 0:
7db13fae 5428 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
2423f660
TS
5429 rn = "Framemask";
5430 break;
9c2149c8
TS
5431 default:
5432 goto die;
5433 }
5434 break;
5435 case 22:
d9bea114 5436 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
5437 rn = "'Diagnostic"; /* implementation dependent */
5438 break;
9c2149c8
TS
5439 case 23:
5440 switch (sel) {
5441 case 0:
895c2d04 5442 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
2423f660
TS
5443 rn = "Debug";
5444 break;
9c2149c8 5445 case 1:
895c2d04 5446// gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
2423f660
TS
5447 rn = "TraceControl";
5448// break;
9c2149c8 5449 case 2:
895c2d04 5450// gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
2423f660
TS
5451 rn = "TraceControl2";
5452// break;
9c2149c8 5453 case 3:
895c2d04 5454// gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
2423f660
TS
5455 rn = "UserTraceData";
5456// break;
9c2149c8 5457 case 4:
895c2d04 5458// gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
2423f660
TS
5459 rn = "TraceBPC";
5460// break;
9c2149c8
TS
5461 default:
5462 goto die;
5463 }
5464 break;
5465 case 24:
5466 switch (sel) {
5467 case 0:
f0b3f3ae 5468 /* EJTAG support */
7db13fae 5469 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
2423f660
TS
5470 rn = "DEPC";
5471 break;
9c2149c8
TS
5472 default:
5473 goto die;
5474 }
5475 break;
5476 case 25:
5477 switch (sel) {
5478 case 0:
7db13fae 5479 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
2423f660 5480 rn = "Performance0";
9c2149c8
TS
5481 break;
5482 case 1:
d9bea114 5483// gen_helper_dmfc0_performance1(arg);
2423f660
TS
5484 rn = "Performance1";
5485// break;
9c2149c8 5486 case 2:
d9bea114 5487// gen_helper_dmfc0_performance2(arg);
2423f660
TS
5488 rn = "Performance2";
5489// break;
9c2149c8 5490 case 3:
d9bea114 5491// gen_helper_dmfc0_performance3(arg);
2423f660
TS
5492 rn = "Performance3";
5493// break;
9c2149c8 5494 case 4:
d9bea114 5495// gen_helper_dmfc0_performance4(arg);
2423f660
TS
5496 rn = "Performance4";
5497// break;
9c2149c8 5498 case 5:
d9bea114 5499// gen_helper_dmfc0_performance5(arg);
2423f660
TS
5500 rn = "Performance5";
5501// break;
9c2149c8 5502 case 6:
d9bea114 5503// gen_helper_dmfc0_performance6(arg);
2423f660
TS
5504 rn = "Performance6";
5505// break;
9c2149c8 5506 case 7:
d9bea114 5507// gen_helper_dmfc0_performance7(arg);
2423f660
TS
5508 rn = "Performance7";
5509// break;
9c2149c8
TS
5510 default:
5511 goto die;
5512 }
5513 break;
5514 case 26:
d9bea114 5515 tcg_gen_movi_tl(arg, 0); /* unimplemented */
da80682b
AJ
5516 rn = "ECC";
5517 break;
9c2149c8
TS
5518 case 27:
5519 switch (sel) {
5520 /* ignored */
5521 case 0 ... 3:
d9bea114 5522 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
5523 rn = "CacheErr";
5524 break;
9c2149c8
TS
5525 default:
5526 goto die;
5527 }
5528 break;
5529 case 28:
5530 switch (sel) {
5531 case 0:
5532 case 2:
5533 case 4:
5534 case 6:
7db13fae 5535 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
9c2149c8
TS
5536 rn = "TagLo";
5537 break;
5538 case 1:
5539 case 3:
5540 case 5:
5541 case 7:
7db13fae 5542 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
9c2149c8
TS
5543 rn = "DataLo";
5544 break;
5545 default:
5546 goto die;
5547 }
5548 break;
5549 case 29:
5550 switch (sel) {
5551 case 0:
5552 case 2:
5553 case 4:
5554 case 6:
7db13fae 5555 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
9c2149c8
TS
5556 rn = "TagHi";
5557 break;
5558 case 1:
5559 case 3:
5560 case 5:
5561 case 7:
7db13fae 5562 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
9c2149c8
TS
5563 rn = "DataHi";
5564 break;
5565 default:
5566 goto die;
5567 }
5568 break;
5569 case 30:
5570 switch (sel) {
5571 case 0:
7db13fae 5572 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
2423f660
TS
5573 rn = "ErrorEPC";
5574 break;
9c2149c8
TS
5575 default:
5576 goto die;
5577 }
5578 break;
5579 case 31:
5580 switch (sel) {
5581 case 0:
f0b3f3ae 5582 /* EJTAG support */
7db13fae 5583 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
5584 rn = "DESAVE";
5585 break;
9c2149c8
TS
5586 default:
5587 goto die;
5588 }
5589 break;
5590 default:
876d4b07 5591 goto die;
9c2149c8 5592 }
2abf314d 5593 (void)rn; /* avoid a compiler warning */
d12d51d5 5594 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
5595 return;
5596
5597die:
d12d51d5 5598 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
5599 generate_exception(ctx, EXCP_RI);
5600}
5601
7db13fae 5602static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8
TS
5603{
5604 const char *rn = "invalid";
5605
e189e748
TS
5606 if (sel != 0)
5607 check_insn(env, ctx, ISA_MIPS64);
5608
2e70f6ef
PB
5609 if (use_icount)
5610 gen_io_start();
5611
9c2149c8
TS
5612 switch (reg) {
5613 case 0:
5614 switch (sel) {
5615 case 0:
895c2d04 5616 gen_helper_mtc0_index(cpu_env, arg);
9c2149c8
TS
5617 rn = "Index";
5618 break;
5619 case 1:
7385ac0b 5620 check_insn(env, ctx, ASE_MT);
895c2d04 5621 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
9c2149c8 5622 rn = "MVPControl";
ead9360e 5623 break;
9c2149c8 5624 case 2:
7385ac0b 5625 check_insn(env, ctx, ASE_MT);
ead9360e 5626 /* ignored */
9c2149c8 5627 rn = "MVPConf0";
ead9360e 5628 break;
9c2149c8 5629 case 3:
7385ac0b 5630 check_insn(env, ctx, ASE_MT);
ead9360e 5631 /* ignored */
9c2149c8 5632 rn = "MVPConf1";
ead9360e 5633 break;
9c2149c8
TS
5634 default:
5635 goto die;
5636 }
5637 break;
5638 case 1:
5639 switch (sel) {
5640 case 0:
2423f660 5641 /* ignored */
9c2149c8 5642 rn = "Random";
2423f660 5643 break;
9c2149c8 5644 case 1:
7385ac0b 5645 check_insn(env, ctx, ASE_MT);
895c2d04 5646 gen_helper_mtc0_vpecontrol(cpu_env, arg);
9c2149c8 5647 rn = "VPEControl";
ead9360e 5648 break;
9c2149c8 5649 case 2:
7385ac0b 5650 check_insn(env, ctx, ASE_MT);
895c2d04 5651 gen_helper_mtc0_vpeconf0(cpu_env, arg);
9c2149c8 5652 rn = "VPEConf0";
ead9360e 5653 break;
9c2149c8 5654 case 3:
7385ac0b 5655 check_insn(env, ctx, ASE_MT);
895c2d04 5656 gen_helper_mtc0_vpeconf1(cpu_env, arg);
9c2149c8 5657 rn = "VPEConf1";
ead9360e 5658 break;
9c2149c8 5659 case 4:
7385ac0b 5660 check_insn(env, ctx, ASE_MT);
895c2d04 5661 gen_helper_mtc0_yqmask(cpu_env, arg);
9c2149c8 5662 rn = "YQMask";
ead9360e 5663 break;
9c2149c8 5664 case 5:
7385ac0b 5665 check_insn(env, ctx, ASE_MT);
7db13fae 5666 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
9c2149c8 5667 rn = "VPESchedule";
ead9360e 5668 break;
9c2149c8 5669 case 6:
7385ac0b 5670 check_insn(env, ctx, ASE_MT);
7db13fae 5671 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
9c2149c8 5672 rn = "VPEScheFBack";
ead9360e 5673 break;
9c2149c8 5674 case 7:
7385ac0b 5675 check_insn(env, ctx, ASE_MT);
895c2d04 5676 gen_helper_mtc0_vpeopt(cpu_env, arg);
9c2149c8 5677 rn = "VPEOpt";
ead9360e 5678 break;
9c2149c8
TS
5679 default:
5680 goto die;
5681 }
5682 break;
5683 case 2:
5684 switch (sel) {
5685 case 0:
895c2d04 5686 gen_helper_mtc0_entrylo0(cpu_env, arg);
2423f660
TS
5687 rn = "EntryLo0";
5688 break;
9c2149c8 5689 case 1:
7385ac0b 5690 check_insn(env, ctx, ASE_MT);
895c2d04 5691 gen_helper_mtc0_tcstatus(cpu_env, arg);
2423f660 5692 rn = "TCStatus";
ead9360e 5693 break;
9c2149c8 5694 case 2:
7385ac0b 5695 check_insn(env, ctx, ASE_MT);
895c2d04 5696 gen_helper_mtc0_tcbind(cpu_env, arg);
2423f660 5697 rn = "TCBind";
ead9360e 5698 break;
9c2149c8 5699 case 3:
7385ac0b 5700 check_insn(env, ctx, ASE_MT);
895c2d04 5701 gen_helper_mtc0_tcrestart(cpu_env, arg);
2423f660 5702 rn = "TCRestart";
ead9360e 5703 break;
9c2149c8 5704 case 4:
7385ac0b 5705 check_insn(env, ctx, ASE_MT);
895c2d04 5706 gen_helper_mtc0_tchalt(cpu_env, arg);
2423f660 5707 rn = "TCHalt";
ead9360e 5708 break;
9c2149c8 5709 case 5:
7385ac0b 5710 check_insn(env, ctx, ASE_MT);
895c2d04 5711 gen_helper_mtc0_tccontext(cpu_env, arg);
2423f660 5712 rn = "TCContext";
ead9360e 5713 break;
9c2149c8 5714 case 6:
7385ac0b 5715 check_insn(env, ctx, ASE_MT);
895c2d04 5716 gen_helper_mtc0_tcschedule(cpu_env, arg);
2423f660 5717 rn = "TCSchedule";
ead9360e 5718 break;
9c2149c8 5719 case 7:
7385ac0b 5720 check_insn(env, ctx, ASE_MT);
895c2d04 5721 gen_helper_mtc0_tcschefback(cpu_env, arg);
2423f660 5722 rn = "TCScheFBack";
ead9360e 5723 break;
9c2149c8
TS
5724 default:
5725 goto die;
5726 }
5727 break;
5728 case 3:
5729 switch (sel) {
5730 case 0:
895c2d04 5731 gen_helper_mtc0_entrylo1(cpu_env, arg);
2423f660
TS
5732 rn = "EntryLo1";
5733 break;
9c2149c8
TS
5734 default:
5735 goto die;
876d4b07 5736 }
9c2149c8
TS
5737 break;
5738 case 4:
5739 switch (sel) {
5740 case 0:
895c2d04 5741 gen_helper_mtc0_context(cpu_env, arg);
2423f660
TS
5742 rn = "Context";
5743 break;
9c2149c8 5744 case 1:
895c2d04 5745// gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
2423f660
TS
5746 rn = "ContextConfig";
5747// break;
9c2149c8
TS
5748 default:
5749 goto die;
876d4b07 5750 }
9c2149c8
TS
5751 break;
5752 case 5:
5753 switch (sel) {
5754 case 0:
895c2d04 5755 gen_helper_mtc0_pagemask(cpu_env, arg);
2423f660
TS
5756 rn = "PageMask";
5757 break;
9c2149c8 5758 case 1:
e189e748 5759 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5760 gen_helper_mtc0_pagegrain(cpu_env, arg);
2423f660
TS
5761 rn = "PageGrain";
5762 break;
9c2149c8
TS
5763 default:
5764 goto die;
876d4b07 5765 }
9c2149c8
TS
5766 break;
5767 case 6:
5768 switch (sel) {
5769 case 0:
895c2d04 5770 gen_helper_mtc0_wired(cpu_env, arg);
2423f660
TS
5771 rn = "Wired";
5772 break;
9c2149c8 5773 case 1:
e189e748 5774 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5775 gen_helper_mtc0_srsconf0(cpu_env, arg);
2423f660 5776 rn = "SRSConf0";
ead9360e 5777 break;
9c2149c8 5778 case 2:
e189e748 5779 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5780 gen_helper_mtc0_srsconf1(cpu_env, arg);
2423f660 5781 rn = "SRSConf1";
ead9360e 5782 break;
9c2149c8 5783 case 3:
e189e748 5784 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5785 gen_helper_mtc0_srsconf2(cpu_env, arg);
2423f660 5786 rn = "SRSConf2";
ead9360e 5787 break;
9c2149c8 5788 case 4:
e189e748 5789 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5790 gen_helper_mtc0_srsconf3(cpu_env, arg);
2423f660 5791 rn = "SRSConf3";
ead9360e 5792 break;
9c2149c8 5793 case 5:
e189e748 5794 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5795 gen_helper_mtc0_srsconf4(cpu_env, arg);
2423f660 5796 rn = "SRSConf4";
ead9360e 5797 break;
9c2149c8
TS
5798 default:
5799 goto die;
876d4b07 5800 }
9c2149c8
TS
5801 break;
5802 case 7:
5803 switch (sel) {
5804 case 0:
e189e748 5805 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5806 gen_helper_mtc0_hwrena(cpu_env, arg);
2423f660
TS
5807 rn = "HWREna";
5808 break;
9c2149c8
TS
5809 default:
5810 goto die;
876d4b07 5811 }
9c2149c8
TS
5812 break;
5813 case 8:
5814 /* ignored */
f0b3f3ae 5815 rn = "BadVAddr";
9c2149c8
TS
5816 break;
5817 case 9:
5818 switch (sel) {
5819 case 0:
895c2d04 5820 gen_helper_mtc0_count(cpu_env, arg);
2423f660
TS
5821 rn = "Count";
5822 break;
876d4b07 5823 /* 6,7 are implementation dependent */
9c2149c8
TS
5824 default:
5825 goto die;
876d4b07
TS
5826 }
5827 /* Stop translation as we may have switched the execution mode */
5828 ctx->bstate = BS_STOP;
9c2149c8
TS
5829 break;
5830 case 10:
5831 switch (sel) {
5832 case 0:
895c2d04 5833 gen_helper_mtc0_entryhi(cpu_env, arg);
2423f660
TS
5834 rn = "EntryHi";
5835 break;
9c2149c8
TS
5836 default:
5837 goto die;
876d4b07 5838 }
9c2149c8
TS
5839 break;
5840 case 11:
5841 switch (sel) {
5842 case 0:
895c2d04 5843 gen_helper_mtc0_compare(cpu_env, arg);
2423f660
TS
5844 rn = "Compare";
5845 break;
876d4b07 5846 /* 6,7 are implementation dependent */
9c2149c8
TS
5847 default:
5848 goto die;
876d4b07 5849 }
de9a95f0
AJ
5850 /* Stop translation as we may have switched the execution mode */
5851 ctx->bstate = BS_STOP;
9c2149c8
TS
5852 break;
5853 case 12:
5854 switch (sel) {
5855 case 0:
867abc7e 5856 save_cpu_state(ctx, 1);
895c2d04 5857 gen_helper_mtc0_status(cpu_env, arg);
8487327a
TS
5858 /* BS_STOP isn't good enough here, hflags may have changed. */
5859 gen_save_pc(ctx->pc + 4);
5860 ctx->bstate = BS_EXCP;
2423f660
TS
5861 rn = "Status";
5862 break;
9c2149c8 5863 case 1:
e189e748 5864 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5865 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a
TS
5866 /* Stop translation as we may have switched the execution mode */
5867 ctx->bstate = BS_STOP;
2423f660
TS
5868 rn = "IntCtl";
5869 break;
9c2149c8 5870 case 2:
e189e748 5871 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5872 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a
TS
5873 /* Stop translation as we may have switched the execution mode */
5874 ctx->bstate = BS_STOP;
2423f660
TS
5875 rn = "SRSCtl";
5876 break;
9c2149c8 5877 case 3:
e189e748 5878 check_insn(env, ctx, ISA_MIPS32R2);
7db13fae 5879 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a
TS
5880 /* Stop translation as we may have switched the execution mode */
5881 ctx->bstate = BS_STOP;
2423f660
TS
5882 rn = "SRSMap";
5883 break;
5884 default:
9c2149c8 5885 goto die;
876d4b07 5886 }
9c2149c8
TS
5887 break;
5888 case 13:
5889 switch (sel) {
5890 case 0:
867abc7e 5891 save_cpu_state(ctx, 1);
5dc5d9f0
AJ
5892 /* Mark as an IO operation because we may trigger a software
5893 interrupt. */
5894 if (use_icount) {
5895 gen_io_start();
5896 }
895c2d04 5897 gen_helper_mtc0_cause(cpu_env, arg);
5dc5d9f0
AJ
5898 if (use_icount) {
5899 gen_io_end();
5900 }
5901 /* Stop translation as we may have triggered an intetrupt */
5902 ctx->bstate = BS_STOP;
2423f660
TS
5903 rn = "Cause";
5904 break;
9c2149c8
TS
5905 default:
5906 goto die;
876d4b07 5907 }
9c2149c8
TS
5908 break;
5909 case 14:
5910 switch (sel) {
5911 case 0:
7db13fae 5912 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
2423f660
TS
5913 rn = "EPC";
5914 break;
9c2149c8
TS
5915 default:
5916 goto die;
876d4b07 5917 }
9c2149c8
TS
5918 break;
5919 case 15:
5920 switch (sel) {
5921 case 0:
2423f660
TS
5922 /* ignored */
5923 rn = "PRid";
5924 break;
9c2149c8 5925 case 1:
e189e748 5926 check_insn(env, ctx, ISA_MIPS32R2);
895c2d04 5927 gen_helper_mtc0_ebase(cpu_env, arg);
2423f660
TS
5928 rn = "EBase";
5929 break;
9c2149c8
TS
5930 default:
5931 goto die;
876d4b07 5932 }
9c2149c8
TS
5933 break;
5934 case 16:
5935 switch (sel) {
5936 case 0:
895c2d04 5937 gen_helper_mtc0_config0(cpu_env, arg);
9c2149c8 5938 rn = "Config";
2423f660
TS
5939 /* Stop translation as we may have switched the execution mode */
5940 ctx->bstate = BS_STOP;
9c2149c8
TS
5941 break;
5942 case 1:
1fc7bf6e 5943 /* ignored, read only */
9c2149c8
TS
5944 rn = "Config1";
5945 break;
5946 case 2:
895c2d04 5947 gen_helper_mtc0_config2(cpu_env, arg);
9c2149c8 5948 rn = "Config2";
2423f660
TS
5949 /* Stop translation as we may have switched the execution mode */
5950 ctx->bstate = BS_STOP;
9c2149c8
TS
5951 break;
5952 case 3:
2423f660 5953 /* ignored */
9c2149c8
TS
5954 rn = "Config3";
5955 break;
5956 /* 6,7 are implementation dependent */
5957 default:
5958 rn = "Invalid config selector";
5959 goto die;
5960 }
9c2149c8
TS
5961 break;
5962 case 17:
5963 switch (sel) {
5964 case 0:
895c2d04 5965 gen_helper_mtc0_lladdr(cpu_env, arg);
2423f660
TS
5966 rn = "LLAddr";
5967 break;
9c2149c8
TS
5968 default:
5969 goto die;
5970 }
5971 break;
5972 case 18:
5973 switch (sel) {
fd88b6ab 5974 case 0 ... 7:
895c2d04 5975 gen_helper_0e1i(mtc0_watchlo, arg, sel);
2423f660
TS
5976 rn = "WatchLo";
5977 break;
9c2149c8
TS
5978 default:
5979 goto die;
5980 }
5981 break;
5982 case 19:
5983 switch (sel) {
fd88b6ab 5984 case 0 ... 7:
895c2d04 5985 gen_helper_0e1i(mtc0_watchhi, arg, sel);
2423f660
TS
5986 rn = "WatchHi";
5987 break;
9c2149c8
TS
5988 default:
5989 goto die;
5990 }
5991 break;
5992 case 20:
5993 switch (sel) {
5994 case 0:
e189e748 5995 check_insn(env, ctx, ISA_MIPS3);
895c2d04 5996 gen_helper_mtc0_xcontext(cpu_env, arg);
2423f660
TS
5997 rn = "XContext";
5998 break;
9c2149c8
TS
5999 default:
6000 goto die;
6001 }
6002 break;
6003 case 21:
6004 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6005 switch (sel) {
6006 case 0:
895c2d04 6007 gen_helper_mtc0_framemask(cpu_env, arg);
2423f660
TS
6008 rn = "Framemask";
6009 break;
9c2149c8
TS
6010 default:
6011 goto die;
6012 }
6013 break;
6014 case 22:
6015 /* ignored */
6016 rn = "Diagnostic"; /* implementation dependent */
876d4b07 6017 break;
9c2149c8
TS
6018 case 23:
6019 switch (sel) {
6020 case 0:
895c2d04 6021 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8487327a
TS
6022 /* BS_STOP isn't good enough here, hflags may have changed. */
6023 gen_save_pc(ctx->pc + 4);
6024 ctx->bstate = BS_EXCP;
2423f660
TS
6025 rn = "Debug";
6026 break;
9c2149c8 6027 case 1:
895c2d04 6028// gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
8487327a
TS
6029 /* Stop translation as we may have switched the execution mode */
6030 ctx->bstate = BS_STOP;
2423f660
TS
6031 rn = "TraceControl";
6032// break;
9c2149c8 6033 case 2:
895c2d04 6034// gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
8487327a
TS
6035 /* Stop translation as we may have switched the execution mode */
6036 ctx->bstate = BS_STOP;
2423f660
TS
6037 rn = "TraceControl2";
6038// break;
9c2149c8 6039 case 3:
895c2d04 6040// gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
8487327a
TS
6041 /* Stop translation as we may have switched the execution mode */
6042 ctx->bstate = BS_STOP;
2423f660
TS
6043 rn = "UserTraceData";
6044// break;
9c2149c8 6045 case 4:
895c2d04 6046// gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
8487327a
TS
6047 /* Stop translation as we may have switched the execution mode */
6048 ctx->bstate = BS_STOP;
2423f660
TS
6049 rn = "TraceBPC";
6050// break;
9c2149c8
TS
6051 default:
6052 goto die;
6053 }
9c2149c8
TS
6054 break;
6055 case 24:
6056 switch (sel) {
6057 case 0:
f1aa6320 6058 /* EJTAG support */
7db13fae 6059 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
2423f660
TS
6060 rn = "DEPC";
6061 break;
9c2149c8
TS
6062 default:
6063 goto die;
6064 }
6065 break;
6066 case 25:
6067 switch (sel) {
6068 case 0:
895c2d04 6069 gen_helper_mtc0_performance0(cpu_env, arg);
2423f660
TS
6070 rn = "Performance0";
6071 break;
9c2149c8 6072 case 1:
895c2d04 6073// gen_helper_mtc0_performance1(cpu_env, arg);
2423f660
TS
6074 rn = "Performance1";
6075// break;
9c2149c8 6076 case 2:
895c2d04 6077// gen_helper_mtc0_performance2(cpu_env, arg);
2423f660
TS
6078 rn = "Performance2";
6079// break;
9c2149c8 6080 case 3:
895c2d04 6081// gen_helper_mtc0_performance3(cpu_env, arg);
2423f660
TS
6082 rn = "Performance3";
6083// break;
9c2149c8 6084 case 4:
895c2d04 6085// gen_helper_mtc0_performance4(cpu_env, arg);
2423f660
TS
6086 rn = "Performance4";
6087// break;
9c2149c8 6088 case 5:
895c2d04 6089// gen_helper_mtc0_performance5(cpu_env, arg);
2423f660
TS
6090 rn = "Performance5";
6091// break;
9c2149c8 6092 case 6:
895c2d04 6093// gen_helper_mtc0_performance6(cpu_env, arg);
2423f660
TS
6094 rn = "Performance6";
6095// break;
9c2149c8 6096 case 7:
895c2d04 6097// gen_helper_mtc0_performance7(cpu_env, arg);
2423f660
TS
6098 rn = "Performance7";
6099// break;
9c2149c8
TS
6100 default:
6101 goto die;
6102 }
876d4b07 6103 break;
9c2149c8 6104 case 26:
876d4b07 6105 /* ignored */
9c2149c8 6106 rn = "ECC";
876d4b07 6107 break;
9c2149c8
TS
6108 case 27:
6109 switch (sel) {
6110 case 0 ... 3:
2423f660
TS
6111 /* ignored */
6112 rn = "CacheErr";
6113 break;
9c2149c8
TS
6114 default:
6115 goto die;
6116 }
876d4b07 6117 break;
9c2149c8
TS
6118 case 28:
6119 switch (sel) {
6120 case 0:
6121 case 2:
6122 case 4:
6123 case 6:
895c2d04 6124 gen_helper_mtc0_taglo(cpu_env, arg);
9c2149c8
TS
6125 rn = "TagLo";
6126 break;
6127 case 1:
6128 case 3:
6129 case 5:
6130 case 7:
895c2d04 6131 gen_helper_mtc0_datalo(cpu_env, arg);
9c2149c8
TS
6132 rn = "DataLo";
6133 break;
6134 default:
6135 goto die;
6136 }
6137 break;
6138 case 29:
6139 switch (sel) {
6140 case 0:
6141 case 2:
6142 case 4:
6143 case 6:
895c2d04 6144 gen_helper_mtc0_taghi(cpu_env, arg);
9c2149c8
TS
6145 rn = "TagHi";
6146 break;
6147 case 1:
6148 case 3:
6149 case 5:
6150 case 7:
895c2d04 6151 gen_helper_mtc0_datahi(cpu_env, arg);
9c2149c8
TS
6152 rn = "DataHi";
6153 break;
6154 default:
6155 rn = "invalid sel";
6156 goto die;
6157 }
876d4b07 6158 break;
9c2149c8
TS
6159 case 30:
6160 switch (sel) {
6161 case 0:
7db13fae 6162 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
2423f660
TS
6163 rn = "ErrorEPC";
6164 break;
9c2149c8
TS
6165 default:
6166 goto die;
6167 }
6168 break;
6169 case 31:
6170 switch (sel) {
6171 case 0:
f1aa6320 6172 /* EJTAG support */
7db13fae 6173 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
6174 rn = "DESAVE";
6175 break;
9c2149c8
TS
6176 default:
6177 goto die;
6178 }
876d4b07
TS
6179 /* Stop translation as we may have switched the execution mode */
6180 ctx->bstate = BS_STOP;
9c2149c8
TS
6181 break;
6182 default:
876d4b07 6183 goto die;
9c2149c8 6184 }
2abf314d 6185 (void)rn; /* avoid a compiler warning */
d12d51d5 6186 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
bf20dc07 6187 /* For simplicity assume that all writes can cause interrupts. */
2e70f6ef
PB
6188 if (use_icount) {
6189 gen_io_end();
6190 ctx->bstate = BS_STOP;
6191 }
9c2149c8
TS
6192 return;
6193
6194die:
d12d51d5 6195 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
6196 generate_exception(ctx, EXCP_RI);
6197}
d26bc211 6198#endif /* TARGET_MIPS64 */
9c2149c8 6199
7db13fae 6200static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
ead9360e
TS
6201 int u, int sel, int h)
6202{
6203 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 6204 TCGv t0 = tcg_temp_local_new();
ead9360e
TS
6205
6206 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
6207 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
6208 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
1a3fd9c3 6209 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
6210 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
6211 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
1a3fd9c3 6212 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
6213 else if (u == 0) {
6214 switch (rt) {
5a25ce94
EI
6215 case 1:
6216 switch (sel) {
6217 case 1:
895c2d04 6218 gen_helper_mftc0_vpecontrol(t0, cpu_env);
5a25ce94
EI
6219 break;
6220 case 2:
895c2d04 6221 gen_helper_mftc0_vpeconf0(t0, cpu_env);
5a25ce94
EI
6222 break;
6223 default:
6224 goto die;
6225 break;
6226 }
6227 break;
ead9360e
TS
6228 case 2:
6229 switch (sel) {
6230 case 1:
895c2d04 6231 gen_helper_mftc0_tcstatus(t0, cpu_env);
ead9360e
TS
6232 break;
6233 case 2:
895c2d04 6234 gen_helper_mftc0_tcbind(t0, cpu_env);
ead9360e
TS
6235 break;
6236 case 3:
895c2d04 6237 gen_helper_mftc0_tcrestart(t0, cpu_env);
ead9360e
TS
6238 break;
6239 case 4:
895c2d04 6240 gen_helper_mftc0_tchalt(t0, cpu_env);
ead9360e
TS
6241 break;
6242 case 5:
895c2d04 6243 gen_helper_mftc0_tccontext(t0, cpu_env);
ead9360e
TS
6244 break;
6245 case 6:
895c2d04 6246 gen_helper_mftc0_tcschedule(t0, cpu_env);
ead9360e
TS
6247 break;
6248 case 7:
895c2d04 6249 gen_helper_mftc0_tcschefback(t0, cpu_env);
ead9360e
TS
6250 break;
6251 default:
1a3fd9c3 6252 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
6253 break;
6254 }
6255 break;
6256 case 10:
6257 switch (sel) {
6258 case 0:
895c2d04 6259 gen_helper_mftc0_entryhi(t0, cpu_env);
ead9360e
TS
6260 break;
6261 default:
1a3fd9c3 6262 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
6263 break;
6264 }
6265 case 12:
6266 switch (sel) {
6267 case 0:
895c2d04 6268 gen_helper_mftc0_status(t0, cpu_env);
ead9360e
TS
6269 break;
6270 default:
1a3fd9c3 6271 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
6272 break;
6273 }
5a25ce94
EI
6274 case 13:
6275 switch (sel) {
6276 case 0:
895c2d04 6277 gen_helper_mftc0_cause(t0, cpu_env);
5a25ce94
EI
6278 break;
6279 default:
6280 goto die;
6281 break;
6282 }
6283 break;
6284 case 14:
6285 switch (sel) {
6286 case 0:
895c2d04 6287 gen_helper_mftc0_epc(t0, cpu_env);
5a25ce94
EI
6288 break;
6289 default:
6290 goto die;
6291 break;
6292 }
6293 break;
6294 case 15:
6295 switch (sel) {
6296 case 1:
895c2d04 6297 gen_helper_mftc0_ebase(t0, cpu_env);
5a25ce94
EI
6298 break;
6299 default:
6300 goto die;
6301 break;
6302 }
6303 break;
6304 case 16:
6305 switch (sel) {
6306 case 0 ... 7:
895c2d04 6307 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
5a25ce94
EI
6308 break;
6309 default:
6310 goto die;
6311 break;
6312 }
6313 break;
ead9360e
TS
6314 case 23:
6315 switch (sel) {
6316 case 0:
895c2d04 6317 gen_helper_mftc0_debug(t0, cpu_env);
ead9360e
TS
6318 break;
6319 default:
1a3fd9c3 6320 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
6321 break;
6322 }
6323 break;
6324 default:
1a3fd9c3 6325 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
6326 }
6327 } else switch (sel) {
6328 /* GPR registers. */
6329 case 0:
895c2d04 6330 gen_helper_1e0i(mftgpr, t0, rt);
ead9360e
TS
6331 break;
6332 /* Auxiliary CPU registers */
6333 case 1:
6334 switch (rt) {
6335 case 0:
895c2d04 6336 gen_helper_1e0i(mftlo, t0, 0);
ead9360e
TS
6337 break;
6338 case 1:
895c2d04 6339 gen_helper_1e0i(mfthi, t0, 0);
ead9360e
TS
6340 break;
6341 case 2:
895c2d04 6342 gen_helper_1e0i(mftacx, t0, 0);
ead9360e
TS
6343 break;
6344 case 4:
895c2d04 6345 gen_helper_1e0i(mftlo, t0, 1);
ead9360e
TS
6346 break;
6347 case 5:
895c2d04 6348 gen_helper_1e0i(mfthi, t0, 1);
ead9360e
TS
6349 break;
6350 case 6:
895c2d04 6351 gen_helper_1e0i(mftacx, t0, 1);
ead9360e
TS
6352 break;
6353 case 8:
895c2d04 6354 gen_helper_1e0i(mftlo, t0, 2);
ead9360e
TS
6355 break;
6356 case 9:
895c2d04 6357 gen_helper_1e0i(mfthi, t0, 2);
ead9360e
TS
6358 break;
6359 case 10:
895c2d04 6360 gen_helper_1e0i(mftacx, t0, 2);
ead9360e
TS
6361 break;
6362 case 12:
895c2d04 6363 gen_helper_1e0i(mftlo, t0, 3);
ead9360e
TS
6364 break;
6365 case 13:
895c2d04 6366 gen_helper_1e0i(mfthi, t0, 3);
ead9360e
TS
6367 break;
6368 case 14:
895c2d04 6369 gen_helper_1e0i(mftacx, t0, 3);
ead9360e
TS
6370 break;
6371 case 16:
895c2d04 6372 gen_helper_mftdsp(t0, cpu_env);
ead9360e
TS
6373 break;
6374 default:
6375 goto die;
6376 }
6377 break;
6378 /* Floating point (COP1). */
6379 case 2:
6380 /* XXX: For now we support only a single FPU context. */
6381 if (h == 0) {
a7812ae4 6382 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6383
6384 gen_load_fpr32(fp0, rt);
6385 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 6386 tcg_temp_free_i32(fp0);
ead9360e 6387 } else {
a7812ae4 6388 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6389
6390 gen_load_fpr32h(fp0, rt);
6391 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 6392 tcg_temp_free_i32(fp0);
ead9360e
TS
6393 }
6394 break;
6395 case 3:
6396 /* XXX: For now we support only a single FPU context. */
895c2d04 6397 gen_helper_1e0i(cfc1, t0, rt);
ead9360e
TS
6398 break;
6399 /* COP2: Not implemented. */
6400 case 4:
6401 case 5:
6402 /* fall through */
6403 default:
6404 goto die;
6405 }
d12d51d5 6406 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
1a3fd9c3
TS
6407 gen_store_gpr(t0, rd);
6408 tcg_temp_free(t0);
ead9360e
TS
6409 return;
6410
6411die:
1a3fd9c3 6412 tcg_temp_free(t0);
d12d51d5 6413 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
ead9360e
TS
6414 generate_exception(ctx, EXCP_RI);
6415}
6416
7db13fae 6417static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
ead9360e
TS
6418 int u, int sel, int h)
6419{
6420 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 6421 TCGv t0 = tcg_temp_local_new();
ead9360e 6422
1a3fd9c3 6423 gen_load_gpr(t0, rt);
ead9360e 6424 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
6425 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
6426 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
ead9360e
TS
6427 /* NOP */ ;
6428 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
6429 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
6430 /* NOP */ ;
6431 else if (u == 0) {
6432 switch (rd) {
5a25ce94
EI
6433 case 1:
6434 switch (sel) {
6435 case 1:
895c2d04 6436 gen_helper_mttc0_vpecontrol(cpu_env, t0);
5a25ce94
EI
6437 break;
6438 case 2:
895c2d04 6439 gen_helper_mttc0_vpeconf0(cpu_env, t0);
5a25ce94
EI
6440 break;
6441 default:
6442 goto die;
6443 break;
6444 }
6445 break;
ead9360e
TS
6446 case 2:
6447 switch (sel) {
6448 case 1:
895c2d04 6449 gen_helper_mttc0_tcstatus(cpu_env, t0);
ead9360e
TS
6450 break;
6451 case 2:
895c2d04 6452 gen_helper_mttc0_tcbind(cpu_env, t0);
ead9360e
TS
6453 break;
6454 case 3:
895c2d04 6455 gen_helper_mttc0_tcrestart(cpu_env, t0);
ead9360e
TS
6456 break;
6457 case 4:
895c2d04 6458 gen_helper_mttc0_tchalt(cpu_env, t0);
ead9360e
TS
6459 break;
6460 case 5:
895c2d04 6461 gen_helper_mttc0_tccontext(cpu_env, t0);
ead9360e
TS
6462 break;
6463 case 6:
895c2d04 6464 gen_helper_mttc0_tcschedule(cpu_env, t0);
ead9360e
TS
6465 break;
6466 case 7:
895c2d04 6467 gen_helper_mttc0_tcschefback(cpu_env, t0);
ead9360e
TS
6468 break;
6469 default:
1a3fd9c3 6470 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
6471 break;
6472 }
6473 break;
6474 case 10:
6475 switch (sel) {
6476 case 0:
895c2d04 6477 gen_helper_mttc0_entryhi(cpu_env, t0);
ead9360e
TS
6478 break;
6479 default:
1a3fd9c3 6480 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
6481 break;
6482 }
6483 case 12:
6484 switch (sel) {
6485 case 0:
895c2d04 6486 gen_helper_mttc0_status(cpu_env, t0);
ead9360e
TS
6487 break;
6488 default:
1a3fd9c3 6489 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
6490 break;
6491 }
5a25ce94
EI
6492 case 13:
6493 switch (sel) {
6494 case 0:
895c2d04 6495 gen_helper_mttc0_cause(cpu_env, t0);
5a25ce94
EI
6496 break;
6497 default:
6498 goto die;
6499 break;
6500 }
6501 break;
6502 case 15:
6503 switch (sel) {
6504 case 1:
895c2d04 6505 gen_helper_mttc0_ebase(cpu_env, t0);
5a25ce94
EI
6506 break;
6507 default:
6508 goto die;
6509 break;
6510 }
6511 break;
ead9360e
TS
6512 case 23:
6513 switch (sel) {
6514 case 0:
895c2d04 6515 gen_helper_mttc0_debug(cpu_env, t0);
ead9360e
TS
6516 break;
6517 default:
1a3fd9c3 6518 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
6519 break;
6520 }
6521 break;
6522 default:
1a3fd9c3 6523 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
6524 }
6525 } else switch (sel) {
6526 /* GPR registers. */
6527 case 0:
895c2d04 6528 gen_helper_0e1i(mttgpr, t0, rd);
ead9360e
TS
6529 break;
6530 /* Auxiliary CPU registers */
6531 case 1:
6532 switch (rd) {
6533 case 0:
895c2d04 6534 gen_helper_0e1i(mttlo, t0, 0);
ead9360e
TS
6535 break;
6536 case 1:
895c2d04 6537 gen_helper_0e1i(mtthi, t0, 0);
ead9360e
TS
6538 break;
6539 case 2:
895c2d04 6540 gen_helper_0e1i(mttacx, t0, 0);
ead9360e
TS
6541 break;
6542 case 4:
895c2d04 6543 gen_helper_0e1i(mttlo, t0, 1);
ead9360e
TS
6544 break;
6545 case 5:
895c2d04 6546 gen_helper_0e1i(mtthi, t0, 1);
ead9360e
TS
6547 break;
6548 case 6:
895c2d04 6549 gen_helper_0e1i(mttacx, t0, 1);
ead9360e
TS
6550 break;
6551 case 8:
895c2d04 6552 gen_helper_0e1i(mttlo, t0, 2);
ead9360e
TS
6553 break;
6554 case 9:
895c2d04 6555 gen_helper_0e1i(mtthi, t0, 2);
ead9360e
TS
6556 break;
6557 case 10:
895c2d04 6558 gen_helper_0e1i(mttacx, t0, 2);
ead9360e
TS
6559 break;
6560 case 12:
895c2d04 6561 gen_helper_0e1i(mttlo, t0, 3);
ead9360e
TS
6562 break;
6563 case 13:
895c2d04 6564 gen_helper_0e1i(mtthi, t0, 3);
ead9360e
TS
6565 break;
6566 case 14:
895c2d04 6567 gen_helper_0e1i(mttacx, t0, 3);
ead9360e
TS
6568 break;
6569 case 16:
895c2d04 6570 gen_helper_mttdsp(cpu_env, t0);
ead9360e
TS
6571 break;
6572 default:
6573 goto die;
6574 }
6575 break;
6576 /* Floating point (COP1). */
6577 case 2:
6578 /* XXX: For now we support only a single FPU context. */
6579 if (h == 0) {
a7812ae4 6580 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6581
6582 tcg_gen_trunc_tl_i32(fp0, t0);
6583 gen_store_fpr32(fp0, rd);
a7812ae4 6584 tcg_temp_free_i32(fp0);
ead9360e 6585 } else {
a7812ae4 6586 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6587
6588 tcg_gen_trunc_tl_i32(fp0, t0);
6589 gen_store_fpr32h(fp0, rd);
a7812ae4 6590 tcg_temp_free_i32(fp0);
ead9360e
TS
6591 }
6592 break;
6593 case 3:
6594 /* XXX: For now we support only a single FPU context. */
895c2d04 6595 gen_helper_0e1i(ctc1, t0, rd);
ead9360e
TS
6596 break;
6597 /* COP2: Not implemented. */
6598 case 4:
6599 case 5:
6600 /* fall through */
6601 default:
6602 goto die;
6603 }
d12d51d5 6604 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
1a3fd9c3 6605 tcg_temp_free(t0);
ead9360e
TS
6606 return;
6607
6608die:
1a3fd9c3 6609 tcg_temp_free(t0);
d12d51d5 6610 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
ead9360e
TS
6611 generate_exception(ctx, EXCP_RI);
6612}
6613
7db13fae 6614static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
6af0bf9c 6615{
287c4b84 6616 const char *opn = "ldst";
6af0bf9c 6617
2e15497c 6618 check_cp0_enabled(ctx);
6af0bf9c
FB
6619 switch (opc) {
6620 case OPC_MFC0:
6621 if (rt == 0) {
ead9360e 6622 /* Treat as NOP. */
6af0bf9c
FB
6623 return;
6624 }
1fc7bf6e 6625 gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
6af0bf9c
FB
6626 opn = "mfc0";
6627 break;
6628 case OPC_MTC0:
1a3fd9c3 6629 {
1fc7bf6e 6630 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
6631
6632 gen_load_gpr(t0, rt);
1a3fd9c3
TS
6633 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
6634 tcg_temp_free(t0);
6635 }
6af0bf9c
FB
6636 opn = "mtc0";
6637 break;
d26bc211 6638#if defined(TARGET_MIPS64)
9c2149c8 6639 case OPC_DMFC0:
e189e748 6640 check_insn(env, ctx, ISA_MIPS3);
9c2149c8 6641 if (rt == 0) {
ead9360e 6642 /* Treat as NOP. */
9c2149c8
TS
6643 return;
6644 }
1fc7bf6e 6645 gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9c2149c8
TS
6646 opn = "dmfc0";
6647 break;
6648 case OPC_DMTC0:
e189e748 6649 check_insn(env, ctx, ISA_MIPS3);
1a3fd9c3 6650 {
1fc7bf6e 6651 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
6652
6653 gen_load_gpr(t0, rt);
1a3fd9c3
TS
6654 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
6655 tcg_temp_free(t0);
6656 }
9c2149c8
TS
6657 opn = "dmtc0";
6658 break;
534ce69f 6659#endif
ead9360e 6660 case OPC_MFTR:
7385ac0b 6661 check_insn(env, ctx, ASE_MT);
ead9360e
TS
6662 if (rd == 0) {
6663 /* Treat as NOP. */
6664 return;
6665 }
6c5c1e20 6666 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
ead9360e 6667 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
ead9360e
TS
6668 opn = "mftr";
6669 break;
6670 case OPC_MTTR:
7385ac0b 6671 check_insn(env, ctx, ASE_MT);
6c5c1e20 6672 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
ead9360e
TS
6673 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
6674 opn = "mttr";
6675 break;
6af0bf9c 6676 case OPC_TLBWI:
6af0bf9c 6677 opn = "tlbwi";
c01fccd2 6678 if (!env->tlb->helper_tlbwi)
29929e34 6679 goto die;
895c2d04 6680 gen_helper_tlbwi(cpu_env);
6af0bf9c
FB
6681 break;
6682 case OPC_TLBWR:
6af0bf9c 6683 opn = "tlbwr";
c01fccd2 6684 if (!env->tlb->helper_tlbwr)
29929e34 6685 goto die;
895c2d04 6686 gen_helper_tlbwr(cpu_env);
6af0bf9c
FB
6687 break;
6688 case OPC_TLBP:
6af0bf9c 6689 opn = "tlbp";
c01fccd2 6690 if (!env->tlb->helper_tlbp)
29929e34 6691 goto die;
895c2d04 6692 gen_helper_tlbp(cpu_env);
6af0bf9c
FB
6693 break;
6694 case OPC_TLBR:
6af0bf9c 6695 opn = "tlbr";
c01fccd2 6696 if (!env->tlb->helper_tlbr)
29929e34 6697 goto die;
895c2d04 6698 gen_helper_tlbr(cpu_env);
6af0bf9c 6699 break;
6af0bf9c
FB
6700 case OPC_ERET:
6701 opn = "eret";
e189e748 6702 check_insn(env, ctx, ISA_MIPS2);
895c2d04 6703 gen_helper_eret(cpu_env);
6af0bf9c
FB
6704 ctx->bstate = BS_EXCP;
6705 break;
6706 case OPC_DERET:
6707 opn = "deret";
e189e748 6708 check_insn(env, ctx, ISA_MIPS32);
6af0bf9c 6709 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
923617a3 6710 MIPS_INVAL(opn);
6af0bf9c
FB
6711 generate_exception(ctx, EXCP_RI);
6712 } else {
895c2d04 6713 gen_helper_deret(cpu_env);
6af0bf9c
FB
6714 ctx->bstate = BS_EXCP;
6715 }
6716 break;
4ad40f36
FB
6717 case OPC_WAIT:
6718 opn = "wait";
e189e748 6719 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
4ad40f36
FB
6720 /* If we get an exception, we want to restart at next instruction */
6721 ctx->pc += 4;
6722 save_cpu_state(ctx, 1);
6723 ctx->pc -= 4;
895c2d04 6724 gen_helper_wait(cpu_env);
4ad40f36
FB
6725 ctx->bstate = BS_EXCP;
6726 break;
6af0bf9c 6727 default:
29929e34 6728 die:
923617a3 6729 MIPS_INVAL(opn);
6af0bf9c
FB
6730 generate_exception(ctx, EXCP_RI);
6731 return;
6732 }
2abf314d 6733 (void)opn; /* avoid a compiler warning */
6af0bf9c
FB
6734 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
6735}
f1aa6320 6736#endif /* !CONFIG_USER_ONLY */
6af0bf9c 6737
6ea83fed 6738/* CP1 Branches (before delay slot) */
7db13fae 6739static void gen_compute_branch1 (CPUMIPSState *env, DisasContext *ctx, uint32_t op,
5a5012ec 6740 int32_t cc, int32_t offset)
6ea83fed
FB
6741{
6742 target_ulong btarget;
923617a3 6743 const char *opn = "cp1 cond branch";
a7812ae4 6744 TCGv_i32 t0 = tcg_temp_new_i32();
6ea83fed 6745
e189e748
TS
6746 if (cc != 0)
6747 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
6748
6ea83fed
FB
6749 btarget = ctx->pc + 4 + offset;
6750
7a387fff
TS
6751 switch (op) {
6752 case OPC_BC1F:
d94536f4
AJ
6753 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6754 tcg_gen_not_i32(t0, t0);
6755 tcg_gen_andi_i32(t0, t0, 1);
6756 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 6757 opn = "bc1f";
6ea83fed 6758 goto not_likely;
7a387fff 6759 case OPC_BC1FL:
d94536f4
AJ
6760 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6761 tcg_gen_not_i32(t0, t0);
6762 tcg_gen_andi_i32(t0, t0, 1);
6763 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 6764 opn = "bc1fl";
6ea83fed 6765 goto likely;
7a387fff 6766 case OPC_BC1T:
d94536f4
AJ
6767 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6768 tcg_gen_andi_i32(t0, t0, 1);
6769 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 6770 opn = "bc1t";
5a5012ec 6771 goto not_likely;
7a387fff 6772 case OPC_BC1TL:
d94536f4
AJ
6773 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6774 tcg_gen_andi_i32(t0, t0, 1);
6775 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 6776 opn = "bc1tl";
6ea83fed
FB
6777 likely:
6778 ctx->hflags |= MIPS_HFLAG_BL;
6779 break;
5a5012ec 6780 case OPC_BC1FANY2:
a16336e4 6781 {
d94536f4
AJ
6782 TCGv_i32 t1 = tcg_temp_new_i32();
6783 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6784 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
d7f66b52 6785 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 6786 tcg_temp_free_i32(t1);
d94536f4
AJ
6787 tcg_gen_andi_i32(t0, t0, 1);
6788 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 6789 }
fd4a04eb 6790 opn = "bc1any2f";
5a5012ec
TS
6791 goto not_likely;
6792 case OPC_BC1TANY2:
a16336e4 6793 {
d94536f4
AJ
6794 TCGv_i32 t1 = tcg_temp_new_i32();
6795 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6796 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6797 tcg_gen_or_i32(t0, t0, t1);
6798 tcg_temp_free_i32(t1);
6799 tcg_gen_andi_i32(t0, t0, 1);
6800 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 6801 }
fd4a04eb 6802 opn = "bc1any2t";
5a5012ec
TS
6803 goto not_likely;
6804 case OPC_BC1FANY4:
a16336e4 6805 {
d94536f4
AJ
6806 TCGv_i32 t1 = tcg_temp_new_i32();
6807 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6808 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
d7f66b52 6809 tcg_gen_and_i32(t0, t0, t1);
d94536f4 6810 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
d7f66b52 6811 tcg_gen_and_i32(t0, t0, t1);
d94536f4 6812 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
d7f66b52 6813 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 6814 tcg_temp_free_i32(t1);
d94536f4
AJ
6815 tcg_gen_andi_i32(t0, t0, 1);
6816 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 6817 }
fd4a04eb 6818 opn = "bc1any4f";
5a5012ec
TS
6819 goto not_likely;
6820 case OPC_BC1TANY4:
a16336e4 6821 {
d94536f4
AJ
6822 TCGv_i32 t1 = tcg_temp_new_i32();
6823 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6824 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6825 tcg_gen_or_i32(t0, t0, t1);
6826 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6827 tcg_gen_or_i32(t0, t0, t1);
6828 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
6829 tcg_gen_or_i32(t0, t0, t1);
6830 tcg_temp_free_i32(t1);
6831 tcg_gen_andi_i32(t0, t0, 1);
6832 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 6833 }
fd4a04eb 6834 opn = "bc1any4t";
5a5012ec
TS
6835 not_likely:
6836 ctx->hflags |= MIPS_HFLAG_BC;
5a5012ec
TS
6837 break;
6838 default:
923617a3 6839 MIPS_INVAL(opn);
e397ee33 6840 generate_exception (ctx, EXCP_RI);
6c5c1e20 6841 goto out;
6ea83fed 6842 }
2abf314d 6843 (void)opn; /* avoid a compiler warning */
923617a3 6844 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
6ea83fed
FB
6845 ctx->hflags, btarget);
6846 ctx->btarget = btarget;
6c5c1e20
TS
6847
6848 out:
a7812ae4 6849 tcg_temp_free_i32(t0);
6ea83fed
FB
6850}
6851
6af0bf9c 6852/* Coprocessor 1 (FPU) */
5a5012ec 6853
5a5012ec
TS
6854#define FOP(func, fmt) (((fmt) << 21) | (func))
6855
bf4120ad
NF
6856enum fopcode {
6857 OPC_ADD_S = FOP(0, FMT_S),
6858 OPC_SUB_S = FOP(1, FMT_S),
6859 OPC_MUL_S = FOP(2, FMT_S),
6860 OPC_DIV_S = FOP(3, FMT_S),
6861 OPC_SQRT_S = FOP(4, FMT_S),
6862 OPC_ABS_S = FOP(5, FMT_S),
6863 OPC_MOV_S = FOP(6, FMT_S),
6864 OPC_NEG_S = FOP(7, FMT_S),
6865 OPC_ROUND_L_S = FOP(8, FMT_S),
6866 OPC_TRUNC_L_S = FOP(9, FMT_S),
6867 OPC_CEIL_L_S = FOP(10, FMT_S),
6868 OPC_FLOOR_L_S = FOP(11, FMT_S),
6869 OPC_ROUND_W_S = FOP(12, FMT_S),
6870 OPC_TRUNC_W_S = FOP(13, FMT_S),
6871 OPC_CEIL_W_S = FOP(14, FMT_S),
6872 OPC_FLOOR_W_S = FOP(15, FMT_S),
6873 OPC_MOVCF_S = FOP(17, FMT_S),
6874 OPC_MOVZ_S = FOP(18, FMT_S),
6875 OPC_MOVN_S = FOP(19, FMT_S),
6876 OPC_RECIP_S = FOP(21, FMT_S),
6877 OPC_RSQRT_S = FOP(22, FMT_S),
6878 OPC_RECIP2_S = FOP(28, FMT_S),
6879 OPC_RECIP1_S = FOP(29, FMT_S),
6880 OPC_RSQRT1_S = FOP(30, FMT_S),
6881 OPC_RSQRT2_S = FOP(31, FMT_S),
6882 OPC_CVT_D_S = FOP(33, FMT_S),
6883 OPC_CVT_W_S = FOP(36, FMT_S),
6884 OPC_CVT_L_S = FOP(37, FMT_S),
6885 OPC_CVT_PS_S = FOP(38, FMT_S),
6886 OPC_CMP_F_S = FOP (48, FMT_S),
6887 OPC_CMP_UN_S = FOP (49, FMT_S),
6888 OPC_CMP_EQ_S = FOP (50, FMT_S),
6889 OPC_CMP_UEQ_S = FOP (51, FMT_S),
6890 OPC_CMP_OLT_S = FOP (52, FMT_S),
6891 OPC_CMP_ULT_S = FOP (53, FMT_S),
6892 OPC_CMP_OLE_S = FOP (54, FMT_S),
6893 OPC_CMP_ULE_S = FOP (55, FMT_S),
6894 OPC_CMP_SF_S = FOP (56, FMT_S),
6895 OPC_CMP_NGLE_S = FOP (57, FMT_S),
6896 OPC_CMP_SEQ_S = FOP (58, FMT_S),
6897 OPC_CMP_NGL_S = FOP (59, FMT_S),
6898 OPC_CMP_LT_S = FOP (60, FMT_S),
6899 OPC_CMP_NGE_S = FOP (61, FMT_S),
6900 OPC_CMP_LE_S = FOP (62, FMT_S),
6901 OPC_CMP_NGT_S = FOP (63, FMT_S),
6902
6903 OPC_ADD_D = FOP(0, FMT_D),
6904 OPC_SUB_D = FOP(1, FMT_D),
6905 OPC_MUL_D = FOP(2, FMT_D),
6906 OPC_DIV_D = FOP(3, FMT_D),
6907 OPC_SQRT_D = FOP(4, FMT_D),
6908 OPC_ABS_D = FOP(5, FMT_D),
6909 OPC_MOV_D = FOP(6, FMT_D),
6910 OPC_NEG_D = FOP(7, FMT_D),
6911 OPC_ROUND_L_D = FOP(8, FMT_D),
6912 OPC_TRUNC_L_D = FOP(9, FMT_D),
6913 OPC_CEIL_L_D = FOP(10, FMT_D),
6914 OPC_FLOOR_L_D = FOP(11, FMT_D),
6915 OPC_ROUND_W_D = FOP(12, FMT_D),
6916 OPC_TRUNC_W_D = FOP(13, FMT_D),
6917 OPC_CEIL_W_D = FOP(14, FMT_D),
6918 OPC_FLOOR_W_D = FOP(15, FMT_D),
6919 OPC_MOVCF_D = FOP(17, FMT_D),
6920 OPC_MOVZ_D = FOP(18, FMT_D),
6921 OPC_MOVN_D = FOP(19, FMT_D),
6922 OPC_RECIP_D = FOP(21, FMT_D),
6923 OPC_RSQRT_D = FOP(22, FMT_D),
6924 OPC_RECIP2_D = FOP(28, FMT_D),
6925 OPC_RECIP1_D = FOP(29, FMT_D),
6926 OPC_RSQRT1_D = FOP(30, FMT_D),
6927 OPC_RSQRT2_D = FOP(31, FMT_D),
6928 OPC_CVT_S_D = FOP(32, FMT_D),
6929 OPC_CVT_W_D = FOP(36, FMT_D),
6930 OPC_CVT_L_D = FOP(37, FMT_D),
6931 OPC_CMP_F_D = FOP (48, FMT_D),
6932 OPC_CMP_UN_D = FOP (49, FMT_D),
6933 OPC_CMP_EQ_D = FOP (50, FMT_D),
6934 OPC_CMP_UEQ_D = FOP (51, FMT_D),
6935 OPC_CMP_OLT_D = FOP (52, FMT_D),
6936 OPC_CMP_ULT_D = FOP (53, FMT_D),
6937 OPC_CMP_OLE_D = FOP (54, FMT_D),
6938 OPC_CMP_ULE_D = FOP (55, FMT_D),
6939 OPC_CMP_SF_D = FOP (56, FMT_D),
6940 OPC_CMP_NGLE_D = FOP (57, FMT_D),
6941 OPC_CMP_SEQ_D = FOP (58, FMT_D),
6942 OPC_CMP_NGL_D = FOP (59, FMT_D),
6943 OPC_CMP_LT_D = FOP (60, FMT_D),
6944 OPC_CMP_NGE_D = FOP (61, FMT_D),
6945 OPC_CMP_LE_D = FOP (62, FMT_D),
6946 OPC_CMP_NGT_D = FOP (63, FMT_D),
6947
6948 OPC_CVT_S_W = FOP(32, FMT_W),
6949 OPC_CVT_D_W = FOP(33, FMT_W),
6950 OPC_CVT_S_L = FOP(32, FMT_L),
6951 OPC_CVT_D_L = FOP(33, FMT_L),
6952 OPC_CVT_PS_PW = FOP(38, FMT_W),
6953
6954 OPC_ADD_PS = FOP(0, FMT_PS),
6955 OPC_SUB_PS = FOP(1, FMT_PS),
6956 OPC_MUL_PS = FOP(2, FMT_PS),
6957 OPC_DIV_PS = FOP(3, FMT_PS),
6958 OPC_ABS_PS = FOP(5, FMT_PS),
6959 OPC_MOV_PS = FOP(6, FMT_PS),
6960 OPC_NEG_PS = FOP(7, FMT_PS),
6961 OPC_MOVCF_PS = FOP(17, FMT_PS),
6962 OPC_MOVZ_PS = FOP(18, FMT_PS),
6963 OPC_MOVN_PS = FOP(19, FMT_PS),
6964 OPC_ADDR_PS = FOP(24, FMT_PS),
6965 OPC_MULR_PS = FOP(26, FMT_PS),
6966 OPC_RECIP2_PS = FOP(28, FMT_PS),
6967 OPC_RECIP1_PS = FOP(29, FMT_PS),
6968 OPC_RSQRT1_PS = FOP(30, FMT_PS),
6969 OPC_RSQRT2_PS = FOP(31, FMT_PS),
6970
6971 OPC_CVT_S_PU = FOP(32, FMT_PS),
6972 OPC_CVT_PW_PS = FOP(36, FMT_PS),
6973 OPC_CVT_S_PL = FOP(40, FMT_PS),
6974 OPC_PLL_PS = FOP(44, FMT_PS),
6975 OPC_PLU_PS = FOP(45, FMT_PS),
6976 OPC_PUL_PS = FOP(46, FMT_PS),
6977 OPC_PUU_PS = FOP(47, FMT_PS),
6978 OPC_CMP_F_PS = FOP (48, FMT_PS),
6979 OPC_CMP_UN_PS = FOP (49, FMT_PS),
6980 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
6981 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
6982 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
6983 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
6984 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
6985 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
6986 OPC_CMP_SF_PS = FOP (56, FMT_PS),
6987 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
6988 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
6989 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
6990 OPC_CMP_LT_PS = FOP (60, FMT_PS),
6991 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
6992 OPC_CMP_LE_PS = FOP (62, FMT_PS),
6993 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
6994};
6995
7a387fff 6996static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6ea83fed 6997{
923617a3 6998 const char *opn = "cp1 move";
72c3a3ee 6999 TCGv t0 = tcg_temp_new();
6ea83fed
FB
7000
7001 switch (opc) {
7002 case OPC_MFC1:
b6d96bed 7003 {
a7812ae4 7004 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7005
7006 gen_load_fpr32(fp0, fs);
7007 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 7008 tcg_temp_free_i32(fp0);
6958549d 7009 }
6c5c1e20 7010 gen_store_gpr(t0, rt);
6ea83fed
FB
7011 opn = "mfc1";
7012 break;
7013 case OPC_MTC1:
6c5c1e20 7014 gen_load_gpr(t0, rt);
b6d96bed 7015 {
a7812ae4 7016 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7017
7018 tcg_gen_trunc_tl_i32(fp0, t0);
7019 gen_store_fpr32(fp0, fs);
a7812ae4 7020 tcg_temp_free_i32(fp0);
6958549d 7021 }
6ea83fed
FB
7022 opn = "mtc1";
7023 break;
7024 case OPC_CFC1:
895c2d04 7025 gen_helper_1e0i(cfc1, t0, fs);
6c5c1e20 7026 gen_store_gpr(t0, rt);
6ea83fed
FB
7027 opn = "cfc1";
7028 break;
7029 case OPC_CTC1:
6c5c1e20 7030 gen_load_gpr(t0, rt);
895c2d04 7031 gen_helper_0e1i(ctc1, t0, fs);
6ea83fed
FB
7032 opn = "ctc1";
7033 break;
72c3a3ee 7034#if defined(TARGET_MIPS64)
9c2149c8 7035 case OPC_DMFC1:
72c3a3ee 7036 gen_load_fpr64(ctx, t0, fs);
6c5c1e20 7037 gen_store_gpr(t0, rt);
5a5012ec
TS
7038 opn = "dmfc1";
7039 break;
9c2149c8 7040 case OPC_DMTC1:
6c5c1e20 7041 gen_load_gpr(t0, rt);
72c3a3ee 7042 gen_store_fpr64(ctx, t0, fs);
5a5012ec
TS
7043 opn = "dmtc1";
7044 break;
72c3a3ee 7045#endif
5a5012ec 7046 case OPC_MFHC1:
b6d96bed 7047 {
a7812ae4 7048 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7049
7050 gen_load_fpr32h(fp0, fs);
7051 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 7052 tcg_temp_free_i32(fp0);
6958549d 7053 }
6c5c1e20 7054 gen_store_gpr(t0, rt);
5a5012ec
TS
7055 opn = "mfhc1";
7056 break;
7057 case OPC_MTHC1:
6c5c1e20 7058 gen_load_gpr(t0, rt);
b6d96bed 7059 {
a7812ae4 7060 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7061
7062 tcg_gen_trunc_tl_i32(fp0, t0);
7063 gen_store_fpr32h(fp0, fs);
a7812ae4 7064 tcg_temp_free_i32(fp0);
6958549d 7065 }
5a5012ec
TS
7066 opn = "mthc1";
7067 break;
6ea83fed 7068 default:
923617a3 7069 MIPS_INVAL(opn);
e397ee33 7070 generate_exception (ctx, EXCP_RI);
6c5c1e20 7071 goto out;
6ea83fed 7072 }
2abf314d 7073 (void)opn; /* avoid a compiler warning */
6ea83fed 7074 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
6c5c1e20
TS
7075
7076 out:
7077 tcg_temp_free(t0);
6ea83fed
FB
7078}
7079
5a5012ec
TS
7080static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
7081{
af58f9ca 7082 int l1;
e214b9bb 7083 TCGCond cond;
af58f9ca
AJ
7084 TCGv_i32 t0;
7085
7086 if (rd == 0) {
7087 /* Treat as NOP. */
7088 return;
7089 }
6ea83fed 7090
e214b9bb 7091 if (tf)
e214b9bb 7092 cond = TCG_COND_EQ;
27848470
TS
7093 else
7094 cond = TCG_COND_NE;
7095
af58f9ca
AJ
7096 l1 = gen_new_label();
7097 t0 = tcg_temp_new_i32();
fa31af0e 7098 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
af58f9ca 7099 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 7100 tcg_temp_free_i32(t0);
af58f9ca
AJ
7101 if (rs == 0) {
7102 tcg_gen_movi_tl(cpu_gpr[rd], 0);
7103 } else {
7104 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
7105 }
e214b9bb 7106 gen_set_label(l1);
5a5012ec
TS
7107}
7108
b6d96bed 7109static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
a16336e4 7110{
a16336e4 7111 int cond;
cbc37b28 7112 TCGv_i32 t0 = tcg_temp_new_i32();
a16336e4
TS
7113 int l1 = gen_new_label();
7114
a16336e4
TS
7115 if (tf)
7116 cond = TCG_COND_EQ;
7117 else
7118 cond = TCG_COND_NE;
7119
fa31af0e 7120 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28
AJ
7121 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7122 gen_load_fpr32(t0, fs);
7123 gen_store_fpr32(t0, fd);
a16336e4 7124 gen_set_label(l1);
cbc37b28 7125 tcg_temp_free_i32(t0);
5a5012ec 7126}
a16336e4 7127
b6d96bed 7128static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
a16336e4 7129{
a16336e4 7130 int cond;
cbc37b28
AJ
7131 TCGv_i32 t0 = tcg_temp_new_i32();
7132 TCGv_i64 fp0;
a16336e4
TS
7133 int l1 = gen_new_label();
7134
a16336e4
TS
7135 if (tf)
7136 cond = TCG_COND_EQ;
7137 else
7138 cond = TCG_COND_NE;
7139
fa31af0e 7140 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 7141 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 7142 tcg_temp_free_i32(t0);
11f94258 7143 fp0 = tcg_temp_new_i64();
9bf3eb2c 7144 gen_load_fpr64(ctx, fp0, fs);
9bf3eb2c 7145 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7146 tcg_temp_free_i64(fp0);
cbc37b28 7147 gen_set_label(l1);
a16336e4
TS
7148}
7149
b6d96bed 7150static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
a16336e4
TS
7151{
7152 int cond;
cbc37b28 7153 TCGv_i32 t0 = tcg_temp_new_i32();
a16336e4
TS
7154 int l1 = gen_new_label();
7155 int l2 = gen_new_label();
7156
7157 if (tf)
7158 cond = TCG_COND_EQ;
7159 else
7160 cond = TCG_COND_NE;
7161
fa31af0e 7162 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28
AJ
7163 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7164 gen_load_fpr32(t0, fs);
7165 gen_store_fpr32(t0, fd);
a16336e4 7166 gen_set_label(l1);
9bf3eb2c 7167
fa31af0e 7168 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
cbc37b28
AJ
7169 tcg_gen_brcondi_i32(cond, t0, 0, l2);
7170 gen_load_fpr32h(t0, fs);
7171 gen_store_fpr32h(t0, fd);
52a0e9eb 7172 tcg_temp_free_i32(t0);
a16336e4 7173 gen_set_label(l2);
a16336e4
TS
7174}
7175
6ea83fed 7176
bf4120ad 7177static void gen_farith (DisasContext *ctx, enum fopcode op1,
5e755519 7178 int ft, int fs, int fd, int cc)
6ea83fed 7179{
923617a3 7180 const char *opn = "farith";
6ea83fed
FB
7181 const char *condnames[] = {
7182 "c.f",
7183 "c.un",
7184 "c.eq",
7185 "c.ueq",
7186 "c.olt",
7187 "c.ult",
7188 "c.ole",
7189 "c.ule",
7190 "c.sf",
7191 "c.ngle",
7192 "c.seq",
7193 "c.ngl",
7194 "c.lt",
7195 "c.nge",
7196 "c.le",
7197 "c.ngt",
7198 };
5a1e8ffb
TS
7199 const char *condnames_abs[] = {
7200 "cabs.f",
7201 "cabs.un",
7202 "cabs.eq",
7203 "cabs.ueq",
7204 "cabs.olt",
7205 "cabs.ult",
7206 "cabs.ole",
7207 "cabs.ule",
7208 "cabs.sf",
7209 "cabs.ngle",
7210 "cabs.seq",
7211 "cabs.ngl",
7212 "cabs.lt",
7213 "cabs.nge",
7214 "cabs.le",
7215 "cabs.ngt",
7216 };
7217 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
7a387fff
TS
7218 uint32_t func = ctx->opcode & 0x3f;
7219
bf4120ad
NF
7220 switch (op1) {
7221 case OPC_ADD_S:
b6d96bed 7222 {
a7812ae4
PB
7223 TCGv_i32 fp0 = tcg_temp_new_i32();
7224 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7225
7226 gen_load_fpr32(fp0, fs);
7227 gen_load_fpr32(fp1, ft);
895c2d04 7228 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
a7812ae4 7229 tcg_temp_free_i32(fp1);
b6d96bed 7230 gen_store_fpr32(fp0, fd);
a7812ae4 7231 tcg_temp_free_i32(fp0);
b6d96bed 7232 }
5a5012ec 7233 opn = "add.s";
5a1e8ffb 7234 optype = BINOP;
5a5012ec 7235 break;
bf4120ad 7236 case OPC_SUB_S:
b6d96bed 7237 {
a7812ae4
PB
7238 TCGv_i32 fp0 = tcg_temp_new_i32();
7239 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7240
7241 gen_load_fpr32(fp0, fs);
7242 gen_load_fpr32(fp1, ft);
895c2d04 7243 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
a7812ae4 7244 tcg_temp_free_i32(fp1);
b6d96bed 7245 gen_store_fpr32(fp0, fd);
a7812ae4 7246 tcg_temp_free_i32(fp0);
b6d96bed 7247 }
5a5012ec 7248 opn = "sub.s";
5a1e8ffb 7249 optype = BINOP;
5a5012ec 7250 break;
bf4120ad 7251 case OPC_MUL_S:
b6d96bed 7252 {
a7812ae4
PB
7253 TCGv_i32 fp0 = tcg_temp_new_i32();
7254 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7255
7256 gen_load_fpr32(fp0, fs);
7257 gen_load_fpr32(fp1, ft);
895c2d04 7258 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
a7812ae4 7259 tcg_temp_free_i32(fp1);
b6d96bed 7260 gen_store_fpr32(fp0, fd);
a7812ae4 7261 tcg_temp_free_i32(fp0);
b6d96bed 7262 }
5a5012ec 7263 opn = "mul.s";
5a1e8ffb 7264 optype = BINOP;
5a5012ec 7265 break;
bf4120ad 7266 case OPC_DIV_S:
b6d96bed 7267 {
a7812ae4
PB
7268 TCGv_i32 fp0 = tcg_temp_new_i32();
7269 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7270
7271 gen_load_fpr32(fp0, fs);
7272 gen_load_fpr32(fp1, ft);
895c2d04 7273 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
a7812ae4 7274 tcg_temp_free_i32(fp1);
b6d96bed 7275 gen_store_fpr32(fp0, fd);
a7812ae4 7276 tcg_temp_free_i32(fp0);
b6d96bed 7277 }
5a5012ec 7278 opn = "div.s";
5a1e8ffb 7279 optype = BINOP;
5a5012ec 7280 break;
bf4120ad 7281 case OPC_SQRT_S:
b6d96bed 7282 {
a7812ae4 7283 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7284
7285 gen_load_fpr32(fp0, fs);
895c2d04 7286 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
b6d96bed 7287 gen_store_fpr32(fp0, fd);
a7812ae4 7288 tcg_temp_free_i32(fp0);
b6d96bed 7289 }
5a5012ec
TS
7290 opn = "sqrt.s";
7291 break;
bf4120ad 7292 case OPC_ABS_S:
b6d96bed 7293 {
a7812ae4 7294 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7295
7296 gen_load_fpr32(fp0, fs);
a7812ae4 7297 gen_helper_float_abs_s(fp0, fp0);
b6d96bed 7298 gen_store_fpr32(fp0, fd);
a7812ae4 7299 tcg_temp_free_i32(fp0);
b6d96bed 7300 }
5a5012ec
TS
7301 opn = "abs.s";
7302 break;
bf4120ad 7303 case OPC_MOV_S:
b6d96bed 7304 {
a7812ae4 7305 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7306
7307 gen_load_fpr32(fp0, fs);
7308 gen_store_fpr32(fp0, fd);
a7812ae4 7309 tcg_temp_free_i32(fp0);
b6d96bed 7310 }
5a5012ec
TS
7311 opn = "mov.s";
7312 break;
bf4120ad 7313 case OPC_NEG_S:
b6d96bed 7314 {
a7812ae4 7315 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7316
7317 gen_load_fpr32(fp0, fs);
a7812ae4 7318 gen_helper_float_chs_s(fp0, fp0);
b6d96bed 7319 gen_store_fpr32(fp0, fd);
a7812ae4 7320 tcg_temp_free_i32(fp0);
b6d96bed 7321 }
5a5012ec
TS
7322 opn = "neg.s";
7323 break;
bf4120ad 7324 case OPC_ROUND_L_S:
5e755519 7325 check_cp1_64bitmode(ctx);
b6d96bed 7326 {
a7812ae4
PB
7327 TCGv_i32 fp32 = tcg_temp_new_i32();
7328 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7329
7330 gen_load_fpr32(fp32, fs);
895c2d04 7331 gen_helper_float_roundl_s(fp64, cpu_env, fp32);
a7812ae4 7332 tcg_temp_free_i32(fp32);
b6d96bed 7333 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 7334 tcg_temp_free_i64(fp64);
b6d96bed 7335 }
5a5012ec
TS
7336 opn = "round.l.s";
7337 break;
bf4120ad 7338 case OPC_TRUNC_L_S:
5e755519 7339 check_cp1_64bitmode(ctx);
b6d96bed 7340 {
a7812ae4
PB
7341 TCGv_i32 fp32 = tcg_temp_new_i32();
7342 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7343
7344 gen_load_fpr32(fp32, fs);
895c2d04 7345 gen_helper_float_truncl_s(fp64, cpu_env, fp32);
a7812ae4 7346 tcg_temp_free_i32(fp32);
b6d96bed 7347 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 7348 tcg_temp_free_i64(fp64);
b6d96bed 7349 }
5a5012ec
TS
7350 opn = "trunc.l.s";
7351 break;
bf4120ad 7352 case OPC_CEIL_L_S:
5e755519 7353 check_cp1_64bitmode(ctx);
b6d96bed 7354 {
a7812ae4
PB
7355 TCGv_i32 fp32 = tcg_temp_new_i32();
7356 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7357
7358 gen_load_fpr32(fp32, fs);
895c2d04 7359 gen_helper_float_ceill_s(fp64, cpu_env, fp32);
a7812ae4 7360 tcg_temp_free_i32(fp32);
b6d96bed 7361 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 7362 tcg_temp_free_i64(fp64);
b6d96bed 7363 }
5a5012ec
TS
7364 opn = "ceil.l.s";
7365 break;
bf4120ad 7366 case OPC_FLOOR_L_S:
5e755519 7367 check_cp1_64bitmode(ctx);
b6d96bed 7368 {
a7812ae4
PB
7369 TCGv_i32 fp32 = tcg_temp_new_i32();
7370 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7371
7372 gen_load_fpr32(fp32, fs);
895c2d04 7373 gen_helper_float_floorl_s(fp64, cpu_env, fp32);
a7812ae4 7374 tcg_temp_free_i32(fp32);
b6d96bed 7375 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 7376 tcg_temp_free_i64(fp64);
b6d96bed 7377 }
5a5012ec
TS
7378 opn = "floor.l.s";
7379 break;
bf4120ad 7380 case OPC_ROUND_W_S:
b6d96bed 7381 {
a7812ae4 7382 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7383
7384 gen_load_fpr32(fp0, fs);
895c2d04 7385 gen_helper_float_roundw_s(fp0, cpu_env, fp0);
b6d96bed 7386 gen_store_fpr32(fp0, fd);
a7812ae4 7387 tcg_temp_free_i32(fp0);
b6d96bed 7388 }
5a5012ec
TS
7389 opn = "round.w.s";
7390 break;
bf4120ad 7391 case OPC_TRUNC_W_S:
b6d96bed 7392 {
a7812ae4 7393 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7394
7395 gen_load_fpr32(fp0, fs);
895c2d04 7396 gen_helper_float_truncw_s(fp0, cpu_env, fp0);
b6d96bed 7397 gen_store_fpr32(fp0, fd);
a7812ae4 7398 tcg_temp_free_i32(fp0);
b6d96bed 7399 }
5a5012ec
TS
7400 opn = "trunc.w.s";
7401 break;
bf4120ad 7402 case OPC_CEIL_W_S:
b6d96bed 7403 {
a7812ae4 7404 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7405
7406 gen_load_fpr32(fp0, fs);
895c2d04 7407 gen_helper_float_ceilw_s(fp0, cpu_env, fp0);
b6d96bed 7408 gen_store_fpr32(fp0, fd);
a7812ae4 7409 tcg_temp_free_i32(fp0);
b6d96bed 7410 }
5a5012ec
TS
7411 opn = "ceil.w.s";
7412 break;
bf4120ad 7413 case OPC_FLOOR_W_S:
b6d96bed 7414 {
a7812ae4 7415 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7416
7417 gen_load_fpr32(fp0, fs);
895c2d04 7418 gen_helper_float_floorw_s(fp0, cpu_env, fp0);
b6d96bed 7419 gen_store_fpr32(fp0, fd);
a7812ae4 7420 tcg_temp_free_i32(fp0);
b6d96bed 7421 }
5a5012ec
TS
7422 opn = "floor.w.s";
7423 break;
bf4120ad 7424 case OPC_MOVCF_S:
b6d96bed 7425 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec
TS
7426 opn = "movcf.s";
7427 break;
bf4120ad 7428 case OPC_MOVZ_S:
a16336e4
TS
7429 {
7430 int l1 = gen_new_label();
c9297f4d 7431 TCGv_i32 fp0;
a16336e4 7432
c9297f4d
AJ
7433 if (ft != 0) {
7434 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7435 }
7436 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7437 gen_load_fpr32(fp0, fs);
7438 gen_store_fpr32(fp0, fd);
a7812ae4 7439 tcg_temp_free_i32(fp0);
a16336e4
TS
7440 gen_set_label(l1);
7441 }
5a5012ec
TS
7442 opn = "movz.s";
7443 break;
bf4120ad 7444 case OPC_MOVN_S:
a16336e4
TS
7445 {
7446 int l1 = gen_new_label();
c9297f4d
AJ
7447 TCGv_i32 fp0;
7448
7449 if (ft != 0) {
7450 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7451 fp0 = tcg_temp_new_i32();
7452 gen_load_fpr32(fp0, fs);
7453 gen_store_fpr32(fp0, fd);
7454 tcg_temp_free_i32(fp0);
7455 gen_set_label(l1);
7456 }
a16336e4 7457 }
5a5012ec
TS
7458 opn = "movn.s";
7459 break;
bf4120ad 7460 case OPC_RECIP_S:
b8aa4598 7461 check_cop1x(ctx);
b6d96bed 7462 {
a7812ae4 7463 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7464
7465 gen_load_fpr32(fp0, fs);
895c2d04 7466 gen_helper_float_recip_s(fp0, cpu_env, fp0);
b6d96bed 7467 gen_store_fpr32(fp0, fd);
a7812ae4 7468 tcg_temp_free_i32(fp0);
b6d96bed 7469 }
57fa1fb3
TS
7470 opn = "recip.s";
7471 break;
bf4120ad 7472 case OPC_RSQRT_S:
b8aa4598 7473 check_cop1x(ctx);
b6d96bed 7474 {
a7812ae4 7475 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7476
7477 gen_load_fpr32(fp0, fs);
895c2d04 7478 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
b6d96bed 7479 gen_store_fpr32(fp0, fd);
a7812ae4 7480 tcg_temp_free_i32(fp0);
b6d96bed 7481 }
57fa1fb3
TS
7482 opn = "rsqrt.s";
7483 break;
bf4120ad 7484 case OPC_RECIP2_S:
5e755519 7485 check_cp1_64bitmode(ctx);
b6d96bed 7486 {
a7812ae4
PB
7487 TCGv_i32 fp0 = tcg_temp_new_i32();
7488 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7489
7490 gen_load_fpr32(fp0, fs);
d22d7289 7491 gen_load_fpr32(fp1, ft);
895c2d04 7492 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
a7812ae4 7493 tcg_temp_free_i32(fp1);
b6d96bed 7494 gen_store_fpr32(fp0, fd);
a7812ae4 7495 tcg_temp_free_i32(fp0);
b6d96bed 7496 }
57fa1fb3
TS
7497 opn = "recip2.s";
7498 break;
bf4120ad 7499 case OPC_RECIP1_S:
5e755519 7500 check_cp1_64bitmode(ctx);
b6d96bed 7501 {
a7812ae4 7502 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7503
7504 gen_load_fpr32(fp0, fs);
895c2d04 7505 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
b6d96bed 7506 gen_store_fpr32(fp0, fd);
a7812ae4 7507 tcg_temp_free_i32(fp0);
b6d96bed 7508 }
57fa1fb3
TS
7509 opn = "recip1.s";
7510 break;
bf4120ad 7511 case OPC_RSQRT1_S:
5e755519 7512 check_cp1_64bitmode(ctx);
b6d96bed 7513 {
a7812ae4 7514 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7515
7516 gen_load_fpr32(fp0, fs);
895c2d04 7517 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
b6d96bed 7518 gen_store_fpr32(fp0, fd);
a7812ae4 7519 tcg_temp_free_i32(fp0);
b6d96bed 7520 }
57fa1fb3
TS
7521 opn = "rsqrt1.s";
7522 break;
bf4120ad 7523 case OPC_RSQRT2_S:
5e755519 7524 check_cp1_64bitmode(ctx);
b6d96bed 7525 {
a7812ae4
PB
7526 TCGv_i32 fp0 = tcg_temp_new_i32();
7527 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7528
7529 gen_load_fpr32(fp0, fs);
7530 gen_load_fpr32(fp1, ft);
895c2d04 7531 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
a7812ae4 7532 tcg_temp_free_i32(fp1);
b6d96bed 7533 gen_store_fpr32(fp0, fd);
a7812ae4 7534 tcg_temp_free_i32(fp0);
b6d96bed 7535 }
57fa1fb3
TS
7536 opn = "rsqrt2.s";
7537 break;
bf4120ad 7538 case OPC_CVT_D_S:
5e755519 7539 check_cp1_registers(ctx, fd);
b6d96bed 7540 {
a7812ae4
PB
7541 TCGv_i32 fp32 = tcg_temp_new_i32();
7542 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7543
7544 gen_load_fpr32(fp32, fs);
895c2d04 7545 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
a7812ae4 7546 tcg_temp_free_i32(fp32);
b6d96bed 7547 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 7548 tcg_temp_free_i64(fp64);
b6d96bed 7549 }
5a5012ec
TS
7550 opn = "cvt.d.s";
7551 break;
bf4120ad 7552 case OPC_CVT_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_cvtw_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 = "cvt.w.s";
7562 break;
bf4120ad 7563 case OPC_CVT_L_S:
5e755519 7564 check_cp1_64bitmode(ctx);
b6d96bed 7565 {
a7812ae4
PB
7566 TCGv_i32 fp32 = tcg_temp_new_i32();
7567 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7568
7569 gen_load_fpr32(fp32, fs);
895c2d04 7570 gen_helper_float_cvtl_s(fp64, cpu_env, fp32);
a7812ae4 7571 tcg_temp_free_i32(fp32);
b6d96bed 7572 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 7573 tcg_temp_free_i64(fp64);
b6d96bed 7574 }
5a5012ec
TS
7575 opn = "cvt.l.s";
7576 break;
bf4120ad 7577 case OPC_CVT_PS_S:
5e755519 7578 check_cp1_64bitmode(ctx);
b6d96bed 7579 {
a7812ae4
PB
7580 TCGv_i64 fp64 = tcg_temp_new_i64();
7581 TCGv_i32 fp32_0 = tcg_temp_new_i32();
7582 TCGv_i32 fp32_1 = tcg_temp_new_i32();
b6d96bed
TS
7583
7584 gen_load_fpr32(fp32_0, fs);
7585 gen_load_fpr32(fp32_1, ft);
13d24f49 7586 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
a7812ae4
PB
7587 tcg_temp_free_i32(fp32_1);
7588 tcg_temp_free_i32(fp32_0);
36aa55dc 7589 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 7590 tcg_temp_free_i64(fp64);
b6d96bed 7591 }
5a5012ec
TS
7592 opn = "cvt.ps.s";
7593 break;
bf4120ad
NF
7594 case OPC_CMP_F_S:
7595 case OPC_CMP_UN_S:
7596 case OPC_CMP_EQ_S:
7597 case OPC_CMP_UEQ_S:
7598 case OPC_CMP_OLT_S:
7599 case OPC_CMP_ULT_S:
7600 case OPC_CMP_OLE_S:
7601 case OPC_CMP_ULE_S:
7602 case OPC_CMP_SF_S:
7603 case OPC_CMP_NGLE_S:
7604 case OPC_CMP_SEQ_S:
7605 case OPC_CMP_NGL_S:
7606 case OPC_CMP_LT_S:
7607 case OPC_CMP_NGE_S:
7608 case OPC_CMP_LE_S:
7609 case OPC_CMP_NGT_S:
8153667c
NF
7610 if (ctx->opcode & (1 << 6)) {
7611 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
7612 opn = condnames_abs[func-48];
7613 } else {
7614 gen_cmp_s(ctx, func-48, ft, fs, cc);
7615 opn = condnames[func-48];
5a1e8ffb 7616 }
5a5012ec 7617 break;
bf4120ad 7618 case OPC_ADD_D:
5e755519 7619 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 7620 {
a7812ae4
PB
7621 TCGv_i64 fp0 = tcg_temp_new_i64();
7622 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7623
7624 gen_load_fpr64(ctx, fp0, fs);
7625 gen_load_fpr64(ctx, fp1, ft);
895c2d04 7626 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
a7812ae4 7627 tcg_temp_free_i64(fp1);
b6d96bed 7628 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7629 tcg_temp_free_i64(fp0);
b6d96bed 7630 }
6ea83fed 7631 opn = "add.d";
5a1e8ffb 7632 optype = BINOP;
6ea83fed 7633 break;
bf4120ad 7634 case OPC_SUB_D:
5e755519 7635 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 7636 {
a7812ae4
PB
7637 TCGv_i64 fp0 = tcg_temp_new_i64();
7638 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7639
7640 gen_load_fpr64(ctx, fp0, fs);
7641 gen_load_fpr64(ctx, fp1, ft);
895c2d04 7642 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
a7812ae4 7643 tcg_temp_free_i64(fp1);
b6d96bed 7644 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7645 tcg_temp_free_i64(fp0);
b6d96bed 7646 }
6ea83fed 7647 opn = "sub.d";
5a1e8ffb 7648 optype = BINOP;
6ea83fed 7649 break;
bf4120ad 7650 case OPC_MUL_D:
5e755519 7651 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 7652 {
a7812ae4
PB
7653 TCGv_i64 fp0 = tcg_temp_new_i64();
7654 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7655
7656 gen_load_fpr64(ctx, fp0, fs);
7657 gen_load_fpr64(ctx, fp1, ft);
895c2d04 7658 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
a7812ae4 7659 tcg_temp_free_i64(fp1);
b6d96bed 7660 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7661 tcg_temp_free_i64(fp0);
b6d96bed 7662 }
6ea83fed 7663 opn = "mul.d";
5a1e8ffb 7664 optype = BINOP;
6ea83fed 7665 break;
bf4120ad 7666 case OPC_DIV_D:
5e755519 7667 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 7668 {
a7812ae4
PB
7669 TCGv_i64 fp0 = tcg_temp_new_i64();
7670 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7671
7672 gen_load_fpr64(ctx, fp0, fs);
7673 gen_load_fpr64(ctx, fp1, ft);
895c2d04 7674 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
a7812ae4 7675 tcg_temp_free_i64(fp1);
b6d96bed 7676 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7677 tcg_temp_free_i64(fp0);
b6d96bed 7678 }
6ea83fed 7679 opn = "div.d";
5a1e8ffb 7680 optype = BINOP;
6ea83fed 7681 break;
bf4120ad 7682 case OPC_SQRT_D:
5e755519 7683 check_cp1_registers(ctx, fs | fd);
b6d96bed 7684 {
a7812ae4 7685 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7686
7687 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7688 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
b6d96bed 7689 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7690 tcg_temp_free_i64(fp0);
b6d96bed 7691 }
6ea83fed
FB
7692 opn = "sqrt.d";
7693 break;
bf4120ad 7694 case OPC_ABS_D:
5e755519 7695 check_cp1_registers(ctx, fs | fd);
b6d96bed 7696 {
a7812ae4 7697 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7698
7699 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7700 gen_helper_float_abs_d(fp0, fp0);
b6d96bed 7701 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7702 tcg_temp_free_i64(fp0);
b6d96bed 7703 }
6ea83fed
FB
7704 opn = "abs.d";
7705 break;
bf4120ad 7706 case OPC_MOV_D:
5e755519 7707 check_cp1_registers(ctx, fs | fd);
b6d96bed 7708 {
a7812ae4 7709 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7710
7711 gen_load_fpr64(ctx, fp0, fs);
7712 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7713 tcg_temp_free_i64(fp0);
b6d96bed 7714 }
6ea83fed
FB
7715 opn = "mov.d";
7716 break;
bf4120ad 7717 case OPC_NEG_D:
5e755519 7718 check_cp1_registers(ctx, fs | fd);
b6d96bed 7719 {
a7812ae4 7720 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7721
7722 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7723 gen_helper_float_chs_d(fp0, fp0);
b6d96bed 7724 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7725 tcg_temp_free_i64(fp0);
b6d96bed 7726 }
6ea83fed
FB
7727 opn = "neg.d";
7728 break;
bf4120ad 7729 case OPC_ROUND_L_D:
5e755519 7730 check_cp1_64bitmode(ctx);
b6d96bed 7731 {
a7812ae4 7732 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7733
7734 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7735 gen_helper_float_roundl_d(fp0, cpu_env, fp0);
b6d96bed 7736 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7737 tcg_temp_free_i64(fp0);
b6d96bed 7738 }
5a5012ec
TS
7739 opn = "round.l.d";
7740 break;
bf4120ad 7741 case OPC_TRUNC_L_D:
5e755519 7742 check_cp1_64bitmode(ctx);
b6d96bed 7743 {
a7812ae4 7744 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7745
7746 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7747 gen_helper_float_truncl_d(fp0, cpu_env, fp0);
b6d96bed 7748 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7749 tcg_temp_free_i64(fp0);
b6d96bed 7750 }
5a5012ec
TS
7751 opn = "trunc.l.d";
7752 break;
bf4120ad 7753 case OPC_CEIL_L_D:
5e755519 7754 check_cp1_64bitmode(ctx);
b6d96bed 7755 {
a7812ae4 7756 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7757
7758 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7759 gen_helper_float_ceill_d(fp0, cpu_env, fp0);
b6d96bed 7760 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7761 tcg_temp_free_i64(fp0);
b6d96bed 7762 }
5a5012ec
TS
7763 opn = "ceil.l.d";
7764 break;
bf4120ad 7765 case OPC_FLOOR_L_D:
5e755519 7766 check_cp1_64bitmode(ctx);
b6d96bed 7767 {
a7812ae4 7768 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7769
7770 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7771 gen_helper_float_floorl_d(fp0, cpu_env, fp0);
b6d96bed 7772 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7773 tcg_temp_free_i64(fp0);
b6d96bed 7774 }
5a5012ec
TS
7775 opn = "floor.l.d";
7776 break;
bf4120ad 7777 case OPC_ROUND_W_D:
5e755519 7778 check_cp1_registers(ctx, fs);
b6d96bed 7779 {
a7812ae4
PB
7780 TCGv_i32 fp32 = tcg_temp_new_i32();
7781 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7782
7783 gen_load_fpr64(ctx, fp64, fs);
895c2d04 7784 gen_helper_float_roundw_d(fp32, cpu_env, fp64);
a7812ae4 7785 tcg_temp_free_i64(fp64);
b6d96bed 7786 gen_store_fpr32(fp32, fd);
a7812ae4 7787 tcg_temp_free_i32(fp32);
b6d96bed 7788 }
6ea83fed
FB
7789 opn = "round.w.d";
7790 break;
bf4120ad 7791 case OPC_TRUNC_W_D:
5e755519 7792 check_cp1_registers(ctx, fs);
b6d96bed 7793 {
a7812ae4
PB
7794 TCGv_i32 fp32 = tcg_temp_new_i32();
7795 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7796
7797 gen_load_fpr64(ctx, fp64, fs);
895c2d04 7798 gen_helper_float_truncw_d(fp32, cpu_env, fp64);
a7812ae4 7799 tcg_temp_free_i64(fp64);
b6d96bed 7800 gen_store_fpr32(fp32, fd);
a7812ae4 7801 tcg_temp_free_i32(fp32);
b6d96bed 7802 }
6ea83fed
FB
7803 opn = "trunc.w.d";
7804 break;
bf4120ad 7805 case OPC_CEIL_W_D:
5e755519 7806 check_cp1_registers(ctx, fs);
b6d96bed 7807 {
a7812ae4
PB
7808 TCGv_i32 fp32 = tcg_temp_new_i32();
7809 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7810
7811 gen_load_fpr64(ctx, fp64, fs);
895c2d04 7812 gen_helper_float_ceilw_d(fp32, cpu_env, fp64);
a7812ae4 7813 tcg_temp_free_i64(fp64);
b6d96bed 7814 gen_store_fpr32(fp32, fd);
a7812ae4 7815 tcg_temp_free_i32(fp32);
b6d96bed 7816 }
6ea83fed
FB
7817 opn = "ceil.w.d";
7818 break;
bf4120ad 7819 case OPC_FLOOR_W_D:
5e755519 7820 check_cp1_registers(ctx, fs);
b6d96bed 7821 {
a7812ae4
PB
7822 TCGv_i32 fp32 = tcg_temp_new_i32();
7823 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7824
7825 gen_load_fpr64(ctx, fp64, fs);
895c2d04 7826 gen_helper_float_floorw_d(fp32, cpu_env, fp64);
a7812ae4 7827 tcg_temp_free_i64(fp64);
b6d96bed 7828 gen_store_fpr32(fp32, fd);
a7812ae4 7829 tcg_temp_free_i32(fp32);
b6d96bed 7830 }
7a387fff 7831 opn = "floor.w.d";
6ea83fed 7832 break;
bf4120ad 7833 case OPC_MOVCF_D:
b6d96bed 7834 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 7835 opn = "movcf.d";
dd016883 7836 break;
bf4120ad 7837 case OPC_MOVZ_D:
a16336e4
TS
7838 {
7839 int l1 = gen_new_label();
c9297f4d 7840 TCGv_i64 fp0;
a16336e4 7841
c9297f4d
AJ
7842 if (ft != 0) {
7843 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7844 }
7845 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7846 gen_load_fpr64(ctx, fp0, fs);
7847 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7848 tcg_temp_free_i64(fp0);
a16336e4
TS
7849 gen_set_label(l1);
7850 }
5a5012ec
TS
7851 opn = "movz.d";
7852 break;
bf4120ad 7853 case OPC_MOVN_D:
a16336e4
TS
7854 {
7855 int l1 = gen_new_label();
c9297f4d
AJ
7856 TCGv_i64 fp0;
7857
7858 if (ft != 0) {
7859 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7860 fp0 = tcg_temp_new_i64();
7861 gen_load_fpr64(ctx, fp0, fs);
7862 gen_store_fpr64(ctx, fp0, fd);
7863 tcg_temp_free_i64(fp0);
7864 gen_set_label(l1);
7865 }
a16336e4 7866 }
5a5012ec 7867 opn = "movn.d";
6ea83fed 7868 break;
bf4120ad 7869 case OPC_RECIP_D:
b8aa4598 7870 check_cp1_64bitmode(ctx);
b6d96bed 7871 {
a7812ae4 7872 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7873
7874 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7875 gen_helper_float_recip_d(fp0, cpu_env, fp0);
b6d96bed 7876 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7877 tcg_temp_free_i64(fp0);
b6d96bed 7878 }
57fa1fb3
TS
7879 opn = "recip.d";
7880 break;
bf4120ad 7881 case OPC_RSQRT_D:
b8aa4598 7882 check_cp1_64bitmode(ctx);
b6d96bed 7883 {
a7812ae4 7884 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7885
7886 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7887 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
b6d96bed 7888 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7889 tcg_temp_free_i64(fp0);
b6d96bed 7890 }
57fa1fb3
TS
7891 opn = "rsqrt.d";
7892 break;
bf4120ad 7893 case OPC_RECIP2_D:
5e755519 7894 check_cp1_64bitmode(ctx);
b6d96bed 7895 {
a7812ae4
PB
7896 TCGv_i64 fp0 = tcg_temp_new_i64();
7897 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7898
7899 gen_load_fpr64(ctx, fp0, fs);
7900 gen_load_fpr64(ctx, fp1, ft);
895c2d04 7901 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
a7812ae4 7902 tcg_temp_free_i64(fp1);
b6d96bed 7903 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7904 tcg_temp_free_i64(fp0);
b6d96bed 7905 }
57fa1fb3
TS
7906 opn = "recip2.d";
7907 break;
bf4120ad 7908 case OPC_RECIP1_D:
5e755519 7909 check_cp1_64bitmode(ctx);
b6d96bed 7910 {
a7812ae4 7911 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7912
7913 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7914 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
b6d96bed 7915 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7916 tcg_temp_free_i64(fp0);
b6d96bed 7917 }
57fa1fb3
TS
7918 opn = "recip1.d";
7919 break;
bf4120ad 7920 case OPC_RSQRT1_D:
5e755519 7921 check_cp1_64bitmode(ctx);
b6d96bed 7922 {
a7812ae4 7923 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7924
7925 gen_load_fpr64(ctx, fp0, fs);
895c2d04 7926 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
b6d96bed 7927 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7928 tcg_temp_free_i64(fp0);
b6d96bed 7929 }
57fa1fb3
TS
7930 opn = "rsqrt1.d";
7931 break;
bf4120ad 7932 case OPC_RSQRT2_D:
5e755519 7933 check_cp1_64bitmode(ctx);
b6d96bed 7934 {
a7812ae4
PB
7935 TCGv_i64 fp0 = tcg_temp_new_i64();
7936 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7937
7938 gen_load_fpr64(ctx, fp0, fs);
7939 gen_load_fpr64(ctx, fp1, ft);
895c2d04 7940 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
a7812ae4 7941 tcg_temp_free_i64(fp1);
b6d96bed 7942 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7943 tcg_temp_free_i64(fp0);
b6d96bed 7944 }
57fa1fb3
TS
7945 opn = "rsqrt2.d";
7946 break;
bf4120ad
NF
7947 case OPC_CMP_F_D:
7948 case OPC_CMP_UN_D:
7949 case OPC_CMP_EQ_D:
7950 case OPC_CMP_UEQ_D:
7951 case OPC_CMP_OLT_D:
7952 case OPC_CMP_ULT_D:
7953 case OPC_CMP_OLE_D:
7954 case OPC_CMP_ULE_D:
7955 case OPC_CMP_SF_D:
7956 case OPC_CMP_NGLE_D:
7957 case OPC_CMP_SEQ_D:
7958 case OPC_CMP_NGL_D:
7959 case OPC_CMP_LT_D:
7960 case OPC_CMP_NGE_D:
7961 case OPC_CMP_LE_D:
7962 case OPC_CMP_NGT_D:
8153667c
NF
7963 if (ctx->opcode & (1 << 6)) {
7964 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
7965 opn = condnames_abs[func-48];
7966 } else {
7967 gen_cmp_d(ctx, func-48, ft, fs, cc);
7968 opn = condnames[func-48];
5a1e8ffb 7969 }
6ea83fed 7970 break;
bf4120ad 7971 case OPC_CVT_S_D:
5e755519 7972 check_cp1_registers(ctx, fs);
b6d96bed 7973 {
a7812ae4
PB
7974 TCGv_i32 fp32 = tcg_temp_new_i32();
7975 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7976
7977 gen_load_fpr64(ctx, fp64, fs);
895c2d04 7978 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
a7812ae4 7979 tcg_temp_free_i64(fp64);
b6d96bed 7980 gen_store_fpr32(fp32, fd);
a7812ae4 7981 tcg_temp_free_i32(fp32);
b6d96bed 7982 }
5a5012ec
TS
7983 opn = "cvt.s.d";
7984 break;
bf4120ad 7985 case OPC_CVT_W_D:
5e755519 7986 check_cp1_registers(ctx, fs);
b6d96bed 7987 {
a7812ae4
PB
7988 TCGv_i32 fp32 = tcg_temp_new_i32();
7989 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
7990
7991 gen_load_fpr64(ctx, fp64, fs);
895c2d04 7992 gen_helper_float_cvtw_d(fp32, cpu_env, fp64);
a7812ae4 7993 tcg_temp_free_i64(fp64);
b6d96bed 7994 gen_store_fpr32(fp32, fd);
a7812ae4 7995 tcg_temp_free_i32(fp32);
b6d96bed 7996 }
5a5012ec
TS
7997 opn = "cvt.w.d";
7998 break;
bf4120ad 7999 case OPC_CVT_L_D:
5e755519 8000 check_cp1_64bitmode(ctx);
b6d96bed 8001 {
a7812ae4 8002 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8003
8004 gen_load_fpr64(ctx, fp0, fs);
895c2d04 8005 gen_helper_float_cvtl_d(fp0, cpu_env, fp0);
b6d96bed 8006 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8007 tcg_temp_free_i64(fp0);
b6d96bed 8008 }
5a5012ec
TS
8009 opn = "cvt.l.d";
8010 break;
bf4120ad 8011 case OPC_CVT_S_W:
b6d96bed 8012 {
a7812ae4 8013 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
8014
8015 gen_load_fpr32(fp0, fs);
895c2d04 8016 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
b6d96bed 8017 gen_store_fpr32(fp0, fd);
a7812ae4 8018 tcg_temp_free_i32(fp0);
b6d96bed 8019 }
5a5012ec 8020 opn = "cvt.s.w";
6ea83fed 8021 break;
bf4120ad 8022 case OPC_CVT_D_W:
5e755519 8023 check_cp1_registers(ctx, fd);
b6d96bed 8024 {
a7812ae4
PB
8025 TCGv_i32 fp32 = tcg_temp_new_i32();
8026 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
8027
8028 gen_load_fpr32(fp32, fs);
895c2d04 8029 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
a7812ae4 8030 tcg_temp_free_i32(fp32);
b6d96bed 8031 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 8032 tcg_temp_free_i64(fp64);
b6d96bed 8033 }
5a5012ec
TS
8034 opn = "cvt.d.w";
8035 break;
bf4120ad 8036 case OPC_CVT_S_L:
5e755519 8037 check_cp1_64bitmode(ctx);
b6d96bed 8038 {
a7812ae4
PB
8039 TCGv_i32 fp32 = tcg_temp_new_i32();
8040 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
8041
8042 gen_load_fpr64(ctx, fp64, fs);
895c2d04 8043 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
a7812ae4 8044 tcg_temp_free_i64(fp64);
b6d96bed 8045 gen_store_fpr32(fp32, fd);
a7812ae4 8046 tcg_temp_free_i32(fp32);
b6d96bed 8047 }
5a5012ec
TS
8048 opn = "cvt.s.l";
8049 break;
bf4120ad 8050 case OPC_CVT_D_L:
5e755519 8051 check_cp1_64bitmode(ctx);
b6d96bed 8052 {
a7812ae4 8053 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8054
8055 gen_load_fpr64(ctx, fp0, fs);
895c2d04 8056 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
b6d96bed 8057 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8058 tcg_temp_free_i64(fp0);
b6d96bed 8059 }
5a5012ec
TS
8060 opn = "cvt.d.l";
8061 break;
bf4120ad 8062 case OPC_CVT_PS_PW:
5e755519 8063 check_cp1_64bitmode(ctx);
b6d96bed 8064 {
a7812ae4 8065 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8066
8067 gen_load_fpr64(ctx, fp0, fs);
895c2d04 8068 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
b6d96bed 8069 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8070 tcg_temp_free_i64(fp0);
b6d96bed 8071 }
5a5012ec
TS
8072 opn = "cvt.ps.pw";
8073 break;
bf4120ad 8074 case OPC_ADD_PS:
5e755519 8075 check_cp1_64bitmode(ctx);
b6d96bed 8076 {
a7812ae4
PB
8077 TCGv_i64 fp0 = tcg_temp_new_i64();
8078 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
8079
8080 gen_load_fpr64(ctx, fp0, fs);
8081 gen_load_fpr64(ctx, fp1, ft);
895c2d04 8082 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 8083 tcg_temp_free_i64(fp1);
b6d96bed 8084 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8085 tcg_temp_free_i64(fp0);
b6d96bed 8086 }
5a5012ec 8087 opn = "add.ps";
6ea83fed 8088 break;
bf4120ad 8089 case OPC_SUB_PS:
5e755519 8090 check_cp1_64bitmode(ctx);
b6d96bed 8091 {
a7812ae4
PB
8092 TCGv_i64 fp0 = tcg_temp_new_i64();
8093 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
8094
8095 gen_load_fpr64(ctx, fp0, fs);
8096 gen_load_fpr64(ctx, fp1, ft);
895c2d04 8097 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 8098 tcg_temp_free_i64(fp1);
b6d96bed 8099 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8100 tcg_temp_free_i64(fp0);
b6d96bed 8101 }
5a5012ec 8102 opn = "sub.ps";
6ea83fed 8103 break;
bf4120ad 8104 case OPC_MUL_PS:
5e755519 8105 check_cp1_64bitmode(ctx);
b6d96bed 8106 {
a7812ae4
PB
8107 TCGv_i64 fp0 = tcg_temp_new_i64();
8108 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
8109
8110 gen_load_fpr64(ctx, fp0, fs);
8111 gen_load_fpr64(ctx, fp1, ft);
895c2d04 8112 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 8113 tcg_temp_free_i64(fp1);
b6d96bed 8114 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8115 tcg_temp_free_i64(fp0);
b6d96bed 8116 }
5a5012ec 8117 opn = "mul.ps";
6ea83fed 8118 break;
bf4120ad 8119 case OPC_ABS_PS:
5e755519 8120 check_cp1_64bitmode(ctx);
b6d96bed 8121 {
a7812ae4 8122 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8123
8124 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 8125 gen_helper_float_abs_ps(fp0, fp0);
b6d96bed 8126 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8127 tcg_temp_free_i64(fp0);
b6d96bed 8128 }
5a5012ec 8129 opn = "abs.ps";
6ea83fed 8130 break;
bf4120ad 8131 case OPC_MOV_PS:
5e755519 8132 check_cp1_64bitmode(ctx);
b6d96bed 8133 {
a7812ae4 8134 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8135
8136 gen_load_fpr64(ctx, fp0, fs);
8137 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8138 tcg_temp_free_i64(fp0);
b6d96bed 8139 }
5a5012ec 8140 opn = "mov.ps";
6ea83fed 8141 break;
bf4120ad 8142 case OPC_NEG_PS:
5e755519 8143 check_cp1_64bitmode(ctx);
b6d96bed 8144 {
a7812ae4 8145 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8146
8147 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 8148 gen_helper_float_chs_ps(fp0, fp0);
b6d96bed 8149 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8150 tcg_temp_free_i64(fp0);
b6d96bed 8151 }
5a5012ec 8152 opn = "neg.ps";
6ea83fed 8153 break;
bf4120ad 8154 case OPC_MOVCF_PS:
5e755519 8155 check_cp1_64bitmode(ctx);
b6d96bed 8156 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 8157 opn = "movcf.ps";
6ea83fed 8158 break;
bf4120ad 8159 case OPC_MOVZ_PS:
5e755519 8160 check_cp1_64bitmode(ctx);
a16336e4
TS
8161 {
8162 int l1 = gen_new_label();
30a3848b 8163 TCGv_i64 fp0;
a16336e4 8164
c9297f4d
AJ
8165 if (ft != 0)
8166 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
8167 fp0 = tcg_temp_new_i64();
8168 gen_load_fpr64(ctx, fp0, fs);
8169 gen_store_fpr64(ctx, fp0, fd);
8170 tcg_temp_free_i64(fp0);
a16336e4
TS
8171 gen_set_label(l1);
8172 }
5a5012ec 8173 opn = "movz.ps";
6ea83fed 8174 break;
bf4120ad 8175 case OPC_MOVN_PS:
5e755519 8176 check_cp1_64bitmode(ctx);
a16336e4
TS
8177 {
8178 int l1 = gen_new_label();
30a3848b 8179 TCGv_i64 fp0;
c9297f4d
AJ
8180
8181 if (ft != 0) {
8182 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
8183 fp0 = tcg_temp_new_i64();
8184 gen_load_fpr64(ctx, fp0, fs);
8185 gen_store_fpr64(ctx, fp0, fd);
8186 tcg_temp_free_i64(fp0);
8187 gen_set_label(l1);
8188 }
a16336e4 8189 }
5a5012ec 8190 opn = "movn.ps";
6ea83fed 8191 break;
bf4120ad 8192 case OPC_ADDR_PS:
5e755519 8193 check_cp1_64bitmode(ctx);
b6d96bed 8194 {
a7812ae4
PB
8195 TCGv_i64 fp0 = tcg_temp_new_i64();
8196 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
8197
8198 gen_load_fpr64(ctx, fp0, ft);
8199 gen_load_fpr64(ctx, fp1, fs);
895c2d04 8200 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 8201 tcg_temp_free_i64(fp1);
b6d96bed 8202 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8203 tcg_temp_free_i64(fp0);
b6d96bed 8204 }
fbcc6828
TS
8205 opn = "addr.ps";
8206 break;
bf4120ad 8207 case OPC_MULR_PS:
5e755519 8208 check_cp1_64bitmode(ctx);
b6d96bed 8209 {
a7812ae4
PB
8210 TCGv_i64 fp0 = tcg_temp_new_i64();
8211 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
8212
8213 gen_load_fpr64(ctx, fp0, ft);
8214 gen_load_fpr64(ctx, fp1, fs);
895c2d04 8215 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 8216 tcg_temp_free_i64(fp1);
b6d96bed 8217 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8218 tcg_temp_free_i64(fp0);
b6d96bed 8219 }
57fa1fb3
TS
8220 opn = "mulr.ps";
8221 break;
bf4120ad 8222 case OPC_RECIP2_PS:
5e755519 8223 check_cp1_64bitmode(ctx);
b6d96bed 8224 {
a7812ae4
PB
8225 TCGv_i64 fp0 = tcg_temp_new_i64();
8226 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
8227
8228 gen_load_fpr64(ctx, fp0, fs);
d22d7289 8229 gen_load_fpr64(ctx, fp1, ft);
895c2d04 8230 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 8231 tcg_temp_free_i64(fp1);
b6d96bed 8232 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8233 tcg_temp_free_i64(fp0);
b6d96bed 8234 }
57fa1fb3
TS
8235 opn = "recip2.ps";
8236 break;
bf4120ad 8237 case OPC_RECIP1_PS:
5e755519 8238 check_cp1_64bitmode(ctx);
b6d96bed 8239 {
a7812ae4 8240 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8241
8242 gen_load_fpr64(ctx, fp0, fs);
895c2d04 8243 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
b6d96bed 8244 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8245 tcg_temp_free_i64(fp0);
b6d96bed 8246 }
57fa1fb3
TS
8247 opn = "recip1.ps";
8248 break;
bf4120ad 8249 case OPC_RSQRT1_PS:
5e755519 8250 check_cp1_64bitmode(ctx);
b6d96bed 8251 {
a7812ae4 8252 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8253
8254 gen_load_fpr64(ctx, fp0, fs);
895c2d04 8255 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
b6d96bed 8256 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8257 tcg_temp_free_i64(fp0);
b6d96bed 8258 }
57fa1fb3
TS
8259 opn = "rsqrt1.ps";
8260 break;
bf4120ad 8261 case OPC_RSQRT2_PS:
5e755519 8262 check_cp1_64bitmode(ctx);
b6d96bed 8263 {
a7812ae4
PB
8264 TCGv_i64 fp0 = tcg_temp_new_i64();
8265 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
8266
8267 gen_load_fpr64(ctx, fp0, fs);
8268 gen_load_fpr64(ctx, fp1, ft);
895c2d04 8269 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 8270 tcg_temp_free_i64(fp1);
b6d96bed 8271 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8272 tcg_temp_free_i64(fp0);
b6d96bed 8273 }
57fa1fb3
TS
8274 opn = "rsqrt2.ps";
8275 break;
bf4120ad 8276 case OPC_CVT_S_PU:
5e755519 8277 check_cp1_64bitmode(ctx);
b6d96bed 8278 {
a7812ae4 8279 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
8280
8281 gen_load_fpr32h(fp0, fs);
895c2d04 8282 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
b6d96bed 8283 gen_store_fpr32(fp0, fd);
a7812ae4 8284 tcg_temp_free_i32(fp0);
b6d96bed 8285 }
5a5012ec 8286 opn = "cvt.s.pu";
dd016883 8287 break;
bf4120ad 8288 case OPC_CVT_PW_PS:
5e755519 8289 check_cp1_64bitmode(ctx);
b6d96bed 8290 {
a7812ae4 8291 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8292
8293 gen_load_fpr64(ctx, fp0, fs);
895c2d04 8294 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
b6d96bed 8295 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8296 tcg_temp_free_i64(fp0);
b6d96bed 8297 }
5a5012ec 8298 opn = "cvt.pw.ps";
6ea83fed 8299 break;
bf4120ad 8300 case OPC_CVT_S_PL:
5e755519 8301 check_cp1_64bitmode(ctx);
b6d96bed 8302 {
a7812ae4 8303 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
8304
8305 gen_load_fpr32(fp0, fs);
895c2d04 8306 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
b6d96bed 8307 gen_store_fpr32(fp0, fd);
a7812ae4 8308 tcg_temp_free_i32(fp0);
b6d96bed 8309 }
5a5012ec 8310 opn = "cvt.s.pl";
6ea83fed 8311 break;
bf4120ad 8312 case OPC_PLL_PS:
5e755519 8313 check_cp1_64bitmode(ctx);
b6d96bed 8314 {
a7812ae4
PB
8315 TCGv_i32 fp0 = tcg_temp_new_i32();
8316 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
8317
8318 gen_load_fpr32(fp0, fs);
8319 gen_load_fpr32(fp1, ft);
8320 gen_store_fpr32h(fp0, fd);
8321 gen_store_fpr32(fp1, fd);
a7812ae4
PB
8322 tcg_temp_free_i32(fp0);
8323 tcg_temp_free_i32(fp1);
b6d96bed 8324 }
5a5012ec 8325 opn = "pll.ps";
6ea83fed 8326 break;
bf4120ad 8327 case OPC_PLU_PS:
5e755519 8328 check_cp1_64bitmode(ctx);
b6d96bed 8329 {
a7812ae4
PB
8330 TCGv_i32 fp0 = tcg_temp_new_i32();
8331 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
8332
8333 gen_load_fpr32(fp0, fs);
8334 gen_load_fpr32h(fp1, ft);
8335 gen_store_fpr32(fp1, fd);
8336 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
8337 tcg_temp_free_i32(fp0);
8338 tcg_temp_free_i32(fp1);
b6d96bed 8339 }
5a5012ec
TS
8340 opn = "plu.ps";
8341 break;
bf4120ad 8342 case OPC_PUL_PS:
5e755519 8343 check_cp1_64bitmode(ctx);
b6d96bed 8344 {
a7812ae4
PB
8345 TCGv_i32 fp0 = tcg_temp_new_i32();
8346 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
8347
8348 gen_load_fpr32h(fp0, fs);
8349 gen_load_fpr32(fp1, ft);
8350 gen_store_fpr32(fp1, fd);
8351 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
8352 tcg_temp_free_i32(fp0);
8353 tcg_temp_free_i32(fp1);
b6d96bed 8354 }
5a5012ec
TS
8355 opn = "pul.ps";
8356 break;
bf4120ad 8357 case OPC_PUU_PS:
5e755519 8358 check_cp1_64bitmode(ctx);
b6d96bed 8359 {
a7812ae4
PB
8360 TCGv_i32 fp0 = tcg_temp_new_i32();
8361 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
8362
8363 gen_load_fpr32h(fp0, fs);
8364 gen_load_fpr32h(fp1, ft);
8365 gen_store_fpr32(fp1, fd);
8366 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
8367 tcg_temp_free_i32(fp0);
8368 tcg_temp_free_i32(fp1);
b6d96bed 8369 }
5a5012ec
TS
8370 opn = "puu.ps";
8371 break;
bf4120ad
NF
8372 case OPC_CMP_F_PS:
8373 case OPC_CMP_UN_PS:
8374 case OPC_CMP_EQ_PS:
8375 case OPC_CMP_UEQ_PS:
8376 case OPC_CMP_OLT_PS:
8377 case OPC_CMP_ULT_PS:
8378 case OPC_CMP_OLE_PS:
8379 case OPC_CMP_ULE_PS:
8380 case OPC_CMP_SF_PS:
8381 case OPC_CMP_NGLE_PS:
8382 case OPC_CMP_SEQ_PS:
8383 case OPC_CMP_NGL_PS:
8384 case OPC_CMP_LT_PS:
8385 case OPC_CMP_NGE_PS:
8386 case OPC_CMP_LE_PS:
8387 case OPC_CMP_NGT_PS:
8153667c
NF
8388 if (ctx->opcode & (1 << 6)) {
8389 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
8390 opn = condnames_abs[func-48];
8391 } else {
8392 gen_cmp_ps(ctx, func-48, ft, fs, cc);
8393 opn = condnames[func-48];
5a1e8ffb 8394 }
6ea83fed 8395 break;
5a5012ec 8396 default:
923617a3 8397 MIPS_INVAL(opn);
e397ee33 8398 generate_exception (ctx, EXCP_RI);
6ea83fed
FB
8399 return;
8400 }
2abf314d 8401 (void)opn; /* avoid a compiler warning */
5a1e8ffb
TS
8402 switch (optype) {
8403 case BINOP:
6ea83fed 8404 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
5a1e8ffb
TS
8405 break;
8406 case CMPOP:
8407 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
8408 break;
8409 default:
6ea83fed 8410 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
5a1e8ffb
TS
8411 break;
8412 }
6ea83fed 8413}
6af0bf9c 8414
5a5012ec 8415/* Coprocessor 3 (FPU) */
5e755519
TS
8416static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
8417 int fd, int fs, int base, int index)
7a387fff 8418{
923617a3 8419 const char *opn = "extended float load/store";
93b12ccc 8420 int store = 0;
4e2474d6 8421 TCGv t0 = tcg_temp_new();
7a387fff 8422
93b12ccc 8423 if (base == 0) {
6c5c1e20 8424 gen_load_gpr(t0, index);
93b12ccc 8425 } else if (index == 0) {
6c5c1e20 8426 gen_load_gpr(t0, base);
93b12ccc 8427 } else {
05168674 8428 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
93b12ccc 8429 }
5a5012ec 8430 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 8431 memory access. */
4e2474d6 8432 save_cpu_state(ctx, 0);
5a5012ec
TS
8433 switch (opc) {
8434 case OPC_LWXC1:
8c0ab41f 8435 check_cop1x(ctx);
b6d96bed 8436 {
a7812ae4 8437 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 8438
585c88d5
AJ
8439 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
8440 tcg_gen_trunc_tl_i32(fp0, t0);
b6d96bed 8441 gen_store_fpr32(fp0, fd);
a7812ae4 8442 tcg_temp_free_i32(fp0);
b6d96bed 8443 }
5a5012ec
TS
8444 opn = "lwxc1";
8445 break;
8446 case OPC_LDXC1:
8c0ab41f
AJ
8447 check_cop1x(ctx);
8448 check_cp1_registers(ctx, fd);
b6d96bed 8449 {
a7812ae4 8450 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8451
8452 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
8453 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8454 tcg_temp_free_i64(fp0);
b6d96bed 8455 }
5a5012ec
TS
8456 opn = "ldxc1";
8457 break;
8458 case OPC_LUXC1:
8c0ab41f 8459 check_cp1_64bitmode(ctx);
6c5c1e20 8460 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 8461 {
a7812ae4 8462 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8463
8464 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
8465 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 8466 tcg_temp_free_i64(fp0);
b6d96bed 8467 }
5a5012ec
TS
8468 opn = "luxc1";
8469 break;
8470 case OPC_SWXC1:
8c0ab41f 8471 check_cop1x(ctx);
b6d96bed 8472 {
a7812ae4 8473 TCGv_i32 fp0 = tcg_temp_new_i32();
585c88d5 8474 TCGv t1 = tcg_temp_new();
b6d96bed
TS
8475
8476 gen_load_fpr32(fp0, fs);
a7812ae4
PB
8477 tcg_gen_extu_i32_tl(t1, fp0);
8478 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
8479 tcg_temp_free_i32(fp0);
a6035857 8480 tcg_temp_free(t1);
b6d96bed 8481 }
5a5012ec 8482 opn = "swxc1";
93b12ccc 8483 store = 1;
5a5012ec
TS
8484 break;
8485 case OPC_SDXC1:
8c0ab41f
AJ
8486 check_cop1x(ctx);
8487 check_cp1_registers(ctx, fs);
b6d96bed 8488 {
a7812ae4 8489 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8490
8491 gen_load_fpr64(ctx, fp0, fs);
8492 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 8493 tcg_temp_free_i64(fp0);
b6d96bed 8494 }
5a5012ec 8495 opn = "sdxc1";
93b12ccc 8496 store = 1;
5a5012ec
TS
8497 break;
8498 case OPC_SUXC1:
8c0ab41f 8499 check_cp1_64bitmode(ctx);
6c5c1e20 8500 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 8501 {
a7812ae4 8502 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
8503
8504 gen_load_fpr64(ctx, fp0, fs);
8505 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 8506 tcg_temp_free_i64(fp0);
b6d96bed 8507 }
5a5012ec 8508 opn = "suxc1";
93b12ccc 8509 store = 1;
5a5012ec 8510 break;
5a5012ec 8511 }
6c5c1e20 8512 tcg_temp_free(t0);
2abf314d 8513 (void)opn; (void)store; /* avoid compiler warnings */
93b12ccc
TS
8514 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
8515 regnames[index], regnames[base]);
5a5012ec
TS
8516}
8517
5e755519
TS
8518static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
8519 int fd, int fr, int fs, int ft)
5a5012ec 8520{
923617a3 8521 const char *opn = "flt3_arith";
5a5012ec 8522
5a5012ec
TS
8523 switch (opc) {
8524 case OPC_ALNV_PS:
b8aa4598 8525 check_cp1_64bitmode(ctx);
a16336e4 8526 {
a7812ae4 8527 TCGv t0 = tcg_temp_local_new();
c905fdac
AJ
8528 TCGv_i32 fp = tcg_temp_new_i32();
8529 TCGv_i32 fph = tcg_temp_new_i32();
a16336e4
TS
8530 int l1 = gen_new_label();
8531 int l2 = gen_new_label();
8532
6c5c1e20
TS
8533 gen_load_gpr(t0, fr);
8534 tcg_gen_andi_tl(t0, t0, 0x7);
6c5c1e20
TS
8535
8536 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
c905fdac
AJ
8537 gen_load_fpr32(fp, fs);
8538 gen_load_fpr32h(fph, fs);
8539 gen_store_fpr32(fp, fd);
8540 gen_store_fpr32h(fph, fd);
a16336e4
TS
8541 tcg_gen_br(l2);
8542 gen_set_label(l1);
6c5c1e20
TS
8543 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
8544 tcg_temp_free(t0);
a16336e4 8545#ifdef TARGET_WORDS_BIGENDIAN
c905fdac
AJ
8546 gen_load_fpr32(fp, fs);
8547 gen_load_fpr32h(fph, ft);
8548 gen_store_fpr32h(fp, fd);
8549 gen_store_fpr32(fph, fd);
a16336e4 8550#else
c905fdac
AJ
8551 gen_load_fpr32h(fph, fs);
8552 gen_load_fpr32(fp, ft);
8553 gen_store_fpr32(fph, fd);
8554 gen_store_fpr32h(fp, fd);
a16336e4
TS
8555#endif
8556 gen_set_label(l2);
c905fdac
AJ
8557 tcg_temp_free_i32(fp);
8558 tcg_temp_free_i32(fph);
a16336e4 8559 }
5a5012ec
TS
8560 opn = "alnv.ps";
8561 break;
8562 case OPC_MADD_S:
b8aa4598 8563 check_cop1x(ctx);
b6d96bed 8564 {
a7812ae4
PB
8565 TCGv_i32 fp0 = tcg_temp_new_i32();
8566 TCGv_i32 fp1 = tcg_temp_new_i32();
8567 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
8568
8569 gen_load_fpr32(fp0, fs);
8570 gen_load_fpr32(fp1, ft);
8571 gen_load_fpr32(fp2, fr);
895c2d04 8572 gen_helper_float_muladd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8573 tcg_temp_free_i32(fp0);
8574 tcg_temp_free_i32(fp1);
b6d96bed 8575 gen_store_fpr32(fp2, fd);
a7812ae4 8576 tcg_temp_free_i32(fp2);
b6d96bed 8577 }
5a5012ec
TS
8578 opn = "madd.s";
8579 break;
8580 case OPC_MADD_D:
b8aa4598
TS
8581 check_cop1x(ctx);
8582 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 8583 {
a7812ae4
PB
8584 TCGv_i64 fp0 = tcg_temp_new_i64();
8585 TCGv_i64 fp1 = tcg_temp_new_i64();
8586 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8587
8588 gen_load_fpr64(ctx, fp0, fs);
8589 gen_load_fpr64(ctx, fp1, ft);
8590 gen_load_fpr64(ctx, fp2, fr);
895c2d04 8591 gen_helper_float_muladd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8592 tcg_temp_free_i64(fp0);
8593 tcg_temp_free_i64(fp1);
b6d96bed 8594 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8595 tcg_temp_free_i64(fp2);
b6d96bed 8596 }
5a5012ec
TS
8597 opn = "madd.d";
8598 break;
8599 case OPC_MADD_PS:
b8aa4598 8600 check_cp1_64bitmode(ctx);
b6d96bed 8601 {
a7812ae4
PB
8602 TCGv_i64 fp0 = tcg_temp_new_i64();
8603 TCGv_i64 fp1 = tcg_temp_new_i64();
8604 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8605
8606 gen_load_fpr64(ctx, fp0, fs);
8607 gen_load_fpr64(ctx, fp1, ft);
8608 gen_load_fpr64(ctx, fp2, fr);
895c2d04 8609 gen_helper_float_muladd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8610 tcg_temp_free_i64(fp0);
8611 tcg_temp_free_i64(fp1);
b6d96bed 8612 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8613 tcg_temp_free_i64(fp2);
b6d96bed 8614 }
5a5012ec
TS
8615 opn = "madd.ps";
8616 break;
8617 case OPC_MSUB_S:
b8aa4598 8618 check_cop1x(ctx);
b6d96bed 8619 {
a7812ae4
PB
8620 TCGv_i32 fp0 = tcg_temp_new_i32();
8621 TCGv_i32 fp1 = tcg_temp_new_i32();
8622 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
8623
8624 gen_load_fpr32(fp0, fs);
8625 gen_load_fpr32(fp1, ft);
8626 gen_load_fpr32(fp2, fr);
895c2d04 8627 gen_helper_float_mulsub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8628 tcg_temp_free_i32(fp0);
8629 tcg_temp_free_i32(fp1);
b6d96bed 8630 gen_store_fpr32(fp2, fd);
a7812ae4 8631 tcg_temp_free_i32(fp2);
b6d96bed 8632 }
5a5012ec
TS
8633 opn = "msub.s";
8634 break;
8635 case OPC_MSUB_D:
b8aa4598
TS
8636 check_cop1x(ctx);
8637 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 8638 {
a7812ae4
PB
8639 TCGv_i64 fp0 = tcg_temp_new_i64();
8640 TCGv_i64 fp1 = tcg_temp_new_i64();
8641 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8642
8643 gen_load_fpr64(ctx, fp0, fs);
8644 gen_load_fpr64(ctx, fp1, ft);
8645 gen_load_fpr64(ctx, fp2, fr);
895c2d04 8646 gen_helper_float_mulsub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8647 tcg_temp_free_i64(fp0);
8648 tcg_temp_free_i64(fp1);
b6d96bed 8649 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8650 tcg_temp_free_i64(fp2);
b6d96bed 8651 }
5a5012ec
TS
8652 opn = "msub.d";
8653 break;
8654 case OPC_MSUB_PS:
b8aa4598 8655 check_cp1_64bitmode(ctx);
b6d96bed 8656 {
a7812ae4
PB
8657 TCGv_i64 fp0 = tcg_temp_new_i64();
8658 TCGv_i64 fp1 = tcg_temp_new_i64();
8659 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8660
8661 gen_load_fpr64(ctx, fp0, fs);
8662 gen_load_fpr64(ctx, fp1, ft);
8663 gen_load_fpr64(ctx, fp2, fr);
895c2d04 8664 gen_helper_float_mulsub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8665 tcg_temp_free_i64(fp0);
8666 tcg_temp_free_i64(fp1);
b6d96bed 8667 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8668 tcg_temp_free_i64(fp2);
b6d96bed 8669 }
5a5012ec
TS
8670 opn = "msub.ps";
8671 break;
8672 case OPC_NMADD_S:
b8aa4598 8673 check_cop1x(ctx);
b6d96bed 8674 {
a7812ae4
PB
8675 TCGv_i32 fp0 = tcg_temp_new_i32();
8676 TCGv_i32 fp1 = tcg_temp_new_i32();
8677 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
8678
8679 gen_load_fpr32(fp0, fs);
8680 gen_load_fpr32(fp1, ft);
8681 gen_load_fpr32(fp2, fr);
895c2d04 8682 gen_helper_float_nmuladd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8683 tcg_temp_free_i32(fp0);
8684 tcg_temp_free_i32(fp1);
b6d96bed 8685 gen_store_fpr32(fp2, fd);
a7812ae4 8686 tcg_temp_free_i32(fp2);
b6d96bed 8687 }
5a5012ec
TS
8688 opn = "nmadd.s";
8689 break;
8690 case OPC_NMADD_D:
b8aa4598
TS
8691 check_cop1x(ctx);
8692 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 8693 {
a7812ae4
PB
8694 TCGv_i64 fp0 = tcg_temp_new_i64();
8695 TCGv_i64 fp1 = tcg_temp_new_i64();
8696 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8697
8698 gen_load_fpr64(ctx, fp0, fs);
8699 gen_load_fpr64(ctx, fp1, ft);
8700 gen_load_fpr64(ctx, fp2, fr);
895c2d04 8701 gen_helper_float_nmuladd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8702 tcg_temp_free_i64(fp0);
8703 tcg_temp_free_i64(fp1);
b6d96bed 8704 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8705 tcg_temp_free_i64(fp2);
b6d96bed 8706 }
5a5012ec
TS
8707 opn = "nmadd.d";
8708 break;
8709 case OPC_NMADD_PS:
b8aa4598 8710 check_cp1_64bitmode(ctx);
b6d96bed 8711 {
a7812ae4
PB
8712 TCGv_i64 fp0 = tcg_temp_new_i64();
8713 TCGv_i64 fp1 = tcg_temp_new_i64();
8714 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8715
8716 gen_load_fpr64(ctx, fp0, fs);
8717 gen_load_fpr64(ctx, fp1, ft);
8718 gen_load_fpr64(ctx, fp2, fr);
895c2d04 8719 gen_helper_float_nmuladd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8720 tcg_temp_free_i64(fp0);
8721 tcg_temp_free_i64(fp1);
b6d96bed 8722 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8723 tcg_temp_free_i64(fp2);
b6d96bed 8724 }
5a5012ec
TS
8725 opn = "nmadd.ps";
8726 break;
8727 case OPC_NMSUB_S:
b8aa4598 8728 check_cop1x(ctx);
b6d96bed 8729 {
a7812ae4
PB
8730 TCGv_i32 fp0 = tcg_temp_new_i32();
8731 TCGv_i32 fp1 = tcg_temp_new_i32();
8732 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
8733
8734 gen_load_fpr32(fp0, fs);
8735 gen_load_fpr32(fp1, ft);
8736 gen_load_fpr32(fp2, fr);
895c2d04 8737 gen_helper_float_nmulsub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8738 tcg_temp_free_i32(fp0);
8739 tcg_temp_free_i32(fp1);
b6d96bed 8740 gen_store_fpr32(fp2, fd);
a7812ae4 8741 tcg_temp_free_i32(fp2);
b6d96bed 8742 }
5a5012ec
TS
8743 opn = "nmsub.s";
8744 break;
8745 case OPC_NMSUB_D:
b8aa4598
TS
8746 check_cop1x(ctx);
8747 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 8748 {
a7812ae4
PB
8749 TCGv_i64 fp0 = tcg_temp_new_i64();
8750 TCGv_i64 fp1 = tcg_temp_new_i64();
8751 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8752
8753 gen_load_fpr64(ctx, fp0, fs);
8754 gen_load_fpr64(ctx, fp1, ft);
8755 gen_load_fpr64(ctx, fp2, fr);
895c2d04 8756 gen_helper_float_nmulsub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8757 tcg_temp_free_i64(fp0);
8758 tcg_temp_free_i64(fp1);
b6d96bed 8759 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8760 tcg_temp_free_i64(fp2);
b6d96bed 8761 }
5a5012ec
TS
8762 opn = "nmsub.d";
8763 break;
8764 case OPC_NMSUB_PS:
b8aa4598 8765 check_cp1_64bitmode(ctx);
b6d96bed 8766 {
a7812ae4
PB
8767 TCGv_i64 fp0 = tcg_temp_new_i64();
8768 TCGv_i64 fp1 = tcg_temp_new_i64();
8769 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
8770
8771 gen_load_fpr64(ctx, fp0, fs);
8772 gen_load_fpr64(ctx, fp1, ft);
8773 gen_load_fpr64(ctx, fp2, fr);
895c2d04 8774 gen_helper_float_nmulsub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
8775 tcg_temp_free_i64(fp0);
8776 tcg_temp_free_i64(fp1);
b6d96bed 8777 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 8778 tcg_temp_free_i64(fp2);
b6d96bed 8779 }
5a5012ec
TS
8780 opn = "nmsub.ps";
8781 break;
923617a3
TS
8782 default:
8783 MIPS_INVAL(opn);
5a5012ec
TS
8784 generate_exception (ctx, EXCP_RI);
8785 return;
8786 }
2abf314d 8787 (void)opn; /* avoid a compiler warning */
5a5012ec
TS
8788 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
8789 fregnames[fs], fregnames[ft]);
7a387fff
TS
8790}
8791
26ebe468 8792static void
7db13fae 8793gen_rdhwr (CPUMIPSState *env, DisasContext *ctx, int rt, int rd)
26ebe468
NF
8794{
8795 TCGv t0;
8796
b3167288
RH
8797#if !defined(CONFIG_USER_ONLY)
8798 /* The Linux kernel will emulate rdhwr if it's not supported natively.
8799 Therefore only check the ISA in system mode. */
26ebe468 8800 check_insn(env, ctx, ISA_MIPS32R2);
b3167288 8801#endif
26ebe468
NF
8802 t0 = tcg_temp_new();
8803
8804 switch (rd) {
8805 case 0:
8806 save_cpu_state(ctx, 1);
895c2d04 8807 gen_helper_rdhwr_cpunum(t0, cpu_env);
26ebe468
NF
8808 gen_store_gpr(t0, rt);
8809 break;
8810 case 1:
8811 save_cpu_state(ctx, 1);
895c2d04 8812 gen_helper_rdhwr_synci_step(t0, cpu_env);
26ebe468
NF
8813 gen_store_gpr(t0, rt);
8814 break;
8815 case 2:
8816 save_cpu_state(ctx, 1);
895c2d04 8817 gen_helper_rdhwr_cc(t0, cpu_env);
26ebe468
NF
8818 gen_store_gpr(t0, rt);
8819 break;
8820 case 3:
8821 save_cpu_state(ctx, 1);
895c2d04 8822 gen_helper_rdhwr_ccres(t0, cpu_env);
26ebe468
NF
8823 gen_store_gpr(t0, rt);
8824 break;
8825 case 29:
8826#if defined(CONFIG_USER_ONLY)
7db13fae 8827 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, tls_value));
26ebe468
NF
8828 gen_store_gpr(t0, rt);
8829 break;
8830#else
8831 /* XXX: Some CPUs implement this in hardware.
8832 Not supported yet. */
8833#endif
8834 default: /* Invalid */
8835 MIPS_INVAL("rdhwr");
8836 generate_exception(ctx, EXCP_RI);
8837 break;
8838 }
8839 tcg_temp_free(t0);
8840}
8841
7db13fae 8842static void handle_delay_slot (CPUMIPSState *env, DisasContext *ctx,
c9602061
NF
8843 int insn_bytes)
8844{
8845 if (ctx->hflags & MIPS_HFLAG_BMASK) {
364d4831 8846 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
c9602061
NF
8847 /* Branches completion */
8848 ctx->hflags &= ~MIPS_HFLAG_BMASK;
8849 ctx->bstate = BS_BRANCH;
8850 save_cpu_state(ctx, 0);
8851 /* FIXME: Need to clear can_do_io. */
364d4831 8852 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
c9602061
NF
8853 case MIPS_HFLAG_B:
8854 /* unconditional branch */
8855 MIPS_DEBUG("unconditional branch");
364d4831
NF
8856 if (proc_hflags & MIPS_HFLAG_BX) {
8857 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
8858 }
c9602061
NF
8859 gen_goto_tb(ctx, 0, ctx->btarget);
8860 break;
8861 case MIPS_HFLAG_BL:
8862 /* blikely taken case */
8863 MIPS_DEBUG("blikely branch taken");
8864 gen_goto_tb(ctx, 0, ctx->btarget);
8865 break;
8866 case MIPS_HFLAG_BC:
8867 /* Conditional branch */
8868 MIPS_DEBUG("conditional branch");
8869 {
8870 int l1 = gen_new_label();
8871
8872 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8873 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
8874 gen_set_label(l1);
8875 gen_goto_tb(ctx, 0, ctx->btarget);
8876 }
8877 break;
8878 case MIPS_HFLAG_BR:
8879 /* unconditional branch to register */
8880 MIPS_DEBUG("branch to register");
3c824109 8881 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
364d4831
NF
8882 TCGv t0 = tcg_temp_new();
8883 TCGv_i32 t1 = tcg_temp_new_i32();
8884
8885 tcg_gen_andi_tl(t0, btarget, 0x1);
8886 tcg_gen_trunc_tl_i32(t1, t0);
8887 tcg_temp_free(t0);
8888 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
8889 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
8890 tcg_gen_or_i32(hflags, hflags, t1);
8891 tcg_temp_free_i32(t1);
8892
8893 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
8894 } else {
8895 tcg_gen_mov_tl(cpu_PC, btarget);
8896 }
c9602061
NF
8897 if (ctx->singlestep_enabled) {
8898 save_cpu_state(ctx, 0);
895c2d04 8899 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
c9602061
NF
8900 }
8901 tcg_gen_exit_tb(0);
8902 break;
8903 default:
8904 MIPS_DEBUG("unknown branch");
8905 break;
8906 }
8907 }
8908}
8909
7a387fff 8910/* ISA extensions (ASEs) */
6af0bf9c 8911/* MIPS16 extension to MIPS32 */
6ea219d0
NF
8912
8913/* MIPS16 major opcodes */
8914enum {
8915 M16_OPC_ADDIUSP = 0x00,
8916 M16_OPC_ADDIUPC = 0x01,
8917 M16_OPC_B = 0x02,
8918 M16_OPC_JAL = 0x03,
8919 M16_OPC_BEQZ = 0x04,
8920 M16_OPC_BNEQZ = 0x05,
8921 M16_OPC_SHIFT = 0x06,
8922 M16_OPC_LD = 0x07,
8923 M16_OPC_RRIA = 0x08,
8924 M16_OPC_ADDIU8 = 0x09,
8925 M16_OPC_SLTI = 0x0a,
8926 M16_OPC_SLTIU = 0x0b,
8927 M16_OPC_I8 = 0x0c,
8928 M16_OPC_LI = 0x0d,
8929 M16_OPC_CMPI = 0x0e,
8930 M16_OPC_SD = 0x0f,
8931 M16_OPC_LB = 0x10,
8932 M16_OPC_LH = 0x11,
8933 M16_OPC_LWSP = 0x12,
8934 M16_OPC_LW = 0x13,
8935 M16_OPC_LBU = 0x14,
8936 M16_OPC_LHU = 0x15,
8937 M16_OPC_LWPC = 0x16,
8938 M16_OPC_LWU = 0x17,
8939 M16_OPC_SB = 0x18,
8940 M16_OPC_SH = 0x19,
8941 M16_OPC_SWSP = 0x1a,
8942 M16_OPC_SW = 0x1b,
8943 M16_OPC_RRR = 0x1c,
8944 M16_OPC_RR = 0x1d,
8945 M16_OPC_EXTEND = 0x1e,
8946 M16_OPC_I64 = 0x1f
8947};
8948
8949/* I8 funct field */
8950enum {
8951 I8_BTEQZ = 0x0,
8952 I8_BTNEZ = 0x1,
8953 I8_SWRASP = 0x2,
8954 I8_ADJSP = 0x3,
8955 I8_SVRS = 0x4,
8956 I8_MOV32R = 0x5,
8957 I8_MOVR32 = 0x7
8958};
8959
8960/* RRR f field */
8961enum {
8962 RRR_DADDU = 0x0,
8963 RRR_ADDU = 0x1,
8964 RRR_DSUBU = 0x2,
8965 RRR_SUBU = 0x3
8966};
8967
8968/* RR funct field */
8969enum {
8970 RR_JR = 0x00,
8971 RR_SDBBP = 0x01,
8972 RR_SLT = 0x02,
8973 RR_SLTU = 0x03,
8974 RR_SLLV = 0x04,
8975 RR_BREAK = 0x05,
8976 RR_SRLV = 0x06,
8977 RR_SRAV = 0x07,
8978 RR_DSRL = 0x08,
8979 RR_CMP = 0x0a,
8980 RR_NEG = 0x0b,
8981 RR_AND = 0x0c,
8982 RR_OR = 0x0d,
8983 RR_XOR = 0x0e,
8984 RR_NOT = 0x0f,
8985 RR_MFHI = 0x10,
8986 RR_CNVT = 0x11,
8987 RR_MFLO = 0x12,
8988 RR_DSRA = 0x13,
8989 RR_DSLLV = 0x14,
8990 RR_DSRLV = 0x16,
8991 RR_DSRAV = 0x17,
8992 RR_MULT = 0x18,
8993 RR_MULTU = 0x19,
8994 RR_DIV = 0x1a,
8995 RR_DIVU = 0x1b,
8996 RR_DMULT = 0x1c,
8997 RR_DMULTU = 0x1d,
8998 RR_DDIV = 0x1e,
8999 RR_DDIVU = 0x1f
9000};
9001
9002/* I64 funct field */
9003enum {
9004 I64_LDSP = 0x0,
9005 I64_SDSP = 0x1,
9006 I64_SDRASP = 0x2,
9007 I64_DADJSP = 0x3,
9008 I64_LDPC = 0x4,
364d4831 9009 I64_DADDIU5 = 0x5,
6ea219d0
NF
9010 I64_DADDIUPC = 0x6,
9011 I64_DADDIUSP = 0x7
9012};
9013
9014/* RR ry field for CNVT */
9015enum {
9016 RR_RY_CNVT_ZEB = 0x0,
9017 RR_RY_CNVT_ZEH = 0x1,
9018 RR_RY_CNVT_ZEW = 0x2,
9019 RR_RY_CNVT_SEB = 0x4,
9020 RR_RY_CNVT_SEH = 0x5,
9021 RR_RY_CNVT_SEW = 0x6,
9022};
9023
364d4831
NF
9024static int xlat (int r)
9025{
9026 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
9027
9028 return map[r];
9029}
9030
9031static void gen_mips16_save (DisasContext *ctx,
9032 int xsregs, int aregs,
9033 int do_ra, int do_s0, int do_s1,
9034 int framesize)
9035{
9036 TCGv t0 = tcg_temp_new();
9037 TCGv t1 = tcg_temp_new();
9038 int args, astatic;
9039
9040 switch (aregs) {
9041 case 0:
9042 case 1:
9043 case 2:
9044 case 3:
9045 case 11:
9046 args = 0;
9047 break;
9048 case 4:
9049 case 5:
9050 case 6:
9051 case 7:
9052 args = 1;
9053 break;
9054 case 8:
9055 case 9:
9056 case 10:
9057 args = 2;
9058 break;
9059 case 12:
9060 case 13:
9061 args = 3;
9062 break;
9063 case 14:
9064 args = 4;
9065 break;
9066 default:
9067 generate_exception(ctx, EXCP_RI);
9068 return;
9069 }
9070
9071 switch (args) {
9072 case 4:
9073 gen_base_offset_addr(ctx, t0, 29, 12);
9074 gen_load_gpr(t1, 7);
5c13fdfd 9075 op_st_sw(t1, t0, ctx);
364d4831
NF
9076 /* Fall through */
9077 case 3:
9078 gen_base_offset_addr(ctx, t0, 29, 8);
9079 gen_load_gpr(t1, 6);
5c13fdfd 9080 op_st_sw(t1, t0, ctx);
364d4831
NF
9081 /* Fall through */
9082 case 2:
9083 gen_base_offset_addr(ctx, t0, 29, 4);
9084 gen_load_gpr(t1, 5);
5c13fdfd 9085 op_st_sw(t1, t0, ctx);
364d4831
NF
9086 /* Fall through */
9087 case 1:
9088 gen_base_offset_addr(ctx, t0, 29, 0);
9089 gen_load_gpr(t1, 4);
5c13fdfd 9090 op_st_sw(t1, t0, ctx);
364d4831
NF
9091 }
9092
9093 gen_load_gpr(t0, 29);
9094
9095#define DECR_AND_STORE(reg) do { \
9096 tcg_gen_subi_tl(t0, t0, 4); \
9097 gen_load_gpr(t1, reg); \
5c13fdfd 9098 op_st_sw(t1, t0, ctx); \
364d4831
NF
9099 } while (0)
9100
9101 if (do_ra) {
9102 DECR_AND_STORE(31);
9103 }
9104
9105 switch (xsregs) {
9106 case 7:
9107 DECR_AND_STORE(30);
9108 /* Fall through */
9109 case 6:
9110 DECR_AND_STORE(23);
9111 /* Fall through */
9112 case 5:
9113 DECR_AND_STORE(22);
9114 /* Fall through */
9115 case 4:
9116 DECR_AND_STORE(21);
9117 /* Fall through */
9118 case 3:
9119 DECR_AND_STORE(20);
9120 /* Fall through */
9121 case 2:
9122 DECR_AND_STORE(19);
9123 /* Fall through */
9124 case 1:
9125 DECR_AND_STORE(18);
9126 }
9127
9128 if (do_s1) {
9129 DECR_AND_STORE(17);
9130 }
9131 if (do_s0) {
9132 DECR_AND_STORE(16);
9133 }
9134
9135 switch (aregs) {
9136 case 0:
9137 case 4:
9138 case 8:
9139 case 12:
9140 case 14:
9141 astatic = 0;
9142 break;
9143 case 1:
9144 case 5:
9145 case 9:
9146 case 13:
9147 astatic = 1;
9148 break;
9149 case 2:
9150 case 6:
9151 case 10:
9152 astatic = 2;
9153 break;
9154 case 3:
9155 case 7:
9156 astatic = 3;
9157 break;
9158 case 11:
9159 astatic = 4;
9160 break;
9161 default:
9162 generate_exception(ctx, EXCP_RI);
9163 return;
9164 }
9165
9166 if (astatic > 0) {
9167 DECR_AND_STORE(7);
9168 if (astatic > 1) {
9169 DECR_AND_STORE(6);
9170 if (astatic > 2) {
9171 DECR_AND_STORE(5);
9172 if (astatic > 3) {
9173 DECR_AND_STORE(4);
9174 }
9175 }
9176 }
9177 }
9178#undef DECR_AND_STORE
9179
9180 tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
9181 tcg_temp_free(t0);
9182 tcg_temp_free(t1);
9183}
9184
9185static void gen_mips16_restore (DisasContext *ctx,
9186 int xsregs, int aregs,
9187 int do_ra, int do_s0, int do_s1,
9188 int framesize)
9189{
9190 int astatic;
9191 TCGv t0 = tcg_temp_new();
9192 TCGv t1 = tcg_temp_new();
9193
9194 tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
9195
9196#define DECR_AND_LOAD(reg) do { \
9197 tcg_gen_subi_tl(t0, t0, 4); \
5c13fdfd 9198 op_ld_lw(t1, t0, ctx); \
364d4831
NF
9199 gen_store_gpr(t1, reg); \
9200 } while (0)
9201
9202 if (do_ra) {
9203 DECR_AND_LOAD(31);
9204 }
9205
9206 switch (xsregs) {
9207 case 7:
9208 DECR_AND_LOAD(30);
9209 /* Fall through */
9210 case 6:
9211 DECR_AND_LOAD(23);
9212 /* Fall through */
9213 case 5:
9214 DECR_AND_LOAD(22);
9215 /* Fall through */
9216 case 4:
9217 DECR_AND_LOAD(21);
9218 /* Fall through */
9219 case 3:
9220 DECR_AND_LOAD(20);
9221 /* Fall through */
9222 case 2:
9223 DECR_AND_LOAD(19);
9224 /* Fall through */
9225 case 1:
9226 DECR_AND_LOAD(18);
9227 }
9228
9229 if (do_s1) {
9230 DECR_AND_LOAD(17);
9231 }
9232 if (do_s0) {
9233 DECR_AND_LOAD(16);
9234 }
9235
9236 switch (aregs) {
9237 case 0:
9238 case 4:
9239 case 8:
9240 case 12:
9241 case 14:
9242 astatic = 0;
9243 break;
9244 case 1:
9245 case 5:
9246 case 9:
9247 case 13:
9248 astatic = 1;
9249 break;
9250 case 2:
9251 case 6:
9252 case 10:
9253 astatic = 2;
9254 break;
9255 case 3:
9256 case 7:
9257 astatic = 3;
9258 break;
9259 case 11:
9260 astatic = 4;
9261 break;
9262 default:
9263 generate_exception(ctx, EXCP_RI);
9264 return;
9265 }
9266
9267 if (astatic > 0) {
9268 DECR_AND_LOAD(7);
9269 if (astatic > 1) {
9270 DECR_AND_LOAD(6);
9271 if (astatic > 2) {
9272 DECR_AND_LOAD(5);
9273 if (astatic > 3) {
9274 DECR_AND_LOAD(4);
9275 }
9276 }
9277 }
9278 }
9279#undef DECR_AND_LOAD
9280
9281 tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
9282 tcg_temp_free(t0);
9283 tcg_temp_free(t1);
9284}
9285
9286static void gen_addiupc (DisasContext *ctx, int rx, int imm,
9287 int is_64_bit, int extended)
9288{
9289 TCGv t0;
9290
9291 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9292 generate_exception(ctx, EXCP_RI);
9293 return;
9294 }
9295
9296 t0 = tcg_temp_new();
9297
9298 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
9299 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
9300 if (!is_64_bit) {
9301 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9302 }
9303
9304 tcg_temp_free(t0);
9305}
9306
9307#if defined(TARGET_MIPS64)
7db13fae 9308static void decode_i64_mips16 (CPUMIPSState *env, DisasContext *ctx,
364d4831
NF
9309 int ry, int funct, int16_t offset,
9310 int extended)
9311{
9312 switch (funct) {
9313 case I64_LDSP:
9314 check_mips_64(ctx);
9315 offset = extended ? offset : offset << 3;
afa88c3a 9316 gen_ld(env, ctx, OPC_LD, ry, 29, offset);
364d4831
NF
9317 break;
9318 case I64_SDSP:
9319 check_mips_64(ctx);
9320 offset = extended ? offset : offset << 3;
5c13fdfd 9321 gen_st(ctx, OPC_SD, ry, 29, offset);
364d4831
NF
9322 break;
9323 case I64_SDRASP:
9324 check_mips_64(ctx);
9325 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
5c13fdfd 9326 gen_st(ctx, OPC_SD, 31, 29, offset);
364d4831
NF
9327 break;
9328 case I64_DADJSP:
9329 check_mips_64(ctx);
9330 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
9331 gen_arith_imm(env, ctx, OPC_DADDIU, 29, 29, offset);
9332 break;
9333 case I64_LDPC:
9334 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9335 generate_exception(ctx, EXCP_RI);
9336 } else {
9337 offset = extended ? offset : offset << 3;
afa88c3a 9338 gen_ld(env, ctx, OPC_LDPC, ry, 0, offset);
364d4831
NF
9339 }
9340 break;
9341 case I64_DADDIU5:
9342 check_mips_64(ctx);
9343 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
9344 gen_arith_imm(env, ctx, OPC_DADDIU, ry, ry, offset);
9345 break;
9346 case I64_DADDIUPC:
9347 check_mips_64(ctx);
9348 offset = extended ? offset : offset << 2;
9349 gen_addiupc(ctx, ry, offset, 1, extended);
9350 break;
9351 case I64_DADDIUSP:
9352 check_mips_64(ctx);
9353 offset = extended ? offset : offset << 2;
9354 gen_arith_imm(env, ctx, OPC_DADDIU, ry, 29, offset);
9355 break;
9356 }
9357}
9358#endif
9359
7db13fae 9360static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
364d4831
NF
9361 int *is_branch)
9362{
895c2d04 9363 int extend = cpu_lduw_code(env, ctx->pc + 2);
364d4831
NF
9364 int op, rx, ry, funct, sa;
9365 int16_t imm, offset;
9366
9367 ctx->opcode = (ctx->opcode << 16) | extend;
9368 op = (ctx->opcode >> 11) & 0x1f;
9369 sa = (ctx->opcode >> 22) & 0x1f;
9370 funct = (ctx->opcode >> 8) & 0x7;
9371 rx = xlat((ctx->opcode >> 8) & 0x7);
9372 ry = xlat((ctx->opcode >> 5) & 0x7);
9373 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
9374 | ((ctx->opcode >> 21) & 0x3f) << 5
9375 | (ctx->opcode & 0x1f));
9376
9377 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
9378 counterparts. */
9379 switch (op) {
9380 case M16_OPC_ADDIUSP:
9381 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
9382 break;
9383 case M16_OPC_ADDIUPC:
9384 gen_addiupc(ctx, rx, imm, 0, 1);
9385 break;
9386 case M16_OPC_B:
9387 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1);
9388 /* No delay slot, so just process as a normal instruction */
9389 break;
9390 case M16_OPC_BEQZ:
9391 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1);
9392 /* No delay slot, so just process as a normal instruction */
9393 break;
9394 case M16_OPC_BNEQZ:
9395 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1);
9396 /* No delay slot, so just process as a normal instruction */
9397 break;
9398 case M16_OPC_SHIFT:
9399 switch (ctx->opcode & 0x3) {
9400 case 0x0:
9401 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
9402 break;
9403 case 0x1:
9404#if defined(TARGET_MIPS64)
9405 check_mips_64(ctx);
9406 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
9407#else
9408 generate_exception(ctx, EXCP_RI);
9409#endif
9410 break;
9411 case 0x2:
9412 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
9413 break;
9414 case 0x3:
9415 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
9416 break;
9417 }
9418 break;
9419#if defined(TARGET_MIPS64)
9420 case M16_OPC_LD:
9421 check_mips_64(ctx);
afa88c3a 9422 gen_ld(env, ctx, OPC_LD, ry, rx, offset);
364d4831
NF
9423 break;
9424#endif
9425 case M16_OPC_RRIA:
9426 imm = ctx->opcode & 0xf;
9427 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
9428 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
9429 imm = (int16_t) (imm << 1) >> 1;
9430 if ((ctx->opcode >> 4) & 0x1) {
9431#if defined(TARGET_MIPS64)
9432 check_mips_64(ctx);
9433 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
9434#else
9435 generate_exception(ctx, EXCP_RI);
9436#endif
9437 } else {
9438 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
9439 }
9440 break;
9441 case M16_OPC_ADDIU8:
9442 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
9443 break;
9444 case M16_OPC_SLTI:
9fa77488 9445 gen_slt_imm(env, ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
9446 break;
9447 case M16_OPC_SLTIU:
9fa77488 9448 gen_slt_imm(env, ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
9449 break;
9450 case M16_OPC_I8:
9451 switch (funct) {
9452 case I8_BTEQZ:
9453 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1);
9454 break;
9455 case I8_BTNEZ:
9456 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
9457 break;
9458 case I8_SWRASP:
5c13fdfd 9459 gen_st(ctx, OPC_SW, 31, 29, imm);
364d4831
NF
9460 break;
9461 case I8_ADJSP:
9462 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm);
9463 break;
9464 case I8_SVRS:
9465 {
9466 int xsregs = (ctx->opcode >> 24) & 0x7;
9467 int aregs = (ctx->opcode >> 16) & 0xf;
9468 int do_ra = (ctx->opcode >> 6) & 0x1;
9469 int do_s0 = (ctx->opcode >> 5) & 0x1;
9470 int do_s1 = (ctx->opcode >> 4) & 0x1;
9471 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
9472 | (ctx->opcode & 0xf)) << 3;
9473
9474 if (ctx->opcode & (1 << 7)) {
9475 gen_mips16_save(ctx, xsregs, aregs,
9476 do_ra, do_s0, do_s1,
9477 framesize);
9478 } else {
9479 gen_mips16_restore(ctx, xsregs, aregs,
9480 do_ra, do_s0, do_s1,
9481 framesize);
9482 }
9483 }
9484 break;
9485 default:
9486 generate_exception(ctx, EXCP_RI);
9487 break;
9488 }
9489 break;
9490 case M16_OPC_LI:
9491 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
9492 break;
9493 case M16_OPC_CMPI:
9494 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
9495 break;
9496#if defined(TARGET_MIPS64)
9497 case M16_OPC_SD:
5c13fdfd 9498 gen_st(ctx, OPC_SD, ry, rx, offset);
364d4831
NF
9499 break;
9500#endif
9501 case M16_OPC_LB:
afa88c3a 9502 gen_ld(env, ctx, OPC_LB, ry, rx, offset);
364d4831
NF
9503 break;
9504 case M16_OPC_LH:
afa88c3a 9505 gen_ld(env, ctx, OPC_LH, ry, rx, offset);
364d4831
NF
9506 break;
9507 case M16_OPC_LWSP:
afa88c3a 9508 gen_ld(env, ctx, OPC_LW, rx, 29, offset);
364d4831
NF
9509 break;
9510 case M16_OPC_LW:
afa88c3a 9511 gen_ld(env, ctx, OPC_LW, ry, rx, offset);
364d4831
NF
9512 break;
9513 case M16_OPC_LBU:
afa88c3a 9514 gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
9515 break;
9516 case M16_OPC_LHU:
afa88c3a 9517 gen_ld(env, ctx, OPC_LHU, ry, rx, offset);
364d4831
NF
9518 break;
9519 case M16_OPC_LWPC:
afa88c3a 9520 gen_ld(env, ctx, OPC_LWPC, rx, 0, offset);
364d4831
NF
9521 break;
9522#if defined(TARGET_MIPS64)
9523 case M16_OPC_LWU:
afa88c3a 9524 gen_ld(env, ctx, OPC_LWU, ry, rx, offset);
364d4831
NF
9525 break;
9526#endif
9527 case M16_OPC_SB:
5c13fdfd 9528 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
9529 break;
9530 case M16_OPC_SH:
5c13fdfd 9531 gen_st(ctx, OPC_SH, ry, rx, offset);
364d4831
NF
9532 break;
9533 case M16_OPC_SWSP:
5c13fdfd 9534 gen_st(ctx, OPC_SW, rx, 29, offset);
364d4831
NF
9535 break;
9536 case M16_OPC_SW:
5c13fdfd 9537 gen_st(ctx, OPC_SW, ry, rx, offset);
364d4831
NF
9538 break;
9539#if defined(TARGET_MIPS64)
9540 case M16_OPC_I64:
9541 decode_i64_mips16(env, ctx, ry, funct, offset, 1);
9542 break;
9543#endif
9544 default:
9545 generate_exception(ctx, EXCP_RI);
9546 break;
9547 }
9548
9549 return 4;
9550}
9551
7db13fae 9552static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
364d4831
NF
9553 int *is_branch)
9554{
9555 int rx, ry;
9556 int sa;
9557 int op, cnvt_op, op1, offset;
9558 int funct;
9559 int n_bytes;
9560
9561 op = (ctx->opcode >> 11) & 0x1f;
9562 sa = (ctx->opcode >> 2) & 0x7;
9563 sa = sa == 0 ? 8 : sa;
9564 rx = xlat((ctx->opcode >> 8) & 0x7);
9565 cnvt_op = (ctx->opcode >> 5) & 0x7;
9566 ry = xlat((ctx->opcode >> 5) & 0x7);
9567 op1 = offset = ctx->opcode & 0x1f;
9568
9569 n_bytes = 2;
9570
9571 switch (op) {
9572 case M16_OPC_ADDIUSP:
9573 {
9574 int16_t imm = ((uint8_t) ctx->opcode) << 2;
9575
9576 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
9577 }
9578 break;
9579 case M16_OPC_ADDIUPC:
9580 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
9581 break;
9582 case M16_OPC_B:
9583 offset = (ctx->opcode & 0x7ff) << 1;
9584 offset = (int16_t)(offset << 4) >> 4;
9585 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset);
9586 /* No delay slot, so just process as a normal instruction */
9587 break;
9588 case M16_OPC_JAL:
895c2d04 9589 offset = cpu_lduw_code(env, ctx->pc + 2);
364d4831
NF
9590 offset = (((ctx->opcode & 0x1f) << 21)
9591 | ((ctx->opcode >> 5) & 0x1f) << 16
9592 | offset) << 2;
620e48f6 9593 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS;
364d4831
NF
9594 gen_compute_branch(ctx, op, 4, rx, ry, offset);
9595 n_bytes = 4;
9596 *is_branch = 1;
9597 break;
9598 case M16_OPC_BEQZ:
9599 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
9600 /* No delay slot, so just process as a normal instruction */
9601 break;
9602 case M16_OPC_BNEQZ:
9603 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
9604 /* No delay slot, so just process as a normal instruction */
9605 break;
9606 case M16_OPC_SHIFT:
9607 switch (ctx->opcode & 0x3) {
9608 case 0x0:
9609 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
9610 break;
9611 case 0x1:
9612#if defined(TARGET_MIPS64)
9613 check_mips_64(ctx);
9614 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
9615#else
9616 generate_exception(ctx, EXCP_RI);
9617#endif
9618 break;
9619 case 0x2:
9620 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
9621 break;
9622 case 0x3:
9623 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
9624 break;
9625 }
9626 break;
9627#if defined(TARGET_MIPS64)
9628 case M16_OPC_LD:
9629 check_mips_64(ctx);
afa88c3a 9630 gen_ld(env, ctx, OPC_LD, ry, rx, offset << 3);
364d4831
NF
9631 break;
9632#endif
9633 case M16_OPC_RRIA:
9634 {
9635 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
9636
9637 if ((ctx->opcode >> 4) & 1) {
9638#if defined(TARGET_MIPS64)
9639 check_mips_64(ctx);
9640 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
9641#else
9642 generate_exception(ctx, EXCP_RI);
9643#endif
9644 } else {
9645 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
9646 }
9647 }
9648 break;
9649 case M16_OPC_ADDIU8:
9650 {
9651 int16_t imm = (int8_t) ctx->opcode;
9652
9653 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
9654 }
9655 break;
9656 case M16_OPC_SLTI:
9657 {
9658 int16_t imm = (uint8_t) ctx->opcode;
9fa77488 9659 gen_slt_imm(env, ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
9660 }
9661 break;
9662 case M16_OPC_SLTIU:
9663 {
9664 int16_t imm = (uint8_t) ctx->opcode;
9fa77488 9665 gen_slt_imm(env, ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
9666 }
9667 break;
9668 case M16_OPC_I8:
9669 {
9670 int reg32;
9671
9672 funct = (ctx->opcode >> 8) & 0x7;
9673 switch (funct) {
9674 case I8_BTEQZ:
9675 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
9676 ((int8_t)ctx->opcode) << 1);
9677 break;
9678 case I8_BTNEZ:
9679 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
9680 ((int8_t)ctx->opcode) << 1);
9681 break;
9682 case I8_SWRASP:
5c13fdfd 9683 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
364d4831
NF
9684 break;
9685 case I8_ADJSP:
9686 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29,
9687 ((int8_t)ctx->opcode) << 3);
9688 break;
9689 case I8_SVRS:
9690 {
9691 int do_ra = ctx->opcode & (1 << 6);
9692 int do_s0 = ctx->opcode & (1 << 5);
9693 int do_s1 = ctx->opcode & (1 << 4);
9694 int framesize = ctx->opcode & 0xf;
9695
9696 if (framesize == 0) {
9697 framesize = 128;
9698 } else {
9699 framesize = framesize << 3;
9700 }
9701
9702 if (ctx->opcode & (1 << 7)) {
9703 gen_mips16_save(ctx, 0, 0,
9704 do_ra, do_s0, do_s1, framesize);
9705 } else {
9706 gen_mips16_restore(ctx, 0, 0,
9707 do_ra, do_s0, do_s1, framesize);
9708 }
9709 }
9710 break;
9711 case I8_MOV32R:
9712 {
9713 int rz = xlat(ctx->opcode & 0x7);
9714
9715 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
9716 ((ctx->opcode >> 5) & 0x7);
9717 gen_arith(env, ctx, OPC_ADDU, reg32, rz, 0);
9718 }
9719 break;
9720 case I8_MOVR32:
9721 reg32 = ctx->opcode & 0x1f;
9722 gen_arith(env, ctx, OPC_ADDU, ry, reg32, 0);
9723 break;
9724 default:
9725 generate_exception(ctx, EXCP_RI);
9726 break;
9727 }
9728 }
9729 break;
9730 case M16_OPC_LI:
9731 {
9732 int16_t imm = (uint8_t) ctx->opcode;
9733
9734 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 0, imm);
9735 }
9736 break;
9737 case M16_OPC_CMPI:
9738 {
9739 int16_t imm = (uint8_t) ctx->opcode;
9fa77488 9740 gen_logic_imm(env, ctx, OPC_XORI, 24, rx, imm);
364d4831
NF
9741 }
9742 break;
9743#if defined(TARGET_MIPS64)
9744 case M16_OPC_SD:
9745 check_mips_64(ctx);
5c13fdfd 9746 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
364d4831
NF
9747 break;
9748#endif
9749 case M16_OPC_LB:
afa88c3a 9750 gen_ld(env, ctx, OPC_LB, ry, rx, offset);
364d4831
NF
9751 break;
9752 case M16_OPC_LH:
afa88c3a 9753 gen_ld(env, ctx, OPC_LH, ry, rx, offset << 1);
364d4831
NF
9754 break;
9755 case M16_OPC_LWSP:
afa88c3a 9756 gen_ld(env, ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
9757 break;
9758 case M16_OPC_LW:
afa88c3a 9759 gen_ld(env, ctx, OPC_LW, ry, rx, offset << 2);
364d4831
NF
9760 break;
9761 case M16_OPC_LBU:
afa88c3a 9762 gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
9763 break;
9764 case M16_OPC_LHU:
afa88c3a 9765 gen_ld(env, ctx, OPC_LHU, ry, rx, offset << 1);
364d4831
NF
9766 break;
9767 case M16_OPC_LWPC:
afa88c3a 9768 gen_ld(env, ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
9769 break;
9770#if defined (TARGET_MIPS64)
9771 case M16_OPC_LWU:
9772 check_mips_64(ctx);
afa88c3a 9773 gen_ld(env, ctx, OPC_LWU, ry, rx, offset << 2);
364d4831
NF
9774 break;
9775#endif
9776 case M16_OPC_SB:
5c13fdfd 9777 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
9778 break;
9779 case M16_OPC_SH:
5c13fdfd 9780 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
364d4831
NF
9781 break;
9782 case M16_OPC_SWSP:
5c13fdfd 9783 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
9784 break;
9785 case M16_OPC_SW:
5c13fdfd 9786 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
364d4831
NF
9787 break;
9788 case M16_OPC_RRR:
9789 {
9790 int rz = xlat((ctx->opcode >> 2) & 0x7);
9791 int mips32_op;
9792
9793 switch (ctx->opcode & 0x3) {
9794 case RRR_ADDU:
9795 mips32_op = OPC_ADDU;
9796 break;
9797 case RRR_SUBU:
9798 mips32_op = OPC_SUBU;
9799 break;
9800#if defined(TARGET_MIPS64)
9801 case RRR_DADDU:
9802 mips32_op = OPC_DADDU;
9803 check_mips_64(ctx);
9804 break;
9805 case RRR_DSUBU:
9806 mips32_op = OPC_DSUBU;
9807 check_mips_64(ctx);
9808 break;
9809#endif
9810 default:
9811 generate_exception(ctx, EXCP_RI);
9812 goto done;
9813 }
9814
9815 gen_arith(env, ctx, mips32_op, rz, rx, ry);
9816 done:
9817 ;
9818 }
9819 break;
9820 case M16_OPC_RR:
9821 switch (op1) {
9822 case RR_JR:
9823 {
9824 int nd = (ctx->opcode >> 7) & 0x1;
9825 int link = (ctx->opcode >> 6) & 0x1;
9826 int ra = (ctx->opcode >> 5) & 0x1;
9827
9828 if (link) {
620e48f6 9829 op = nd ? OPC_JALRC : OPC_JALRS;
364d4831
NF
9830 } else {
9831 op = OPC_JR;
9832 }
9833
9834 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
9835 if (!nd) {
9836 *is_branch = 1;
9837 }
9838 }
9839 break;
9840 case RR_SDBBP:
9841 /* XXX: not clear which exception should be raised
9842 * when in debug mode...
9843 */
9844 check_insn(env, ctx, ISA_MIPS32);
9845 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9846 generate_exception(ctx, EXCP_DBp);
9847 } else {
9848 generate_exception(ctx, EXCP_DBp);
9849 }
9850 break;
9851 case RR_SLT:
9fa77488 9852 gen_slt(env, ctx, OPC_SLT, 24, rx, ry);
364d4831
NF
9853 break;
9854 case RR_SLTU:
9fa77488 9855 gen_slt(env, ctx, OPC_SLTU, 24, rx, ry);
364d4831
NF
9856 break;
9857 case RR_BREAK:
9858 generate_exception(ctx, EXCP_BREAK);
9859 break;
9860 case RR_SLLV:
9861 gen_shift(env, ctx, OPC_SLLV, ry, rx, ry);
9862 break;
9863 case RR_SRLV:
9864 gen_shift(env, ctx, OPC_SRLV, ry, rx, ry);
9865 break;
9866 case RR_SRAV:
9867 gen_shift(env, ctx, OPC_SRAV, ry, rx, ry);
9868 break;
9869#if defined (TARGET_MIPS64)
9870 case RR_DSRL:
9871 check_mips_64(ctx);
9872 gen_shift_imm(env, ctx, OPC_DSRL, ry, ry, sa);
9873 break;
9874#endif
9875 case RR_CMP:
9fa77488 9876 gen_logic(env, ctx, OPC_XOR, 24, rx, ry);
364d4831
NF
9877 break;
9878 case RR_NEG:
9879 gen_arith(env, ctx, OPC_SUBU, rx, 0, ry);
9880 break;
9881 case RR_AND:
9fa77488 9882 gen_logic(env, ctx, OPC_AND, rx, rx, ry);
364d4831
NF
9883 break;
9884 case RR_OR:
9fa77488 9885 gen_logic(env, ctx, OPC_OR, rx, rx, ry);
364d4831
NF
9886 break;
9887 case RR_XOR:
9fa77488 9888 gen_logic(env, ctx, OPC_XOR, rx, rx, ry);
364d4831
NF
9889 break;
9890 case RR_NOT:
9fa77488 9891 gen_logic(env, ctx, OPC_NOR, rx, ry, 0);
364d4831
NF
9892 break;
9893 case RR_MFHI:
9894 gen_HILO(ctx, OPC_MFHI, rx);
9895 break;
9896 case RR_CNVT:
9897 switch (cnvt_op) {
9898 case RR_RY_CNVT_ZEB:
9899 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9900 break;
9901 case RR_RY_CNVT_ZEH:
9902 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9903 break;
9904 case RR_RY_CNVT_SEB:
9905 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9906 break;
9907 case RR_RY_CNVT_SEH:
9908 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9909 break;
9910#if defined (TARGET_MIPS64)
9911 case RR_RY_CNVT_ZEW:
9912 check_mips_64(ctx);
9913 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9914 break;
9915 case RR_RY_CNVT_SEW:
9916 check_mips_64(ctx);
9917 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9918 break;
9919#endif
9920 default:
9921 generate_exception(ctx, EXCP_RI);
9922 break;
9923 }
9924 break;
9925 case RR_MFLO:
9926 gen_HILO(ctx, OPC_MFLO, rx);
9927 break;
9928#if defined (TARGET_MIPS64)
9929 case RR_DSRA:
9930 check_mips_64(ctx);
9931 gen_shift_imm(env, ctx, OPC_DSRA, ry, ry, sa);
9932 break;
9933 case RR_DSLLV:
9934 check_mips_64(ctx);
9935 gen_shift(env, ctx, OPC_DSLLV, ry, rx, ry);
9936 break;
9937 case RR_DSRLV:
9938 check_mips_64(ctx);
9939 gen_shift(env, ctx, OPC_DSRLV, ry, rx, ry);
9940 break;
9941 case RR_DSRAV:
9942 check_mips_64(ctx);
9943 gen_shift(env, ctx, OPC_DSRAV, ry, rx, ry);
9944 break;
9945#endif
9946 case RR_MULT:
9947 gen_muldiv(ctx, OPC_MULT, rx, ry);
9948 break;
9949 case RR_MULTU:
9950 gen_muldiv(ctx, OPC_MULTU, rx, ry);
9951 break;
9952 case RR_DIV:
9953 gen_muldiv(ctx, OPC_DIV, rx, ry);
9954 break;
9955 case RR_DIVU:
9956 gen_muldiv(ctx, OPC_DIVU, rx, ry);
9957 break;
9958#if defined (TARGET_MIPS64)
9959 case RR_DMULT:
9960 check_mips_64(ctx);
9961 gen_muldiv(ctx, OPC_DMULT, rx, ry);
9962 break;
9963 case RR_DMULTU:
9964 check_mips_64(ctx);
9965 gen_muldiv(ctx, OPC_DMULTU, rx, ry);
9966 break;
9967 case RR_DDIV:
9968 check_mips_64(ctx);
9969 gen_muldiv(ctx, OPC_DDIV, rx, ry);
9970 break;
9971 case RR_DDIVU:
9972 check_mips_64(ctx);
9973 gen_muldiv(ctx, OPC_DDIVU, rx, ry);
9974 break;
9975#endif
9976 default:
9977 generate_exception(ctx, EXCP_RI);
9978 break;
9979 }
9980 break;
9981 case M16_OPC_EXTEND:
9982 decode_extended_mips16_opc(env, ctx, is_branch);
9983 n_bytes = 4;
9984 break;
9985#if defined(TARGET_MIPS64)
9986 case M16_OPC_I64:
9987 funct = (ctx->opcode >> 8) & 0x7;
9988 decode_i64_mips16(env, ctx, ry, funct, offset, 0);
9989 break;
9990#endif
9991 default:
9992 generate_exception(ctx, EXCP_RI);
9993 break;
9994 }
9995
9996 return n_bytes;
9997}
9998
3c824109 9999/* microMIPS extension to MIPS32 */
6af0bf9c 10000
3c824109 10001/* microMIPS32 major opcodes */
6af0bf9c 10002
3c824109
NF
10003enum {
10004 POOL32A = 0x00,
10005 POOL16A = 0x01,
10006 LBU16 = 0x02,
10007 MOVE16 = 0x03,
10008 ADDI32 = 0x04,
10009 LBU32 = 0x05,
10010 SB32 = 0x06,
10011 LB32 = 0x07,
10012
10013 POOL32B = 0x08,
10014 POOL16B = 0x09,
10015 LHU16 = 0x0a,
10016 ANDI16 = 0x0b,
10017 ADDIU32 = 0x0c,
10018 LHU32 = 0x0d,
10019 SH32 = 0x0e,
10020 LH32 = 0x0f,
10021
10022 POOL32I = 0x10,
10023 POOL16C = 0x11,
10024 LWSP16 = 0x12,
10025 POOL16D = 0x13,
10026 ORI32 = 0x14,
10027 POOL32F = 0x15,
10028 POOL32S = 0x16,
10029 DADDIU32 = 0x17,
10030
10031 POOL32C = 0x18,
10032 LWGP16 = 0x19,
10033 LW16 = 0x1a,
10034 POOL16E = 0x1b,
10035 XORI32 = 0x1c,
10036 JALS32 = 0x1d,
10037 ADDIUPC = 0x1e,
10038 POOL48A = 0x1f,
10039
10040 /* 0x20 is reserved */
10041 RES_20 = 0x20,
10042 POOL16F = 0x21,
10043 SB16 = 0x22,
10044 BEQZ16 = 0x23,
10045 SLTI32 = 0x24,
10046 BEQ32 = 0x25,
10047 SWC132 = 0x26,
10048 LWC132 = 0x27,
10049
10050 /* 0x28 and 0x29 are reserved */
10051 RES_28 = 0x28,
10052 RES_29 = 0x29,
10053 SH16 = 0x2a,
10054 BNEZ16 = 0x2b,
10055 SLTIU32 = 0x2c,
10056 BNE32 = 0x2d,
10057 SDC132 = 0x2e,
10058 LDC132 = 0x2f,
10059
10060 /* 0x30 and 0x31 are reserved */
10061 RES_30 = 0x30,
10062 RES_31 = 0x31,
10063 SWSP16 = 0x32,
10064 B16 = 0x33,
10065 ANDI32 = 0x34,
10066 J32 = 0x35,
10067 SD32 = 0x36,
10068 LD32 = 0x37,
10069
10070 /* 0x38 and 0x39 are reserved */
10071 RES_38 = 0x38,
10072 RES_39 = 0x39,
10073 SW16 = 0x3a,
10074 LI16 = 0x3b,
10075 JALX32 = 0x3c,
10076 JAL32 = 0x3d,
10077 SW32 = 0x3e,
10078 LW32 = 0x3f
10079};
10080
10081/* POOL32A encoding of minor opcode field */
10082
10083enum {
10084 /* These opcodes are distinguished only by bits 9..6; those bits are
10085 * what are recorded below. */
10086 SLL32 = 0x0,
10087 SRL32 = 0x1,
10088 SRA = 0x2,
10089 ROTR = 0x3,
10090
10091 SLLV = 0x0,
10092 SRLV = 0x1,
10093 SRAV = 0x2,
10094 ROTRV = 0x3,
10095 ADD = 0x4,
10096 ADDU32 = 0x5,
10097 SUB = 0x6,
10098 SUBU32 = 0x7,
10099 MUL = 0x8,
10100 AND = 0x9,
10101 OR32 = 0xa,
10102 NOR = 0xb,
10103 XOR32 = 0xc,
10104 SLT = 0xd,
10105 SLTU = 0xe,
10106
10107 MOVN = 0x0,
10108 MOVZ = 0x1,
10109 LWXS = 0x4,
10110
10111 /* The following can be distinguished by their lower 6 bits. */
10112 INS = 0x0c,
10113 EXT = 0x2c,
10114 POOL32AXF = 0x3c
10115};
10116
10117/* POOL32AXF encoding of minor opcode field extension */
10118
10119enum {
10120 /* bits 11..6 */
10121 TEQ = 0x00,
10122 TGE = 0x08,
10123 TGEU = 0x10,
10124 TLT = 0x20,
10125 TLTU = 0x28,
10126 TNE = 0x30,
10127
10128 MFC0 = 0x03,
10129 MTC0 = 0x0b,
10130
10131 /* bits 13..12 for 0x01 */
10132 MFHI_ACC = 0x0,
10133 MFLO_ACC = 0x1,
10134 MTHI_ACC = 0x2,
10135 MTLO_ACC = 0x3,
10136
10137 /* bits 13..12 for 0x2a */
10138 MADD_ACC = 0x0,
10139 MADDU_ACC = 0x1,
10140 MSUB_ACC = 0x2,
10141 MSUBU_ACC = 0x3,
10142
10143 /* bits 13..12 for 0x32 */
10144 MULT_ACC = 0x0,
10145 MULTU_ACC = 0x0,
10146
10147 /* bits 15..12 for 0x2c */
10148 SEB = 0x2,
10149 SEH = 0x3,
10150 CLO = 0x4,
10151 CLZ = 0x5,
10152 RDHWR = 0x6,
10153 WSBH = 0x7,
10154 MULT = 0x8,
10155 MULTU = 0x9,
10156 DIV = 0xa,
10157 DIVU = 0xb,
10158 MADD = 0xc,
10159 MADDU = 0xd,
10160 MSUB = 0xe,
10161 MSUBU = 0xf,
10162
10163 /* bits 15..12 for 0x34 */
10164 MFC2 = 0x4,
10165 MTC2 = 0x5,
10166 MFHC2 = 0x8,
10167 MTHC2 = 0x9,
10168 CFC2 = 0xc,
10169 CTC2 = 0xd,
10170
10171 /* bits 15..12 for 0x3c */
10172 JALR = 0x0,
10173 JR = 0x0, /* alias */
10174 JALR_HB = 0x1,
10175 JALRS = 0x4,
10176 JALRS_HB = 0x5,
10177
10178 /* bits 15..12 for 0x05 */
10179 RDPGPR = 0xe,
10180 WRPGPR = 0xf,
10181
10182 /* bits 15..12 for 0x0d */
10183 TLBP = 0x0,
10184 TLBR = 0x1,
10185 TLBWI = 0x2,
10186 TLBWR = 0x3,
10187 WAIT = 0x9,
10188 IRET = 0xd,
10189 DERET = 0xe,
10190 ERET = 0xf,
10191
10192 /* bits 15..12 for 0x15 */
10193 DMT = 0x0,
10194 DVPE = 0x1,
10195 EMT = 0x2,
10196 EVPE = 0x3,
10197
10198 /* bits 15..12 for 0x1d */
10199 DI = 0x4,
10200 EI = 0x5,
10201
10202 /* bits 15..12 for 0x2d */
10203 SYNC = 0x6,
10204 SYSCALL = 0x8,
10205 SDBBP = 0xd,
10206
10207 /* bits 15..12 for 0x35 */
10208 MFHI32 = 0x0,
10209 MFLO32 = 0x1,
10210 MTHI32 = 0x2,
10211 MTLO32 = 0x3,
10212};
10213
10214/* POOL32B encoding of minor opcode field (bits 15..12) */
10215
10216enum {
10217 LWC2 = 0x0,
10218 LWP = 0x1,
10219 LDP = 0x4,
10220 LWM32 = 0x5,
10221 CACHE = 0x6,
10222 LDM = 0x7,
10223 SWC2 = 0x8,
10224 SWP = 0x9,
10225 SDP = 0xc,
10226 SWM32 = 0xd,
10227 SDM = 0xf
10228};
10229
10230/* POOL32C encoding of minor opcode field (bits 15..12) */
10231
10232enum {
10233 LWL = 0x0,
10234 SWL = 0x8,
10235 LWR = 0x1,
10236 SWR = 0x9,
10237 PREF = 0x2,
10238 /* 0xa is reserved */
10239 LL = 0x3,
10240 SC = 0xb,
10241 LDL = 0x4,
10242 SDL = 0xc,
10243 LDR = 0x5,
10244 SDR = 0xd,
10245 /* 0x6 is reserved */
10246 LWU = 0xe,
10247 LLD = 0x7,
10248 SCD = 0xf
10249};
10250
10251/* POOL32F encoding of minor opcode field (bits 5..0) */
10252
10253enum {
10254 /* These are the bit 7..6 values */
10255 ADD_FMT = 0x0,
10256 MOVN_FMT = 0x0,
10257
10258 SUB_FMT = 0x1,
10259 MOVZ_FMT = 0x1,
10260
10261 MUL_FMT = 0x2,
10262
10263 DIV_FMT = 0x3,
10264
10265 /* These are the bit 8..6 values */
10266 RSQRT2_FMT = 0x0,
10267 MOVF_FMT = 0x0,
10268
10269 LWXC1 = 0x1,
10270 MOVT_FMT = 0x1,
10271
10272 PLL_PS = 0x2,
10273 SWXC1 = 0x2,
10274
10275 PLU_PS = 0x3,
10276 LDXC1 = 0x3,
10277
10278 PUL_PS = 0x4,
10279 SDXC1 = 0x4,
10280 RECIP2_FMT = 0x4,
10281
10282 PUU_PS = 0x5,
10283 LUXC1 = 0x5,
10284
10285 CVT_PS_S = 0x6,
10286 SUXC1 = 0x6,
10287 ADDR_PS = 0x6,
10288 PREFX = 0x6,
10289
10290 MULR_PS = 0x7,
10291
10292 MADD_S = 0x01,
10293 MADD_D = 0x09,
10294 MADD_PS = 0x11,
10295 ALNV_PS = 0x19,
10296 MSUB_S = 0x21,
10297 MSUB_D = 0x29,
10298 MSUB_PS = 0x31,
10299
10300 NMADD_S = 0x02,
10301 NMADD_D = 0x0a,
10302 NMADD_PS = 0x12,
10303 NMSUB_S = 0x22,
10304 NMSUB_D = 0x2a,
10305 NMSUB_PS = 0x32,
10306
10307 POOL32FXF = 0x3b,
10308
10309 CABS_COND_FMT = 0x1c, /* MIPS3D */
10310 C_COND_FMT = 0x3c
10311};
10312
10313/* POOL32Fxf encoding of minor opcode extension field */
10314
10315enum {
10316 CVT_L = 0x04,
10317 RSQRT_FMT = 0x08,
10318 FLOOR_L = 0x0c,
10319 CVT_PW_PS = 0x1c,
10320 CVT_W = 0x24,
10321 SQRT_FMT = 0x28,
10322 FLOOR_W = 0x2c,
10323 CVT_PS_PW = 0x3c,
10324 CFC1 = 0x40,
10325 RECIP_FMT = 0x48,
10326 CEIL_L = 0x4c,
10327 CTC1 = 0x60,
10328 CEIL_W = 0x6c,
10329 MFC1 = 0x80,
10330 CVT_S_PL = 0x84,
10331 TRUNC_L = 0x8c,
10332 MTC1 = 0xa0,
10333 CVT_S_PU = 0xa4,
10334 TRUNC_W = 0xac,
10335 MFHC1 = 0xc0,
10336 ROUND_L = 0xcc,
10337 MTHC1 = 0xe0,
10338 ROUND_W = 0xec,
10339
10340 MOV_FMT = 0x01,
10341 MOVF = 0x05,
10342 ABS_FMT = 0x0d,
10343 RSQRT1_FMT = 0x1d,
10344 MOVT = 0x25,
10345 NEG_FMT = 0x2d,
10346 CVT_D = 0x4d,
10347 RECIP1_FMT = 0x5d,
10348 CVT_S = 0x6d
10349};
10350
10351/* POOL32I encoding of minor opcode field (bits 25..21) */
10352
10353enum {
10354 BLTZ = 0x00,
10355 BLTZAL = 0x01,
10356 BGEZ = 0x02,
10357 BGEZAL = 0x03,
10358 BLEZ = 0x04,
10359 BNEZC = 0x05,
10360 BGTZ = 0x06,
10361 BEQZC = 0x07,
10362 TLTI = 0x08,
10363 TGEI = 0x09,
10364 TLTIU = 0x0a,
10365 TGEIU = 0x0b,
10366 TNEI = 0x0c,
10367 LUI = 0x0d,
10368 TEQI = 0x0e,
10369 SYNCI = 0x10,
10370 BLTZALS = 0x11,
10371 BGEZALS = 0x13,
10372 BC2F = 0x14,
10373 BC2T = 0x15,
10374 BPOSGE64 = 0x1a,
10375 BPOSGE32 = 0x1b,
10376 /* These overlap and are distinguished by bit16 of the instruction */
10377 BC1F = 0x1c,
10378 BC1T = 0x1d,
10379 BC1ANY2F = 0x1c,
10380 BC1ANY2T = 0x1d,
10381 BC1ANY4F = 0x1e,
10382 BC1ANY4T = 0x1f
10383};
10384
10385/* POOL16A encoding of minor opcode field */
10386
10387enum {
10388 ADDU16 = 0x0,
10389 SUBU16 = 0x1
10390};
10391
10392/* POOL16B encoding of minor opcode field */
10393
10394enum {
10395 SLL16 = 0x0,
10396 SRL16 = 0x1
10397};
10398
10399/* POOL16C encoding of minor opcode field */
10400
10401enum {
10402 NOT16 = 0x00,
10403 XOR16 = 0x04,
10404 AND16 = 0x08,
10405 OR16 = 0x0c,
10406 LWM16 = 0x10,
10407 SWM16 = 0x14,
10408 JR16 = 0x18,
10409 JRC16 = 0x1a,
10410 JALR16 = 0x1c,
10411 JALR16S = 0x1e,
10412 MFHI16 = 0x20,
10413 MFLO16 = 0x24,
10414 BREAK16 = 0x28,
10415 SDBBP16 = 0x2c,
10416 JRADDIUSP = 0x30
10417};
10418
10419/* POOL16D encoding of minor opcode field */
10420
10421enum {
10422 ADDIUS5 = 0x0,
10423 ADDIUSP = 0x1
10424};
10425
10426/* POOL16E encoding of minor opcode field */
10427
10428enum {
10429 ADDIUR2 = 0x0,
10430 ADDIUR1SP = 0x1
10431};
10432
10433static int mmreg (int r)
10434{
10435 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
10436
10437 return map[r];
10438}
10439
10440/* Used for 16-bit store instructions. */
10441static int mmreg2 (int r)
10442{
10443 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
10444
10445 return map[r];
10446}
10447
10448#define uMIPS_RD(op) ((op >> 7) & 0x7)
10449#define uMIPS_RS(op) ((op >> 4) & 0x7)
10450#define uMIPS_RS2(op) uMIPS_RS(op)
10451#define uMIPS_RS1(op) ((op >> 1) & 0x7)
10452#define uMIPS_RD5(op) ((op >> 5) & 0x1f)
10453#define uMIPS_RS5(op) (op & 0x1f)
10454
10455/* Signed immediate */
10456#define SIMM(op, start, width) \
10457 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
10458 << (32-width)) \
10459 >> (32-width))
10460/* Zero-extended immediate */
10461#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
10462
7db13fae 10463static void gen_addiur1sp (CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
10464{
10465 int rd = mmreg(uMIPS_RD(ctx->opcode));
10466
10467 gen_arith_imm(env, ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
10468}
10469
7db13fae 10470static void gen_addiur2 (CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
10471{
10472 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
10473 int rd = mmreg(uMIPS_RD(ctx->opcode));
10474 int rs = mmreg(uMIPS_RS(ctx->opcode));
10475
10476 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
10477}
10478
7db13fae 10479static void gen_addiusp (CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
10480{
10481 int encoded = ZIMM(ctx->opcode, 1, 9);
10482 int decoded;
10483
10484 if (encoded <= 1) {
10485 decoded = 256 + encoded;
10486 } else if (encoded <= 255) {
10487 decoded = encoded;
10488 } else if (encoded <= 509) {
10489 decoded = encoded - 512;
10490 } else {
10491 decoded = encoded - 768;
10492 }
10493
10494 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, decoded << 2);
10495}
10496
7db13fae 10497static void gen_addius5 (CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
10498{
10499 int imm = SIMM(ctx->opcode, 1, 4);
10500 int rd = (ctx->opcode >> 5) & 0x1f;
10501
10502 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rd, imm);
10503}
10504
7db13fae 10505static void gen_andi16 (CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
10506{
10507 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
10508 31, 32, 63, 64, 255, 32768, 65535 };
10509 int rd = mmreg(uMIPS_RD(ctx->opcode));
10510 int rs = mmreg(uMIPS_RS(ctx->opcode));
10511 int encoded = ZIMM(ctx->opcode, 0, 4);
10512
9fa77488 10513 gen_logic_imm(env, ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
3c824109
NF
10514}
10515
10516static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
10517 int base, int16_t offset)
10518{
e1050a76 10519 const char *opn = "ldst_multiple";
3c824109
NF
10520 TCGv t0, t1;
10521 TCGv_i32 t2;
10522
10523 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10524 generate_exception(ctx, EXCP_RI);
10525 return;
10526 }
10527
10528 t0 = tcg_temp_new();
10529
10530 gen_base_offset_addr(ctx, t0, base, offset);
10531
10532 t1 = tcg_const_tl(reglist);
10533 t2 = tcg_const_i32(ctx->mem_idx);
6af0bf9c 10534
3c824109
NF
10535 save_cpu_state(ctx, 1);
10536 switch (opc) {
10537 case LWM32:
895c2d04 10538 gen_helper_lwm(cpu_env, t0, t1, t2);
e1050a76 10539 opn = "lwm";
3c824109
NF
10540 break;
10541 case SWM32:
895c2d04 10542 gen_helper_swm(cpu_env, t0, t1, t2);
e1050a76 10543 opn = "swm";
3c824109
NF
10544 break;
10545#ifdef TARGET_MIPS64
10546 case LDM:
895c2d04 10547 gen_helper_ldm(cpu_env, t0, t1, t2);
e1050a76 10548 opn = "ldm";
3c824109
NF
10549 break;
10550 case SDM:
895c2d04 10551 gen_helper_sdm(cpu_env, t0, t1, t2);
e1050a76 10552 opn = "sdm";
3c824109 10553 break;
6af0bf9c 10554#endif
3c824109 10555 }
e1050a76 10556 (void)opn;
3c824109
NF
10557 MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
10558 tcg_temp_free(t0);
33087598 10559 tcg_temp_free(t1);
3c824109
NF
10560 tcg_temp_free_i32(t2);
10561}
6af0bf9c 10562
3c824109 10563
7db13fae 10564static void gen_pool16c_insn (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
6af0bf9c 10565{
3c824109
NF
10566 int rd = mmreg((ctx->opcode >> 3) & 0x7);
10567 int rs = mmreg(ctx->opcode & 0x7);
10568 int opc;
6af0bf9c 10569
3c824109
NF
10570 switch (((ctx->opcode) >> 4) & 0x3f) {
10571 case NOT16 + 0:
10572 case NOT16 + 1:
10573 case NOT16 + 2:
10574 case NOT16 + 3:
9fa77488 10575 gen_logic(env, ctx, OPC_NOR, rd, rs, 0);
3c824109
NF
10576 break;
10577 case XOR16 + 0:
10578 case XOR16 + 1:
10579 case XOR16 + 2:
10580 case XOR16 + 3:
9fa77488 10581 gen_logic(env, ctx, OPC_XOR, rd, rd, rs);
3c824109
NF
10582 break;
10583 case AND16 + 0:
10584 case AND16 + 1:
10585 case AND16 + 2:
10586 case AND16 + 3:
9fa77488 10587 gen_logic(env, ctx, OPC_AND, rd, rd, rs);
3c824109
NF
10588 break;
10589 case OR16 + 0:
10590 case OR16 + 1:
10591 case OR16 + 2:
10592 case OR16 + 3:
9fa77488 10593 gen_logic(env, ctx, OPC_OR, rd, rd, rs);
3c824109
NF
10594 break;
10595 case LWM16 + 0:
10596 case LWM16 + 1:
10597 case LWM16 + 2:
10598 case LWM16 + 3:
10599 {
10600 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
10601 int offset = ZIMM(ctx->opcode, 0, 4);
10602
10603 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
10604 29, offset << 2);
10605 }
10606 break;
10607 case SWM16 + 0:
10608 case SWM16 + 1:
10609 case SWM16 + 2:
10610 case SWM16 + 3:
10611 {
10612 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
10613 int offset = ZIMM(ctx->opcode, 0, 4);
10614
10615 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
10616 29, offset << 2);
10617 }
10618 break;
10619 case JR16 + 0:
10620 case JR16 + 1:
10621 {
10622 int reg = ctx->opcode & 0x1f;
10623
10624 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
10625 }
10626 *is_branch = 1;
10627 break;
10628 case JRC16 + 0:
10629 case JRC16 + 1:
10630 {
10631 int reg = ctx->opcode & 0x1f;
10632
10633 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
10634 /* Let normal delay slot handling in our caller take us
10635 to the branch target. */
10636 }
10637 break;
10638 case JALR16 + 0:
10639 case JALR16 + 1:
10640 opc = OPC_JALR;
10641 goto do_jalr;
10642 case JALR16S + 0:
10643 case JALR16S + 1:
10644 opc = OPC_JALRS;
10645 do_jalr:
10646 {
10647 int reg = ctx->opcode & 0x1f;
10648
10649 gen_compute_branch(ctx, opc, 2, reg, 31, 0);
10650 }
10651 *is_branch = 1;
10652 break;
10653 case MFHI16 + 0:
10654 case MFHI16 + 1:
10655 gen_HILO(ctx, OPC_MFHI, uMIPS_RS5(ctx->opcode));
10656 break;
10657 case MFLO16 + 0:
10658 case MFLO16 + 1:
10659 gen_HILO(ctx, OPC_MFLO, uMIPS_RS5(ctx->opcode));
10660 break;
10661 case BREAK16:
10662 generate_exception(ctx, EXCP_BREAK);
10663 break;
10664 case SDBBP16:
10665 /* XXX: not clear which exception should be raised
10666 * when in debug mode...
10667 */
10668 check_insn(env, ctx, ISA_MIPS32);
10669 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10670 generate_exception(ctx, EXCP_DBp);
10671 } else {
10672 generate_exception(ctx, EXCP_DBp);
10673 }
10674 break;
10675 case JRADDIUSP + 0:
10676 case JRADDIUSP + 1:
10677 {
10678 int imm = ZIMM(ctx->opcode, 0, 5);
10679
10680 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0);
10681 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm << 2);
10682 /* Let normal delay slot handling in our caller take us
10683 to the branch target. */
10684 }
10685 break;
10686 default:
10687 generate_exception(ctx, EXCP_RI);
10688 break;
10689 }
10690}
10691
10692static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
10693{
10694 TCGv t0 = tcg_temp_new();
10695 TCGv t1 = tcg_temp_new();
10696
10697 gen_load_gpr(t0, base);
10698
10699 if (index != 0) {
10700 gen_load_gpr(t1, index);
10701 tcg_gen_shli_tl(t1, t1, 2);
10702 gen_op_addr_add(ctx, t0, t1, t0);
10703 }
10704
10705 save_cpu_state(ctx, 0);
5c13fdfd 10706 op_ld_lw(t1, t0, ctx);
3c824109
NF
10707 gen_store_gpr(t1, rd);
10708
10709 tcg_temp_free(t0);
10710 tcg_temp_free(t1);
10711}
10712
10713static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
10714 int base, int16_t offset)
10715{
10716 const char *opn = "ldst_pair";
10717 TCGv t0, t1;
10718
36c6711b 10719 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
3c824109 10720 generate_exception(ctx, EXCP_RI);
d796321b
FB
10721 return;
10722 }
10723
3c824109
NF
10724 t0 = tcg_temp_new();
10725 t1 = tcg_temp_new();
8e9ade68 10726
3c824109
NF
10727 gen_base_offset_addr(ctx, t0, base, offset);
10728
10729 switch (opc) {
10730 case LWP:
36c6711b
EJ
10731 if (rd == base) {
10732 generate_exception(ctx, EXCP_RI);
10733 return;
10734 }
3c824109 10735 save_cpu_state(ctx, 0);
5c13fdfd 10736 op_ld_lw(t1, t0, ctx);
3c824109
NF
10737 gen_store_gpr(t1, rd);
10738 tcg_gen_movi_tl(t1, 4);
10739 gen_op_addr_add(ctx, t0, t0, t1);
5c13fdfd 10740 op_ld_lw(t1, t0, ctx);
3c824109
NF
10741 gen_store_gpr(t1, rd+1);
10742 opn = "lwp";
10743 break;
10744 case SWP:
b835e919 10745 save_cpu_state(ctx, 0);
3c824109 10746 gen_load_gpr(t1, rd);
5c13fdfd 10747 op_st_sw(t1, t0, ctx);
3c824109
NF
10748 tcg_gen_movi_tl(t1, 4);
10749 gen_op_addr_add(ctx, t0, t0, t1);
10750 gen_load_gpr(t1, rd+1);
5c13fdfd 10751 op_st_sw(t1, t0, ctx);
3c824109
NF
10752 opn = "swp";
10753 break;
10754#ifdef TARGET_MIPS64
10755 case LDP:
36c6711b
EJ
10756 if (rd == base) {
10757 generate_exception(ctx, EXCP_RI);
10758 return;
10759 }
3c824109 10760 save_cpu_state(ctx, 0);
5c13fdfd 10761 op_ld_ld(t1, t0, ctx);
3c824109
NF
10762 gen_store_gpr(t1, rd);
10763 tcg_gen_movi_tl(t1, 8);
10764 gen_op_addr_add(ctx, t0, t0, t1);
5c13fdfd 10765 op_ld_ld(t1, t0, ctx);
3c824109
NF
10766 gen_store_gpr(t1, rd+1);
10767 opn = "ldp";
10768 break;
10769 case SDP:
b835e919 10770 save_cpu_state(ctx, 0);
3c824109 10771 gen_load_gpr(t1, rd);
5c13fdfd 10772 op_st_sd(t1, t0, ctx);
3c824109
NF
10773 tcg_gen_movi_tl(t1, 8);
10774 gen_op_addr_add(ctx, t0, t0, t1);
10775 gen_load_gpr(t1, rd+1);
5c13fdfd 10776 op_st_sd(t1, t0, ctx);
3c824109
NF
10777 opn = "sdp";
10778 break;
10779#endif
6af0bf9c 10780 }
2abf314d 10781 (void)opn; /* avoid a compiler warning */
3c824109
NF
10782 MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
10783 tcg_temp_free(t0);
10784 tcg_temp_free(t1);
10785}
618b0fe9 10786
7db13fae 10787static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
3c824109
NF
10788 int *is_branch)
10789{
10790 int extension = (ctx->opcode >> 6) & 0x3f;
10791 int minor = (ctx->opcode >> 12) & 0xf;
10792 uint32_t mips32_op;
10793
10794 switch (extension) {
10795 case TEQ:
10796 mips32_op = OPC_TEQ;
10797 goto do_trap;
10798 case TGE:
10799 mips32_op = OPC_TGE;
10800 goto do_trap;
10801 case TGEU:
10802 mips32_op = OPC_TGEU;
10803 goto do_trap;
10804 case TLT:
10805 mips32_op = OPC_TLT;
10806 goto do_trap;
10807 case TLTU:
10808 mips32_op = OPC_TLTU;
10809 goto do_trap;
10810 case TNE:
10811 mips32_op = OPC_TNE;
10812 do_trap:
10813 gen_trap(ctx, mips32_op, rs, rt, -1);
10814 break;
10815#ifndef CONFIG_USER_ONLY
10816 case MFC0:
10817 case MFC0 + 32:
2e15497c 10818 check_cp0_enabled(ctx);
3c824109
NF
10819 if (rt == 0) {
10820 /* Treat as NOP. */
10821 break;
10822 }
10823 gen_mfc0(env, ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
10824 break;
10825 case MTC0:
10826 case MTC0 + 32:
2e15497c 10827 check_cp0_enabled(ctx);
3c824109
NF
10828 {
10829 TCGv t0 = tcg_temp_new();
618b0fe9 10830
3c824109
NF
10831 gen_load_gpr(t0, rt);
10832 gen_mtc0(env, ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
10833 tcg_temp_free(t0);
10834 }
10835 break;
10836#endif
10837 case 0x2c:
10838 switch (minor) {
10839 case SEB:
10840 gen_bshfl(ctx, OPC_SEB, rs, rt);
10841 break;
10842 case SEH:
10843 gen_bshfl(ctx, OPC_SEH, rs, rt);
10844 break;
10845 case CLO:
10846 mips32_op = OPC_CLO;
10847 goto do_cl;
10848 case CLZ:
10849 mips32_op = OPC_CLZ;
10850 do_cl:
10851 check_insn(env, ctx, ISA_MIPS32);
10852 gen_cl(ctx, mips32_op, rt, rs);
10853 break;
10854 case RDHWR:
10855 gen_rdhwr(env, ctx, rt, rs);
10856 break;
10857 case WSBH:
10858 gen_bshfl(ctx, OPC_WSBH, rs, rt);
10859 break;
10860 case MULT:
10861 mips32_op = OPC_MULT;
10862 goto do_muldiv;
10863 case MULTU:
10864 mips32_op = OPC_MULTU;
10865 goto do_muldiv;
10866 case DIV:
10867 mips32_op = OPC_DIV;
10868 goto do_muldiv;
10869 case DIVU:
10870 mips32_op = OPC_DIVU;
10871 goto do_muldiv;
10872 case MADD:
10873 mips32_op = OPC_MADD;
10874 goto do_muldiv;
10875 case MADDU:
10876 mips32_op = OPC_MADDU;
10877 goto do_muldiv;
10878 case MSUB:
10879 mips32_op = OPC_MSUB;
10880 goto do_muldiv;
10881 case MSUBU:
10882 mips32_op = OPC_MSUBU;
10883 do_muldiv:
10884 check_insn(env, ctx, ISA_MIPS32);
10885 gen_muldiv(ctx, mips32_op, rs, rt);
10886 break;
10887 default:
10888 goto pool32axf_invalid;
10889 }
10890 break;
10891 case 0x34:
10892 switch (minor) {
10893 case MFC2:
10894 case MTC2:
10895 case MFHC2:
10896 case MTHC2:
10897 case CFC2:
10898 case CTC2:
10899 generate_exception_err(ctx, EXCP_CpU, 2);
10900 break;
10901 default:
10902 goto pool32axf_invalid;
10903 }
10904 break;
10905 case 0x3c:
10906 switch (minor) {
10907 case JALR:
10908 case JALR_HB:
10909 gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0);
10910 *is_branch = 1;
10911 break;
10912 case JALRS:
10913 case JALRS_HB:
10914 gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0);
10915 *is_branch = 1;
10916 break;
10917 default:
10918 goto pool32axf_invalid;
10919 }
10920 break;
10921 case 0x05:
10922 switch (minor) {
10923 case RDPGPR:
2e15497c 10924 check_cp0_enabled(ctx);
3c824109
NF
10925 check_insn(env, ctx, ISA_MIPS32R2);
10926 gen_load_srsgpr(rt, rs);
10927 break;
10928 case WRPGPR:
2e15497c 10929 check_cp0_enabled(ctx);
3c824109
NF
10930 check_insn(env, ctx, ISA_MIPS32R2);
10931 gen_store_srsgpr(rt, rs);
10932 break;
10933 default:
10934 goto pool32axf_invalid;
10935 }
10936 break;
10937#ifndef CONFIG_USER_ONLY
10938 case 0x0d:
10939 switch (minor) {
10940 case TLBP:
10941 mips32_op = OPC_TLBP;
10942 goto do_cp0;
10943 case TLBR:
10944 mips32_op = OPC_TLBR;
10945 goto do_cp0;
10946 case TLBWI:
10947 mips32_op = OPC_TLBWI;
10948 goto do_cp0;
10949 case TLBWR:
10950 mips32_op = OPC_TLBWR;
10951 goto do_cp0;
10952 case WAIT:
10953 mips32_op = OPC_WAIT;
10954 goto do_cp0;
10955 case DERET:
10956 mips32_op = OPC_DERET;
10957 goto do_cp0;
10958 case ERET:
10959 mips32_op = OPC_ERET;
10960 do_cp0:
10961 gen_cp0(env, ctx, mips32_op, rt, rs);
10962 break;
10963 default:
10964 goto pool32axf_invalid;
10965 }
10966 break;
10967 case 0x1d:
10968 switch (minor) {
10969 case DI:
2e15497c 10970 check_cp0_enabled(ctx);
3c824109
NF
10971 {
10972 TCGv t0 = tcg_temp_new();
10973
10974 save_cpu_state(ctx, 1);
895c2d04 10975 gen_helper_di(t0, cpu_env);
3c824109
NF
10976 gen_store_gpr(t0, rs);
10977 /* Stop translation as we may have switched the execution mode */
10978 ctx->bstate = BS_STOP;
10979 tcg_temp_free(t0);
10980 }
10981 break;
10982 case EI:
2e15497c 10983 check_cp0_enabled(ctx);
3c824109
NF
10984 {
10985 TCGv t0 = tcg_temp_new();
10986
10987 save_cpu_state(ctx, 1);
895c2d04 10988 gen_helper_ei(t0, cpu_env);
3c824109
NF
10989 gen_store_gpr(t0, rs);
10990 /* Stop translation as we may have switched the execution mode */
10991 ctx->bstate = BS_STOP;
10992 tcg_temp_free(t0);
10993 }
10994 break;
10995 default:
10996 goto pool32axf_invalid;
10997 }
10998 break;
10999#endif
11000 case 0x2d:
11001 switch (minor) {
11002 case SYNC:
11003 /* NOP */
11004 break;
11005 case SYSCALL:
11006 generate_exception(ctx, EXCP_SYSCALL);
11007 ctx->bstate = BS_STOP;
11008 break;
11009 case SDBBP:
11010 check_insn(env, ctx, ISA_MIPS32);
11011 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11012 generate_exception(ctx, EXCP_DBp);
11013 } else {
11014 generate_exception(ctx, EXCP_DBp);
11015 }
11016 break;
11017 default:
11018 goto pool32axf_invalid;
11019 }
11020 break;
11021 case 0x35:
11022 switch (minor) {
11023 case MFHI32:
11024 gen_HILO(ctx, OPC_MFHI, rs);
11025 break;
11026 case MFLO32:
11027 gen_HILO(ctx, OPC_MFLO, rs);
11028 break;
11029 case MTHI32:
11030 gen_HILO(ctx, OPC_MTHI, rs);
11031 break;
11032 case MTLO32:
11033 gen_HILO(ctx, OPC_MTLO, rs);
11034 break;
11035 default:
11036 goto pool32axf_invalid;
11037 }
11038 break;
11039 default:
11040 pool32axf_invalid:
11041 MIPS_INVAL("pool32axf");
11042 generate_exception(ctx, EXCP_RI);
11043 break;
11044 }
11045}
11046
11047/* Values for microMIPS fmt field. Variable-width, depending on which
11048 formats the instruction supports. */
11049
11050enum {
11051 FMT_SD_S = 0,
11052 FMT_SD_D = 1,
11053
11054 FMT_SDPS_S = 0,
11055 FMT_SDPS_D = 1,
11056 FMT_SDPS_PS = 2,
11057
11058 FMT_SWL_S = 0,
11059 FMT_SWL_W = 1,
11060 FMT_SWL_L = 2,
11061
11062 FMT_DWL_D = 0,
11063 FMT_DWL_W = 1,
11064 FMT_DWL_L = 2
11065};
11066
7db13fae 11067static void gen_pool32fxf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
3c824109
NF
11068{
11069 int extension = (ctx->opcode >> 6) & 0x3ff;
11070 uint32_t mips32_op;
11071
11072#define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
11073#define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
11074#define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
11075
11076 switch (extension) {
11077 case FLOAT_1BIT_FMT(CFC1, 0):
11078 mips32_op = OPC_CFC1;
11079 goto do_cp1;
11080 case FLOAT_1BIT_FMT(CTC1, 0):
11081 mips32_op = OPC_CTC1;
11082 goto do_cp1;
11083 case FLOAT_1BIT_FMT(MFC1, 0):
11084 mips32_op = OPC_MFC1;
11085 goto do_cp1;
11086 case FLOAT_1BIT_FMT(MTC1, 0):
11087 mips32_op = OPC_MTC1;
11088 goto do_cp1;
11089 case FLOAT_1BIT_FMT(MFHC1, 0):
11090 mips32_op = OPC_MFHC1;
11091 goto do_cp1;
11092 case FLOAT_1BIT_FMT(MTHC1, 0):
11093 mips32_op = OPC_MTHC1;
11094 do_cp1:
11095 gen_cp1(ctx, mips32_op, rt, rs);
11096 break;
11097
11098 /* Reciprocal square root */
11099 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
11100 mips32_op = OPC_RSQRT_S;
11101 goto do_unaryfp;
11102 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
11103 mips32_op = OPC_RSQRT_D;
11104 goto do_unaryfp;
11105
11106 /* Square root */
11107 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
11108 mips32_op = OPC_SQRT_S;
11109 goto do_unaryfp;
11110 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
11111 mips32_op = OPC_SQRT_D;
11112 goto do_unaryfp;
11113
11114 /* Reciprocal */
11115 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
11116 mips32_op = OPC_RECIP_S;
11117 goto do_unaryfp;
11118 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
11119 mips32_op = OPC_RECIP_D;
11120 goto do_unaryfp;
11121
11122 /* Floor */
11123 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
11124 mips32_op = OPC_FLOOR_L_S;
11125 goto do_unaryfp;
11126 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
11127 mips32_op = OPC_FLOOR_L_D;
11128 goto do_unaryfp;
11129 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
11130 mips32_op = OPC_FLOOR_W_S;
11131 goto do_unaryfp;
11132 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
11133 mips32_op = OPC_FLOOR_W_D;
11134 goto do_unaryfp;
11135
11136 /* Ceiling */
11137 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
11138 mips32_op = OPC_CEIL_L_S;
11139 goto do_unaryfp;
11140 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
11141 mips32_op = OPC_CEIL_L_D;
11142 goto do_unaryfp;
11143 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
11144 mips32_op = OPC_CEIL_W_S;
11145 goto do_unaryfp;
11146 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
11147 mips32_op = OPC_CEIL_W_D;
11148 goto do_unaryfp;
11149
11150 /* Truncation */
11151 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
11152 mips32_op = OPC_TRUNC_L_S;
11153 goto do_unaryfp;
11154 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
11155 mips32_op = OPC_TRUNC_L_D;
11156 goto do_unaryfp;
11157 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
11158 mips32_op = OPC_TRUNC_W_S;
11159 goto do_unaryfp;
11160 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
11161 mips32_op = OPC_TRUNC_W_D;
11162 goto do_unaryfp;
11163
11164 /* Round */
11165 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
11166 mips32_op = OPC_ROUND_L_S;
11167 goto do_unaryfp;
11168 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
11169 mips32_op = OPC_ROUND_L_D;
11170 goto do_unaryfp;
11171 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
11172 mips32_op = OPC_ROUND_W_S;
11173 goto do_unaryfp;
11174 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
11175 mips32_op = OPC_ROUND_W_D;
11176 goto do_unaryfp;
11177
11178 /* Integer to floating-point conversion */
11179 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
11180 mips32_op = OPC_CVT_L_S;
11181 goto do_unaryfp;
11182 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
11183 mips32_op = OPC_CVT_L_D;
11184 goto do_unaryfp;
11185 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
11186 mips32_op = OPC_CVT_W_S;
11187 goto do_unaryfp;
11188 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
11189 mips32_op = OPC_CVT_W_D;
11190 goto do_unaryfp;
11191
11192 /* Paired-foo conversions */
11193 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
11194 mips32_op = OPC_CVT_S_PL;
11195 goto do_unaryfp;
11196 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
11197 mips32_op = OPC_CVT_S_PU;
11198 goto do_unaryfp;
11199 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
11200 mips32_op = OPC_CVT_PW_PS;
11201 goto do_unaryfp;
11202 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
11203 mips32_op = OPC_CVT_PS_PW;
11204 goto do_unaryfp;
11205
11206 /* Floating-point moves */
11207 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
11208 mips32_op = OPC_MOV_S;
11209 goto do_unaryfp;
11210 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
11211 mips32_op = OPC_MOV_D;
11212 goto do_unaryfp;
11213 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
11214 mips32_op = OPC_MOV_PS;
11215 goto do_unaryfp;
11216
11217 /* Absolute value */
11218 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
11219 mips32_op = OPC_ABS_S;
11220 goto do_unaryfp;
11221 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
11222 mips32_op = OPC_ABS_D;
11223 goto do_unaryfp;
11224 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
11225 mips32_op = OPC_ABS_PS;
11226 goto do_unaryfp;
11227
11228 /* Negation */
11229 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
11230 mips32_op = OPC_NEG_S;
11231 goto do_unaryfp;
11232 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
11233 mips32_op = OPC_NEG_D;
11234 goto do_unaryfp;
11235 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
11236 mips32_op = OPC_NEG_PS;
11237 goto do_unaryfp;
11238
11239 /* Reciprocal square root step */
11240 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
11241 mips32_op = OPC_RSQRT1_S;
11242 goto do_unaryfp;
11243 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
11244 mips32_op = OPC_RSQRT1_D;
11245 goto do_unaryfp;
11246 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
11247 mips32_op = OPC_RSQRT1_PS;
11248 goto do_unaryfp;
11249
11250 /* Reciprocal step */
11251 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
11252 mips32_op = OPC_RECIP1_S;
11253 goto do_unaryfp;
11254 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
11255 mips32_op = OPC_RECIP1_S;
11256 goto do_unaryfp;
11257 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
11258 mips32_op = OPC_RECIP1_PS;
11259 goto do_unaryfp;
11260
11261 /* Conversions from double */
11262 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
11263 mips32_op = OPC_CVT_D_S;
11264 goto do_unaryfp;
11265 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
11266 mips32_op = OPC_CVT_D_W;
11267 goto do_unaryfp;
11268 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
11269 mips32_op = OPC_CVT_D_L;
11270 goto do_unaryfp;
11271
11272 /* Conversions from single */
11273 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
11274 mips32_op = OPC_CVT_S_D;
11275 goto do_unaryfp;
11276 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
11277 mips32_op = OPC_CVT_S_W;
11278 goto do_unaryfp;
11279 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
11280 mips32_op = OPC_CVT_S_L;
11281 do_unaryfp:
11282 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
11283 break;
11284
11285 /* Conditional moves on floating-point codes */
11286 case COND_FLOAT_MOV(MOVT, 0):
11287 case COND_FLOAT_MOV(MOVT, 1):
11288 case COND_FLOAT_MOV(MOVT, 2):
11289 case COND_FLOAT_MOV(MOVT, 3):
11290 case COND_FLOAT_MOV(MOVT, 4):
11291 case COND_FLOAT_MOV(MOVT, 5):
11292 case COND_FLOAT_MOV(MOVT, 6):
11293 case COND_FLOAT_MOV(MOVT, 7):
11294 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
11295 break;
11296 case COND_FLOAT_MOV(MOVF, 0):
11297 case COND_FLOAT_MOV(MOVF, 1):
11298 case COND_FLOAT_MOV(MOVF, 2):
11299 case COND_FLOAT_MOV(MOVF, 3):
11300 case COND_FLOAT_MOV(MOVF, 4):
11301 case COND_FLOAT_MOV(MOVF, 5):
11302 case COND_FLOAT_MOV(MOVF, 6):
11303 case COND_FLOAT_MOV(MOVF, 7):
11304 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
11305 break;
11306 default:
11307 MIPS_INVAL("pool32fxf");
11308 generate_exception(ctx, EXCP_RI);
11309 break;
11310 }
11311}
11312
7db13fae 11313static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
3c824109
NF
11314 uint16_t insn_hw1, int *is_branch)
11315{
11316 int32_t offset;
11317 uint16_t insn;
11318 int rt, rs, rd, rr;
11319 int16_t imm;
11320 uint32_t op, minor, mips32_op;
11321 uint32_t cond, fmt, cc;
11322
895c2d04 11323 insn = cpu_lduw_code(env, ctx->pc + 2);
3c824109
NF
11324 ctx->opcode = (ctx->opcode << 16) | insn;
11325
11326 rt = (ctx->opcode >> 21) & 0x1f;
11327 rs = (ctx->opcode >> 16) & 0x1f;
11328 rd = (ctx->opcode >> 11) & 0x1f;
11329 rr = (ctx->opcode >> 6) & 0x1f;
11330 imm = (int16_t) ctx->opcode;
11331
11332 op = (ctx->opcode >> 26) & 0x3f;
11333 switch (op) {
11334 case POOL32A:
11335 minor = ctx->opcode & 0x3f;
11336 switch (minor) {
11337 case 0x00:
11338 minor = (ctx->opcode >> 6) & 0xf;
11339 switch (minor) {
11340 case SLL32:
11341 mips32_op = OPC_SLL;
11342 goto do_shifti;
11343 case SRA:
11344 mips32_op = OPC_SRA;
11345 goto do_shifti;
11346 case SRL32:
11347 mips32_op = OPC_SRL;
11348 goto do_shifti;
11349 case ROTR:
11350 mips32_op = OPC_ROTR;
11351 do_shifti:
11352 gen_shift_imm(env, ctx, mips32_op, rt, rs, rd);
11353 break;
11354 default:
11355 goto pool32a_invalid;
11356 }
11357 break;
11358 case 0x10:
11359 minor = (ctx->opcode >> 6) & 0xf;
11360 switch (minor) {
11361 /* Arithmetic */
11362 case ADD:
11363 mips32_op = OPC_ADD;
11364 goto do_arith;
11365 case ADDU32:
11366 mips32_op = OPC_ADDU;
11367 goto do_arith;
11368 case SUB:
11369 mips32_op = OPC_SUB;
11370 goto do_arith;
11371 case SUBU32:
11372 mips32_op = OPC_SUBU;
11373 goto do_arith;
11374 case MUL:
11375 mips32_op = OPC_MUL;
11376 do_arith:
11377 gen_arith(env, ctx, mips32_op, rd, rs, rt);
11378 break;
11379 /* Shifts */
11380 case SLLV:
11381 mips32_op = OPC_SLLV;
11382 goto do_shift;
11383 case SRLV:
11384 mips32_op = OPC_SRLV;
11385 goto do_shift;
11386 case SRAV:
11387 mips32_op = OPC_SRAV;
11388 goto do_shift;
11389 case ROTRV:
11390 mips32_op = OPC_ROTRV;
11391 do_shift:
11392 gen_shift(env, ctx, mips32_op, rd, rs, rt);
11393 break;
11394 /* Logical operations */
11395 case AND:
11396 mips32_op = OPC_AND;
11397 goto do_logic;
11398 case OR32:
11399 mips32_op = OPC_OR;
11400 goto do_logic;
11401 case NOR:
11402 mips32_op = OPC_NOR;
11403 goto do_logic;
11404 case XOR32:
11405 mips32_op = OPC_XOR;
11406 do_logic:
9fa77488 11407 gen_logic(env, ctx, mips32_op, rd, rs, rt);
3c824109
NF
11408 break;
11409 /* Set less than */
11410 case SLT:
11411 mips32_op = OPC_SLT;
11412 goto do_slt;
11413 case SLTU:
11414 mips32_op = OPC_SLTU;
11415 do_slt:
9fa77488 11416 gen_slt(env, ctx, mips32_op, rd, rs, rt);
3c824109
NF
11417 break;
11418 default:
11419 goto pool32a_invalid;
11420 }
11421 break;
11422 case 0x18:
11423 minor = (ctx->opcode >> 6) & 0xf;
11424 switch (minor) {
11425 /* Conditional moves */
11426 case MOVN:
11427 mips32_op = OPC_MOVN;
11428 goto do_cmov;
11429 case MOVZ:
11430 mips32_op = OPC_MOVZ;
11431 do_cmov:
9fa77488 11432 gen_cond_move(env, ctx, mips32_op, rd, rs, rt);
3c824109
NF
11433 break;
11434 case LWXS:
11435 gen_ldxs(ctx, rs, rt, rd);
11436 break;
11437 default:
11438 goto pool32a_invalid;
11439 }
11440 break;
11441 case INS:
11442 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
11443 return;
11444 case EXT:
11445 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
11446 return;
11447 case POOL32AXF:
11448 gen_pool32axf(env, ctx, rt, rs, is_branch);
11449 break;
11450 case 0x07:
11451 generate_exception(ctx, EXCP_BREAK);
11452 break;
11453 default:
11454 pool32a_invalid:
11455 MIPS_INVAL("pool32a");
11456 generate_exception(ctx, EXCP_RI);
11457 break;
11458 }
11459 break;
11460 case POOL32B:
11461 minor = (ctx->opcode >> 12) & 0xf;
11462 switch (minor) {
11463 case CACHE:
2e15497c 11464 check_cp0_enabled(ctx);
3c824109
NF
11465 /* Treat as no-op. */
11466 break;
11467 case LWC2:
11468 case SWC2:
11469 /* COP2: Not implemented. */
11470 generate_exception_err(ctx, EXCP_CpU, 2);
11471 break;
11472 case LWP:
11473 case SWP:
11474#ifdef TARGET_MIPS64
11475 case LDP:
11476 case SDP:
11477#endif
11478 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
11479 break;
11480 case LWM32:
11481 case SWM32:
11482#ifdef TARGET_MIPS64
11483 case LDM:
11484 case SDM:
11485#endif
11486 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
11487 break;
11488 default:
11489 MIPS_INVAL("pool32b");
11490 generate_exception(ctx, EXCP_RI);
11491 break;
11492 }
11493 break;
11494 case POOL32F:
11495 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
11496 minor = ctx->opcode & 0x3f;
11497 check_cp1_enabled(ctx);
11498 switch (minor) {
11499 case ALNV_PS:
11500 mips32_op = OPC_ALNV_PS;
11501 goto do_madd;
11502 case MADD_S:
11503 mips32_op = OPC_MADD_S;
11504 goto do_madd;
11505 case MADD_D:
11506 mips32_op = OPC_MADD_D;
11507 goto do_madd;
11508 case MADD_PS:
11509 mips32_op = OPC_MADD_PS;
11510 goto do_madd;
11511 case MSUB_S:
11512 mips32_op = OPC_MSUB_S;
11513 goto do_madd;
11514 case MSUB_D:
11515 mips32_op = OPC_MSUB_D;
11516 goto do_madd;
11517 case MSUB_PS:
11518 mips32_op = OPC_MSUB_PS;
11519 goto do_madd;
11520 case NMADD_S:
11521 mips32_op = OPC_NMADD_S;
11522 goto do_madd;
11523 case NMADD_D:
11524 mips32_op = OPC_NMADD_D;
11525 goto do_madd;
11526 case NMADD_PS:
11527 mips32_op = OPC_NMADD_PS;
11528 goto do_madd;
11529 case NMSUB_S:
11530 mips32_op = OPC_NMSUB_S;
11531 goto do_madd;
11532 case NMSUB_D:
11533 mips32_op = OPC_NMSUB_D;
11534 goto do_madd;
11535 case NMSUB_PS:
11536 mips32_op = OPC_NMSUB_PS;
11537 do_madd:
11538 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
11539 break;
11540 case CABS_COND_FMT:
11541 cond = (ctx->opcode >> 6) & 0xf;
11542 cc = (ctx->opcode >> 13) & 0x7;
11543 fmt = (ctx->opcode >> 10) & 0x3;
11544 switch (fmt) {
11545 case 0x0:
11546 gen_cmpabs_s(ctx, cond, rt, rs, cc);
11547 break;
11548 case 0x1:
11549 gen_cmpabs_d(ctx, cond, rt, rs, cc);
11550 break;
11551 case 0x2:
11552 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
11553 break;
11554 default:
11555 goto pool32f_invalid;
11556 }
11557 break;
11558 case C_COND_FMT:
11559 cond = (ctx->opcode >> 6) & 0xf;
11560 cc = (ctx->opcode >> 13) & 0x7;
11561 fmt = (ctx->opcode >> 10) & 0x3;
11562 switch (fmt) {
11563 case 0x0:
11564 gen_cmp_s(ctx, cond, rt, rs, cc);
11565 break;
11566 case 0x1:
11567 gen_cmp_d(ctx, cond, rt, rs, cc);
11568 break;
11569 case 0x2:
11570 gen_cmp_ps(ctx, cond, rt, rs, cc);
11571 break;
11572 default:
11573 goto pool32f_invalid;
11574 }
11575 break;
11576 case POOL32FXF:
11577 gen_pool32fxf(env, ctx, rt, rs);
11578 break;
11579 case 0x00:
11580 /* PLL foo */
11581 switch ((ctx->opcode >> 6) & 0x7) {
11582 case PLL_PS:
11583 mips32_op = OPC_PLL_PS;
11584 goto do_ps;
11585 case PLU_PS:
11586 mips32_op = OPC_PLU_PS;
11587 goto do_ps;
11588 case PUL_PS:
11589 mips32_op = OPC_PUL_PS;
11590 goto do_ps;
11591 case PUU_PS:
11592 mips32_op = OPC_PUU_PS;
11593 goto do_ps;
11594 case CVT_PS_S:
11595 mips32_op = OPC_CVT_PS_S;
11596 do_ps:
11597 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
11598 break;
11599 default:
11600 goto pool32f_invalid;
11601 }
11602 break;
11603 case 0x08:
11604 /* [LS][WDU]XC1 */
11605 switch ((ctx->opcode >> 6) & 0x7) {
11606 case LWXC1:
11607 mips32_op = OPC_LWXC1;
11608 goto do_ldst_cp1;
11609 case SWXC1:
11610 mips32_op = OPC_SWXC1;
11611 goto do_ldst_cp1;
11612 case LDXC1:
11613 mips32_op = OPC_LDXC1;
11614 goto do_ldst_cp1;
11615 case SDXC1:
11616 mips32_op = OPC_SDXC1;
11617 goto do_ldst_cp1;
11618 case LUXC1:
11619 mips32_op = OPC_LUXC1;
11620 goto do_ldst_cp1;
11621 case SUXC1:
11622 mips32_op = OPC_SUXC1;
11623 do_ldst_cp1:
11624 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
11625 break;
11626 default:
11627 goto pool32f_invalid;
11628 }
11629 break;
11630 case 0x18:
11631 /* 3D insns */
11632 fmt = (ctx->opcode >> 9) & 0x3;
11633 switch ((ctx->opcode >> 6) & 0x7) {
11634 case RSQRT2_FMT:
11635 switch (fmt) {
11636 case FMT_SDPS_S:
11637 mips32_op = OPC_RSQRT2_S;
11638 goto do_3d;
11639 case FMT_SDPS_D:
11640 mips32_op = OPC_RSQRT2_D;
11641 goto do_3d;
11642 case FMT_SDPS_PS:
11643 mips32_op = OPC_RSQRT2_PS;
11644 goto do_3d;
11645 default:
11646 goto pool32f_invalid;
11647 }
11648 break;
11649 case RECIP2_FMT:
11650 switch (fmt) {
11651 case FMT_SDPS_S:
11652 mips32_op = OPC_RECIP2_S;
11653 goto do_3d;
11654 case FMT_SDPS_D:
11655 mips32_op = OPC_RECIP2_D;
11656 goto do_3d;
11657 case FMT_SDPS_PS:
11658 mips32_op = OPC_RECIP2_PS;
11659 goto do_3d;
11660 default:
11661 goto pool32f_invalid;
11662 }
11663 break;
11664 case ADDR_PS:
11665 mips32_op = OPC_ADDR_PS;
11666 goto do_3d;
11667 case MULR_PS:
11668 mips32_op = OPC_MULR_PS;
11669 do_3d:
11670 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
11671 break;
11672 default:
11673 goto pool32f_invalid;
11674 }
11675 break;
11676 case 0x20:
11677 /* MOV[FT].fmt and PREFX */
11678 cc = (ctx->opcode >> 13) & 0x7;
11679 fmt = (ctx->opcode >> 9) & 0x3;
11680 switch ((ctx->opcode >> 6) & 0x7) {
11681 case MOVF_FMT:
11682 switch (fmt) {
11683 case FMT_SDPS_S:
11684 gen_movcf_s(rs, rt, cc, 0);
11685 break;
11686 case FMT_SDPS_D:
11687 gen_movcf_d(ctx, rs, rt, cc, 0);
11688 break;
11689 case FMT_SDPS_PS:
11690 gen_movcf_ps(rs, rt, cc, 0);
11691 break;
11692 default:
11693 goto pool32f_invalid;
11694 }
11695 break;
11696 case MOVT_FMT:
11697 switch (fmt) {
11698 case FMT_SDPS_S:
11699 gen_movcf_s(rs, rt, cc, 1);
11700 break;
11701 case FMT_SDPS_D:
11702 gen_movcf_d(ctx, rs, rt, cc, 1);
11703 break;
11704 case FMT_SDPS_PS:
11705 gen_movcf_ps(rs, rt, cc, 1);
11706 break;
11707 default:
11708 goto pool32f_invalid;
11709 }
11710 break;
11711 case PREFX:
11712 break;
11713 default:
11714 goto pool32f_invalid;
11715 }
11716 break;
11717#define FINSN_3ARG_SDPS(prfx) \
11718 switch ((ctx->opcode >> 8) & 0x3) { \
11719 case FMT_SDPS_S: \
11720 mips32_op = OPC_##prfx##_S; \
11721 goto do_fpop; \
11722 case FMT_SDPS_D: \
11723 mips32_op = OPC_##prfx##_D; \
11724 goto do_fpop; \
11725 case FMT_SDPS_PS: \
11726 mips32_op = OPC_##prfx##_PS; \
11727 goto do_fpop; \
11728 default: \
11729 goto pool32f_invalid; \
11730 }
11731 case 0x30:
11732 /* regular FP ops */
11733 switch ((ctx->opcode >> 6) & 0x3) {
11734 case ADD_FMT:
11735 FINSN_3ARG_SDPS(ADD);
11736 break;
11737 case SUB_FMT:
11738 FINSN_3ARG_SDPS(SUB);
11739 break;
11740 case MUL_FMT:
11741 FINSN_3ARG_SDPS(MUL);
11742 break;
11743 case DIV_FMT:
11744 fmt = (ctx->opcode >> 8) & 0x3;
11745 if (fmt == 1) {
11746 mips32_op = OPC_DIV_D;
11747 } else if (fmt == 0) {
11748 mips32_op = OPC_DIV_S;
11749 } else {
11750 goto pool32f_invalid;
11751 }
11752 goto do_fpop;
11753 default:
11754 goto pool32f_invalid;
11755 }
11756 break;
11757 case 0x38:
11758 /* cmovs */
11759 switch ((ctx->opcode >> 6) & 0x3) {
11760 case MOVN_FMT:
11761 FINSN_3ARG_SDPS(MOVN);
11762 break;
11763 case MOVZ_FMT:
11764 FINSN_3ARG_SDPS(MOVZ);
11765 break;
11766 default:
11767 goto pool32f_invalid;
11768 }
11769 break;
11770 do_fpop:
11771 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
11772 break;
11773 default:
11774 pool32f_invalid:
11775 MIPS_INVAL("pool32f");
11776 generate_exception(ctx, EXCP_RI);
11777 break;
11778 }
11779 } else {
11780 generate_exception_err(ctx, EXCP_CpU, 1);
11781 }
11782 break;
11783 case POOL32I:
11784 minor = (ctx->opcode >> 21) & 0x1f;
11785 switch (minor) {
11786 case BLTZ:
11787 mips32_op = OPC_BLTZ;
11788 goto do_branch;
11789 case BLTZAL:
11790 mips32_op = OPC_BLTZAL;
11791 goto do_branch;
11792 case BLTZALS:
11793 mips32_op = OPC_BLTZALS;
11794 goto do_branch;
11795 case BGEZ:
11796 mips32_op = OPC_BGEZ;
11797 goto do_branch;
11798 case BGEZAL:
11799 mips32_op = OPC_BGEZAL;
11800 goto do_branch;
11801 case BGEZALS:
11802 mips32_op = OPC_BGEZALS;
11803 goto do_branch;
11804 case BLEZ:
11805 mips32_op = OPC_BLEZ;
11806 goto do_branch;
11807 case BGTZ:
11808 mips32_op = OPC_BGTZ;
11809 do_branch:
11810 gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1);
11811 *is_branch = 1;
11812 break;
11813
11814 /* Traps */
11815 case TLTI:
11816 mips32_op = OPC_TLTI;
11817 goto do_trapi;
11818 case TGEI:
11819 mips32_op = OPC_TGEI;
11820 goto do_trapi;
11821 case TLTIU:
11822 mips32_op = OPC_TLTIU;
11823 goto do_trapi;
11824 case TGEIU:
11825 mips32_op = OPC_TGEIU;
11826 goto do_trapi;
11827 case TNEI:
11828 mips32_op = OPC_TNEI;
11829 goto do_trapi;
11830 case TEQI:
11831 mips32_op = OPC_TEQI;
11832 do_trapi:
11833 gen_trap(ctx, mips32_op, rs, -1, imm);
11834 break;
11835
11836 case BNEZC:
11837 case BEQZC:
11838 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
11839 4, rs, 0, imm << 1);
11840 /* Compact branches don't have a delay slot, so just let
11841 the normal delay slot handling take us to the branch
11842 target. */
11843 break;
11844 case LUI:
9fa77488 11845 gen_logic_imm(env, ctx, OPC_LUI, rs, -1, imm);
3c824109
NF
11846 break;
11847 case SYNCI:
11848 break;
11849 case BC2F:
11850 case BC2T:
11851 /* COP2: Not implemented. */
11852 generate_exception_err(ctx, EXCP_CpU, 2);
11853 break;
11854 case BC1F:
11855 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
11856 goto do_cp1branch;
11857 case BC1T:
11858 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
11859 goto do_cp1branch;
11860 case BC1ANY4F:
11861 mips32_op = OPC_BC1FANY4;
11862 goto do_cp1mips3d;
11863 case BC1ANY4T:
11864 mips32_op = OPC_BC1TANY4;
11865 do_cp1mips3d:
11866 check_cop1x(ctx);
11867 check_insn(env, ctx, ASE_MIPS3D);
11868 /* Fall through */
11869 do_cp1branch:
11870 gen_compute_branch1(env, ctx, mips32_op,
11871 (ctx->opcode >> 18) & 0x7, imm << 1);
11872 *is_branch = 1;
11873 break;
11874 case BPOSGE64:
11875 case BPOSGE32:
11876 /* MIPS DSP: not implemented */
11877 /* Fall through */
11878 default:
11879 MIPS_INVAL("pool32i");
11880 generate_exception(ctx, EXCP_RI);
11881 break;
11882 }
11883 break;
11884 case POOL32C:
11885 minor = (ctx->opcode >> 12) & 0xf;
11886 switch (minor) {
11887 case LWL:
11888 mips32_op = OPC_LWL;
5c13fdfd 11889 goto do_ld_lr;
3c824109
NF
11890 case SWL:
11891 mips32_op = OPC_SWL;
5c13fdfd 11892 goto do_st_lr;
3c824109
NF
11893 case LWR:
11894 mips32_op = OPC_LWR;
5c13fdfd 11895 goto do_ld_lr;
3c824109
NF
11896 case SWR:
11897 mips32_op = OPC_SWR;
5c13fdfd 11898 goto do_st_lr;
3c824109
NF
11899#if defined(TARGET_MIPS64)
11900 case LDL:
11901 mips32_op = OPC_LDL;
5c13fdfd 11902 goto do_ld_lr;
3c824109
NF
11903 case SDL:
11904 mips32_op = OPC_SDL;
5c13fdfd 11905 goto do_st_lr;
3c824109
NF
11906 case LDR:
11907 mips32_op = OPC_LDR;
5c13fdfd 11908 goto do_ld_lr;
3c824109
NF
11909 case SDR:
11910 mips32_op = OPC_SDR;
5c13fdfd 11911 goto do_st_lr;
3c824109
NF
11912 case LWU:
11913 mips32_op = OPC_LWU;
5c13fdfd 11914 goto do_ld_lr;
3c824109
NF
11915 case LLD:
11916 mips32_op = OPC_LLD;
5c13fdfd 11917 goto do_ld_lr;
3c824109
NF
11918#endif
11919 case LL:
11920 mips32_op = OPC_LL;
5c13fdfd
AJ
11921 goto do_ld_lr;
11922 do_ld_lr:
afa88c3a 11923 gen_ld(env, ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
5c13fdfd
AJ
11924 break;
11925 do_st_lr:
11926 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
3c824109
NF
11927 break;
11928 case SC:
11929 gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
11930 break;
11931#if defined(TARGET_MIPS64)
11932 case SCD:
11933 gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
11934 break;
11935#endif
11936 case PREF:
11937 /* Treat as no-op */
11938 break;
11939 default:
11940 MIPS_INVAL("pool32c");
11941 generate_exception(ctx, EXCP_RI);
11942 break;
11943 }
11944 break;
11945 case ADDI32:
11946 mips32_op = OPC_ADDI;
11947 goto do_addi;
11948 case ADDIU32:
11949 mips32_op = OPC_ADDIU;
11950 do_addi:
11951 gen_arith_imm(env, ctx, mips32_op, rt, rs, imm);
11952 break;
11953
11954 /* Logical operations */
11955 case ORI32:
11956 mips32_op = OPC_ORI;
11957 goto do_logici;
11958 case XORI32:
11959 mips32_op = OPC_XORI;
11960 goto do_logici;
11961 case ANDI32:
11962 mips32_op = OPC_ANDI;
11963 do_logici:
9fa77488 11964 gen_logic_imm(env, ctx, mips32_op, rt, rs, imm);
3c824109
NF
11965 break;
11966
11967 /* Set less than immediate */
11968 case SLTI32:
11969 mips32_op = OPC_SLTI;
11970 goto do_slti;
11971 case SLTIU32:
11972 mips32_op = OPC_SLTIU;
11973 do_slti:
9fa77488 11974 gen_slt_imm(env, ctx, mips32_op, rt, rs, imm);
3c824109
NF
11975 break;
11976 case JALX32:
11977 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
11978 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset);
11979 *is_branch = 1;
11980 break;
11981 case JALS32:
11982 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
11983 gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset);
11984 *is_branch = 1;
11985 break;
11986 case BEQ32:
11987 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1);
11988 *is_branch = 1;
11989 break;
11990 case BNE32:
11991 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1);
11992 *is_branch = 1;
11993 break;
11994 case J32:
11995 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
11996 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11997 *is_branch = 1;
11998 break;
11999 case JAL32:
12000 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
12001 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
12002 *is_branch = 1;
12003 break;
12004 /* Floating point (COP1) */
12005 case LWC132:
12006 mips32_op = OPC_LWC1;
12007 goto do_cop1;
12008 case LDC132:
12009 mips32_op = OPC_LDC1;
12010 goto do_cop1;
12011 case SWC132:
12012 mips32_op = OPC_SWC1;
12013 goto do_cop1;
12014 case SDC132:
12015 mips32_op = OPC_SDC1;
12016 do_cop1:
12017 gen_cop1_ldst(env, ctx, mips32_op, rt, rs, imm);
12018 break;
12019 case ADDIUPC:
12020 {
12021 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
12022 int offset = SIMM(ctx->opcode, 0, 23) << 2;
12023
12024 gen_addiupc(ctx, reg, offset, 0, 0);
12025 }
12026 break;
12027 /* Loads and stores */
12028 case LB32:
12029 mips32_op = OPC_LB;
5c13fdfd 12030 goto do_ld;
3c824109
NF
12031 case LBU32:
12032 mips32_op = OPC_LBU;
5c13fdfd 12033 goto do_ld;
3c824109
NF
12034 case LH32:
12035 mips32_op = OPC_LH;
5c13fdfd 12036 goto do_ld;
3c824109
NF
12037 case LHU32:
12038 mips32_op = OPC_LHU;
5c13fdfd 12039 goto do_ld;
3c824109
NF
12040 case LW32:
12041 mips32_op = OPC_LW;
5c13fdfd 12042 goto do_ld;
3c824109
NF
12043#ifdef TARGET_MIPS64
12044 case LD32:
12045 mips32_op = OPC_LD;
5c13fdfd 12046 goto do_ld;
3c824109
NF
12047 case SD32:
12048 mips32_op = OPC_SD;
5c13fdfd 12049 goto do_st;
3c824109
NF
12050#endif
12051 case SB32:
12052 mips32_op = OPC_SB;
5c13fdfd 12053 goto do_st;
3c824109
NF
12054 case SH32:
12055 mips32_op = OPC_SH;
5c13fdfd 12056 goto do_st;
3c824109
NF
12057 case SW32:
12058 mips32_op = OPC_SW;
5c13fdfd
AJ
12059 goto do_st;
12060 do_ld:
afa88c3a 12061 gen_ld(env, ctx, mips32_op, rt, rs, imm);
5c13fdfd
AJ
12062 break;
12063 do_st:
12064 gen_st(ctx, mips32_op, rt, rs, imm);
3c824109
NF
12065 break;
12066 default:
12067 generate_exception(ctx, EXCP_RI);
12068 break;
12069 }
12070}
12071
7db13fae 12072static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
3c824109
NF
12073{
12074 uint32_t op;
12075
12076 /* make sure instructions are on a halfword boundary */
12077 if (ctx->pc & 0x1) {
12078 env->CP0_BadVAddr = ctx->pc;
12079 generate_exception(ctx, EXCP_AdEL);
12080 ctx->bstate = BS_STOP;
12081 return 2;
12082 }
12083
12084 op = (ctx->opcode >> 10) & 0x3f;
12085 /* Enforce properly-sized instructions in a delay slot */
12086 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12087 int bits = ctx->hflags & MIPS_HFLAG_BMASK_EXT;
12088
12089 switch (op) {
12090 case POOL32A:
12091 case POOL32B:
12092 case POOL32I:
12093 case POOL32C:
12094 case ADDI32:
12095 case ADDIU32:
12096 case ORI32:
12097 case XORI32:
12098 case SLTI32:
12099 case SLTIU32:
12100 case ANDI32:
12101 case JALX32:
12102 case LBU32:
12103 case LHU32:
12104 case POOL32F:
12105 case JALS32:
12106 case BEQ32:
12107 case BNE32:
12108 case J32:
12109 case JAL32:
12110 case SB32:
12111 case SH32:
12112 case POOL32S:
12113 case ADDIUPC:
12114 case SWC132:
12115 case SDC132:
12116 case SD32:
12117 case SW32:
12118 case LB32:
12119 case LH32:
12120 case DADDIU32:
12121 case POOL48A: /* ??? */
12122 case LWC132:
12123 case LDC132:
12124 case LD32:
12125 case LW32:
12126 if (bits & MIPS_HFLAG_BDS16) {
12127 generate_exception(ctx, EXCP_RI);
12128 /* Just stop translation; the user is confused. */
12129 ctx->bstate = BS_STOP;
12130 return 2;
12131 }
12132 break;
12133 case POOL16A:
12134 case POOL16B:
12135 case POOL16C:
12136 case LWGP16:
12137 case POOL16F:
12138 case LBU16:
12139 case LHU16:
12140 case LWSP16:
12141 case LW16:
12142 case SB16:
12143 case SH16:
12144 case SWSP16:
12145 case SW16:
12146 case MOVE16:
12147 case ANDI16:
12148 case POOL16D:
12149 case POOL16E:
12150 case BEQZ16:
12151 case BNEZ16:
12152 case B16:
12153 case LI16:
12154 if (bits & MIPS_HFLAG_BDS32) {
12155 generate_exception(ctx, EXCP_RI);
12156 /* Just stop translation; the user is confused. */
12157 ctx->bstate = BS_STOP;
12158 return 2;
12159 }
12160 break;
12161 default:
12162 break;
12163 }
12164 }
12165 switch (op) {
12166 case POOL16A:
12167 {
12168 int rd = mmreg(uMIPS_RD(ctx->opcode));
12169 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
12170 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
12171 uint32_t opc = 0;
12172
12173 switch (ctx->opcode & 0x1) {
12174 case ADDU16:
12175 opc = OPC_ADDU;
12176 break;
12177 case SUBU16:
12178 opc = OPC_SUBU;
12179 break;
12180 }
12181
12182 gen_arith(env, ctx, opc, rd, rs1, rs2);
12183 }
12184 break;
12185 case POOL16B:
12186 {
12187 int rd = mmreg(uMIPS_RD(ctx->opcode));
12188 int rs = mmreg(uMIPS_RS(ctx->opcode));
12189 int amount = (ctx->opcode >> 1) & 0x7;
12190 uint32_t opc = 0;
12191 amount = amount == 0 ? 8 : amount;
12192
12193 switch (ctx->opcode & 0x1) {
12194 case SLL16:
12195 opc = OPC_SLL;
12196 break;
12197 case SRL16:
12198 opc = OPC_SRL;
12199 break;
12200 }
12201
12202 gen_shift_imm(env, ctx, opc, rd, rs, amount);
12203 }
12204 break;
12205 case POOL16C:
12206 gen_pool16c_insn(env, ctx, is_branch);
12207 break;
12208 case LWGP16:
12209 {
12210 int rd = mmreg(uMIPS_RD(ctx->opcode));
12211 int rb = 28; /* GP */
12212 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
12213
afa88c3a 12214 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
3c824109
NF
12215 }
12216 break;
12217 case POOL16F:
12218 if (ctx->opcode & 1) {
12219 generate_exception(ctx, EXCP_RI);
12220 } else {
12221 /* MOVEP */
12222 int enc_dest = uMIPS_RD(ctx->opcode);
12223 int enc_rt = uMIPS_RS2(ctx->opcode);
12224 int enc_rs = uMIPS_RS1(ctx->opcode);
12225 int rd, rs, re, rt;
12226 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
12227 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
12228 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
12229
12230 rd = rd_enc[enc_dest];
12231 re = re_enc[enc_dest];
12232 rs = rs_rt_enc[enc_rs];
12233 rt = rs_rt_enc[enc_rt];
12234
12235 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
12236 gen_arith_imm(env, ctx, OPC_ADDIU, re, rt, 0);
12237 }
12238 break;
12239 case LBU16:
12240 {
12241 int rd = mmreg(uMIPS_RD(ctx->opcode));
12242 int rb = mmreg(uMIPS_RS(ctx->opcode));
12243 int16_t offset = ZIMM(ctx->opcode, 0, 4);
12244 offset = (offset == 0xf ? -1 : offset);
12245
afa88c3a 12246 gen_ld(env, ctx, OPC_LBU, rd, rb, offset);
3c824109
NF
12247 }
12248 break;
12249 case LHU16:
12250 {
12251 int rd = mmreg(uMIPS_RD(ctx->opcode));
12252 int rb = mmreg(uMIPS_RS(ctx->opcode));
12253 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
12254
afa88c3a 12255 gen_ld(env, ctx, OPC_LHU, rd, rb, offset);
3c824109
NF
12256 }
12257 break;
12258 case LWSP16:
12259 {
12260 int rd = (ctx->opcode >> 5) & 0x1f;
12261 int rb = 29; /* SP */
12262 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
12263
afa88c3a 12264 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
3c824109
NF
12265 }
12266 break;
12267 case LW16:
12268 {
12269 int rd = mmreg(uMIPS_RD(ctx->opcode));
12270 int rb = mmreg(uMIPS_RS(ctx->opcode));
12271 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
12272
afa88c3a 12273 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
3c824109
NF
12274 }
12275 break;
12276 case SB16:
12277 {
12278 int rd = mmreg2(uMIPS_RD(ctx->opcode));
12279 int rb = mmreg(uMIPS_RS(ctx->opcode));
12280 int16_t offset = ZIMM(ctx->opcode, 0, 4);
12281
5c13fdfd 12282 gen_st(ctx, OPC_SB, rd, rb, offset);
3c824109
NF
12283 }
12284 break;
12285 case SH16:
12286 {
12287 int rd = mmreg2(uMIPS_RD(ctx->opcode));
12288 int rb = mmreg(uMIPS_RS(ctx->opcode));
12289 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
12290
5c13fdfd 12291 gen_st(ctx, OPC_SH, rd, rb, offset);
3c824109
NF
12292 }
12293 break;
12294 case SWSP16:
12295 {
12296 int rd = (ctx->opcode >> 5) & 0x1f;
12297 int rb = 29; /* SP */
12298 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
12299
5c13fdfd 12300 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
12301 }
12302 break;
12303 case SW16:
12304 {
12305 int rd = mmreg2(uMIPS_RD(ctx->opcode));
12306 int rb = mmreg(uMIPS_RS(ctx->opcode));
12307 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
12308
5c13fdfd 12309 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
12310 }
12311 break;
12312 case MOVE16:
12313 {
12314 int rd = uMIPS_RD5(ctx->opcode);
12315 int rs = uMIPS_RS5(ctx->opcode);
12316
12317 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
12318 }
12319 break;
12320 case ANDI16:
12321 gen_andi16(env, ctx);
12322 break;
12323 case POOL16D:
12324 switch (ctx->opcode & 0x1) {
12325 case ADDIUS5:
12326 gen_addius5(env, ctx);
12327 break;
12328 case ADDIUSP:
12329 gen_addiusp(env, ctx);
12330 break;
12331 }
12332 break;
12333 case POOL16E:
12334 switch (ctx->opcode & 0x1) {
12335 case ADDIUR2:
12336 gen_addiur2(env, ctx);
12337 break;
12338 case ADDIUR1SP:
12339 gen_addiur1sp(env, ctx);
12340 break;
12341 }
12342 break;
12343 case B16:
12344 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
12345 SIMM(ctx->opcode, 0, 10) << 1);
12346 *is_branch = 1;
12347 break;
12348 case BNEZ16:
12349 case BEQZ16:
12350 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
12351 mmreg(uMIPS_RD(ctx->opcode)),
12352 0, SIMM(ctx->opcode, 0, 7) << 1);
12353 *is_branch = 1;
12354 break;
12355 case LI16:
12356 {
12357 int reg = mmreg(uMIPS_RD(ctx->opcode));
12358 int imm = ZIMM(ctx->opcode, 0, 7);
12359
12360 imm = (imm == 0x7f ? -1 : imm);
12361 tcg_gen_movi_tl(cpu_gpr[reg], imm);
12362 }
12363 break;
12364 case RES_20:
12365 case RES_28:
12366 case RES_29:
12367 case RES_30:
12368 case RES_31:
12369 case RES_38:
12370 case RES_39:
12371 generate_exception(ctx, EXCP_RI);
12372 break;
12373 default:
12374 decode_micromips32_opc (env, ctx, op, is_branch);
12375 return 4;
12376 }
12377
12378 return 2;
12379}
12380
12381/* SmartMIPS extension to MIPS32 */
12382
12383#if defined(TARGET_MIPS64)
12384
12385/* MDMX extension to MIPS64 */
12386
12387#endif
12388
9b1a1d68
JL
12389/* MIPSDSP functions. */
12390static void gen_mipsdsp_ld(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
12391 int rd, int base, int offset)
12392{
12393 const char *opn = "ldx";
12394 TCGv t0;
12395
12396 if (rd == 0) {
12397 MIPS_DEBUG("NOP");
12398 return;
12399 }
12400
12401 check_dsp(ctx);
12402 t0 = tcg_temp_new();
12403
12404 if (base == 0) {
12405 gen_load_gpr(t0, offset);
12406 } else if (offset == 0) {
12407 gen_load_gpr(t0, base);
12408 } else {
12409 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
12410 }
12411
12412 save_cpu_state(ctx, 0);
12413 switch (opc) {
12414 case OPC_LBUX:
12415 op_ld_lbu(t0, t0, ctx);
12416 gen_store_gpr(t0, rd);
12417 opn = "lbux";
12418 break;
12419 case OPC_LHX:
12420 op_ld_lh(t0, t0, ctx);
12421 gen_store_gpr(t0, rd);
12422 opn = "lhx";
12423 break;
12424 case OPC_LWX:
12425 op_ld_lw(t0, t0, ctx);
12426 gen_store_gpr(t0, rd);
12427 opn = "lwx";
12428 break;
12429#if defined(TARGET_MIPS64)
12430 case OPC_LDX:
12431 op_ld_ld(t0, t0, ctx);
12432 gen_store_gpr(t0, rd);
12433 opn = "ldx";
12434 break;
12435#endif
12436 }
12437 (void)opn; /* avoid a compiler warning */
12438 MIPS_DEBUG("%s %s, %s(%s)", opn,
12439 regnames[rd], regnames[offset], regnames[base]);
12440 tcg_temp_free(t0);
12441}
12442
461c08df
JL
12443static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
12444 int ret, int v1, int v2)
12445{
12446 const char *opn = "mipsdsp arith";
12447 TCGv v1_t;
12448 TCGv v2_t;
12449
12450 if (ret == 0) {
12451 /* Treat as NOP. */
12452 MIPS_DEBUG("NOP");
12453 return;
12454 }
12455
12456 v1_t = tcg_temp_new();
12457 v2_t = tcg_temp_new();
12458
12459 gen_load_gpr(v1_t, v1);
12460 gen_load_gpr(v2_t, v2);
12461
12462 switch (op1) {
12463 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
12464 case OPC_MULT_G_2E:
12465 check_dspr2(ctx);
12466 switch (op2) {
12467 case OPC_ADDUH_QB:
12468 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
12469 break;
12470 case OPC_ADDUH_R_QB:
12471 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
12472 break;
12473 case OPC_ADDQH_PH:
12474 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
12475 break;
12476 case OPC_ADDQH_R_PH:
12477 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
12478 break;
12479 case OPC_ADDQH_W:
12480 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
12481 break;
12482 case OPC_ADDQH_R_W:
12483 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
12484 break;
12485 case OPC_SUBUH_QB:
12486 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
12487 break;
12488 case OPC_SUBUH_R_QB:
12489 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
12490 break;
12491 case OPC_SUBQH_PH:
12492 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
12493 break;
12494 case OPC_SUBQH_R_PH:
12495 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
12496 break;
12497 case OPC_SUBQH_W:
12498 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
12499 break;
12500 case OPC_SUBQH_R_W:
12501 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
12502 break;
12503 }
12504 break;
12505 case OPC_ABSQ_S_PH_DSP:
12506 switch (op2) {
12507 case OPC_ABSQ_S_QB:
12508 check_dspr2(ctx);
12509 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
12510 break;
12511 case OPC_ABSQ_S_PH:
12512 check_dsp(ctx);
12513 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
12514 break;
12515 case OPC_ABSQ_S_W:
12516 check_dsp(ctx);
12517 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
12518 break;
12519 case OPC_PRECEQ_W_PHL:
12520 check_dsp(ctx);
12521 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
12522 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
12523 break;
12524 case OPC_PRECEQ_W_PHR:
12525 check_dsp(ctx);
12526 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
12527 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
12528 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
12529 break;
12530 case OPC_PRECEQU_PH_QBL:
12531 check_dsp(ctx);
12532 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
12533 break;
12534 case OPC_PRECEQU_PH_QBR:
12535 check_dsp(ctx);
12536 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
12537 break;
12538 case OPC_PRECEQU_PH_QBLA:
12539 check_dsp(ctx);
12540 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
12541 break;
12542 case OPC_PRECEQU_PH_QBRA:
12543 check_dsp(ctx);
12544 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
12545 break;
12546 case OPC_PRECEU_PH_QBL:
12547 check_dsp(ctx);
12548 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
12549 break;
12550 case OPC_PRECEU_PH_QBR:
12551 check_dsp(ctx);
12552 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
12553 break;
12554 case OPC_PRECEU_PH_QBLA:
12555 check_dsp(ctx);
12556 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
12557 break;
12558 case OPC_PRECEU_PH_QBRA:
12559 check_dsp(ctx);
12560 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
12561 break;
12562 }
12563 break;
12564 case OPC_ADDU_QB_DSP:
12565 switch (op2) {
12566 case OPC_ADDQ_PH:
12567 check_dsp(ctx);
12568 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12569 break;
12570 case OPC_ADDQ_S_PH:
12571 check_dsp(ctx);
12572 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12573 break;
12574 case OPC_ADDQ_S_W:
12575 check_dsp(ctx);
12576 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12577 break;
12578 case OPC_ADDU_QB:
12579 check_dsp(ctx);
12580 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12581 break;
12582 case OPC_ADDU_S_QB:
12583 check_dsp(ctx);
12584 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12585 break;
12586 case OPC_ADDU_PH:
12587 check_dspr2(ctx);
12588 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12589 break;
12590 case OPC_ADDU_S_PH:
12591 check_dspr2(ctx);
12592 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12593 break;
12594 case OPC_SUBQ_PH:
12595 check_dsp(ctx);
12596 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12597 break;
12598 case OPC_SUBQ_S_PH:
12599 check_dsp(ctx);
12600 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12601 break;
12602 case OPC_SUBQ_S_W:
12603 check_dsp(ctx);
12604 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12605 break;
12606 case OPC_SUBU_QB:
12607 check_dsp(ctx);
12608 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12609 break;
12610 case OPC_SUBU_S_QB:
12611 check_dsp(ctx);
12612 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12613 break;
12614 case OPC_SUBU_PH:
12615 check_dspr2(ctx);
12616 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12617 break;
12618 case OPC_SUBU_S_PH:
12619 check_dspr2(ctx);
12620 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12621 break;
12622 case OPC_ADDSC:
12623 check_dsp(ctx);
12624 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12625 break;
12626 case OPC_ADDWC:
12627 check_dsp(ctx);
12628 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12629 break;
12630 case OPC_MODSUB:
12631 check_dsp(ctx);
12632 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
12633 break;
12634 case OPC_RADDU_W_QB:
12635 check_dsp(ctx);
12636 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
12637 break;
12638 }
12639 break;
12640 case OPC_CMPU_EQ_QB_DSP:
12641 switch (op2) {
12642 case OPC_PRECR_QB_PH:
12643 check_dspr2(ctx);
12644 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
12645 break;
12646 case OPC_PRECRQ_QB_PH:
12647 check_dsp(ctx);
12648 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
12649 break;
12650 case OPC_PRECR_SRA_PH_W:
12651 check_dspr2(ctx);
12652 {
12653 TCGv_i32 sa_t = tcg_const_i32(v2);
12654 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
12655 cpu_gpr[ret]);
12656 tcg_temp_free_i32(sa_t);
12657 break;
12658 }
12659 case OPC_PRECR_SRA_R_PH_W:
12660 check_dspr2(ctx);
12661 {
12662 TCGv_i32 sa_t = tcg_const_i32(v2);
12663 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
12664 cpu_gpr[ret]);
12665 tcg_temp_free_i32(sa_t);
12666 break;
12667 }
12668 case OPC_PRECRQ_PH_W:
12669 check_dsp(ctx);
12670 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
12671 break;
12672 case OPC_PRECRQ_RS_PH_W:
12673 check_dsp(ctx);
12674 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12675 break;
12676 case OPC_PRECRQU_S_QB_PH:
12677 check_dsp(ctx);
12678 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12679 break;
12680 }
12681 break;
12682#ifdef TARGET_MIPS64
12683 case OPC_ABSQ_S_QH_DSP:
12684 switch (op2) {
12685 case OPC_PRECEQ_L_PWL:
12686 check_dsp(ctx);
12687 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
12688 break;
12689 case OPC_PRECEQ_L_PWR:
12690 check_dsp(ctx);
12691 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
12692 break;
12693 case OPC_PRECEQ_PW_QHL:
12694 check_dsp(ctx);
12695 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
12696 break;
12697 case OPC_PRECEQ_PW_QHR:
12698 check_dsp(ctx);
12699 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
12700 break;
12701 case OPC_PRECEQ_PW_QHLA:
12702 check_dsp(ctx);
12703 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
12704 break;
12705 case OPC_PRECEQ_PW_QHRA:
12706 check_dsp(ctx);
12707 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
12708 break;
12709 case OPC_PRECEQU_QH_OBL:
12710 check_dsp(ctx);
12711 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
12712 break;
12713 case OPC_PRECEQU_QH_OBR:
12714 check_dsp(ctx);
12715 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
12716 break;
12717 case OPC_PRECEQU_QH_OBLA:
12718 check_dsp(ctx);
12719 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
12720 break;
12721 case OPC_PRECEQU_QH_OBRA:
12722 check_dsp(ctx);
12723 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
12724 break;
12725 case OPC_PRECEU_QH_OBL:
12726 check_dsp(ctx);
12727 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
12728 break;
12729 case OPC_PRECEU_QH_OBR:
12730 check_dsp(ctx);
12731 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
12732 break;
12733 case OPC_PRECEU_QH_OBLA:
12734 check_dsp(ctx);
12735 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
12736 break;
12737 case OPC_PRECEU_QH_OBRA:
12738 check_dsp(ctx);
12739 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
12740 break;
12741 case OPC_ABSQ_S_OB:
12742 check_dspr2(ctx);
12743 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
12744 break;
12745 case OPC_ABSQ_S_PW:
12746 check_dsp(ctx);
12747 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
12748 break;
12749 case OPC_ABSQ_S_QH:
12750 check_dsp(ctx);
12751 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
12752 break;
12753 }
12754 break;
12755 case OPC_ADDU_OB_DSP:
12756 switch (op2) {
12757 case OPC_RADDU_L_OB:
12758 check_dsp(ctx);
12759 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
12760 break;
12761 case OPC_SUBQ_PW:
12762 check_dsp(ctx);
12763 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12764 break;
12765 case OPC_SUBQ_S_PW:
12766 check_dsp(ctx);
12767 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12768 break;
12769 case OPC_SUBQ_QH:
12770 check_dsp(ctx);
12771 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12772 break;
12773 case OPC_SUBQ_S_QH:
12774 check_dsp(ctx);
12775 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12776 break;
12777 case OPC_SUBU_OB:
12778 check_dsp(ctx);
12779 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12780 break;
12781 case OPC_SUBU_S_OB:
12782 check_dsp(ctx);
12783 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12784 break;
12785 case OPC_SUBU_QH:
12786 check_dspr2(ctx);
12787 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12788 break;
12789 case OPC_SUBU_S_QH:
12790 check_dspr2(ctx);
12791 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12792 break;
12793 case OPC_SUBUH_OB:
12794 check_dspr2(ctx);
12795 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
12796 break;
12797 case OPC_SUBUH_R_OB:
12798 check_dspr2(ctx);
12799 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
12800 break;
12801 case OPC_ADDQ_PW:
12802 check_dsp(ctx);
12803 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12804 break;
12805 case OPC_ADDQ_S_PW:
12806 check_dsp(ctx);
12807 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12808 break;
12809 case OPC_ADDQ_QH:
12810 check_dsp(ctx);
12811 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12812 break;
12813 case OPC_ADDQ_S_QH:
12814 check_dsp(ctx);
12815 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12816 break;
12817 case OPC_ADDU_OB:
12818 check_dsp(ctx);
12819 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12820 break;
12821 case OPC_ADDU_S_OB:
12822 check_dsp(ctx);
12823 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12824 break;
12825 case OPC_ADDU_QH:
12826 check_dspr2(ctx);
12827 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12828 break;
12829 case OPC_ADDU_S_QH:
12830 check_dspr2(ctx);
12831 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12832 break;
12833 case OPC_ADDUH_OB:
12834 check_dspr2(ctx);
12835 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
12836 break;
12837 case OPC_ADDUH_R_OB:
12838 check_dspr2(ctx);
12839 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
12840 break;
12841 }
12842 break;
12843 case OPC_CMPU_EQ_OB_DSP:
12844 switch (op2) {
12845 case OPC_PRECR_OB_QH:
12846 check_dspr2(ctx);
12847 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
12848 break;
12849 case OPC_PRECR_SRA_QH_PW:
12850 check_dspr2(ctx);
12851 {
12852 TCGv_i32 ret_t = tcg_const_i32(ret);
12853 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
12854 tcg_temp_free_i32(ret_t);
12855 break;
12856 }
12857 case OPC_PRECR_SRA_R_QH_PW:
12858 check_dspr2(ctx);
12859 {
12860 TCGv_i32 sa_v = tcg_const_i32(ret);
12861 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
12862 tcg_temp_free_i32(sa_v);
12863 break;
12864 }
12865 case OPC_PRECRQ_OB_QH:
12866 check_dsp(ctx);
12867 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
12868 break;
12869 case OPC_PRECRQ_PW_L:
12870 check_dsp(ctx);
12871 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
12872 break;
12873 case OPC_PRECRQ_QH_PW:
12874 check_dsp(ctx);
12875 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
12876 break;
12877 case OPC_PRECRQ_RS_QH_PW:
12878 check_dsp(ctx);
12879 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12880 break;
12881 case OPC_PRECRQU_S_OB_QH:
12882 check_dsp(ctx);
12883 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12884 break;
12885 }
12886 break;
12887#endif
12888 }
12889
12890 tcg_temp_free(v1_t);
12891 tcg_temp_free(v2_t);
12892
12893 (void)opn; /* avoid a compiler warning */
12894 MIPS_DEBUG("%s", opn);
12895}
9b1a1d68
JL
12896
12897/* End MIPSDSP functions. */
12898
7db13fae 12899static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
3c824109
NF
12900{
12901 int32_t offset;
12902 int rs, rt, rd, sa;
12903 uint32_t op, op1, op2;
12904 int16_t imm;
12905
12906 /* make sure instructions are on a word boundary */
12907 if (ctx->pc & 0x3) {
12908 env->CP0_BadVAddr = ctx->pc;
12909 generate_exception(ctx, EXCP_AdEL);
12910 return;
12911 }
12912
12913 /* Handle blikely not taken case */
12914 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
12915 int l1 = gen_new_label();
12916
12917 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
12918 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
12919 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
12920 gen_goto_tb(ctx, 1, ctx->pc + 4);
12921 gen_set_label(l1);
12922 }
12923
fdefe51c 12924 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
3c824109 12925 tcg_gen_debug_insn_start(ctx->pc);
fdefe51c 12926 }
3c824109
NF
12927
12928 op = MASK_OP_MAJOR(ctx->opcode);
12929 rs = (ctx->opcode >> 21) & 0x1f;
12930 rt = (ctx->opcode >> 16) & 0x1f;
12931 rd = (ctx->opcode >> 11) & 0x1f;
12932 sa = (ctx->opcode >> 6) & 0x1f;
12933 imm = (int16_t)ctx->opcode;
12934 switch (op) {
7a387fff
TS
12935 case OPC_SPECIAL:
12936 op1 = MASK_SPECIAL(ctx->opcode);
6af0bf9c 12937 switch (op1) {
324d9e32
AJ
12938 case OPC_SLL: /* Shift with immediate */
12939 case OPC_SRA:
324d9e32 12940 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7a387fff 12941 break;
ea63e2c3
NF
12942 case OPC_SRL:
12943 switch ((ctx->opcode >> 21) & 0x1f) {
12944 case 1:
12945 /* rotr is decoded as srl on non-R2 CPUs */
12946 if (env->insn_flags & ISA_MIPS32R2) {
12947 op1 = OPC_ROTR;
12948 }
12949 /* Fallthrough */
12950 case 0:
12951 gen_shift_imm(env, ctx, op1, rd, rt, sa);
12952 break;
12953 default:
12954 generate_exception(ctx, EXCP_RI);
12955 break;
12956 }
12957 break;
460f00c4
AJ
12958 case OPC_MOVN: /* Conditional move */
12959 case OPC_MOVZ:
aa8f4009
AJ
12960 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32 |
12961 INSN_LOONGSON2E | INSN_LOONGSON2F);
9fa77488 12962 gen_cond_move(env, ctx, op1, rd, rs, rt);
460f00c4
AJ
12963 break;
12964 case OPC_ADD ... OPC_SUBU:
e189e748 12965 gen_arith(env, ctx, op1, rd, rs, rt);
7a387fff 12966 break;
460f00c4 12967 case OPC_SLLV: /* Shifts */
460f00c4
AJ
12968 case OPC_SRAV:
12969 gen_shift(env, ctx, op1, rd, rs, rt);
12970 break;
ea63e2c3
NF
12971 case OPC_SRLV:
12972 switch ((ctx->opcode >> 6) & 0x1f) {
12973 case 1:
12974 /* rotrv is decoded as srlv on non-R2 CPUs */
12975 if (env->insn_flags & ISA_MIPS32R2) {
12976 op1 = OPC_ROTRV;
12977 }
12978 /* Fallthrough */
12979 case 0:
12980 gen_shift(env, ctx, op1, rd, rs, rt);
12981 break;
12982 default:
12983 generate_exception(ctx, EXCP_RI);
12984 break;
12985 }
12986 break;
460f00c4
AJ
12987 case OPC_SLT: /* Set on less than */
12988 case OPC_SLTU:
9fa77488 12989 gen_slt(env, ctx, op1, rd, rs, rt);
460f00c4
AJ
12990 break;
12991 case OPC_AND: /* Logic*/
12992 case OPC_OR:
12993 case OPC_NOR:
12994 case OPC_XOR:
9fa77488 12995 gen_logic(env, ctx, op1, rd, rs, rt);
460f00c4 12996 break;
7a387fff 12997 case OPC_MULT ... OPC_DIVU:
e9c71dd1
TS
12998 if (sa) {
12999 check_insn(env, ctx, INSN_VR54XX);
13000 op1 = MASK_MUL_VR54XX(ctx->opcode);
13001 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
13002 } else
13003 gen_muldiv(ctx, op1, rs, rt);
7a387fff
TS
13004 break;
13005 case OPC_JR ... OPC_JALR:
7dca4ad0 13006 gen_compute_branch(ctx, op1, 4, rs, rd, sa);
c9602061
NF
13007 *is_branch = 1;
13008 break;
7a387fff
TS
13009 case OPC_TGE ... OPC_TEQ: /* Traps */
13010 case OPC_TNE:
13011 gen_trap(ctx, op1, rs, rt, -1);
6af0bf9c 13012 break;
7a387fff
TS
13013 case OPC_MFHI: /* Move from HI/LO */
13014 case OPC_MFLO:
13015 gen_HILO(ctx, op1, rd);
6af0bf9c 13016 break;
7a387fff
TS
13017 case OPC_MTHI:
13018 case OPC_MTLO: /* Move to HI/LO */
13019 gen_HILO(ctx, op1, rs);
6af0bf9c 13020 break;
b48cfdff
TS
13021 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
13022#ifdef MIPS_STRICT_STANDARD
13023 MIPS_INVAL("PMON / selsl");
13024 generate_exception(ctx, EXCP_RI);
13025#else
895c2d04 13026 gen_helper_0e0i(pmon, sa);
b48cfdff 13027#endif
7a387fff
TS
13028 break;
13029 case OPC_SYSCALL:
6af0bf9c 13030 generate_exception(ctx, EXCP_SYSCALL);
8e0f950d 13031 ctx->bstate = BS_STOP;
6af0bf9c 13032 break;
7a387fff 13033 case OPC_BREAK:
6af0bf9c
FB
13034 generate_exception(ctx, EXCP_BREAK);
13035 break;
b48cfdff
TS
13036 case OPC_SPIM:
13037#ifdef MIPS_STRICT_STANDARD
13038 MIPS_INVAL("SPIM");
13039 generate_exception(ctx, EXCP_RI);
13040#else
7a387fff
TS
13041 /* Implemented as RI exception for now. */
13042 MIPS_INVAL("spim (unofficial)");
13043 generate_exception(ctx, EXCP_RI);
b48cfdff 13044#endif
6af0bf9c 13045 break;
7a387fff 13046 case OPC_SYNC:
ead9360e 13047 /* Treat as NOP. */
6af0bf9c 13048 break;
4ad40f36 13049
7a387fff 13050 case OPC_MOVCI:
e189e748 13051 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
36d23958 13052 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 13053 check_cp1_enabled(ctx);
36d23958
TS
13054 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
13055 (ctx->opcode >> 16) & 1);
13056 } else {
e397ee33 13057 generate_exception_err(ctx, EXCP_CpU, 1);
36d23958 13058 }
4ad40f36
FB
13059 break;
13060
d26bc211 13061#if defined(TARGET_MIPS64)
7a387fff
TS
13062 /* MIPS64 specific opcodes */
13063 case OPC_DSLL:
324d9e32 13064 case OPC_DSRA:
7a387fff 13065 case OPC_DSLL32:
324d9e32 13066 case OPC_DSRA32:
e189e748
TS
13067 check_insn(env, ctx, ISA_MIPS3);
13068 check_mips_64(ctx);
324d9e32 13069 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7a387fff 13070 break;
ea63e2c3
NF
13071 case OPC_DSRL:
13072 switch ((ctx->opcode >> 21) & 0x1f) {
13073 case 1:
13074 /* drotr is decoded as dsrl on non-R2 CPUs */
13075 if (env->insn_flags & ISA_MIPS32R2) {
13076 op1 = OPC_DROTR;
13077 }
13078 /* Fallthrough */
13079 case 0:
13080 check_insn(env, ctx, ISA_MIPS3);
13081 check_mips_64(ctx);
13082 gen_shift_imm(env, ctx, op1, rd, rt, sa);
13083 break;
13084 default:
13085 generate_exception(ctx, EXCP_RI);
13086 break;
13087 }
13088 break;
13089 case OPC_DSRL32:
13090 switch ((ctx->opcode >> 21) & 0x1f) {
13091 case 1:
13092 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
13093 if (env->insn_flags & ISA_MIPS32R2) {
13094 op1 = OPC_DROTR32;
13095 }
13096 /* Fallthrough */
13097 case 0:
13098 check_insn(env, ctx, ISA_MIPS3);
13099 check_mips_64(ctx);
13100 gen_shift_imm(env, ctx, op1, rd, rt, sa);
13101 break;
13102 default:
13103 generate_exception(ctx, EXCP_RI);
13104 break;
13105 }
13106 break;
7a387fff 13107 case OPC_DADD ... OPC_DSUBU:
e189e748
TS
13108 check_insn(env, ctx, ISA_MIPS3);
13109 check_mips_64(ctx);
13110 gen_arith(env, ctx, op1, rd, rs, rt);
7a387fff 13111 break;
460f00c4
AJ
13112 case OPC_DSLLV:
13113 case OPC_DSRAV:
460f00c4
AJ
13114 check_insn(env, ctx, ISA_MIPS3);
13115 check_mips_64(ctx);
13116 gen_shift(env, ctx, op1, rd, rs, rt);
13117 break;
ea63e2c3
NF
13118 case OPC_DSRLV:
13119 switch ((ctx->opcode >> 6) & 0x1f) {
13120 case 1:
13121 /* drotrv is decoded as dsrlv on non-R2 CPUs */
13122 if (env->insn_flags & ISA_MIPS32R2) {
13123 op1 = OPC_DROTRV;
13124 }
13125 /* Fallthrough */
13126 case 0:
13127 check_insn(env, ctx, ISA_MIPS3);
13128 check_mips_64(ctx);
13129 gen_shift(env, ctx, op1, rd, rs, rt);
13130 break;
13131 default:
13132 generate_exception(ctx, EXCP_RI);
13133 break;
13134 }
13135 break;
7a387fff 13136 case OPC_DMULT ... OPC_DDIVU:
e189e748
TS
13137 check_insn(env, ctx, ISA_MIPS3);
13138 check_mips_64(ctx);
7a387fff
TS
13139 gen_muldiv(ctx, op1, rs, rt);
13140 break;
6af0bf9c
FB
13141#endif
13142 default: /* Invalid */
13143 MIPS_INVAL("special");
13144 generate_exception(ctx, EXCP_RI);
13145 break;
13146 }
13147 break;
7a387fff
TS
13148 case OPC_SPECIAL2:
13149 op1 = MASK_SPECIAL2(ctx->opcode);
6af0bf9c 13150 switch (op1) {
7a387fff
TS
13151 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
13152 case OPC_MSUB ... OPC_MSUBU:
e189e748 13153 check_insn(env, ctx, ISA_MIPS32);
7a387fff 13154 gen_muldiv(ctx, op1, rs, rt);
6af0bf9c 13155 break;
7a387fff 13156 case OPC_MUL:
e189e748 13157 gen_arith(env, ctx, op1, rd, rs, rt);
6af0bf9c 13158 break;
20e1fb52
AJ
13159 case OPC_CLO:
13160 case OPC_CLZ:
e189e748 13161 check_insn(env, ctx, ISA_MIPS32);
7a387fff 13162 gen_cl(ctx, op1, rd, rs);
6af0bf9c 13163 break;
7a387fff 13164 case OPC_SDBBP:
6af0bf9c
FB
13165 /* XXX: not clear which exception should be raised
13166 * when in debug mode...
13167 */
e189e748 13168 check_insn(env, ctx, ISA_MIPS32);
6af0bf9c
FB
13169 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
13170 generate_exception(ctx, EXCP_DBp);
13171 } else {
13172 generate_exception(ctx, EXCP_DBp);
13173 }
ead9360e 13174 /* Treat as NOP. */
6af0bf9c 13175 break;
161f85e6
AJ
13176 case OPC_DIV_G_2F:
13177 case OPC_DIVU_G_2F:
13178 case OPC_MULT_G_2F:
13179 case OPC_MULTU_G_2F:
13180 case OPC_MOD_G_2F:
13181 case OPC_MODU_G_2F:
13182 check_insn(env, ctx, INSN_LOONGSON2F);
13183 gen_loongson_integer(ctx, op1, rd, rs, rt);
13184 break;
d26bc211 13185#if defined(TARGET_MIPS64)
20e1fb52
AJ
13186 case OPC_DCLO:
13187 case OPC_DCLZ:
e189e748
TS
13188 check_insn(env, ctx, ISA_MIPS64);
13189 check_mips_64(ctx);
7a387fff
TS
13190 gen_cl(ctx, op1, rd, rs);
13191 break;
161f85e6
AJ
13192 case OPC_DMULT_G_2F:
13193 case OPC_DMULTU_G_2F:
13194 case OPC_DDIV_G_2F:
13195 case OPC_DDIVU_G_2F:
13196 case OPC_DMOD_G_2F:
13197 case OPC_DMODU_G_2F:
13198 check_insn(env, ctx, INSN_LOONGSON2F);
13199 gen_loongson_integer(ctx, op1, rd, rs, rt);
13200 break;
7a387fff 13201#endif
6af0bf9c
FB
13202 default: /* Invalid */
13203 MIPS_INVAL("special2");
13204 generate_exception(ctx, EXCP_RI);
13205 break;
13206 }
13207 break;
7a387fff 13208 case OPC_SPECIAL3:
2b0233ab
TS
13209 op1 = MASK_SPECIAL3(ctx->opcode);
13210 switch (op1) {
13211 case OPC_EXT:
13212 case OPC_INS:
13213 check_insn(env, ctx, ISA_MIPS32R2);
13214 gen_bitops(ctx, op1, rt, rs, sa, rd);
13215 break;
13216 case OPC_BSHFL:
13217 check_insn(env, ctx, ISA_MIPS32R2);
13218 op2 = MASK_BSHFL(ctx->opcode);
49bcf33c 13219 gen_bshfl(ctx, op2, rt, rd);
7a387fff 13220 break;
1579a72e 13221 case OPC_RDHWR:
26ebe468 13222 gen_rdhwr(env, ctx, rt, rd);
1579a72e 13223 break;
ead9360e 13224 case OPC_FORK:
7385ac0b 13225 check_insn(env, ctx, ASE_MT);
6c5c1e20 13226 {
35fbce2c
AJ
13227 TCGv t0 = tcg_temp_new();
13228 TCGv t1 = tcg_temp_new();
6c5c1e20
TS
13229
13230 gen_load_gpr(t0, rt);
13231 gen_load_gpr(t1, rs);
a7812ae4 13232 gen_helper_fork(t0, t1);
6c5c1e20
TS
13233 tcg_temp_free(t0);
13234 tcg_temp_free(t1);
13235 }
ead9360e
TS
13236 break;
13237 case OPC_YIELD:
7385ac0b 13238 check_insn(env, ctx, ASE_MT);
6c5c1e20 13239 {
35fbce2c 13240 TCGv t0 = tcg_temp_new();
6c5c1e20 13241
35fbce2c 13242 save_cpu_state(ctx, 1);
6c5c1e20 13243 gen_load_gpr(t0, rs);
895c2d04 13244 gen_helper_yield(t0, cpu_env, t0);
6c5c1e20
TS
13245 gen_store_gpr(t0, rd);
13246 tcg_temp_free(t0);
13247 }
ead9360e 13248 break;
161f85e6 13249 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
161f85e6 13250 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
461c08df
JL
13251 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
13252 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
13253 * the same mask and op1. */
13254 if ((env->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
13255 op2 = MASK_ADDUH_QB(ctx->opcode);
13256 switch (op2) {
13257 case OPC_ADDUH_QB:
13258 case OPC_ADDUH_R_QB:
13259 case OPC_ADDQH_PH:
13260 case OPC_ADDQH_R_PH:
13261 case OPC_ADDQH_W:
13262 case OPC_ADDQH_R_W:
13263 case OPC_SUBUH_QB:
13264 case OPC_SUBUH_R_QB:
13265 case OPC_SUBQH_PH:
13266 case OPC_SUBQH_R_PH:
13267 case OPC_SUBQH_W:
13268 case OPC_SUBQH_R_W:
13269 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
13270 break;
13271 default:
13272 MIPS_INVAL("MASK ADDUH.QB");
13273 generate_exception(ctx, EXCP_RI);
13274 break;
13275 }
13276 } else if (env->insn_flags & INSN_LOONGSON2E) {
13277 gen_loongson_integer(ctx, op1, rd, rs, rt);
13278 } else {
13279 generate_exception(ctx, EXCP_RI);
13280 }
161f85e6 13281 break;
9b1a1d68
JL
13282 case OPC_LX_DSP:
13283 op2 = MASK_LX(ctx->opcode);
13284 switch (op2) {
13285#if defined(TARGET_MIPS64)
13286 case OPC_LDX:
13287#endif
13288 case OPC_LBUX:
13289 case OPC_LHX:
13290 case OPC_LWX:
13291 gen_mipsdsp_ld(env, ctx, op2, rd, rs, rt);
13292 break;
13293 default: /* Invalid */
13294 MIPS_INVAL("MASK LX");
13295 generate_exception(ctx, EXCP_RI);
13296 break;
13297 }
13298 break;
461c08df
JL
13299 case OPC_ABSQ_S_PH_DSP:
13300 op2 = MASK_ABSQ_S_PH(ctx->opcode);
13301 switch (op2) {
13302 case OPC_ABSQ_S_QB:
13303 case OPC_ABSQ_S_PH:
13304 case OPC_ABSQ_S_W:
13305 case OPC_PRECEQ_W_PHL:
13306 case OPC_PRECEQ_W_PHR:
13307 case OPC_PRECEQU_PH_QBL:
13308 case OPC_PRECEQU_PH_QBR:
13309 case OPC_PRECEQU_PH_QBLA:
13310 case OPC_PRECEQU_PH_QBRA:
13311 case OPC_PRECEU_PH_QBL:
13312 case OPC_PRECEU_PH_QBR:
13313 case OPC_PRECEU_PH_QBLA:
13314 case OPC_PRECEU_PH_QBRA:
13315 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
13316 break;
13317 default:
13318 MIPS_INVAL("MASK ABSQ_S.PH");
13319 generate_exception(ctx, EXCP_RI);
13320 break;
13321 }
13322 break;
13323 case OPC_ADDU_QB_DSP:
13324 op2 = MASK_ADDU_QB(ctx->opcode);
13325 switch (op2) {
13326 case OPC_ADDQ_PH:
13327 case OPC_ADDQ_S_PH:
13328 case OPC_ADDQ_S_W:
13329 case OPC_ADDU_QB:
13330 case OPC_ADDU_S_QB:
13331 case OPC_ADDU_PH:
13332 case OPC_ADDU_S_PH:
13333 case OPC_SUBQ_PH:
13334 case OPC_SUBQ_S_PH:
13335 case OPC_SUBQ_S_W:
13336 case OPC_SUBU_QB:
13337 case OPC_SUBU_S_QB:
13338 case OPC_SUBU_PH:
13339 case OPC_SUBU_S_PH:
13340 case OPC_ADDSC:
13341 case OPC_ADDWC:
13342 case OPC_MODSUB:
13343 case OPC_RADDU_W_QB:
13344 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
13345 break;
13346 default: /* Invalid */
13347 MIPS_INVAL("MASK ADDU.QB");
13348 generate_exception(ctx, EXCP_RI);
13349 break;
13350
13351 }
13352 break;
13353 case OPC_CMPU_EQ_QB_DSP:
13354 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
13355 switch (op2) {
13356 case OPC_PRECR_SRA_PH_W:
13357 case OPC_PRECR_SRA_R_PH_W:
13358 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
13359 break;
13360 case OPC_PRECR_QB_PH:
13361 case OPC_PRECRQ_QB_PH:
13362 case OPC_PRECRQ_PH_W:
13363 case OPC_PRECRQ_RS_PH_W:
13364 case OPC_PRECRQU_S_QB_PH:
13365 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
13366 break;
13367 default: /* Invalid */
13368 MIPS_INVAL("MASK CMPU.EQ.QB");
13369 generate_exception(ctx, EXCP_RI);
13370 break;
13371 }
13372 break;
d26bc211 13373#if defined(TARGET_MIPS64)
1579a72e
TS
13374 case OPC_DEXTM ... OPC_DEXT:
13375 case OPC_DINSM ... OPC_DINS:
e189e748
TS
13376 check_insn(env, ctx, ISA_MIPS64R2);
13377 check_mips_64(ctx);
1579a72e 13378 gen_bitops(ctx, op1, rt, rs, sa, rd);
7a387fff 13379 break;
1579a72e 13380 case OPC_DBSHFL:
e189e748
TS
13381 check_insn(env, ctx, ISA_MIPS64R2);
13382 check_mips_64(ctx);
1579a72e 13383 op2 = MASK_DBSHFL(ctx->opcode);
49bcf33c 13384 gen_bshfl(ctx, op2, rt, rd);
c6d6dd7c 13385 break;
161f85e6
AJ
13386 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
13387 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
13388 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
13389 check_insn(env, ctx, INSN_LOONGSON2E);
13390 gen_loongson_integer(ctx, op1, rd, rs, rt);
13391 break;
461c08df
JL
13392 case OPC_ABSQ_S_QH_DSP:
13393 op2 = MASK_ABSQ_S_QH(ctx->opcode);
13394 switch (op2) {
13395 case OPC_PRECEQ_L_PWL:
13396 case OPC_PRECEQ_L_PWR:
13397 case OPC_PRECEQ_PW_QHL:
13398 case OPC_PRECEQ_PW_QHR:
13399 case OPC_PRECEQ_PW_QHLA:
13400 case OPC_PRECEQ_PW_QHRA:
13401 case OPC_PRECEQU_QH_OBL:
13402 case OPC_PRECEQU_QH_OBR:
13403 case OPC_PRECEQU_QH_OBLA:
13404 case OPC_PRECEQU_QH_OBRA:
13405 case OPC_PRECEU_QH_OBL:
13406 case OPC_PRECEU_QH_OBR:
13407 case OPC_PRECEU_QH_OBLA:
13408 case OPC_PRECEU_QH_OBRA:
13409 case OPC_ABSQ_S_OB:
13410 case OPC_ABSQ_S_PW:
13411 case OPC_ABSQ_S_QH:
13412 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
13413 break;
13414 default: /* Invalid */
13415 MIPS_INVAL("MASK ABSQ_S.QH");
13416 generate_exception(ctx, EXCP_RI);
13417 break;
13418 }
13419 break;
13420 case OPC_ADDU_OB_DSP:
13421 op2 = MASK_ADDU_OB(ctx->opcode);
13422 switch (op2) {
13423 case OPC_RADDU_L_OB:
13424 case OPC_SUBQ_PW:
13425 case OPC_SUBQ_S_PW:
13426 case OPC_SUBQ_QH:
13427 case OPC_SUBQ_S_QH:
13428 case OPC_SUBU_OB:
13429 case OPC_SUBU_S_OB:
13430 case OPC_SUBU_QH:
13431 case OPC_SUBU_S_QH:
13432 case OPC_SUBUH_OB:
13433 case OPC_SUBUH_R_OB:
13434 case OPC_ADDQ_PW:
13435 case OPC_ADDQ_S_PW:
13436 case OPC_ADDQ_QH:
13437 case OPC_ADDQ_S_QH:
13438 case OPC_ADDU_OB:
13439 case OPC_ADDU_S_OB:
13440 case OPC_ADDU_QH:
13441 case OPC_ADDU_S_QH:
13442 case OPC_ADDUH_OB:
13443 case OPC_ADDUH_R_OB:
13444 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
13445 break;
13446 default: /* Invalid */
13447 MIPS_INVAL("MASK ADDU.OB");
13448 generate_exception(ctx, EXCP_RI);
13449 break;
13450 }
13451 break;
13452 case OPC_CMPU_EQ_OB_DSP:
13453 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
13454 switch (op2) {
13455 case OPC_PRECR_SRA_QH_PW:
13456 case OPC_PRECR_SRA_R_QH_PW:
13457 /* Return value is rt. */
13458 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
13459 break;
13460 case OPC_PRECR_OB_QH:
13461 case OPC_PRECRQ_OB_QH:
13462 case OPC_PRECRQ_PW_L:
13463 case OPC_PRECRQ_QH_PW:
13464 case OPC_PRECRQ_RS_QH_PW:
13465 case OPC_PRECRQU_S_OB_QH:
13466 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
13467 break;
13468 default: /* Invalid */
13469 MIPS_INVAL("MASK CMPU_EQ.OB");
13470 generate_exception(ctx, EXCP_RI);
13471 break;
13472 }
13473 break;
7a387fff
TS
13474#endif
13475 default: /* Invalid */
13476 MIPS_INVAL("special3");
13477 generate_exception(ctx, EXCP_RI);
13478 break;
13479 }
13480 break;
13481 case OPC_REGIMM:
13482 op1 = MASK_REGIMM(ctx->opcode);
13483 switch (op1) {
13484 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
13485 case OPC_BLTZAL ... OPC_BGEZALL:
7dca4ad0 13486 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
c9602061
NF
13487 *is_branch = 1;
13488 break;
7a387fff
TS
13489 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
13490 case OPC_TNEI:
13491 gen_trap(ctx, op1, rs, -1, imm);
13492 break;
13493 case OPC_SYNCI:
e189e748 13494 check_insn(env, ctx, ISA_MIPS32R2);
ead9360e 13495 /* Treat as NOP. */
6af0bf9c 13496 break;
e45a93e2
JL
13497 case OPC_BPOSGE32: /* MIPS DSP branch */
13498#if defined(TARGET_MIPS64)
13499 case OPC_BPOSGE64:
13500#endif
13501 check_dsp(ctx);
13502 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2);
13503 *is_branch = 1;
13504 break;
6af0bf9c 13505 default: /* Invalid */
923617a3 13506 MIPS_INVAL("regimm");
6af0bf9c
FB
13507 generate_exception(ctx, EXCP_RI);
13508 break;
13509 }
13510 break;
7a387fff 13511 case OPC_CP0:
387a8fe5 13512 check_cp0_enabled(ctx);
7a387fff 13513 op1 = MASK_CP0(ctx->opcode);
6af0bf9c 13514 switch (op1) {
7a387fff
TS
13515 case OPC_MFC0:
13516 case OPC_MTC0:
ead9360e
TS
13517 case OPC_MFTR:
13518 case OPC_MTTR:
d26bc211 13519#if defined(TARGET_MIPS64)
7a387fff
TS
13520 case OPC_DMFC0:
13521 case OPC_DMTC0:
13522#endif
f1aa6320 13523#ifndef CONFIG_USER_ONLY
932e71cd 13524 gen_cp0(env, ctx, op1, rt, rd);
0eaef5aa 13525#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
13526 break;
13527 case OPC_C0_FIRST ... OPC_C0_LAST:
f1aa6320 13528#ifndef CONFIG_USER_ONLY
932e71cd 13529 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
0eaef5aa 13530#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
13531 break;
13532 case OPC_MFMC0:
8706c382 13533#ifndef CONFIG_USER_ONLY
932e71cd 13534 {
35fbce2c 13535 TCGv t0 = tcg_temp_new();
6c5c1e20 13536
0eaef5aa 13537 op2 = MASK_MFMC0(ctx->opcode);
6c5c1e20
TS
13538 switch (op2) {
13539 case OPC_DMT:
13540 check_insn(env, ctx, ASE_MT);
9ed5726c 13541 gen_helper_dmt(t0);
35fbce2c 13542 gen_store_gpr(t0, rt);
6c5c1e20
TS
13543 break;
13544 case OPC_EMT:
13545 check_insn(env, ctx, ASE_MT);
9ed5726c 13546 gen_helper_emt(t0);
35fbce2c 13547 gen_store_gpr(t0, rt);
da80682b 13548 break;
6c5c1e20
TS
13549 case OPC_DVPE:
13550 check_insn(env, ctx, ASE_MT);
895c2d04 13551 gen_helper_dvpe(t0, cpu_env);
35fbce2c 13552 gen_store_gpr(t0, rt);
6c5c1e20
TS
13553 break;
13554 case OPC_EVPE:
13555 check_insn(env, ctx, ASE_MT);
895c2d04 13556 gen_helper_evpe(t0, cpu_env);
35fbce2c 13557 gen_store_gpr(t0, rt);
6c5c1e20
TS
13558 break;
13559 case OPC_DI:
13560 check_insn(env, ctx, ISA_MIPS32R2);
867abc7e 13561 save_cpu_state(ctx, 1);
895c2d04 13562 gen_helper_di(t0, cpu_env);
35fbce2c 13563 gen_store_gpr(t0, rt);
6c5c1e20
TS
13564 /* Stop translation as we may have switched the execution mode */
13565 ctx->bstate = BS_STOP;
13566 break;
13567 case OPC_EI:
13568 check_insn(env, ctx, ISA_MIPS32R2);
867abc7e 13569 save_cpu_state(ctx, 1);
895c2d04 13570 gen_helper_ei(t0, cpu_env);
35fbce2c 13571 gen_store_gpr(t0, rt);
6c5c1e20
TS
13572 /* Stop translation as we may have switched the execution mode */
13573 ctx->bstate = BS_STOP;
13574 break;
13575 default: /* Invalid */
13576 MIPS_INVAL("mfmc0");
13577 generate_exception(ctx, EXCP_RI);
13578 break;
13579 }
6c5c1e20 13580 tcg_temp_free(t0);
7a387fff 13581 }
0eaef5aa 13582#endif /* !CONFIG_USER_ONLY */
6af0bf9c 13583 break;
7a387fff 13584 case OPC_RDPGPR:
e189e748 13585 check_insn(env, ctx, ISA_MIPS32R2);
be24bb4f 13586 gen_load_srsgpr(rt, rd);
ead9360e 13587 break;
7a387fff 13588 case OPC_WRPGPR:
e189e748 13589 check_insn(env, ctx, ISA_MIPS32R2);
be24bb4f 13590 gen_store_srsgpr(rt, rd);
38121543 13591 break;
6af0bf9c 13592 default:
923617a3 13593 MIPS_INVAL("cp0");
7a387fff 13594 generate_exception(ctx, EXCP_RI);
6af0bf9c
FB
13595 break;
13596 }
13597 break;
324d9e32
AJ
13598 case OPC_ADDI: /* Arithmetic with immediate opcode */
13599 case OPC_ADDIU:
e189e748 13600 gen_arith_imm(env, ctx, op, rt, rs, imm);
7a387fff 13601 break;
324d9e32
AJ
13602 case OPC_SLTI: /* Set on less than with immediate opcode */
13603 case OPC_SLTIU:
9fa77488 13604 gen_slt_imm(env, ctx, op, rt, rs, imm);
324d9e32
AJ
13605 break;
13606 case OPC_ANDI: /* Arithmetic with immediate opcode */
13607 case OPC_LUI:
13608 case OPC_ORI:
13609 case OPC_XORI:
9fa77488 13610 gen_logic_imm(env, ctx, op, rt, rs, imm);
324d9e32 13611 break;
7a387fff
TS
13612 case OPC_J ... OPC_JAL: /* Jump */
13613 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
7dca4ad0 13614 gen_compute_branch(ctx, op, 4, rs, rt, offset);
c9602061
NF
13615 *is_branch = 1;
13616 break;
7a387fff
TS
13617 case OPC_BEQ ... OPC_BGTZ: /* Branch */
13618 case OPC_BEQL ... OPC_BGTZL:
7dca4ad0 13619 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
c9602061
NF
13620 *is_branch = 1;
13621 break;
7a387fff 13622 case OPC_LB ... OPC_LWR: /* Load and stores */
5c13fdfd 13623 case OPC_LL:
afa88c3a 13624 gen_ld(env, ctx, op, rt, rs, imm);
5c13fdfd 13625 break;
7a387fff
TS
13626 case OPC_SB ... OPC_SW:
13627 case OPC_SWR:
5c13fdfd 13628 gen_st(ctx, op, rt, rs, imm);
7a387fff 13629 break;
d66c7132
AJ
13630 case OPC_SC:
13631 gen_st_cond(ctx, op, rt, rs, imm);
13632 break;
7a387fff 13633 case OPC_CACHE:
2e15497c 13634 check_cp0_enabled(ctx);
e189e748 13635 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
ead9360e 13636 /* Treat as NOP. */
34ae7b51 13637 break;
7a387fff 13638 case OPC_PREF:
e189e748 13639 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
ead9360e 13640 /* Treat as NOP. */
6af0bf9c 13641 break;
4ad40f36 13642
923617a3 13643 /* Floating point (COP1). */
7a387fff
TS
13644 case OPC_LWC1:
13645 case OPC_LDC1:
13646 case OPC_SWC1:
13647 case OPC_SDC1:
26ebe468 13648 gen_cop1_ldst(env, ctx, op, rt, rs, imm);
6ea83fed
FB
13649 break;
13650
7a387fff 13651 case OPC_CP1:
36d23958 13652 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 13653 check_cp1_enabled(ctx);
36d23958
TS
13654 op1 = MASK_CP1(ctx->opcode);
13655 switch (op1) {
3a95e3a7
TS
13656 case OPC_MFHC1:
13657 case OPC_MTHC1:
e189e748 13658 check_insn(env, ctx, ISA_MIPS32R2);
36d23958
TS
13659 case OPC_MFC1:
13660 case OPC_CFC1:
13661 case OPC_MTC1:
13662 case OPC_CTC1:
e189e748
TS
13663 gen_cp1(ctx, op1, rt, rd);
13664 break;
d26bc211 13665#if defined(TARGET_MIPS64)
36d23958
TS
13666 case OPC_DMFC1:
13667 case OPC_DMTC1:
e189e748 13668 check_insn(env, ctx, ISA_MIPS3);
36d23958
TS
13669 gen_cp1(ctx, op1, rt, rd);
13670 break;
e189e748 13671#endif
fbcc6828
TS
13672 case OPC_BC1ANY2:
13673 case OPC_BC1ANY4:
b8aa4598 13674 check_cop1x(ctx);
7385ac0b 13675 check_insn(env, ctx, ASE_MIPS3D);
d8a5950a
TS
13676 /* fall through */
13677 case OPC_BC1:
e189e748 13678 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
5a5012ec 13679 (rt >> 2) & 0x7, imm << 2);
c9602061
NF
13680 *is_branch = 1;
13681 break;
36d23958
TS
13682 case OPC_S_FMT:
13683 case OPC_D_FMT:
13684 case OPC_W_FMT:
13685 case OPC_L_FMT:
5a5012ec 13686 case OPC_PS_FMT:
bf4120ad 13687 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
5a5012ec 13688 (imm >> 8) & 0x7);
36d23958
TS
13689 break;
13690 default:
923617a3 13691 MIPS_INVAL("cp1");
e397ee33 13692 generate_exception (ctx, EXCP_RI);
36d23958
TS
13693 break;
13694 }
13695 } else {
13696 generate_exception_err(ctx, EXCP_CpU, 1);
6ea83fed 13697 }
4ad40f36
FB
13698 break;
13699
13700 /* COP2. */
7a387fff
TS
13701 case OPC_LWC2:
13702 case OPC_LDC2:
13703 case OPC_SWC2:
13704 case OPC_SDC2:
7a387fff 13705 /* COP2: Not implemented. */
4ad40f36
FB
13706 generate_exception_err(ctx, EXCP_CpU, 2);
13707 break;
bd277fa1
RH
13708 case OPC_CP2:
13709 check_insn(env, ctx, INSN_LOONGSON2F);
13710 /* Note that these instructions use different fields. */
13711 gen_loongson_multimedia(ctx, sa, rd, rt);
13712 break;
4ad40f36 13713
7a387fff 13714 case OPC_CP3:
36d23958 13715 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 13716 check_cp1_enabled(ctx);
36d23958
TS
13717 op1 = MASK_CP3(ctx->opcode);
13718 switch (op1) {
5a5012ec
TS
13719 case OPC_LWXC1:
13720 case OPC_LDXC1:
13721 case OPC_LUXC1:
13722 case OPC_SWXC1:
13723 case OPC_SDXC1:
13724 case OPC_SUXC1:
93b12ccc 13725 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
5a5012ec 13726 break;
e0c84da7 13727 case OPC_PREFX:
ead9360e 13728 /* Treat as NOP. */
e0c84da7 13729 break;
5a5012ec
TS
13730 case OPC_ALNV_PS:
13731 case OPC_MADD_S:
13732 case OPC_MADD_D:
13733 case OPC_MADD_PS:
13734 case OPC_MSUB_S:
13735 case OPC_MSUB_D:
13736 case OPC_MSUB_PS:
13737 case OPC_NMADD_S:
13738 case OPC_NMADD_D:
13739 case OPC_NMADD_PS:
13740 case OPC_NMSUB_S:
13741 case OPC_NMSUB_D:
13742 case OPC_NMSUB_PS:
13743 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
13744 break;
36d23958 13745 default:
923617a3 13746 MIPS_INVAL("cp3");
e397ee33 13747 generate_exception (ctx, EXCP_RI);
36d23958
TS
13748 break;
13749 }
13750 } else {
e397ee33 13751 generate_exception_err(ctx, EXCP_CpU, 1);
7a387fff 13752 }
4ad40f36
FB
13753 break;
13754
d26bc211 13755#if defined(TARGET_MIPS64)
7a387fff
TS
13756 /* MIPS64 opcodes */
13757 case OPC_LWU:
13758 case OPC_LDL ... OPC_LDR:
7a387fff
TS
13759 case OPC_LLD:
13760 case OPC_LD:
5c13fdfd
AJ
13761 check_insn(env, ctx, ISA_MIPS3);
13762 check_mips_64(ctx);
afa88c3a 13763 gen_ld(env, ctx, op, rt, rs, imm);
5c13fdfd
AJ
13764 break;
13765 case OPC_SDL ... OPC_SDR:
7a387fff 13766 case OPC_SD:
e189e748
TS
13767 check_insn(env, ctx, ISA_MIPS3);
13768 check_mips_64(ctx);
5c13fdfd 13769 gen_st(ctx, op, rt, rs, imm);
7a387fff 13770 break;
d66c7132
AJ
13771 case OPC_SCD:
13772 check_insn(env, ctx, ISA_MIPS3);
13773 check_mips_64(ctx);
13774 gen_st_cond(ctx, op, rt, rs, imm);
13775 break;
324d9e32
AJ
13776 case OPC_DADDI:
13777 case OPC_DADDIU:
e189e748
TS
13778 check_insn(env, ctx, ISA_MIPS3);
13779 check_mips_64(ctx);
13780 gen_arith_imm(env, ctx, op, rt, rs, imm);
7a387fff 13781 break;
6af0bf9c 13782#endif
7a387fff 13783 case OPC_JALX:
3c824109 13784 check_insn(env, ctx, ASE_MIPS16 | ASE_MICROMIPS);
364d4831
NF
13785 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
13786 gen_compute_branch(ctx, op, 4, rs, rt, offset);
13787 *is_branch = 1;
13788 break;
7a387fff 13789 case OPC_MDMX:
e189e748 13790 check_insn(env, ctx, ASE_MDMX);
7a387fff 13791 /* MDMX: Not implemented. */
6af0bf9c 13792 default: /* Invalid */
923617a3 13793 MIPS_INVAL("major opcode");
6af0bf9c
FB
13794 generate_exception(ctx, EXCP_RI);
13795 break;
13796 }
6af0bf9c
FB
13797}
13798
2cfc5f17 13799static inline void
7db13fae 13800gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
820e00f2 13801 int search_pc)
6af0bf9c 13802{
278d0702 13803 DisasContext ctx;
6af0bf9c
FB
13804 target_ulong pc_start;
13805 uint16_t *gen_opc_end;
a1d1bb31 13806 CPUBreakpoint *bp;
6af0bf9c 13807 int j, lj = -1;
2e70f6ef
PB
13808 int num_insns;
13809 int max_insns;
c9602061
NF
13810 int insn_bytes;
13811 int is_branch;
6af0bf9c 13812
93fcfe39
AL
13813 if (search_pc)
13814 qemu_log("search pc %d\n", search_pc);
4ad40f36 13815
6af0bf9c 13816 pc_start = tb->pc;
d42320c2 13817 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6af0bf9c 13818 ctx.pc = pc_start;
4ad40f36 13819 ctx.saved_pc = -1;
7b270ef2 13820 ctx.singlestep_enabled = env->singlestep_enabled;
6af0bf9c
FB
13821 ctx.tb = tb;
13822 ctx.bstate = BS_NONE;
4ad40f36 13823 /* Restore delay slot state from the tb context. */
c068688b 13824 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
fd4a04eb 13825 restore_cpu_state(env, &ctx);
932e71cd 13826#ifdef CONFIG_USER_ONLY
0eaef5aa 13827 ctx.mem_idx = MIPS_HFLAG_UM;
932e71cd 13828#else
0eaef5aa 13829 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
932e71cd 13830#endif
2e70f6ef
PB
13831 num_insns = 0;
13832 max_insns = tb->cflags & CF_COUNT_MASK;
13833 if (max_insns == 0)
13834 max_insns = CF_COUNT_MASK;
d12d51d5 13835 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
2e70f6ef 13836 gen_icount_start();
faf7aaa9 13837 while (ctx.bstate == BS_NONE) {
72cf2d4f
BS
13838 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
13839 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
a1d1bb31 13840 if (bp->pc == ctx.pc) {
278d0702 13841 save_cpu_state(&ctx, 1);
4ad40f36 13842 ctx.bstate = BS_BRANCH;
895c2d04 13843 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
ce62e5ba
TS
13844 /* Include the breakpoint location or the tb won't
13845 * be flushed when it must be. */
13846 ctx.pc += 4;
4ad40f36
FB
13847 goto done_generating;
13848 }
13849 }
13850 }
13851
6af0bf9c
FB
13852 if (search_pc) {
13853 j = gen_opc_ptr - gen_opc_buf;
6af0bf9c
FB
13854 if (lj < j) {
13855 lj++;
13856 while (lj < j)
13857 gen_opc_instr_start[lj++] = 0;
6af0bf9c 13858 }
4ad40f36
FB
13859 gen_opc_pc[lj] = ctx.pc;
13860 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
13861 gen_opc_instr_start[lj] = 1;
2e70f6ef 13862 gen_opc_icount[lj] = num_insns;
6af0bf9c 13863 }
2e70f6ef
PB
13864 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
13865 gen_io_start();
c9602061
NF
13866
13867 is_branch = 0;
364d4831 13868 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
895c2d04 13869 ctx.opcode = cpu_ldl_code(env, ctx.pc);
c9602061
NF
13870 insn_bytes = 4;
13871 decode_opc(env, &ctx, &is_branch);
3c824109 13872 } else if (env->insn_flags & ASE_MICROMIPS) {
895c2d04 13873 ctx.opcode = cpu_lduw_code(env, ctx.pc);
3c824109 13874 insn_bytes = decode_micromips_opc(env, &ctx, &is_branch);
364d4831 13875 } else if (env->insn_flags & ASE_MIPS16) {
895c2d04 13876 ctx.opcode = cpu_lduw_code(env, ctx.pc);
364d4831 13877 insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
c9602061
NF
13878 } else {
13879 generate_exception(&ctx, EXCP_RI);
3c824109 13880 ctx.bstate = BS_STOP;
c9602061
NF
13881 break;
13882 }
13883 if (!is_branch) {
13884 handle_delay_slot(env, &ctx, insn_bytes);
13885 }
13886 ctx.pc += insn_bytes;
13887
2e70f6ef 13888 num_insns++;
4ad40f36 13889
7b270ef2
NF
13890 /* Execute a branch and its delay slot as a single instruction.
13891 This is what GDB expects and is consistent with what the
13892 hardware does (e.g. if a delay slot instruction faults, the
13893 reported PC is the PC of the branch). */
13894 if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
4ad40f36
FB
13895 break;
13896
6af0bf9c
FB
13897 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
13898 break;
4ad40f36 13899
faf7aaa9
TS
13900 if (gen_opc_ptr >= gen_opc_end)
13901 break;
13902
2e70f6ef
PB
13903 if (num_insns >= max_insns)
13904 break;
1b530a6d
AJ
13905
13906 if (singlestep)
13907 break;
6af0bf9c 13908 }
2e70f6ef
PB
13909 if (tb->cflags & CF_LAST_IO)
13910 gen_io_end();
7b270ef2 13911 if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) {
278d0702 13912 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
895c2d04 13913 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
16c00cb2 13914 } else {
6958549d 13915 switch (ctx.bstate) {
16c00cb2 13916 case BS_STOP:
df1561e2
TS
13917 gen_goto_tb(&ctx, 0, ctx.pc);
13918 break;
16c00cb2 13919 case BS_NONE:
278d0702 13920 save_cpu_state(&ctx, 0);
16c00cb2
TS
13921 gen_goto_tb(&ctx, 0, ctx.pc);
13922 break;
5a5012ec 13923 case BS_EXCP:
57fec1fe 13924 tcg_gen_exit_tb(0);
16c00cb2 13925 break;
5a5012ec
TS
13926 case BS_BRANCH:
13927 default:
13928 break;
6958549d 13929 }
6af0bf9c 13930 }
4ad40f36 13931done_generating:
2e70f6ef 13932 gen_icount_end(tb, num_insns);
6af0bf9c
FB
13933 *gen_opc_ptr = INDEX_op_end;
13934 if (search_pc) {
13935 j = gen_opc_ptr - gen_opc_buf;
13936 lj++;
13937 while (lj <= j)
13938 gen_opc_instr_start[lj++] = 0;
6af0bf9c
FB
13939 } else {
13940 tb->size = ctx.pc - pc_start;
2e70f6ef 13941 tb->icount = num_insns;
6af0bf9c
FB
13942 }
13943#ifdef DEBUG_DISAS
d12d51d5 13944 LOG_DISAS("\n");
8fec2b8c 13945 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
93fcfe39
AL
13946 qemu_log("IN: %s\n", lookup_symbol(pc_start));
13947 log_target_disas(pc_start, ctx.pc - pc_start, 0);
13948 qemu_log("\n");
6af0bf9c
FB
13949 }
13950#endif
6af0bf9c
FB
13951}
13952
7db13fae 13953void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
6af0bf9c 13954{
2cfc5f17 13955 gen_intermediate_code_internal(env, tb, 0);
6af0bf9c
FB
13956}
13957
7db13fae 13958void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
6af0bf9c 13959{
2cfc5f17 13960 gen_intermediate_code_internal(env, tb, 1);
6af0bf9c
FB
13961}
13962
7db13fae 13963static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
8706c382 13964 int flags)
6ea83fed
FB
13965{
13966 int i;
5e755519 13967 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
5a5012ec 13968
2a5612e6
SW
13969#define printfpr(fp) \
13970 do { \
13971 if (is_fpu64) \
13972 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
13973 " fd:%13g fs:%13g psu: %13g\n", \
13974 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
13975 (double)(fp)->fd, \
13976 (double)(fp)->fs[FP_ENDIAN_IDX], \
13977 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
13978 else { \
13979 fpr_t tmp; \
13980 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
13981 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
13982 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
13983 " fd:%13g fs:%13g psu:%13g\n", \
13984 tmp.w[FP_ENDIAN_IDX], tmp.d, \
13985 (double)tmp.fd, \
13986 (double)tmp.fs[FP_ENDIAN_IDX], \
13987 (double)tmp.fs[!FP_ENDIAN_IDX]); \
13988 } \
6ea83fed
FB
13989 } while(0)
13990
5a5012ec 13991
9a78eead
SW
13992 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
13993 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
f01be154 13994 get_float_exception_flags(&env->active_fpu.fp_status));
5a5012ec
TS
13995 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
13996 fpu_fprintf(f, "%3s: ", fregnames[i]);
f01be154 13997 printfpr(&env->active_fpu.fpr[i]);
6ea83fed
FB
13998 }
13999
14000#undef printfpr
14001}
14002
d26bc211 14003#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16 14004/* Debug help: The architecture requires 32bit code to maintain proper
c7e8a937 14005 sign-extended values on 64bit machines. */
c570fd16
TS
14006
14007#define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
14008
8706c382 14009static void
7db13fae 14010cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f,
9a78eead 14011 fprintf_function cpu_fprintf,
8706c382 14012 int flags)
c570fd16
TS
14013{
14014 int i;
14015
b5dc7732
TS
14016 if (!SIGN_EXT_P(env->active_tc.PC))
14017 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
14018 if (!SIGN_EXT_P(env->active_tc.HI[0]))
14019 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
14020 if (!SIGN_EXT_P(env->active_tc.LO[0]))
14021 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
c570fd16 14022 if (!SIGN_EXT_P(env->btarget))
3594c774 14023 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
c570fd16
TS
14024
14025 for (i = 0; i < 32; i++) {
b5dc7732
TS
14026 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
14027 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
c570fd16
TS
14028 }
14029
14030 if (!SIGN_EXT_P(env->CP0_EPC))
3594c774 14031 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
5499b6ff
AJ
14032 if (!SIGN_EXT_P(env->lladdr))
14033 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
c570fd16
TS
14034}
14035#endif
14036
7db13fae 14037void cpu_dump_state (CPUMIPSState *env, FILE *f, fprintf_function cpu_fprintf,
6af0bf9c
FB
14038 int flags)
14039{
14040 int i;
3b46e624 14041
a7200c9f
SW
14042 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
14043 " LO=0x" TARGET_FMT_lx " ds %04x "
14044 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
3d5be870
TS
14045 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
14046 env->hflags, env->btarget, env->bcond);
6af0bf9c
FB
14047 for (i = 0; i < 32; i++) {
14048 if ((i & 3) == 0)
14049 cpu_fprintf(f, "GPR%02d:", i);
b5dc7732 14050 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
6af0bf9c
FB
14051 if ((i & 3) == 3)
14052 cpu_fprintf(f, "\n");
14053 }
568b600d 14054
3594c774 14055 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
5e755519 14056 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
3594c774 14057 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
5499b6ff 14058 env->CP0_Config0, env->CP0_Config1, env->lladdr);
5e755519 14059 if (env->hflags & MIPS_HFLAG_FPU)
7a387fff 14060 fpu_dump_state(env, f, cpu_fprintf, flags);
d26bc211 14061#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16
TS
14062 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
14063#endif
6af0bf9c
FB
14064}
14065
39454628
TS
14066static void mips_tcg_init(void)
14067{
f01be154 14068 int i;
39454628
TS
14069 static int inited;
14070
14071 /* Initialize various static tables. */
14072 if (inited)
6958549d 14073 return;
39454628 14074
a7812ae4 14075 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
f2c94b92 14076 TCGV_UNUSED(cpu_gpr[0]);
bb928dbe 14077 for (i = 1; i < 32; i++)
a7812ae4 14078 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
7db13fae 14079 offsetof(CPUMIPSState, active_tc.gpr[i]),
4b2eb8d2 14080 regnames[i]);
d73ee8a2
RH
14081
14082 for (i = 0; i < 32; i++) {
14083 int off = offsetof(CPUMIPSState, active_fpu.fpr[i]);
14084 fpu_f64[i] = tcg_global_mem_new_i64(TCG_AREG0, off, fregnames[i]);
14085 }
14086
a7812ae4 14087 cpu_PC = tcg_global_mem_new(TCG_AREG0,
7db13fae 14088 offsetof(CPUMIPSState, active_tc.PC), "PC");
4b2eb8d2 14089 for (i = 0; i < MIPS_DSP_ACC; i++) {
a7812ae4 14090 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
7db13fae 14091 offsetof(CPUMIPSState, active_tc.HI[i]),
4b2eb8d2 14092 regnames_HI[i]);
a7812ae4 14093 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
7db13fae 14094 offsetof(CPUMIPSState, active_tc.LO[i]),
4b2eb8d2 14095 regnames_LO[i]);
a7812ae4 14096 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
7db13fae 14097 offsetof(CPUMIPSState, active_tc.ACX[i]),
4b2eb8d2
TS
14098 regnames_ACX[i]);
14099 }
a7812ae4 14100 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
7db13fae 14101 offsetof(CPUMIPSState, active_tc.DSPControl),
4b2eb8d2 14102 "DSPControl");
1ba74fb8 14103 bcond = tcg_global_mem_new(TCG_AREG0,
7db13fae 14104 offsetof(CPUMIPSState, bcond), "bcond");
a7812ae4 14105 btarget = tcg_global_mem_new(TCG_AREG0,
7db13fae 14106 offsetof(CPUMIPSState, btarget), "btarget");
41db4607 14107 hflags = tcg_global_mem_new_i32(TCG_AREG0,
7db13fae 14108 offsetof(CPUMIPSState, hflags), "hflags");
41db4607 14109
a7812ae4 14110 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
7db13fae 14111 offsetof(CPUMIPSState, active_fpu.fcr0),
a7812ae4
PB
14112 "fcr0");
14113 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
7db13fae 14114 offsetof(CPUMIPSState, active_fpu.fcr31),
a7812ae4 14115 "fcr31");
39454628 14116
7dd9e556 14117 /* register helpers */
a7812ae4 14118#define GEN_HELPER 2
7dd9e556
TS
14119#include "helper.h"
14120
39454628
TS
14121 inited = 1;
14122}
14123
aaed909a
FB
14124#include "translate_init.c"
14125
30bf942d 14126MIPSCPU *cpu_mips_init(const char *cpu_model)
6af0bf9c 14127{
0f71a709 14128 MIPSCPU *cpu;
6af0bf9c 14129 CPUMIPSState *env;
c227f099 14130 const mips_def_t *def;
6af0bf9c 14131
aaed909a
FB
14132 def = cpu_mips_find_by_name(cpu_model);
14133 if (!def)
14134 return NULL;
0f71a709
AF
14135 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
14136 env = &cpu->env;
aaed909a 14137 env->cpu_model = def;
51cc2e78 14138 env->cpu_model_str = cpu_model;
aaed909a 14139
51cc2e78
BS
14140#ifndef CONFIG_USER_ONLY
14141 mmu_init(env, def);
14142#endif
14143 fpu_init(env, def);
14144 mvp_init(env, def);
39454628 14145 mips_tcg_init();
3bd4122e 14146 cpu_reset(CPU(cpu));
0bf46a40 14147 qemu_init_vcpu(env);
30bf942d 14148 return cpu;
6ae81775
TS
14149}
14150
1bba0dc9 14151void cpu_state_reset(CPUMIPSState *env)
6ae81775 14152{
eca1bdf4
AL
14153 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
14154 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
14155 log_cpu_state(env, 0);
14156 }
14157
6ae81775 14158 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
6af0bf9c 14159 tlb_flush(env, 1);
6ae81775 14160
51cc2e78
BS
14161 /* Reset registers to their default values */
14162 env->CP0_PRid = env->cpu_model->CP0_PRid;
14163 env->CP0_Config0 = env->cpu_model->CP0_Config0;
14164#ifdef TARGET_WORDS_BIGENDIAN
14165 env->CP0_Config0 |= (1 << CP0C0_BE);
14166#endif
14167 env->CP0_Config1 = env->cpu_model->CP0_Config1;
14168 env->CP0_Config2 = env->cpu_model->CP0_Config2;
14169 env->CP0_Config3 = env->cpu_model->CP0_Config3;
14170 env->CP0_Config6 = env->cpu_model->CP0_Config6;
14171 env->CP0_Config7 = env->cpu_model->CP0_Config7;
2a6e32dd
AJ
14172 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
14173 << env->cpu_model->CP0_LLAddr_shift;
14174 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
51cc2e78
BS
14175 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
14176 env->CCRes = env->cpu_model->CCRes;
14177 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
14178 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
14179 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
14180 env->current_tc = 0;
14181 env->SEGBITS = env->cpu_model->SEGBITS;
14182 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
14183#if defined(TARGET_MIPS64)
14184 if (env->cpu_model->insn_flags & ISA_MIPS3) {
14185 env->SEGMask |= 3ULL << 62;
14186 }
14187#endif
14188 env->PABITS = env->cpu_model->PABITS;
14189 env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
14190 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
14191 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
14192 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
14193 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
14194 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
14195 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
14196 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
14197 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
14198 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
14199 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
f1cb0951 14200 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
51cc2e78
BS
14201 env->insn_flags = env->cpu_model->insn_flags;
14202
0eaef5aa 14203#if defined(CONFIG_USER_ONLY)
03e6e501 14204 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
94159135
MI
14205 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
14206 hardware registers. */
14207 env->CP0_HWREna |= 0x0000000F;
91a75935 14208 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
03e6e501 14209 env->CP0_Status |= (1 << CP0St_CU1);
91a75935 14210 }
853c3240
JL
14211 if (env->cpu_model->insn_flags & ASE_DSPR2) {
14212 env->hflags |= MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2;
14213 } else if (env->cpu_model->insn_flags & ASE_DSP) {
14214 env->hflags |= MIPS_HFLAG_DSP;
14215 }
932e71cd
AJ
14216#else
14217 if (env->hflags & MIPS_HFLAG_BMASK) {
14218 /* If the exception was raised from a delay slot,
14219 come back to the jump. */
14220 env->CP0_ErrorEPC = env->active_tc.PC - 4;
aa328add 14221 } else {
932e71cd
AJ
14222 env->CP0_ErrorEPC = env->active_tc.PC;
14223 }
14224 env->active_tc.PC = (int32_t)0xBFC00000;
51cc2e78
BS
14225 env->CP0_Random = env->tlb->nb_tlb - 1;
14226 env->tlb->tlb_in_use = env->tlb->nb_tlb;
932e71cd 14227 env->CP0_Wired = 0;
671b0f36 14228 env->CP0_EBase = 0x80000000 | (env->cpu_index & 0x3FF);
932e71cd
AJ
14229 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
14230 /* vectored interrupts not implemented, timer on int 7,
14231 no performance counters. */
14232 env->CP0_IntCtl = 0xe0000000;
14233 {
14234 int i;
14235
14236 for (i = 0; i < 7; i++) {
14237 env->CP0_WatchLo[i] = 0;
14238 env->CP0_WatchHi[i] = 0x80000000;
fd88b6ab 14239 }
932e71cd
AJ
14240 env->CP0_WatchLo[7] = 0;
14241 env->CP0_WatchHi[7] = 0;
fd88b6ab 14242 }
932e71cd
AJ
14243 /* Count register increments in debug mode, EJTAG version 1 */
14244 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
9e56e756
EI
14245
14246 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
14247 int i;
14248
14249 /* Only TC0 on VPE 0 starts as active. */
14250 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
14251 env->tcs[i].CP0_TCBind = env->cpu_index << CP0TCBd_CurVPE;
14252 env->tcs[i].CP0_TCHalt = 1;
14253 }
14254 env->active_tc.CP0_TCHalt = 1;
14255 env->halted = 1;
14256
14257 if (!env->cpu_index) {
14258 /* VPE0 starts up enabled. */
14259 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
14260 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
14261
14262 /* TC0 starts up unhalted. */
14263 env->halted = 0;
14264 env->active_tc.CP0_TCHalt = 0;
14265 env->tcs[0].CP0_TCHalt = 0;
14266 /* With thread 0 active. */
14267 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
14268 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
14269 }
14270 }
51cc2e78 14271#endif
03e6e501 14272 compute_hflags(env);
6af0bf9c 14273 env->exception_index = EXCP_NONE;
6af0bf9c 14274}
d2856f1a 14275
7db13fae 14276void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
d2856f1a 14277{
b5dc7732 14278 env->active_tc.PC = gen_opc_pc[pc_pos];
d2856f1a
AJ
14279 env->hflags &= ~MIPS_HFLAG_BMASK;
14280 env->hflags |= gen_opc_hflags[pc_pos];
14281}