]> Git Repo - qemu.git/blame - target-mips/translate.c
target-mips: optimize gen_movci()
[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)
6af0bf9c
FB
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
fad6cb1a 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
6af0bf9c
FB
21 */
22
23#include <stdarg.h>
24#include <stdlib.h>
25#include <stdio.h>
26#include <string.h>
27#include <inttypes.h>
28
29#include "cpu.h"
30#include "exec-all.h"
31#include "disas.h"
57fec1fe 32#include "tcg-op.h"
ca10f867 33#include "qemu-common.h"
6af0bf9c 34
a7812ae4
PB
35#include "helper.h"
36#define GEN_HELPER 1
37#include "helper.h"
38
eeef26cd 39//#define MIPS_DEBUG_DISAS
c570fd16 40//#define MIPS_DEBUG_SIGN_EXTENSIONS
6af0bf9c
FB
41//#define MIPS_SINGLE_STEP
42
7a387fff
TS
43/* MIPS major opcodes */
44#define MASK_OP_MAJOR(op) (op & (0x3F << 26))
e37e863f
FB
45
46enum {
47 /* indirect opcode tables */
7a387fff
TS
48 OPC_SPECIAL = (0x00 << 26),
49 OPC_REGIMM = (0x01 << 26),
50 OPC_CP0 = (0x10 << 26),
51 OPC_CP1 = (0x11 << 26),
52 OPC_CP2 = (0x12 << 26),
53 OPC_CP3 = (0x13 << 26),
54 OPC_SPECIAL2 = (0x1C << 26),
55 OPC_SPECIAL3 = (0x1F << 26),
e37e863f 56 /* arithmetic with immediate */
7a387fff
TS
57 OPC_ADDI = (0x08 << 26),
58 OPC_ADDIU = (0x09 << 26),
59 OPC_SLTI = (0x0A << 26),
60 OPC_SLTIU = (0x0B << 26),
61 OPC_ANDI = (0x0C << 26),
62 OPC_ORI = (0x0D << 26),
63 OPC_XORI = (0x0E << 26),
64 OPC_LUI = (0x0F << 26),
65 OPC_DADDI = (0x18 << 26),
66 OPC_DADDIU = (0x19 << 26),
e37e863f 67 /* Jump and branches */
7a387fff
TS
68 OPC_J = (0x02 << 26),
69 OPC_JAL = (0x03 << 26),
70 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
71 OPC_BEQL = (0x14 << 26),
72 OPC_BNE = (0x05 << 26),
73 OPC_BNEL = (0x15 << 26),
74 OPC_BLEZ = (0x06 << 26),
75 OPC_BLEZL = (0x16 << 26),
76 OPC_BGTZ = (0x07 << 26),
77 OPC_BGTZL = (0x17 << 26),
78 OPC_JALX = (0x1D << 26), /* MIPS 16 only */
e37e863f 79 /* Load and stores */
7a387fff
TS
80 OPC_LDL = (0x1A << 26),
81 OPC_LDR = (0x1B << 26),
82 OPC_LB = (0x20 << 26),
83 OPC_LH = (0x21 << 26),
84 OPC_LWL = (0x22 << 26),
85 OPC_LW = (0x23 << 26),
86 OPC_LBU = (0x24 << 26),
87 OPC_LHU = (0x25 << 26),
88 OPC_LWR = (0x26 << 26),
89 OPC_LWU = (0x27 << 26),
90 OPC_SB = (0x28 << 26),
91 OPC_SH = (0x29 << 26),
92 OPC_SWL = (0x2A << 26),
93 OPC_SW = (0x2B << 26),
94 OPC_SDL = (0x2C << 26),
95 OPC_SDR = (0x2D << 26),
96 OPC_SWR = (0x2E << 26),
97 OPC_LL = (0x30 << 26),
98 OPC_LLD = (0x34 << 26),
99 OPC_LD = (0x37 << 26),
100 OPC_SC = (0x38 << 26),
101 OPC_SCD = (0x3C << 26),
102 OPC_SD = (0x3F << 26),
e37e863f 103 /* Floating point load/store */
7a387fff
TS
104 OPC_LWC1 = (0x31 << 26),
105 OPC_LWC2 = (0x32 << 26),
106 OPC_LDC1 = (0x35 << 26),
107 OPC_LDC2 = (0x36 << 26),
108 OPC_SWC1 = (0x39 << 26),
109 OPC_SWC2 = (0x3A << 26),
110 OPC_SDC1 = (0x3D << 26),
111 OPC_SDC2 = (0x3E << 26),
112 /* MDMX ASE specific */
113 OPC_MDMX = (0x1E << 26),
e37e863f 114 /* Cache and prefetch */
7a387fff
TS
115 OPC_CACHE = (0x2F << 26),
116 OPC_PREF = (0x33 << 26),
117 /* Reserved major opcode */
118 OPC_MAJOR3B_RESERVED = (0x3B << 26),
e37e863f
FB
119};
120
121/* MIPS special opcodes */
7a387fff
TS
122#define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
123
e37e863f
FB
124enum {
125 /* Shifts */
7a387fff 126 OPC_SLL = 0x00 | OPC_SPECIAL,
e37e863f
FB
127 /* NOP is SLL r0, r0, 0 */
128 /* SSNOP is SLL r0, r0, 1 */
7a387fff
TS
129 /* EHB is SLL r0, r0, 3 */
130 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
131 OPC_SRA = 0x03 | OPC_SPECIAL,
132 OPC_SLLV = 0x04 | OPC_SPECIAL,
e189e748 133 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
7a387fff
TS
134 OPC_SRAV = 0x07 | OPC_SPECIAL,
135 OPC_DSLLV = 0x14 | OPC_SPECIAL,
136 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
137 OPC_DSRAV = 0x17 | OPC_SPECIAL,
138 OPC_DSLL = 0x38 | OPC_SPECIAL,
139 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
140 OPC_DSRA = 0x3B | OPC_SPECIAL,
141 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
142 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
143 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
e37e863f 144 /* Multiplication / division */
7a387fff
TS
145 OPC_MULT = 0x18 | OPC_SPECIAL,
146 OPC_MULTU = 0x19 | OPC_SPECIAL,
147 OPC_DIV = 0x1A | OPC_SPECIAL,
148 OPC_DIVU = 0x1B | OPC_SPECIAL,
149 OPC_DMULT = 0x1C | OPC_SPECIAL,
150 OPC_DMULTU = 0x1D | OPC_SPECIAL,
151 OPC_DDIV = 0x1E | OPC_SPECIAL,
152 OPC_DDIVU = 0x1F | OPC_SPECIAL,
e37e863f 153 /* 2 registers arithmetic / logic */
7a387fff
TS
154 OPC_ADD = 0x20 | OPC_SPECIAL,
155 OPC_ADDU = 0x21 | OPC_SPECIAL,
156 OPC_SUB = 0x22 | OPC_SPECIAL,
157 OPC_SUBU = 0x23 | OPC_SPECIAL,
158 OPC_AND = 0x24 | OPC_SPECIAL,
159 OPC_OR = 0x25 | OPC_SPECIAL,
160 OPC_XOR = 0x26 | OPC_SPECIAL,
161 OPC_NOR = 0x27 | OPC_SPECIAL,
162 OPC_SLT = 0x2A | OPC_SPECIAL,
163 OPC_SLTU = 0x2B | OPC_SPECIAL,
164 OPC_DADD = 0x2C | OPC_SPECIAL,
165 OPC_DADDU = 0x2D | OPC_SPECIAL,
166 OPC_DSUB = 0x2E | OPC_SPECIAL,
167 OPC_DSUBU = 0x2F | OPC_SPECIAL,
e37e863f 168 /* Jumps */
7a387fff
TS
169 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
170 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
e37e863f 171 /* Traps */
7a387fff
TS
172 OPC_TGE = 0x30 | OPC_SPECIAL,
173 OPC_TGEU = 0x31 | OPC_SPECIAL,
174 OPC_TLT = 0x32 | OPC_SPECIAL,
175 OPC_TLTU = 0x33 | OPC_SPECIAL,
176 OPC_TEQ = 0x34 | OPC_SPECIAL,
177 OPC_TNE = 0x36 | OPC_SPECIAL,
e37e863f 178 /* HI / LO registers load & stores */
7a387fff
TS
179 OPC_MFHI = 0x10 | OPC_SPECIAL,
180 OPC_MTHI = 0x11 | OPC_SPECIAL,
181 OPC_MFLO = 0x12 | OPC_SPECIAL,
182 OPC_MTLO = 0x13 | OPC_SPECIAL,
e37e863f 183 /* Conditional moves */
7a387fff
TS
184 OPC_MOVZ = 0x0A | OPC_SPECIAL,
185 OPC_MOVN = 0x0B | OPC_SPECIAL,
e37e863f 186
7a387fff 187 OPC_MOVCI = 0x01 | OPC_SPECIAL,
e37e863f
FB
188
189 /* Special */
7a387fff
TS
190 OPC_PMON = 0x05 | OPC_SPECIAL, /* inofficial */
191 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
192 OPC_BREAK = 0x0D | OPC_SPECIAL,
193 OPC_SPIM = 0x0E | OPC_SPECIAL, /* inofficial */
194 OPC_SYNC = 0x0F | OPC_SPECIAL,
195
196 OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
197 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
198 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
199 OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
200 OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
201 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
202 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
203};
204
e9c71dd1
TS
205/* Multiplication variants of the vr54xx. */
206#define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
207
208enum {
209 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
210 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
211 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
212 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
213 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
214 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
215 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
216 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
217 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
218 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
219 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
220 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
221 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
222 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
223};
224
7a387fff
TS
225/* REGIMM (rt field) opcodes */
226#define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
227
228enum {
229 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
230 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
231 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
232 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
233 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
234 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
235 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
236 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
237 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
238 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
239 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
240 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
241 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
242 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
243 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
e37e863f
FB
244};
245
7a387fff
TS
246/* Special2 opcodes */
247#define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
248
e37e863f 249enum {
7a387fff
TS
250 /* Multiply & xxx operations */
251 OPC_MADD = 0x00 | OPC_SPECIAL2,
252 OPC_MADDU = 0x01 | OPC_SPECIAL2,
253 OPC_MUL = 0x02 | OPC_SPECIAL2,
254 OPC_MSUB = 0x04 | OPC_SPECIAL2,
255 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
e37e863f 256 /* Misc */
7a387fff
TS
257 OPC_CLZ = 0x20 | OPC_SPECIAL2,
258 OPC_CLO = 0x21 | OPC_SPECIAL2,
259 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
260 OPC_DCLO = 0x25 | OPC_SPECIAL2,
e37e863f 261 /* Special */
7a387fff
TS
262 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
263};
264
265/* Special3 opcodes */
266#define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
267
268enum {
269 OPC_EXT = 0x00 | OPC_SPECIAL3,
270 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
271 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
272 OPC_DEXT = 0x03 | OPC_SPECIAL3,
273 OPC_INS = 0x04 | OPC_SPECIAL3,
274 OPC_DINSM = 0x05 | OPC_SPECIAL3,
275 OPC_DINSU = 0x06 | OPC_SPECIAL3,
276 OPC_DINS = 0x07 | OPC_SPECIAL3,
ead9360e
TS
277 OPC_FORK = 0x08 | OPC_SPECIAL3,
278 OPC_YIELD = 0x09 | OPC_SPECIAL3,
7a387fff
TS
279 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
280 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
281 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
e37e863f
FB
282};
283
7a387fff
TS
284/* BSHFL opcodes */
285#define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
286
e37e863f 287enum {
7a387fff
TS
288 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
289 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
290 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
e37e863f
FB
291};
292
7a387fff
TS
293/* DBSHFL opcodes */
294#define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
295
e37e863f 296enum {
7a387fff
TS
297 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
298 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
e37e863f
FB
299};
300
7a387fff
TS
301/* Coprocessor 0 (rs field) */
302#define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
303
6ea83fed 304enum {
7a387fff
TS
305 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
306 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
307 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
308 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
ead9360e 309 OPC_MFTR = (0x08 << 21) | OPC_CP0,
7a387fff
TS
310 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
311 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
ead9360e 312 OPC_MTTR = (0x0C << 21) | OPC_CP0,
7a387fff
TS
313 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
314 OPC_C0 = (0x10 << 21) | OPC_CP0,
315 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
316 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
6ea83fed 317};
7a387fff
TS
318
319/* MFMC0 opcodes */
b48cfdff 320#define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
7a387fff
TS
321
322enum {
ead9360e
TS
323 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
324 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
325 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
326 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
7a387fff
TS
327 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
328 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
329};
330
331/* Coprocessor 0 (with rs == C0) */
332#define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
333
334enum {
335 OPC_TLBR = 0x01 | OPC_C0,
336 OPC_TLBWI = 0x02 | OPC_C0,
337 OPC_TLBWR = 0x06 | OPC_C0,
338 OPC_TLBP = 0x08 | OPC_C0,
339 OPC_RFE = 0x10 | OPC_C0,
340 OPC_ERET = 0x18 | OPC_C0,
341 OPC_DERET = 0x1F | OPC_C0,
342 OPC_WAIT = 0x20 | OPC_C0,
343};
344
345/* Coprocessor 1 (rs field) */
346#define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
347
348enum {
349 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
350 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
351 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
5a5012ec 352 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
7a387fff
TS
353 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
354 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
355 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
5a5012ec 356 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
7a387fff 357 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
5a5012ec
TS
358 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
359 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
7a387fff
TS
360 OPC_S_FMT = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */
361 OPC_D_FMT = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */
362 OPC_E_FMT = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */
363 OPC_Q_FMT = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */
364 OPC_W_FMT = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
365 OPC_L_FMT = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
5a5012ec 366 OPC_PS_FMT = (0x16 << 21) | OPC_CP1, /* 22: fmt=paired single fp */
7a387fff
TS
367};
368
5a5012ec
TS
369#define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
370#define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
371
7a387fff
TS
372enum {
373 OPC_BC1F = (0x00 << 16) | OPC_BC1,
374 OPC_BC1T = (0x01 << 16) | OPC_BC1,
375 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
376 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
377};
378
5a5012ec
TS
379enum {
380 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
381 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
382};
383
384enum {
385 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
386 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
387};
7a387fff
TS
388
389#define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
e0c84da7
TS
390
391enum {
392 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
393 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
394 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
395 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
396 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
397 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
398 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
399 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
400 OPC_BC2 = (0x08 << 21) | OPC_CP2,
401};
402
403#define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
404
405enum {
406 OPC_LWXC1 = 0x00 | OPC_CP3,
407 OPC_LDXC1 = 0x01 | OPC_CP3,
408 OPC_LUXC1 = 0x05 | OPC_CP3,
409 OPC_SWXC1 = 0x08 | OPC_CP3,
410 OPC_SDXC1 = 0x09 | OPC_CP3,
411 OPC_SUXC1 = 0x0D | OPC_CP3,
412 OPC_PREFX = 0x0F | OPC_CP3,
413 OPC_ALNV_PS = 0x1E | OPC_CP3,
414 OPC_MADD_S = 0x20 | OPC_CP3,
415 OPC_MADD_D = 0x21 | OPC_CP3,
416 OPC_MADD_PS = 0x26 | OPC_CP3,
417 OPC_MSUB_S = 0x28 | OPC_CP3,
418 OPC_MSUB_D = 0x29 | OPC_CP3,
419 OPC_MSUB_PS = 0x2E | OPC_CP3,
420 OPC_NMADD_S = 0x30 | OPC_CP3,
fbcc6828 421 OPC_NMADD_D = 0x31 | OPC_CP3,
e0c84da7
TS
422 OPC_NMADD_PS= 0x36 | OPC_CP3,
423 OPC_NMSUB_S = 0x38 | OPC_CP3,
424 OPC_NMSUB_D = 0x39 | OPC_CP3,
425 OPC_NMSUB_PS= 0x3E | OPC_CP3,
426};
427
39454628 428/* global register indices */
a7812ae4
PB
429static TCGv_ptr cpu_env;
430static TCGv cpu_gpr[32], cpu_PC;
4b2eb8d2 431static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
41db4607
AJ
432static TCGv cpu_dspctrl, btarget, bcond;
433static TCGv_i32 hflags;
a7812ae4 434static TCGv_i32 fpu_fcr0, fpu_fcr31;
aa0bf00b 435
2e70f6ef
PB
436#include "gen-icount.h"
437
a7812ae4
PB
438#define gen_helper_0i(name, arg) do { \
439 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
440 gen_helper_##name(helper_tmp); \
441 tcg_temp_free_i32(helper_tmp); \
442 } while(0)
be24bb4f 443
a7812ae4
PB
444#define gen_helper_1i(name, arg1, arg2) do { \
445 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
446 gen_helper_##name(arg1, helper_tmp); \
447 tcg_temp_free_i32(helper_tmp); \
448 } while(0)
be24bb4f 449
a7812ae4
PB
450#define gen_helper_2i(name, arg1, arg2, arg3) do { \
451 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
452 gen_helper_##name(arg1, arg2, helper_tmp); \
453 tcg_temp_free_i32(helper_tmp); \
454 } while(0)
be24bb4f 455
a7812ae4
PB
456#define gen_helper_3i(name, arg1, arg2, arg3, arg4) do { \
457 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
458 gen_helper_##name(arg1, arg2, arg3, helper_tmp); \
459 tcg_temp_free_i32(helper_tmp); \
460 } while(0)
c239529e 461
8e9ade68
TS
462typedef struct DisasContext {
463 struct TranslationBlock *tb;
464 target_ulong pc, saved_pc;
465 uint32_t opcode;
8e9ade68
TS
466 /* Routine used to access memory */
467 int mem_idx;
468 uint32_t hflags, saved_hflags;
469 int bstate;
470 target_ulong btarget;
471} DisasContext;
472
473enum {
474 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
d077b6f7 475 * exception condition */
8e9ade68
TS
476 BS_STOP = 1, /* We want to stop translation for any reason */
477 BS_BRANCH = 2, /* We reached a branch condition */
478 BS_EXCP = 3, /* We reached an exception condition */
479};
480
481static const char *regnames[] =
6af0bf9c
FB
482 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
483 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
484 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
485 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
486
4b2eb8d2
TS
487static const char *regnames_HI[] =
488 { "HI0", "HI1", "HI2", "HI3", };
489
490static const char *regnames_LO[] =
491 { "LO0", "LO1", "LO2", "LO3", };
492
493static const char *regnames_ACX[] =
494 { "ACX0", "ACX1", "ACX2", "ACX3", };
495
8e9ade68
TS
496static const char *fregnames[] =
497 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
498 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
499 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
500 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
958fb4a9 501
8e9ade68 502#ifdef MIPS_DEBUG_DISAS
93fcfe39
AL
503#define MIPS_DEBUG(fmt, args...) \
504 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
505 TARGET_FMT_lx ": %08x " fmt "\n", \
506 ctx->pc, ctx->opcode , ##args)
507#define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
8e9ade68
TS
508#else
509#define MIPS_DEBUG(fmt, args...) do { } while(0)
d12d51d5 510#define LOG_DISAS(...) do { } while (0)
8e9ade68 511#endif
958fb4a9 512
8e9ade68
TS
513#define MIPS_INVAL(op) \
514do { \
515 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
516 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
517} while (0)
ead9360e 518
8e9ade68
TS
519/* General purpose registers moves. */
520static inline void gen_load_gpr (TCGv t, int reg)
aaa9128a 521{
8e9ade68
TS
522 if (reg == 0)
523 tcg_gen_movi_tl(t, 0);
524 else
4b2eb8d2 525 tcg_gen_mov_tl(t, cpu_gpr[reg]);
aaa9128a
TS
526}
527
8e9ade68 528static inline void gen_store_gpr (TCGv t, int reg)
aaa9128a 529{
8e9ade68 530 if (reg != 0)
4b2eb8d2 531 tcg_gen_mov_tl(cpu_gpr[reg], t);
aaa9128a
TS
532}
533
b10fa3c9 534/* Moves to/from ACX register. */
4b2eb8d2 535static inline void gen_load_ACX (TCGv t, int reg)
893f9865 536{
4b2eb8d2 537 tcg_gen_mov_tl(t, cpu_ACX[reg]);
893f9865
TS
538}
539
4b2eb8d2 540static inline void gen_store_ACX (TCGv t, int reg)
893f9865 541{
4b2eb8d2 542 tcg_gen_mov_tl(cpu_ACX[reg], t);
893f9865
TS
543}
544
8e9ade68 545/* Moves to/from shadow registers. */
be24bb4f 546static inline void gen_load_srsgpr (int from, int to)
aaa9128a 547{
a7812ae4 548 TCGv r_tmp1 = tcg_temp_new();
be24bb4f
TS
549
550 if (from == 0)
551 tcg_gen_movi_tl(r_tmp1, 0);
8e9ade68 552 else {
a7812ae4
PB
553 TCGv_i32 r_tmp2 = tcg_temp_new_i32();
554 TCGv_ptr addr = tcg_temp_new_ptr();
aaa9128a 555
be24bb4f
TS
556 tcg_gen_ld_i32(r_tmp2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
557 tcg_gen_shri_i32(r_tmp2, r_tmp2, CP0SRSCtl_PSS);
558 tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xf);
559 tcg_gen_muli_i32(r_tmp2, r_tmp2, sizeof(target_ulong) * 32);
a7812ae4
PB
560 tcg_gen_ext_i32_ptr(addr, r_tmp2);
561 tcg_gen_add_ptr(addr, cpu_env, addr);
aaa9128a 562
a7812ae4
PB
563 tcg_gen_ld_tl(r_tmp1, addr, sizeof(target_ulong) * from);
564 tcg_temp_free_ptr(addr);
565 tcg_temp_free_i32(r_tmp2);
8e9ade68 566 }
be24bb4f
TS
567 gen_store_gpr(r_tmp1, to);
568 tcg_temp_free(r_tmp1);
aaa9128a
TS
569}
570
be24bb4f 571static inline void gen_store_srsgpr (int from, int to)
aaa9128a 572{
be24bb4f 573 if (to != 0) {
a7812ae4
PB
574 TCGv r_tmp1 = tcg_temp_new();
575 TCGv_i32 r_tmp2 = tcg_temp_new_i32();
576 TCGv_ptr addr = tcg_temp_new_ptr();
be24bb4f
TS
577
578 gen_load_gpr(r_tmp1, from);
579 tcg_gen_ld_i32(r_tmp2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
580 tcg_gen_shri_i32(r_tmp2, r_tmp2, CP0SRSCtl_PSS);
581 tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xf);
582 tcg_gen_muli_i32(r_tmp2, r_tmp2, sizeof(target_ulong) * 32);
a7812ae4
PB
583 tcg_gen_ext_i32_ptr(addr, r_tmp2);
584 tcg_gen_add_ptr(addr, cpu_env, addr);
be24bb4f 585
a7812ae4
PB
586 tcg_gen_st_tl(r_tmp1, addr, sizeof(target_ulong) * to);
587 tcg_temp_free_ptr(addr);
588 tcg_temp_free_i32(r_tmp2);
be24bb4f 589 tcg_temp_free(r_tmp1);
8e9ade68 590 }
aaa9128a
TS
591}
592
aaa9128a 593/* Floating point register moves. */
a7812ae4 594static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
aa0bf00b 595{
6d066274 596 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
6ea83fed
FB
597}
598
a7812ae4 599static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
aa0bf00b 600{
6d066274
AJ
601 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
602}
603
604static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
605{
606 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
607}
608
609static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
610{
611 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
aa0bf00b 612}
6ea83fed 613
a7812ae4 614static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 615{
f364515c 616 if (ctx->hflags & MIPS_HFLAG_F64) {
6d066274 617 tcg_gen_ld_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
f364515c 618 } else {
6d066274
AJ
619 TCGv_i32 t0 = tcg_temp_new_i32();
620 TCGv_i32 t1 = tcg_temp_new_i32();
621 gen_load_fpr32(t0, reg & ~1);
622 gen_load_fpr32(t1, reg | 1);
623 tcg_gen_concat_i32_i64(t, t0, t1);
624 tcg_temp_free_i32(t0);
625 tcg_temp_free_i32(t1);
aa0bf00b
TS
626 }
627}
6ea83fed 628
a7812ae4 629static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 630{
f364515c 631 if (ctx->hflags & MIPS_HFLAG_F64) {
6d066274 632 tcg_gen_st_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
f364515c 633 } else {
6d066274
AJ
634 TCGv_i64 t0 = tcg_temp_new_i64();
635 TCGv_i32 t1 = tcg_temp_new_i32();
636 tcg_gen_trunc_i64_i32(t1, t);
637 gen_store_fpr32(t1, reg & ~1);
638 tcg_gen_shri_i64(t0, t, 32);
639 tcg_gen_trunc_i64_i32(t1, t0);
640 gen_store_fpr32(t1, reg | 1);
641 tcg_temp_free_i32(t1);
642 tcg_temp_free_i64(t0);
aa0bf00b
TS
643 }
644}
6ea83fed 645
d94536f4 646static inline int get_fp_bit (int cc)
a16336e4 647{
d94536f4
AJ
648 if (cc)
649 return 24 + cc;
650 else
651 return 23;
a16336e4
TS
652}
653
a7812ae4
PB
654#define FOP_CONDS(type, fmt, bits) \
655static inline void gen_cmp ## type ## _ ## fmt(int n, TCGv_i##bits a, \
656 TCGv_i##bits b, int cc) \
b6d96bed 657{ \
a7812ae4
PB
658 switch (n) { \
659 case 0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, a, b, cc); break;\
660 case 1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, a, b, cc); break;\
661 case 2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, a, b, cc); break;\
662 case 3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, a, b, cc); break;\
663 case 4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, a, b, cc); break;\
664 case 5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, a, b, cc); break;\
665 case 6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, a, b, cc); break;\
666 case 7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, a, b, cc); break;\
667 case 8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, a, b, cc); break;\
668 case 9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, a, b, cc); break;\
669 case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, a, b, cc); break;\
670 case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, a, b, cc); break;\
671 case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, a, b, cc); break;\
672 case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, a, b, cc); break;\
673 case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, a, b, cc); break;\
674 case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, a, b, cc); break;\
675 default: abort(); \
676 } \
6ea83fed
FB
677}
678
a7812ae4
PB
679FOP_CONDS(, d, 64)
680FOP_CONDS(abs, d, 64)
681FOP_CONDS(, s, 32)
682FOP_CONDS(abs, s, 32)
683FOP_CONDS(, ps, 64)
684FOP_CONDS(abs, ps, 64)
5d0fc900 685#undef FOP_CONDS
6ea83fed 686
30898801 687/* Tests */
92e90443
AJ
688#define OP_COND(name, cond) \
689static inline void glue(gen_op_, name) (TCGv ret, TCGv t0, TCGv t1) \
690{ \
691 int l1 = gen_new_label(); \
692 int l2 = gen_new_label(); \
693 \
694 tcg_gen_brcond_tl(cond, t0, t1, l1); \
695 tcg_gen_movi_tl(ret, 0); \
696 tcg_gen_br(l2); \
697 gen_set_label(l1); \
698 tcg_gen_movi_tl(ret, 1); \
699 gen_set_label(l2); \
30898801
TS
700}
701OP_COND(eq, TCG_COND_EQ);
702OP_COND(ne, TCG_COND_NE);
703OP_COND(ge, TCG_COND_GE);
704OP_COND(geu, TCG_COND_GEU);
705OP_COND(lt, TCG_COND_LT);
706OP_COND(ltu, TCG_COND_LTU);
707#undef OP_COND
708
92e90443
AJ
709#define OP_CONDI(name, cond) \
710static inline void glue(gen_op_, name) (TCGv ret, TCGv t0, target_ulong val) \
711{ \
712 int l1 = gen_new_label(); \
713 int l2 = gen_new_label(); \
714 \
715 tcg_gen_brcondi_tl(cond, t0, val, l1); \
716 tcg_gen_movi_tl(ret, 0); \
717 tcg_gen_br(l2); \
718 gen_set_label(l1); \
719 tcg_gen_movi_tl(ret, 1); \
720 gen_set_label(l2); \
30898801
TS
721}
722OP_CONDI(lti, TCG_COND_LT);
723OP_CONDI(ltiu, TCG_COND_LTU);
724#undef OP_CONDI
725
726#define OP_CONDZ(name, cond) \
92e90443 727static inline void glue(gen_op_, name) (TCGv ret, TCGv t0) \
30898801
TS
728{ \
729 int l1 = gen_new_label(); \
730 int l2 = gen_new_label(); \
731 \
92e90443
AJ
732 tcg_gen_brcondi_tl(cond, t0, 0, l1); \
733 tcg_gen_movi_tl(ret, 0); \
30898801
TS
734 tcg_gen_br(l2); \
735 gen_set_label(l1); \
92e90443 736 tcg_gen_movi_tl(ret, 1); \
30898801
TS
737 gen_set_label(l2); \
738}
739OP_CONDZ(gez, TCG_COND_GE);
740OP_CONDZ(gtz, TCG_COND_GT);
741OP_CONDZ(lez, TCG_COND_LE);
742OP_CONDZ(ltz, TCG_COND_LT);
743#undef OP_CONDZ
744
8e9ade68
TS
745static inline void gen_save_pc(target_ulong pc)
746{
1eb75d4a 747 tcg_gen_movi_tl(cpu_PC, pc);
8e9ade68 748}
30898801 749
356265ae 750static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
6af0bf9c 751{
d12d51d5 752 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
6af0bf9c 753 if (do_save_pc && ctx->pc != ctx->saved_pc) {
9b9e4393 754 gen_save_pc(ctx->pc);
6af0bf9c
FB
755 ctx->saved_pc = ctx->pc;
756 }
757 if (ctx->hflags != ctx->saved_hflags) {
41db4607 758 tcg_gen_movi_i32(hflags, ctx->hflags);
6af0bf9c 759 ctx->saved_hflags = ctx->hflags;
5a5012ec
TS
760 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
761 case MIPS_HFLAG_BR:
5a5012ec
TS
762 break;
763 case MIPS_HFLAG_BC:
5a5012ec 764 case MIPS_HFLAG_BL:
5a5012ec 765 case MIPS_HFLAG_B:
d077b6f7 766 tcg_gen_movi_tl(btarget, ctx->btarget);
5a5012ec 767 break;
6af0bf9c
FB
768 }
769 }
770}
771
356265ae 772static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
5a5012ec 773{
fd4a04eb
TS
774 ctx->saved_hflags = ctx->hflags;
775 switch (ctx->hflags & MIPS_HFLAG_BMASK) {
776 case MIPS_HFLAG_BR:
fd4a04eb
TS
777 break;
778 case MIPS_HFLAG_BC:
779 case MIPS_HFLAG_BL:
39454628 780 case MIPS_HFLAG_B:
fd4a04eb 781 ctx->btarget = env->btarget;
fd4a04eb 782 break;
5a5012ec
TS
783 }
784}
785
356265ae 786static inline void
48d38ca5 787generate_exception_err (DisasContext *ctx, int excp, int err)
aaa9128a 788{
a7812ae4
PB
789 TCGv_i32 texcp = tcg_const_i32(excp);
790 TCGv_i32 terr = tcg_const_i32(err);
aaa9128a 791 save_cpu_state(ctx, 1);
a7812ae4
PB
792 gen_helper_raise_exception_err(texcp, terr);
793 tcg_temp_free_i32(terr);
794 tcg_temp_free_i32(texcp);
795 gen_helper_interrupt_restart();
aaa9128a
TS
796 tcg_gen_exit_tb(0);
797}
798
356265ae 799static inline void
48d38ca5 800generate_exception (DisasContext *ctx, int excp)
aaa9128a 801{
6af0bf9c 802 save_cpu_state(ctx, 1);
a7812ae4
PB
803 gen_helper_0i(raise_exception, excp);
804 gen_helper_interrupt_restart();
48d38ca5 805 tcg_gen_exit_tb(0);
6af0bf9c
FB
806}
807
48d38ca5 808/* Addresses computation */
d144d1d9 809static inline void gen_op_addr_add (DisasContext *ctx, TCGv t0, TCGv t1)
4ad40f36 810{
be24bb4f 811 tcg_gen_add_tl(t0, t0, t1);
48d38ca5
TS
812
813#if defined(TARGET_MIPS64)
814 /* For compatibility with 32-bit code, data reference in user mode
815 with Status_UX = 0 should be casted to 32-bit and sign extended.
816 See the MIPS64 PRA manual, section 4.10. */
2623c1ec
AJ
817 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
818 !(ctx->hflags & MIPS_HFLAG_UX)) {
be24bb4f 819 tcg_gen_ext32s_i64(t0, t0);
48d38ca5
TS
820 }
821#endif
4ad40f36
FB
822}
823
356265ae 824static inline void check_cp0_enabled(DisasContext *ctx)
387a8fe5 825{
fe253235 826 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
387a8fe5
TS
827 generate_exception_err(ctx, EXCP_CpU, 1);
828}
829
356265ae 830static inline void check_cp1_enabled(DisasContext *ctx)
5e755519 831{
fe253235 832 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
5e755519
TS
833 generate_exception_err(ctx, EXCP_CpU, 1);
834}
835
b8aa4598
TS
836/* Verify that the processor is running with COP1X instructions enabled.
837 This is associated with the nabla symbol in the MIPS32 and MIPS64
838 opcode tables. */
839
356265ae 840static inline void check_cop1x(DisasContext *ctx)
b8aa4598
TS
841{
842 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
843 generate_exception(ctx, EXCP_RI);
844}
845
846/* Verify that the processor is running with 64-bit floating-point
847 operations enabled. */
848
356265ae 849static inline void check_cp1_64bitmode(DisasContext *ctx)
5e755519 850{
b8aa4598 851 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
5e755519
TS
852 generate_exception(ctx, EXCP_RI);
853}
854
855/*
856 * Verify if floating point register is valid; an operation is not defined
857 * if bit 0 of any register specification is set and the FR bit in the
858 * Status register equals zero, since the register numbers specify an
859 * even-odd pair of adjacent coprocessor general registers. When the FR bit
860 * in the Status register equals one, both even and odd register numbers
861 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
862 *
863 * Multiple 64 bit wide registers can be checked by calling
864 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
865 */
356265ae 866static inline void check_cp1_registers(DisasContext *ctx, int regs)
5e755519 867{
fe253235 868 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
5e755519
TS
869 generate_exception(ctx, EXCP_RI);
870}
871
3a95e3a7 872/* This code generates a "reserved instruction" exception if the
e189e748 873 CPU does not support the instruction set corresponding to flags. */
356265ae 874static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
3a95e3a7 875{
e189e748 876 if (unlikely(!(env->insn_flags & flags)))
3a95e3a7
TS
877 generate_exception(ctx, EXCP_RI);
878}
879
e189e748
TS
880/* This code generates a "reserved instruction" exception if 64-bit
881 instructions are not enabled. */
356265ae 882static inline void check_mips_64(DisasContext *ctx)
e189e748 883{
fe253235 884 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
e189e748
TS
885 generate_exception(ctx, EXCP_RI);
886}
887
958fb4a9 888/* load/store instructions. */
aaa9128a 889#define OP_LD(insn,fname) \
356265ae 890static inline void op_ldst_##insn(TCGv t0, DisasContext *ctx) \
aaa9128a 891{ \
be24bb4f 892 tcg_gen_qemu_##fname(t0, t0, ctx->mem_idx); \
aaa9128a
TS
893}
894OP_LD(lb,ld8s);
895OP_LD(lbu,ld8u);
896OP_LD(lh,ld16s);
897OP_LD(lhu,ld16u);
898OP_LD(lw,ld32s);
899#if defined(TARGET_MIPS64)
900OP_LD(lwu,ld32u);
901OP_LD(ld,ld64);
902#endif
903#undef OP_LD
904
905#define OP_ST(insn,fname) \
356265ae 906static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \
aaa9128a 907{ \
be24bb4f 908 tcg_gen_qemu_##fname(t1, t0, ctx->mem_idx); \
aaa9128a
TS
909}
910OP_ST(sb,st8);
911OP_ST(sh,st16);
912OP_ST(sw,st32);
913#if defined(TARGET_MIPS64)
914OP_ST(sd,st64);
915#endif
916#undef OP_ST
917
918#define OP_LD_ATOMIC(insn,fname) \
356265ae 919static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \
aaa9128a 920{ \
be24bb4f
TS
921 tcg_gen_mov_tl(t1, t0); \
922 tcg_gen_qemu_##fname(t0, t0, ctx->mem_idx); \
923 tcg_gen_st_tl(t1, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
aaa9128a
TS
924}
925OP_LD_ATOMIC(ll,ld32s);
926#if defined(TARGET_MIPS64)
927OP_LD_ATOMIC(lld,ld64);
928#endif
929#undef OP_LD_ATOMIC
930
931#define OP_ST_ATOMIC(insn,fname,almask) \
356265ae 932static inline void op_ldst_##insn(TCGv t0, TCGv t1, DisasContext *ctx) \
aaa9128a 933{ \
a7812ae4 934 TCGv r_tmp = tcg_temp_local_new(); \
aaa9128a
TS
935 int l1 = gen_new_label(); \
936 int l2 = gen_new_label(); \
937 int l3 = gen_new_label(); \
938 \
be24bb4f 939 tcg_gen_andi_tl(r_tmp, t0, almask); \
cb63669a 940 tcg_gen_brcondi_tl(TCG_COND_EQ, r_tmp, 0, l1); \
be24bb4f 941 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
f0b3f3ae 942 generate_exception(ctx, EXCP_AdES); \
aaa9128a
TS
943 gen_set_label(l1); \
944 tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
be24bb4f 945 tcg_gen_brcond_tl(TCG_COND_NE, t0, r_tmp, l2); \
be24bb4f
TS
946 tcg_gen_qemu_##fname(t1, t0, ctx->mem_idx); \
947 tcg_gen_movi_tl(t0, 1); \
aaa9128a
TS
948 tcg_gen_br(l3); \
949 gen_set_label(l2); \
be24bb4f 950 tcg_gen_movi_tl(t0, 0); \
aaa9128a 951 gen_set_label(l3); \
c24135ff 952 tcg_temp_free(r_tmp); \
aaa9128a
TS
953}
954OP_ST_ATOMIC(sc,st32,0x3);
955#if defined(TARGET_MIPS64)
956OP_ST_ATOMIC(scd,st64,0x7);
957#endif
958#undef OP_ST_ATOMIC
959
6af0bf9c 960/* Load and store */
7a387fff 961static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
6af0bf9c
FB
962 int base, int16_t offset)
963{
923617a3 964 const char *opn = "ldst";
a7812ae4
PB
965 TCGv t0 = tcg_temp_local_new();
966 TCGv t1 = tcg_temp_local_new();
6af0bf9c
FB
967
968 if (base == 0) {
78723684 969 tcg_gen_movi_tl(t0, offset);
6af0bf9c 970 } else if (offset == 0) {
78723684 971 gen_load_gpr(t0, base);
6af0bf9c 972 } else {
e9203484
AJ
973 tcg_gen_movi_tl(t0, offset);
974 gen_op_addr_add(ctx, t0, cpu_gpr[base]);
6af0bf9c
FB
975 }
976 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 977 memory access. */
6af0bf9c 978 switch (opc) {
d26bc211 979#if defined(TARGET_MIPS64)
6e473128 980 case OPC_LWU:
78723684
TS
981 op_ldst_lwu(t0, ctx);
982 gen_store_gpr(t0, rt);
6e473128
TS
983 opn = "lwu";
984 break;
6af0bf9c 985 case OPC_LD:
78723684
TS
986 op_ldst_ld(t0, ctx);
987 gen_store_gpr(t0, rt);
6af0bf9c
FB
988 opn = "ld";
989 break;
7a387fff 990 case OPC_LLD:
78723684
TS
991 op_ldst_lld(t0, t1, ctx);
992 gen_store_gpr(t0, rt);
7a387fff
TS
993 opn = "lld";
994 break;
6af0bf9c 995 case OPC_SD:
78723684
TS
996 gen_load_gpr(t1, rt);
997 op_ldst_sd(t0, t1, ctx);
6af0bf9c
FB
998 opn = "sd";
999 break;
7a387fff 1000 case OPC_SCD:
62c5609a 1001 save_cpu_state(ctx, 1);
78723684
TS
1002 gen_load_gpr(t1, rt);
1003 op_ldst_scd(t0, t1, ctx);
1004 gen_store_gpr(t0, rt);
7a387fff
TS
1005 opn = "scd";
1006 break;
6af0bf9c 1007 case OPC_LDL:
c8c2227e 1008 save_cpu_state(ctx, 1);
78723684 1009 gen_load_gpr(t1, rt);
a7812ae4 1010 gen_helper_3i(ldl, t1, t0, t1, ctx->mem_idx);
78723684 1011 gen_store_gpr(t1, rt);
6af0bf9c
FB
1012 opn = "ldl";
1013 break;
1014 case OPC_SDL:
c8c2227e 1015 save_cpu_state(ctx, 1);
78723684 1016 gen_load_gpr(t1, rt);
a7812ae4 1017 gen_helper_2i(sdl, t0, t1, ctx->mem_idx);
6af0bf9c
FB
1018 opn = "sdl";
1019 break;
1020 case OPC_LDR:
c8c2227e 1021 save_cpu_state(ctx, 1);
78723684 1022 gen_load_gpr(t1, rt);
a7812ae4 1023 gen_helper_3i(ldr, t1, t0, t1, ctx->mem_idx);
78723684 1024 gen_store_gpr(t1, rt);
6af0bf9c
FB
1025 opn = "ldr";
1026 break;
1027 case OPC_SDR:
c8c2227e 1028 save_cpu_state(ctx, 1);
78723684 1029 gen_load_gpr(t1, rt);
a7812ae4 1030 gen_helper_2i(sdr, t0, t1, ctx->mem_idx);
6af0bf9c
FB
1031 opn = "sdr";
1032 break;
1033#endif
1034 case OPC_LW:
78723684
TS
1035 op_ldst_lw(t0, ctx);
1036 gen_store_gpr(t0, rt);
6af0bf9c
FB
1037 opn = "lw";
1038 break;
1039 case OPC_SW:
78723684
TS
1040 gen_load_gpr(t1, rt);
1041 op_ldst_sw(t0, t1, ctx);
6af0bf9c
FB
1042 opn = "sw";
1043 break;
1044 case OPC_LH:
78723684
TS
1045 op_ldst_lh(t0, ctx);
1046 gen_store_gpr(t0, rt);
6af0bf9c
FB
1047 opn = "lh";
1048 break;
1049 case OPC_SH:
78723684
TS
1050 gen_load_gpr(t1, rt);
1051 op_ldst_sh(t0, t1, ctx);
6af0bf9c
FB
1052 opn = "sh";
1053 break;
1054 case OPC_LHU:
78723684
TS
1055 op_ldst_lhu(t0, ctx);
1056 gen_store_gpr(t0, rt);
6af0bf9c
FB
1057 opn = "lhu";
1058 break;
1059 case OPC_LB:
78723684
TS
1060 op_ldst_lb(t0, ctx);
1061 gen_store_gpr(t0, rt);
6af0bf9c
FB
1062 opn = "lb";
1063 break;
1064 case OPC_SB:
78723684
TS
1065 gen_load_gpr(t1, rt);
1066 op_ldst_sb(t0, t1, ctx);
6af0bf9c
FB
1067 opn = "sb";
1068 break;
1069 case OPC_LBU:
78723684
TS
1070 op_ldst_lbu(t0, ctx);
1071 gen_store_gpr(t0, rt);
6af0bf9c
FB
1072 opn = "lbu";
1073 break;
1074 case OPC_LWL:
c8c2227e 1075 save_cpu_state(ctx, 1);
6958549d 1076 gen_load_gpr(t1, rt);
a7812ae4 1077 gen_helper_3i(lwl, t1, t0, t1, ctx->mem_idx);
78723684 1078 gen_store_gpr(t1, rt);
6af0bf9c
FB
1079 opn = "lwl";
1080 break;
1081 case OPC_SWL:
c8c2227e 1082 save_cpu_state(ctx, 1);
78723684 1083 gen_load_gpr(t1, rt);
a7812ae4 1084 gen_helper_2i(swl, t0, t1, ctx->mem_idx);
6af0bf9c
FB
1085 opn = "swr";
1086 break;
1087 case OPC_LWR:
c8c2227e 1088 save_cpu_state(ctx, 1);
6958549d 1089 gen_load_gpr(t1, rt);
a7812ae4 1090 gen_helper_3i(lwr, t1, t0, t1, ctx->mem_idx);
78723684 1091 gen_store_gpr(t1, rt);
6af0bf9c
FB
1092 opn = "lwr";
1093 break;
1094 case OPC_SWR:
c8c2227e 1095 save_cpu_state(ctx, 1);
78723684 1096 gen_load_gpr(t1, rt);
a7812ae4 1097 gen_helper_2i(swr, t0, t1, ctx->mem_idx);
6af0bf9c
FB
1098 opn = "swr";
1099 break;
1100 case OPC_LL:
78723684
TS
1101 op_ldst_ll(t0, t1, ctx);
1102 gen_store_gpr(t0, rt);
6af0bf9c
FB
1103 opn = "ll";
1104 break;
1105 case OPC_SC:
62c5609a 1106 save_cpu_state(ctx, 1);
78723684
TS
1107 gen_load_gpr(t1, rt);
1108 op_ldst_sc(t0, t1, ctx);
1109 gen_store_gpr(t0, rt);
6af0bf9c
FB
1110 opn = "sc";
1111 break;
1112 default:
923617a3 1113 MIPS_INVAL(opn);
6af0bf9c 1114 generate_exception(ctx, EXCP_RI);
78723684 1115 goto out;
6af0bf9c
FB
1116 }
1117 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
78723684
TS
1118 out:
1119 tcg_temp_free(t0);
1120 tcg_temp_free(t1);
6af0bf9c
FB
1121}
1122
6ea83fed 1123/* Load and store */
7a387fff 1124static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
356265ae 1125 int base, int16_t offset)
6ea83fed 1126{
923617a3 1127 const char *opn = "flt_ldst";
a7812ae4 1128 TCGv t0 = tcg_temp_local_new();
6ea83fed
FB
1129
1130 if (base == 0) {
78723684 1131 tcg_gen_movi_tl(t0, offset);
6ea83fed 1132 } else if (offset == 0) {
78723684 1133 gen_load_gpr(t0, base);
6ea83fed 1134 } else {
e9203484
AJ
1135 tcg_gen_movi_tl(t0, offset);
1136 gen_op_addr_add(ctx, t0, cpu_gpr[base]);
6ea83fed
FB
1137 }
1138 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 1139 memory access. */
6ea83fed
FB
1140 switch (opc) {
1141 case OPC_LWC1:
b6d96bed 1142 {
a7812ae4
PB
1143 TCGv_i32 fp0 = tcg_temp_new_i32();
1144 TCGv t1 = tcg_temp_new();
b6d96bed 1145
a7812ae4
PB
1146 tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx);
1147 tcg_gen_trunc_tl_i32(fp0, t1);
b6d96bed 1148 gen_store_fpr32(fp0, ft);
a7812ae4
PB
1149 tcg_temp_free(t1);
1150 tcg_temp_free_i32(fp0);
b6d96bed 1151 }
6ea83fed
FB
1152 opn = "lwc1";
1153 break;
1154 case OPC_SWC1:
b6d96bed 1155 {
a7812ae4
PB
1156 TCGv_i32 fp0 = tcg_temp_new_i32();
1157 TCGv t1 = tcg_temp_new();
b6d96bed
TS
1158
1159 gen_load_fpr32(fp0, ft);
a7812ae4
PB
1160 tcg_gen_extu_i32_tl(t1, fp0);
1161 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1162 tcg_temp_free(t1);
1163 tcg_temp_free_i32(fp0);
b6d96bed 1164 }
6ea83fed
FB
1165 opn = "swc1";
1166 break;
1167 case OPC_LDC1:
b6d96bed 1168 {
a7812ae4 1169 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
1170
1171 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1172 gen_store_fpr64(ctx, fp0, ft);
a7812ae4 1173 tcg_temp_free_i64(fp0);
b6d96bed 1174 }
6ea83fed
FB
1175 opn = "ldc1";
1176 break;
1177 case OPC_SDC1:
b6d96bed 1178 {
a7812ae4 1179 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
1180
1181 gen_load_fpr64(ctx, fp0, ft);
1182 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 1183 tcg_temp_free_i64(fp0);
b6d96bed 1184 }
6ea83fed
FB
1185 opn = "sdc1";
1186 break;
1187 default:
923617a3 1188 MIPS_INVAL(opn);
e397ee33 1189 generate_exception(ctx, EXCP_RI);
78723684 1190 goto out;
6ea83fed
FB
1191 }
1192 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
78723684
TS
1193 out:
1194 tcg_temp_free(t0);
6ea83fed 1195}
6ea83fed 1196
6af0bf9c 1197/* Arithmetic with immediate operand */
e189e748
TS
1198static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1199 int rt, int rs, int16_t imm)
6af0bf9c 1200{
f469b9db 1201 target_ulong uimm;
923617a3 1202 const char *opn = "imm arith";
a7812ae4 1203 TCGv t0 = tcg_temp_local_new();
6af0bf9c 1204
7a387fff 1205 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
ead9360e
TS
1206 /* If no destination, treat it as a NOP.
1207 For addi, we must generate the overflow exception when needed. */
6af0bf9c 1208 MIPS_DEBUG("NOP");
78723684 1209 goto out;
6af0bf9c 1210 }
5a63bcb2
TS
1211 uimm = (uint16_t)imm;
1212 switch (opc) {
1213 case OPC_ADDI:
1214 case OPC_ADDIU:
d26bc211 1215#if defined(TARGET_MIPS64)
5a63bcb2
TS
1216 case OPC_DADDI:
1217 case OPC_DADDIU:
1218#endif
1219 case OPC_SLTI:
1220 case OPC_SLTIU:
f469b9db 1221 uimm = (target_long)imm; /* Sign extend to 32/64 bits */
5a63bcb2
TS
1222 /* Fall through. */
1223 case OPC_ANDI:
1224 case OPC_ORI:
1225 case OPC_XORI:
78723684 1226 gen_load_gpr(t0, rs);
5a63bcb2
TS
1227 break;
1228 case OPC_LUI:
78723684 1229 tcg_gen_movi_tl(t0, imm << 16);
5a63bcb2
TS
1230 break;
1231 case OPC_SLL:
1232 case OPC_SRA:
1233 case OPC_SRL:
d26bc211 1234#if defined(TARGET_MIPS64)
5a63bcb2
TS
1235 case OPC_DSLL:
1236 case OPC_DSRA:
1237 case OPC_DSRL:
1238 case OPC_DSLL32:
1239 case OPC_DSRA32:
1240 case OPC_DSRL32:
1241#endif
1242 uimm &= 0x1f;
78723684 1243 gen_load_gpr(t0, rs);
5a63bcb2 1244 break;
6af0bf9c
FB
1245 }
1246 switch (opc) {
1247 case OPC_ADDI:
48d38ca5 1248 {
a7812ae4
PB
1249 TCGv r_tmp1 = tcg_temp_new();
1250 TCGv r_tmp2 = tcg_temp_new();
48d38ca5
TS
1251 int l1 = gen_new_label();
1252
1253 save_cpu_state(ctx, 1);
78723684
TS
1254 tcg_gen_ext32s_tl(r_tmp1, t0);
1255 tcg_gen_addi_tl(t0, r_tmp1, uimm);
48d38ca5 1256
507563e8 1257 tcg_gen_xori_tl(r_tmp1, r_tmp1, ~uimm);
78723684 1258 tcg_gen_xori_tl(r_tmp2, t0, uimm);
48d38ca5 1259 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
4f57689a 1260 tcg_temp_free(r_tmp2);
507563e8 1261 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
48d38ca5
TS
1262 /* operands of same sign, result different sign */
1263 generate_exception(ctx, EXCP_OVERFLOW);
1264 gen_set_label(l1);
507563e8 1265 tcg_temp_free(r_tmp1);
48d38ca5 1266
78723684 1267 tcg_gen_ext32s_tl(t0, t0);
48d38ca5 1268 }
6af0bf9c
FB
1269 opn = "addi";
1270 break;
1271 case OPC_ADDIU:
78723684
TS
1272 tcg_gen_addi_tl(t0, t0, uimm);
1273 tcg_gen_ext32s_tl(t0, t0);
6af0bf9c
FB
1274 opn = "addiu";
1275 break;
d26bc211 1276#if defined(TARGET_MIPS64)
7a387fff 1277 case OPC_DADDI:
48d38ca5 1278 {
a7812ae4
PB
1279 TCGv r_tmp1 = tcg_temp_new();
1280 TCGv r_tmp2 = tcg_temp_new();
48d38ca5
TS
1281 int l1 = gen_new_label();
1282
1283 save_cpu_state(ctx, 1);
78723684
TS
1284 tcg_gen_mov_tl(r_tmp1, t0);
1285 tcg_gen_addi_tl(t0, t0, uimm);
48d38ca5 1286
507563e8 1287 tcg_gen_xori_tl(r_tmp1, r_tmp1, ~uimm);
78723684 1288 tcg_gen_xori_tl(r_tmp2, t0, uimm);
48d38ca5 1289 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
4f57689a 1290 tcg_temp_free(r_tmp2);
507563e8 1291 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
48d38ca5
TS
1292 /* operands of same sign, result different sign */
1293 generate_exception(ctx, EXCP_OVERFLOW);
1294 gen_set_label(l1);
507563e8 1295 tcg_temp_free(r_tmp1);
48d38ca5 1296 }
7a387fff
TS
1297 opn = "daddi";
1298 break;
1299 case OPC_DADDIU:
78723684 1300 tcg_gen_addi_tl(t0, t0, uimm);
7a387fff
TS
1301 opn = "daddiu";
1302 break;
1303#endif
6af0bf9c 1304 case OPC_SLTI:
92e90443 1305 gen_op_lti(t0, t0, uimm);
6af0bf9c
FB
1306 opn = "slti";
1307 break;
1308 case OPC_SLTIU:
92e90443 1309 gen_op_ltiu(t0, t0, uimm);
6af0bf9c
FB
1310 opn = "sltiu";
1311 break;
1312 case OPC_ANDI:
78723684 1313 tcg_gen_andi_tl(t0, t0, uimm);
6af0bf9c
FB
1314 opn = "andi";
1315 break;
1316 case OPC_ORI:
78723684 1317 tcg_gen_ori_tl(t0, t0, uimm);
6af0bf9c
FB
1318 opn = "ori";
1319 break;
1320 case OPC_XORI:
78723684 1321 tcg_gen_xori_tl(t0, t0, uimm);
6af0bf9c
FB
1322 opn = "xori";
1323 break;
1324 case OPC_LUI:
1325 opn = "lui";
1326 break;
1327 case OPC_SLL:
78723684
TS
1328 tcg_gen_shli_tl(t0, t0, uimm);
1329 tcg_gen_ext32s_tl(t0, t0);
6af0bf9c
FB
1330 opn = "sll";
1331 break;
1332 case OPC_SRA:
78723684
TS
1333 tcg_gen_ext32s_tl(t0, t0);
1334 tcg_gen_sari_tl(t0, t0, uimm);
6af0bf9c
FB
1335 opn = "sra";
1336 break;
1337 case OPC_SRL:
5a63bcb2
TS
1338 switch ((ctx->opcode >> 21) & 0x1f) {
1339 case 0:
507563e8
AJ
1340 if (uimm != 0) {
1341 tcg_gen_ext32u_tl(t0, t0);
1342 tcg_gen_shri_tl(t0, t0, uimm);
1343 } else {
1344 tcg_gen_ext32s_tl(t0, t0);
1345 }
7a387fff 1346 opn = "srl";
5a63bcb2
TS
1347 break;
1348 case 1:
e189e748
TS
1349 /* rotr is decoded as srl on non-R2 CPUs */
1350 if (env->insn_flags & ISA_MIPS32R2) {
48d38ca5 1351 if (uimm != 0) {
a7812ae4 1352 TCGv_i32 r_tmp1 = tcg_temp_new_i32();
48d38ca5 1353
78723684 1354 tcg_gen_trunc_tl_i32(r_tmp1, t0);
e00fcff7 1355 tcg_gen_rotri_i32(r_tmp1, r_tmp1, uimm);
78723684 1356 tcg_gen_ext_i32_tl(t0, r_tmp1);
a7812ae4 1357 tcg_temp_free_i32(r_tmp1);
48d38ca5 1358 }
e189e748
TS
1359 opn = "rotr";
1360 } else {
507563e8
AJ
1361 if (uimm != 0) {
1362 tcg_gen_ext32u_tl(t0, t0);
1363 tcg_gen_shri_tl(t0, t0, uimm);
1364 } else {
1365 tcg_gen_ext32s_tl(t0, t0);
1366 }
e189e748
TS
1367 opn = "srl";
1368 }
5a63bcb2
TS
1369 break;
1370 default:
1371 MIPS_INVAL("invalid srl flag");
1372 generate_exception(ctx, EXCP_RI);
1373 break;
1374 }
7a387fff 1375 break;
d26bc211 1376#if defined(TARGET_MIPS64)
7a387fff 1377 case OPC_DSLL:
78723684 1378 tcg_gen_shli_tl(t0, t0, uimm);
7a387fff
TS
1379 opn = "dsll";
1380 break;
1381 case OPC_DSRA:
78723684 1382 tcg_gen_sari_tl(t0, t0, uimm);
7a387fff
TS
1383 opn = "dsra";
1384 break;
1385 case OPC_DSRL:
5a63bcb2
TS
1386 switch ((ctx->opcode >> 21) & 0x1f) {
1387 case 0:
78723684 1388 tcg_gen_shri_tl(t0, t0, uimm);
7a387fff 1389 opn = "dsrl";
5a63bcb2
TS
1390 break;
1391 case 1:
e189e748
TS
1392 /* drotr is decoded as dsrl on non-R2 CPUs */
1393 if (env->insn_flags & ISA_MIPS32R2) {
48d38ca5 1394 if (uimm != 0) {
e00fcff7 1395 tcg_gen_rotri_tl(t0, t0, uimm);
48d38ca5 1396 }
e189e748
TS
1397 opn = "drotr";
1398 } else {
78723684 1399 tcg_gen_shri_tl(t0, t0, uimm);
e189e748
TS
1400 opn = "dsrl";
1401 }
5a63bcb2
TS
1402 break;
1403 default:
1404 MIPS_INVAL("invalid dsrl flag");
1405 generate_exception(ctx, EXCP_RI);
1406 break;
1407 }
7a387fff
TS
1408 break;
1409 case OPC_DSLL32:
78723684 1410 tcg_gen_shli_tl(t0, t0, uimm + 32);
7a387fff
TS
1411 opn = "dsll32";
1412 break;
1413 case OPC_DSRA32:
78723684 1414 tcg_gen_sari_tl(t0, t0, uimm + 32);
7a387fff
TS
1415 opn = "dsra32";
1416 break;
1417 case OPC_DSRL32:
5a63bcb2
TS
1418 switch ((ctx->opcode >> 21) & 0x1f) {
1419 case 0:
78723684 1420 tcg_gen_shri_tl(t0, t0, uimm + 32);
7a387fff 1421 opn = "dsrl32";
5a63bcb2
TS
1422 break;
1423 case 1:
e189e748
TS
1424 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
1425 if (env->insn_flags & ISA_MIPS32R2) {
e00fcff7 1426 tcg_gen_rotri_tl(t0, t0, uimm + 32);
e189e748
TS
1427 opn = "drotr32";
1428 } else {
78723684 1429 tcg_gen_shri_tl(t0, t0, uimm + 32);
e189e748
TS
1430 opn = "dsrl32";
1431 }
5a63bcb2
TS
1432 break;
1433 default:
1434 MIPS_INVAL("invalid dsrl32 flag");
1435 generate_exception(ctx, EXCP_RI);
1436 break;
1437 }
6af0bf9c 1438 break;
7a387fff 1439#endif
6af0bf9c 1440 default:
923617a3 1441 MIPS_INVAL(opn);
6af0bf9c 1442 generate_exception(ctx, EXCP_RI);
78723684 1443 goto out;
6af0bf9c 1444 }
78723684 1445 gen_store_gpr(t0, rt);
93b12ccc 1446 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
78723684
TS
1447 out:
1448 tcg_temp_free(t0);
6af0bf9c
FB
1449}
1450
1451/* Arithmetic */
e189e748 1452static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
1453 int rd, int rs, int rt)
1454{
923617a3 1455 const char *opn = "arith";
a7812ae4
PB
1456 TCGv t0 = tcg_temp_local_new();
1457 TCGv t1 = tcg_temp_local_new();
6af0bf9c 1458
7a387fff
TS
1459 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1460 && opc != OPC_DADD && opc != OPC_DSUB) {
ead9360e
TS
1461 /* If no destination, treat it as a NOP.
1462 For add & sub, we must generate the overflow exception when needed. */
6af0bf9c 1463 MIPS_DEBUG("NOP");
78723684 1464 goto out;
6af0bf9c 1465 }
78723684 1466 gen_load_gpr(t0, rs);
185f0762
TS
1467 /* Specialcase the conventional move operation. */
1468 if (rt == 0 && (opc == OPC_ADDU || opc == OPC_DADDU
1469 || opc == OPC_SUBU || opc == OPC_DSUBU)) {
78723684
TS
1470 gen_store_gpr(t0, rd);
1471 goto out;
185f0762 1472 }
78723684 1473 gen_load_gpr(t1, rt);
6af0bf9c
FB
1474 switch (opc) {
1475 case OPC_ADD:
48d38ca5 1476 {
a7812ae4
PB
1477 TCGv r_tmp1 = tcg_temp_new();
1478 TCGv r_tmp2 = tcg_temp_new();
48d38ca5
TS
1479 int l1 = gen_new_label();
1480
1481 save_cpu_state(ctx, 1);
78723684
TS
1482 tcg_gen_ext32s_tl(r_tmp1, t0);
1483 tcg_gen_ext32s_tl(r_tmp2, t1);
1484 tcg_gen_add_tl(t0, r_tmp1, r_tmp2);
48d38ca5 1485
78723684 1486 tcg_gen_xor_tl(r_tmp1, r_tmp1, t1);
48d38ca5 1487 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
78723684 1488 tcg_gen_xor_tl(r_tmp2, t0, t1);
48d38ca5 1489 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
4f57689a 1490 tcg_temp_free(r_tmp2);
507563e8 1491 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
48d38ca5
TS
1492 /* operands of same sign, result different sign */
1493 generate_exception(ctx, EXCP_OVERFLOW);
1494 gen_set_label(l1);
507563e8 1495 tcg_temp_free(r_tmp1);
48d38ca5 1496
78723684 1497 tcg_gen_ext32s_tl(t0, t0);
48d38ca5 1498 }
6af0bf9c
FB
1499 opn = "add";
1500 break;
1501 case OPC_ADDU:
78723684
TS
1502 tcg_gen_add_tl(t0, t0, t1);
1503 tcg_gen_ext32s_tl(t0, t0);
6af0bf9c
FB
1504 opn = "addu";
1505 break;
1506 case OPC_SUB:
48d38ca5 1507 {
a7812ae4
PB
1508 TCGv r_tmp1 = tcg_temp_new();
1509 TCGv r_tmp2 = tcg_temp_new();
48d38ca5
TS
1510 int l1 = gen_new_label();
1511
1512 save_cpu_state(ctx, 1);
78723684
TS
1513 tcg_gen_ext32s_tl(r_tmp1, t0);
1514 tcg_gen_ext32s_tl(r_tmp2, t1);
1515 tcg_gen_sub_tl(t0, r_tmp1, r_tmp2);
48d38ca5 1516
78723684
TS
1517 tcg_gen_xor_tl(r_tmp2, r_tmp1, t1);
1518 tcg_gen_xor_tl(r_tmp1, r_tmp1, t0);
48d38ca5 1519 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
4f57689a 1520 tcg_temp_free(r_tmp2);
507563e8 1521 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
48d38ca5
TS
1522 /* operands of different sign, first operand and result different sign */
1523 generate_exception(ctx, EXCP_OVERFLOW);
1524 gen_set_label(l1);
507563e8 1525 tcg_temp_free(r_tmp1);
48d38ca5 1526
78723684 1527 tcg_gen_ext32s_tl(t0, t0);
48d38ca5 1528 }
6af0bf9c
FB
1529 opn = "sub";
1530 break;
1531 case OPC_SUBU:
78723684
TS
1532 tcg_gen_sub_tl(t0, t0, t1);
1533 tcg_gen_ext32s_tl(t0, t0);
6af0bf9c
FB
1534 opn = "subu";
1535 break;
d26bc211 1536#if defined(TARGET_MIPS64)
7a387fff 1537 case OPC_DADD:
48d38ca5 1538 {
a7812ae4
PB
1539 TCGv r_tmp1 = tcg_temp_new();
1540 TCGv r_tmp2 = tcg_temp_new();
48d38ca5
TS
1541 int l1 = gen_new_label();
1542
1543 save_cpu_state(ctx, 1);
78723684
TS
1544 tcg_gen_mov_tl(r_tmp1, t0);
1545 tcg_gen_add_tl(t0, t0, t1);
48d38ca5 1546
78723684 1547 tcg_gen_xor_tl(r_tmp1, r_tmp1, t1);
48d38ca5 1548 tcg_gen_xori_tl(r_tmp1, r_tmp1, -1);
78723684 1549 tcg_gen_xor_tl(r_tmp2, t0, t1);
48d38ca5 1550 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
4f57689a 1551 tcg_temp_free(r_tmp2);
507563e8 1552 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
48d38ca5
TS
1553 /* operands of same sign, result different sign */
1554 generate_exception(ctx, EXCP_OVERFLOW);
1555 gen_set_label(l1);
507563e8 1556 tcg_temp_free(r_tmp1);
48d38ca5 1557 }
7a387fff
TS
1558 opn = "dadd";
1559 break;
1560 case OPC_DADDU:
78723684 1561 tcg_gen_add_tl(t0, t0, t1);
7a387fff
TS
1562 opn = "daddu";
1563 break;
1564 case OPC_DSUB:
48d38ca5 1565 {
a7812ae4
PB
1566 TCGv r_tmp1 = tcg_temp_new();
1567 TCGv r_tmp2 = tcg_temp_new();
48d38ca5
TS
1568 int l1 = gen_new_label();
1569
1570 save_cpu_state(ctx, 1);
78723684
TS
1571 tcg_gen_mov_tl(r_tmp1, t0);
1572 tcg_gen_sub_tl(t0, t0, t1);
48d38ca5 1573
78723684
TS
1574 tcg_gen_xor_tl(r_tmp2, r_tmp1, t1);
1575 tcg_gen_xor_tl(r_tmp1, r_tmp1, t0);
48d38ca5 1576 tcg_gen_and_tl(r_tmp1, r_tmp1, r_tmp2);
4f57689a 1577 tcg_temp_free(r_tmp2);
507563e8 1578 tcg_gen_brcondi_tl(TCG_COND_GE, r_tmp1, 0, l1);
48d38ca5
TS
1579 /* operands of different sign, first operand and result different sign */
1580 generate_exception(ctx, EXCP_OVERFLOW);
1581 gen_set_label(l1);
507563e8 1582 tcg_temp_free(r_tmp1);
48d38ca5 1583 }
7a387fff
TS
1584 opn = "dsub";
1585 break;
1586 case OPC_DSUBU:
78723684 1587 tcg_gen_sub_tl(t0, t0, t1);
7a387fff
TS
1588 opn = "dsubu";
1589 break;
1590#endif
6af0bf9c 1591 case OPC_SLT:
92e90443 1592 gen_op_lt(t0, t0, t1);
6af0bf9c
FB
1593 opn = "slt";
1594 break;
1595 case OPC_SLTU:
92e90443 1596 gen_op_ltu(t0, t0, t1);
6af0bf9c
FB
1597 opn = "sltu";
1598 break;
1599 case OPC_AND:
78723684 1600 tcg_gen_and_tl(t0, t0, t1);
6af0bf9c
FB
1601 opn = "and";
1602 break;
1603 case OPC_NOR:
a3fe9013 1604 tcg_gen_nor_tl(t0, t0, t1);
6af0bf9c
FB
1605 opn = "nor";
1606 break;
1607 case OPC_OR:
78723684 1608 tcg_gen_or_tl(t0, t0, t1);
6af0bf9c
FB
1609 opn = "or";
1610 break;
1611 case OPC_XOR:
78723684 1612 tcg_gen_xor_tl(t0, t0, t1);
6af0bf9c
FB
1613 opn = "xor";
1614 break;
1615 case OPC_MUL:
78723684
TS
1616 tcg_gen_mul_tl(t0, t0, t1);
1617 tcg_gen_ext32s_tl(t0, t0);
6af0bf9c
FB
1618 opn = "mul";
1619 break;
1620 case OPC_MOVN:
20c4c97c
TS
1621 {
1622 int l1 = gen_new_label();
1623
78723684
TS
1624 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
1625 gen_store_gpr(t0, rd);
20c4c97c
TS
1626 gen_set_label(l1);
1627 }
6af0bf9c
FB
1628 opn = "movn";
1629 goto print;
1630 case OPC_MOVZ:
20c4c97c
TS
1631 {
1632 int l1 = gen_new_label();
1633
78723684
TS
1634 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
1635 gen_store_gpr(t0, rd);
20c4c97c
TS
1636 gen_set_label(l1);
1637 }
6af0bf9c
FB
1638 opn = "movz";
1639 goto print;
1640 case OPC_SLLV:
78723684
TS
1641 tcg_gen_andi_tl(t0, t0, 0x1f);
1642 tcg_gen_shl_tl(t0, t1, t0);
1643 tcg_gen_ext32s_tl(t0, t0);
6af0bf9c
FB
1644 opn = "sllv";
1645 break;
1646 case OPC_SRAV:
78723684
TS
1647 tcg_gen_ext32s_tl(t1, t1);
1648 tcg_gen_andi_tl(t0, t0, 0x1f);
1649 tcg_gen_sar_tl(t0, t1, t0);
6af0bf9c
FB
1650 opn = "srav";
1651 break;
1652 case OPC_SRLV:
5a63bcb2
TS
1653 switch ((ctx->opcode >> 6) & 0x1f) {
1654 case 0:
78723684
TS
1655 tcg_gen_ext32u_tl(t1, t1);
1656 tcg_gen_andi_tl(t0, t0, 0x1f);
1657 tcg_gen_shr_tl(t0, t1, t0);
1658 tcg_gen_ext32s_tl(t0, t0);
7a387fff 1659 opn = "srlv";
5a63bcb2
TS
1660 break;
1661 case 1:
e189e748
TS
1662 /* rotrv is decoded as srlv on non-R2 CPUs */
1663 if (env->insn_flags & ISA_MIPS32R2) {
48d38ca5
TS
1664 int l1 = gen_new_label();
1665 int l2 = gen_new_label();
1666
78723684
TS
1667 tcg_gen_andi_tl(t0, t0, 0x1f);
1668 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
48d38ca5 1669 {
a7812ae4
PB
1670 TCGv_i32 r_tmp1 = tcg_temp_new_i32();
1671 TCGv_i32 r_tmp2 = tcg_temp_new_i32();
48d38ca5 1672
78723684
TS
1673 tcg_gen_trunc_tl_i32(r_tmp1, t0);
1674 tcg_gen_trunc_tl_i32(r_tmp2, t1);
e00fcff7 1675 tcg_gen_rotr_i32(r_tmp1, r_tmp1, r_tmp2);
a7812ae4
PB
1676 tcg_temp_free_i32(r_tmp1);
1677 tcg_temp_free_i32(r_tmp2);
48d38ca5
TS
1678 tcg_gen_br(l2);
1679 }
1680 gen_set_label(l1);
78723684 1681 tcg_gen_mov_tl(t0, t1);
48d38ca5 1682 gen_set_label(l2);
e189e748
TS
1683 opn = "rotrv";
1684 } else {
78723684
TS
1685 tcg_gen_ext32u_tl(t1, t1);
1686 tcg_gen_andi_tl(t0, t0, 0x1f);
1687 tcg_gen_shr_tl(t0, t1, t0);
1688 tcg_gen_ext32s_tl(t0, t0);
e189e748
TS
1689 opn = "srlv";
1690 }
5a63bcb2
TS
1691 break;
1692 default:
1693 MIPS_INVAL("invalid srlv flag");
1694 generate_exception(ctx, EXCP_RI);
1695 break;
1696 }
7a387fff 1697 break;
d26bc211 1698#if defined(TARGET_MIPS64)
7a387fff 1699 case OPC_DSLLV:
78723684
TS
1700 tcg_gen_andi_tl(t0, t0, 0x3f);
1701 tcg_gen_shl_tl(t0, t1, t0);
7a387fff
TS
1702 opn = "dsllv";
1703 break;
1704 case OPC_DSRAV:
78723684
TS
1705 tcg_gen_andi_tl(t0, t0, 0x3f);
1706 tcg_gen_sar_tl(t0, t1, t0);
7a387fff
TS
1707 opn = "dsrav";
1708 break;
1709 case OPC_DSRLV:
5a63bcb2
TS
1710 switch ((ctx->opcode >> 6) & 0x1f) {
1711 case 0:
78723684
TS
1712 tcg_gen_andi_tl(t0, t0, 0x3f);
1713 tcg_gen_shr_tl(t0, t1, t0);
7a387fff 1714 opn = "dsrlv";
5a63bcb2
TS
1715 break;
1716 case 1:
e189e748
TS
1717 /* drotrv is decoded as dsrlv on non-R2 CPUs */
1718 if (env->insn_flags & ISA_MIPS32R2) {
48d38ca5
TS
1719 int l1 = gen_new_label();
1720 int l2 = gen_new_label();
1721
78723684
TS
1722 tcg_gen_andi_tl(t0, t0, 0x3f);
1723 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
48d38ca5 1724 {
e00fcff7 1725 tcg_gen_rotr_tl(t0, t1, t0);
48d38ca5
TS
1726 tcg_gen_br(l2);
1727 }
1728 gen_set_label(l1);
78723684 1729 tcg_gen_mov_tl(t0, t1);
48d38ca5 1730 gen_set_label(l2);
e189e748
TS
1731 opn = "drotrv";
1732 } else {
78723684
TS
1733 tcg_gen_andi_tl(t0, t0, 0x3f);
1734 tcg_gen_shr_tl(t0, t1, t0);
e189e748
TS
1735 opn = "dsrlv";
1736 }
5a63bcb2
TS
1737 break;
1738 default:
1739 MIPS_INVAL("invalid dsrlv flag");
1740 generate_exception(ctx, EXCP_RI);
1741 break;
1742 }
6af0bf9c 1743 break;
7a387fff 1744#endif
6af0bf9c 1745 default:
923617a3 1746 MIPS_INVAL(opn);
6af0bf9c 1747 generate_exception(ctx, EXCP_RI);
78723684 1748 goto out;
6af0bf9c 1749 }
78723684 1750 gen_store_gpr(t0, rd);
6af0bf9c
FB
1751 print:
1752 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
78723684
TS
1753 out:
1754 tcg_temp_free(t0);
1755 tcg_temp_free(t1);
6af0bf9c
FB
1756}
1757
1758/* Arithmetic on HI/LO registers */
7a387fff 1759static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
6af0bf9c 1760{
923617a3 1761 const char *opn = "hilo";
6af0bf9c
FB
1762
1763 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
ead9360e 1764 /* Treat as NOP. */
6af0bf9c 1765 MIPS_DEBUG("NOP");
a1f6684d 1766 return;
6af0bf9c
FB
1767 }
1768 switch (opc) {
1769 case OPC_MFHI:
a1f6684d 1770 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
6af0bf9c
FB
1771 opn = "mfhi";
1772 break;
1773 case OPC_MFLO:
a1f6684d 1774 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
6af0bf9c
FB
1775 opn = "mflo";
1776 break;
1777 case OPC_MTHI:
a1f6684d
AJ
1778 if (reg != 0)
1779 tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
1780 else
1781 tcg_gen_movi_tl(cpu_HI[0], 0);
6af0bf9c
FB
1782 opn = "mthi";
1783 break;
1784 case OPC_MTLO:
a1f6684d
AJ
1785 if (reg != 0)
1786 tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
1787 else
1788 tcg_gen_movi_tl(cpu_LO[0], 0);
6af0bf9c
FB
1789 opn = "mtlo";
1790 break;
6af0bf9c
FB
1791 }
1792 MIPS_DEBUG("%s %s", opn, regnames[reg]);
1793}
1794
7a387fff 1795static void gen_muldiv (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
1796 int rs, int rt)
1797{
923617a3 1798 const char *opn = "mul/div";
d45f89f4
AJ
1799 TCGv t0, t1;
1800
1801 switch (opc) {
1802 case OPC_DIV:
1803 case OPC_DIVU:
1804#if defined(TARGET_MIPS64)
1805 case OPC_DDIV:
1806 case OPC_DDIVU:
1807#endif
1808 t0 = tcg_temp_local_new();
1809 t1 = tcg_temp_local_new();
1810 break;
1811 default:
1812 t0 = tcg_temp_new();
1813 t1 = tcg_temp_new();
1814 break;
1815 }
6af0bf9c 1816
78723684
TS
1817 gen_load_gpr(t0, rs);
1818 gen_load_gpr(t1, rt);
6af0bf9c
FB
1819 switch (opc) {
1820 case OPC_DIV:
48d38ca5
TS
1821 {
1822 int l1 = gen_new_label();
d45f89f4 1823 int l2 = gen_new_label();
48d38ca5 1824
d45f89f4
AJ
1825 tcg_gen_ext32s_tl(t0, t0);
1826 tcg_gen_ext32s_tl(t1, t1);
78723684 1827 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
d45f89f4
AJ
1828 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
1829 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
1830
1831 tcg_gen_mov_tl(cpu_LO[0], t0);
1832 tcg_gen_movi_tl(cpu_HI[0], 0);
1833 tcg_gen_br(l1);
1834 gen_set_label(l2);
1835 tcg_gen_div_tl(cpu_LO[0], t0, t1);
1836 tcg_gen_rem_tl(cpu_HI[0], t0, t1);
1837 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
1838 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
48d38ca5
TS
1839 gen_set_label(l1);
1840 }
6af0bf9c
FB
1841 opn = "div";
1842 break;
1843 case OPC_DIVU:
48d38ca5
TS
1844 {
1845 int l1 = gen_new_label();
1846
0c0ed03b
AJ
1847 tcg_gen_ext32u_tl(t0, t0);
1848 tcg_gen_ext32u_tl(t1, t1);
78723684 1849 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
d45f89f4
AJ
1850 tcg_gen_divu_tl(cpu_LO[0], t0, t1);
1851 tcg_gen_remu_tl(cpu_HI[0], t0, t1);
1852 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
1853 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
48d38ca5
TS
1854 gen_set_label(l1);
1855 }
6af0bf9c
FB
1856 opn = "divu";
1857 break;
1858 case OPC_MULT:
214c465f 1859 {
d45f89f4
AJ
1860 TCGv_i64 t2 = tcg_temp_new_i64();
1861 TCGv_i64 t3 = tcg_temp_new_i64();
1862
1863 tcg_gen_ext_tl_i64(t2, t0);
1864 tcg_gen_ext_tl_i64(t3, t1);
1865 tcg_gen_mul_i64(t2, t2, t3);
1866 tcg_temp_free_i64(t3);
1867 tcg_gen_trunc_i64_tl(t0, t2);
1868 tcg_gen_shri_i64(t2, t2, 32);
1869 tcg_gen_trunc_i64_tl(t1, t2);
1870 tcg_temp_free_i64(t2);
b10fa3c9
AJ
1871 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1872 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 1873 }
6af0bf9c
FB
1874 opn = "mult";
1875 break;
1876 case OPC_MULTU:
214c465f 1877 {
d45f89f4
AJ
1878 TCGv_i64 t2 = tcg_temp_new_i64();
1879 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 1880
78723684
TS
1881 tcg_gen_ext32u_tl(t0, t0);
1882 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
1883 tcg_gen_extu_tl_i64(t2, t0);
1884 tcg_gen_extu_tl_i64(t3, t1);
1885 tcg_gen_mul_i64(t2, t2, t3);
1886 tcg_temp_free_i64(t3);
1887 tcg_gen_trunc_i64_tl(t0, t2);
1888 tcg_gen_shri_i64(t2, t2, 32);
1889 tcg_gen_trunc_i64_tl(t1, t2);
1890 tcg_temp_free_i64(t2);
b10fa3c9
AJ
1891 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1892 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 1893 }
6af0bf9c
FB
1894 opn = "multu";
1895 break;
d26bc211 1896#if defined(TARGET_MIPS64)
7a387fff 1897 case OPC_DDIV:
48d38ca5
TS
1898 {
1899 int l1 = gen_new_label();
d45f89f4 1900 int l2 = gen_new_label();
48d38ca5 1901
78723684 1902 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
d45f89f4
AJ
1903 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
1904 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
1905 tcg_gen_mov_tl(cpu_LO[0], t0);
1906 tcg_gen_movi_tl(cpu_HI[0], 0);
1907 tcg_gen_br(l1);
1908 gen_set_label(l2);
1909 tcg_gen_div_i64(cpu_LO[0], t0, t1);
1910 tcg_gen_rem_i64(cpu_HI[0], t0, t1);
48d38ca5
TS
1911 gen_set_label(l1);
1912 }
7a387fff
TS
1913 opn = "ddiv";
1914 break;
1915 case OPC_DDIVU:
48d38ca5
TS
1916 {
1917 int l1 = gen_new_label();
1918
78723684 1919 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
b10fa3c9
AJ
1920 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
1921 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
48d38ca5
TS
1922 gen_set_label(l1);
1923 }
7a387fff
TS
1924 opn = "ddivu";
1925 break;
1926 case OPC_DMULT:
a7812ae4 1927 gen_helper_dmult(t0, t1);
7a387fff
TS
1928 opn = "dmult";
1929 break;
1930 case OPC_DMULTU:
a7812ae4 1931 gen_helper_dmultu(t0, t1);
7a387fff
TS
1932 opn = "dmultu";
1933 break;
1934#endif
6af0bf9c 1935 case OPC_MADD:
214c465f 1936 {
d45f89f4
AJ
1937 TCGv_i64 t2 = tcg_temp_new_i64();
1938 TCGv_i64 t3 = tcg_temp_new_i64();
1939
1940 tcg_gen_ext_tl_i64(t2, t0);
1941 tcg_gen_ext_tl_i64(t3, t1);
1942 tcg_gen_mul_i64(t2, t2, t3);
1943 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
1944 tcg_gen_add_i64(t2, t2, t3);
1945 tcg_temp_free_i64(t3);
1946 tcg_gen_trunc_i64_tl(t0, t2);
1947 tcg_gen_shri_i64(t2, t2, 32);
1948 tcg_gen_trunc_i64_tl(t1, t2);
1949 tcg_temp_free_i64(t2);
b10fa3c9
AJ
1950 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1951 tcg_gen_ext32s_tl(cpu_LO[1], t1);
214c465f 1952 }
6af0bf9c
FB
1953 opn = "madd";
1954 break;
1955 case OPC_MADDU:
214c465f 1956 {
d45f89f4
AJ
1957 TCGv_i64 t2 = tcg_temp_new_i64();
1958 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 1959
78723684
TS
1960 tcg_gen_ext32u_tl(t0, t0);
1961 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
1962 tcg_gen_extu_tl_i64(t2, t0);
1963 tcg_gen_extu_tl_i64(t3, t1);
1964 tcg_gen_mul_i64(t2, t2, t3);
1965 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
1966 tcg_gen_add_i64(t2, t2, t3);
1967 tcg_temp_free_i64(t3);
1968 tcg_gen_trunc_i64_tl(t0, t2);
1969 tcg_gen_shri_i64(t2, t2, 32);
1970 tcg_gen_trunc_i64_tl(t1, t2);
1971 tcg_temp_free_i64(t2);
b10fa3c9
AJ
1972 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1973 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 1974 }
6af0bf9c
FB
1975 opn = "maddu";
1976 break;
1977 case OPC_MSUB:
214c465f 1978 {
d45f89f4
AJ
1979 TCGv_i64 t2 = tcg_temp_new_i64();
1980 TCGv_i64 t3 = tcg_temp_new_i64();
1981
1982 tcg_gen_ext_tl_i64(t2, t0);
1983 tcg_gen_ext_tl_i64(t3, t1);
1984 tcg_gen_mul_i64(t2, t2, t3);
1985 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
1986 tcg_gen_sub_i64(t2, t2, t3);
1987 tcg_temp_free_i64(t3);
1988 tcg_gen_trunc_i64_tl(t0, t2);
1989 tcg_gen_shri_i64(t2, t2, 32);
1990 tcg_gen_trunc_i64_tl(t1, t2);
1991 tcg_temp_free_i64(t2);
b10fa3c9
AJ
1992 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1993 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 1994 }
6af0bf9c
FB
1995 opn = "msub";
1996 break;
1997 case OPC_MSUBU:
214c465f 1998 {
d45f89f4
AJ
1999 TCGv_i64 t2 = tcg_temp_new_i64();
2000 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 2001
78723684
TS
2002 tcg_gen_ext32u_tl(t0, t0);
2003 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
2004 tcg_gen_extu_tl_i64(t2, t0);
2005 tcg_gen_extu_tl_i64(t3, t1);
2006 tcg_gen_mul_i64(t2, t2, t3);
2007 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2008 tcg_gen_sub_i64(t2, t2, t3);
2009 tcg_temp_free_i64(t3);
2010 tcg_gen_trunc_i64_tl(t0, t2);
2011 tcg_gen_shri_i64(t2, t2, 32);
2012 tcg_gen_trunc_i64_tl(t1, t2);
2013 tcg_temp_free_i64(t2);
b10fa3c9
AJ
2014 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2015 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 2016 }
6af0bf9c
FB
2017 opn = "msubu";
2018 break;
2019 default:
923617a3 2020 MIPS_INVAL(opn);
6af0bf9c 2021 generate_exception(ctx, EXCP_RI);
78723684 2022 goto out;
6af0bf9c
FB
2023 }
2024 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
78723684
TS
2025 out:
2026 tcg_temp_free(t0);
2027 tcg_temp_free(t1);
6af0bf9c
FB
2028}
2029
e9c71dd1
TS
2030static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2031 int rd, int rs, int rt)
2032{
2033 const char *opn = "mul vr54xx";
f157bfe1
AJ
2034 TCGv t0 = tcg_temp_new();
2035 TCGv t1 = tcg_temp_new();
e9c71dd1 2036
6c5c1e20
TS
2037 gen_load_gpr(t0, rs);
2038 gen_load_gpr(t1, rt);
e9c71dd1
TS
2039
2040 switch (opc) {
2041 case OPC_VR54XX_MULS:
a7812ae4 2042 gen_helper_muls(t0, t0, t1);
e9c71dd1 2043 opn = "muls";
6958549d 2044 break;
e9c71dd1 2045 case OPC_VR54XX_MULSU:
a7812ae4 2046 gen_helper_mulsu(t0, t0, t1);
e9c71dd1 2047 opn = "mulsu";
6958549d 2048 break;
e9c71dd1 2049 case OPC_VR54XX_MACC:
a7812ae4 2050 gen_helper_macc(t0, t0, t1);
e9c71dd1 2051 opn = "macc";
6958549d 2052 break;
e9c71dd1 2053 case OPC_VR54XX_MACCU:
a7812ae4 2054 gen_helper_maccu(t0, t0, t1);
e9c71dd1 2055 opn = "maccu";
6958549d 2056 break;
e9c71dd1 2057 case OPC_VR54XX_MSAC:
a7812ae4 2058 gen_helper_msac(t0, t0, t1);
e9c71dd1 2059 opn = "msac";
6958549d 2060 break;
e9c71dd1 2061 case OPC_VR54XX_MSACU:
a7812ae4 2062 gen_helper_msacu(t0, t0, t1);
e9c71dd1 2063 opn = "msacu";
6958549d 2064 break;
e9c71dd1 2065 case OPC_VR54XX_MULHI:
a7812ae4 2066 gen_helper_mulhi(t0, t0, t1);
e9c71dd1 2067 opn = "mulhi";
6958549d 2068 break;
e9c71dd1 2069 case OPC_VR54XX_MULHIU:
a7812ae4 2070 gen_helper_mulhiu(t0, t0, t1);
e9c71dd1 2071 opn = "mulhiu";
6958549d 2072 break;
e9c71dd1 2073 case OPC_VR54XX_MULSHI:
a7812ae4 2074 gen_helper_mulshi(t0, t0, t1);
e9c71dd1 2075 opn = "mulshi";
6958549d 2076 break;
e9c71dd1 2077 case OPC_VR54XX_MULSHIU:
a7812ae4 2078 gen_helper_mulshiu(t0, t0, t1);
e9c71dd1 2079 opn = "mulshiu";
6958549d 2080 break;
e9c71dd1 2081 case OPC_VR54XX_MACCHI:
a7812ae4 2082 gen_helper_macchi(t0, t0, t1);
e9c71dd1 2083 opn = "macchi";
6958549d 2084 break;
e9c71dd1 2085 case OPC_VR54XX_MACCHIU:
a7812ae4 2086 gen_helper_macchiu(t0, t0, t1);
e9c71dd1 2087 opn = "macchiu";
6958549d 2088 break;
e9c71dd1 2089 case OPC_VR54XX_MSACHI:
a7812ae4 2090 gen_helper_msachi(t0, t0, t1);
e9c71dd1 2091 opn = "msachi";
6958549d 2092 break;
e9c71dd1 2093 case OPC_VR54XX_MSACHIU:
a7812ae4 2094 gen_helper_msachiu(t0, t0, t1);
e9c71dd1 2095 opn = "msachiu";
6958549d 2096 break;
e9c71dd1
TS
2097 default:
2098 MIPS_INVAL("mul vr54xx");
2099 generate_exception(ctx, EXCP_RI);
6c5c1e20 2100 goto out;
e9c71dd1 2101 }
6c5c1e20 2102 gen_store_gpr(t0, rd);
e9c71dd1 2103 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
6c5c1e20
TS
2104
2105 out:
2106 tcg_temp_free(t0);
2107 tcg_temp_free(t1);
e9c71dd1
TS
2108}
2109
7a387fff 2110static void gen_cl (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
2111 int rd, int rs)
2112{
923617a3 2113 const char *opn = "CLx";
20e1fb52 2114 TCGv t0;
6c5c1e20 2115
6af0bf9c 2116 if (rd == 0) {
ead9360e 2117 /* Treat as NOP. */
6af0bf9c 2118 MIPS_DEBUG("NOP");
20e1fb52 2119 return;
6af0bf9c 2120 }
20e1fb52 2121 t0 = tcg_temp_new();
6c5c1e20 2122 gen_load_gpr(t0, rs);
6af0bf9c
FB
2123 switch (opc) {
2124 case OPC_CLO:
20e1fb52 2125 gen_helper_clo(cpu_gpr[rd], t0);
6af0bf9c
FB
2126 opn = "clo";
2127 break;
2128 case OPC_CLZ:
20e1fb52 2129 gen_helper_clz(cpu_gpr[rd], t0);
6af0bf9c
FB
2130 opn = "clz";
2131 break;
d26bc211 2132#if defined(TARGET_MIPS64)
7a387fff 2133 case OPC_DCLO:
20e1fb52 2134 gen_helper_dclo(cpu_gpr[rd], t0);
7a387fff
TS
2135 opn = "dclo";
2136 break;
2137 case OPC_DCLZ:
20e1fb52 2138 gen_helper_dclz(cpu_gpr[rd], t0);
7a387fff
TS
2139 opn = "dclz";
2140 break;
2141#endif
6af0bf9c 2142 }
6af0bf9c 2143 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
6c5c1e20 2144 tcg_temp_free(t0);
6af0bf9c
FB
2145}
2146
2147/* Traps */
7a387fff 2148static void gen_trap (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
2149 int rs, int rt, int16_t imm)
2150{
2151 int cond;
cdc0faa6 2152 TCGv t0 = tcg_temp_new();
1ba74fb8 2153 TCGv t1 = tcg_temp_new();
6af0bf9c
FB
2154
2155 cond = 0;
2156 /* Load needed operands */
2157 switch (opc) {
2158 case OPC_TEQ:
2159 case OPC_TGE:
2160 case OPC_TGEU:
2161 case OPC_TLT:
2162 case OPC_TLTU:
2163 case OPC_TNE:
2164 /* Compare two registers */
2165 if (rs != rt) {
be24bb4f
TS
2166 gen_load_gpr(t0, rs);
2167 gen_load_gpr(t1, rt);
6af0bf9c
FB
2168 cond = 1;
2169 }
179e32bb 2170 break;
6af0bf9c
FB
2171 case OPC_TEQI:
2172 case OPC_TGEI:
2173 case OPC_TGEIU:
2174 case OPC_TLTI:
2175 case OPC_TLTIU:
2176 case OPC_TNEI:
2177 /* Compare register to immediate */
2178 if (rs != 0 || imm != 0) {
be24bb4f
TS
2179 gen_load_gpr(t0, rs);
2180 tcg_gen_movi_tl(t1, (int32_t)imm);
6af0bf9c
FB
2181 cond = 1;
2182 }
2183 break;
2184 }
2185 if (cond == 0) {
2186 switch (opc) {
2187 case OPC_TEQ: /* rs == rs */
2188 case OPC_TEQI: /* r0 == 0 */
2189 case OPC_TGE: /* rs >= rs */
2190 case OPC_TGEI: /* r0 >= 0 */
2191 case OPC_TGEU: /* rs >= rs unsigned */
2192 case OPC_TGEIU: /* r0 >= 0 unsigned */
2193 /* Always trap */
cdc0faa6 2194 generate_exception(ctx, EXCP_TRAP);
6af0bf9c
FB
2195 break;
2196 case OPC_TLT: /* rs < rs */
2197 case OPC_TLTI: /* r0 < 0 */
2198 case OPC_TLTU: /* rs < rs unsigned */
2199 case OPC_TLTIU: /* r0 < 0 unsigned */
2200 case OPC_TNE: /* rs != rs */
2201 case OPC_TNEI: /* r0 != 0 */
ead9360e 2202 /* Never trap: treat as NOP. */
cdc0faa6 2203 break;
6af0bf9c
FB
2204 }
2205 } else {
cdc0faa6
AJ
2206 int l1 = gen_new_label();
2207
6af0bf9c
FB
2208 switch (opc) {
2209 case OPC_TEQ:
2210 case OPC_TEQI:
cdc0faa6 2211 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6af0bf9c
FB
2212 break;
2213 case OPC_TGE:
2214 case OPC_TGEI:
cdc0faa6 2215 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6af0bf9c
FB
2216 break;
2217 case OPC_TGEU:
2218 case OPC_TGEIU:
cdc0faa6 2219 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6af0bf9c
FB
2220 break;
2221 case OPC_TLT:
2222 case OPC_TLTI:
cdc0faa6 2223 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6af0bf9c
FB
2224 break;
2225 case OPC_TLTU:
2226 case OPC_TLTIU:
cdc0faa6 2227 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6af0bf9c
FB
2228 break;
2229 case OPC_TNE:
2230 case OPC_TNEI:
cdc0faa6 2231 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6af0bf9c 2232 break;
6af0bf9c 2233 }
cdc0faa6 2234 generate_exception(ctx, EXCP_TRAP);
08ba7963
TS
2235 gen_set_label(l1);
2236 }
be24bb4f
TS
2237 tcg_temp_free(t0);
2238 tcg_temp_free(t1);
6af0bf9c
FB
2239}
2240
356265ae 2241static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
c53be334 2242{
6e256c93
FB
2243 TranslationBlock *tb;
2244 tb = ctx->tb;
2245 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
57fec1fe 2246 tcg_gen_goto_tb(n);
9b9e4393 2247 gen_save_pc(dest);
57fec1fe 2248 tcg_gen_exit_tb((long)tb + n);
6e256c93 2249 } else {
9b9e4393 2250 gen_save_pc(dest);
57fec1fe 2251 tcg_gen_exit_tb(0);
6e256c93 2252 }
c53be334
FB
2253}
2254
6af0bf9c 2255/* Branches (before delay slot) */
7a387fff 2256static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
2257 int rs, int rt, int32_t offset)
2258{
d077b6f7 2259 target_ulong btgt = -1;
3ad4bb2d 2260 int blink = 0;
2fdbad25 2261 int bcond_compute = 0;
1ba74fb8
AJ
2262 TCGv t0 = tcg_temp_new();
2263 TCGv t1 = tcg_temp_new();
3ad4bb2d
TS
2264
2265 if (ctx->hflags & MIPS_HFLAG_BMASK) {
923617a3 2266#ifdef MIPS_DEBUG_DISAS
d12d51d5 2267 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
923617a3 2268#endif
3ad4bb2d 2269 generate_exception(ctx, EXCP_RI);
6c5c1e20 2270 goto out;
3ad4bb2d 2271 }
6af0bf9c 2272
6af0bf9c
FB
2273 /* Load needed operands */
2274 switch (opc) {
2275 case OPC_BEQ:
2276 case OPC_BEQL:
2277 case OPC_BNE:
2278 case OPC_BNEL:
2279 /* Compare two registers */
2280 if (rs != rt) {
6c5c1e20
TS
2281 gen_load_gpr(t0, rs);
2282 gen_load_gpr(t1, rt);
2fdbad25 2283 bcond_compute = 1;
6af0bf9c 2284 }
d077b6f7 2285 btgt = ctx->pc + 4 + offset;
6af0bf9c
FB
2286 break;
2287 case OPC_BGEZ:
2288 case OPC_BGEZAL:
2289 case OPC_BGEZALL:
2290 case OPC_BGEZL:
2291 case OPC_BGTZ:
2292 case OPC_BGTZL:
2293 case OPC_BLEZ:
2294 case OPC_BLEZL:
2295 case OPC_BLTZ:
2296 case OPC_BLTZAL:
2297 case OPC_BLTZALL:
2298 case OPC_BLTZL:
2299 /* Compare to zero */
2300 if (rs != 0) {
6c5c1e20 2301 gen_load_gpr(t0, rs);
2fdbad25 2302 bcond_compute = 1;
6af0bf9c 2303 }
d077b6f7 2304 btgt = ctx->pc + 4 + offset;
6af0bf9c
FB
2305 break;
2306 case OPC_J:
2307 case OPC_JAL:
2308 /* Jump to immediate */
d077b6f7 2309 btgt = ((ctx->pc + 4) & (int32_t)0xF0000000) | (uint32_t)offset;
6af0bf9c
FB
2310 break;
2311 case OPC_JR:
2312 case OPC_JALR:
2313 /* Jump to register */
7a387fff
TS
2314 if (offset != 0 && offset != 16) {
2315 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
cbeb0857 2316 others are reserved. */
923617a3 2317 MIPS_INVAL("jump hint");
6af0bf9c 2318 generate_exception(ctx, EXCP_RI);
6c5c1e20 2319 goto out;
6af0bf9c 2320 }
d077b6f7 2321 gen_load_gpr(btarget, rs);
6af0bf9c
FB
2322 break;
2323 default:
2324 MIPS_INVAL("branch/jump");
2325 generate_exception(ctx, EXCP_RI);
6c5c1e20 2326 goto out;
6af0bf9c 2327 }
2fdbad25 2328 if (bcond_compute == 0) {
6af0bf9c
FB
2329 /* No condition to be computed */
2330 switch (opc) {
2331 case OPC_BEQ: /* rx == rx */
2332 case OPC_BEQL: /* rx == rx likely */
2333 case OPC_BGEZ: /* 0 >= 0 */
2334 case OPC_BGEZL: /* 0 >= 0 likely */
2335 case OPC_BLEZ: /* 0 <= 0 */
2336 case OPC_BLEZL: /* 0 <= 0 likely */
2337 /* Always take */
4ad40f36 2338 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
2339 MIPS_DEBUG("balways");
2340 break;
2341 case OPC_BGEZAL: /* 0 >= 0 */
2342 case OPC_BGEZALL: /* 0 >= 0 likely */
2343 /* Always take and link */
2344 blink = 31;
4ad40f36 2345 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
2346 MIPS_DEBUG("balways and link");
2347 break;
2348 case OPC_BNE: /* rx != rx */
2349 case OPC_BGTZ: /* 0 > 0 */
2350 case OPC_BLTZ: /* 0 < 0 */
ead9360e 2351 /* Treat as NOP. */
6af0bf9c 2352 MIPS_DEBUG("bnever (NOP)");
6c5c1e20 2353 goto out;
eeef26cd 2354 case OPC_BLTZAL: /* 0 < 0 */
1ba74fb8 2355 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
9898128f 2356 MIPS_DEBUG("bnever and link");
6c5c1e20 2357 goto out;
eeef26cd 2358 case OPC_BLTZALL: /* 0 < 0 likely */
1ba74fb8 2359 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
9898128f
TS
2360 /* Skip the instruction in the delay slot */
2361 MIPS_DEBUG("bnever, link and skip");
2362 ctx->pc += 4;
6c5c1e20 2363 goto out;
6af0bf9c
FB
2364 case OPC_BNEL: /* rx != rx likely */
2365 case OPC_BGTZL: /* 0 > 0 likely */
6af0bf9c
FB
2366 case OPC_BLTZL: /* 0 < 0 likely */
2367 /* Skip the instruction in the delay slot */
2368 MIPS_DEBUG("bnever and skip");
9898128f 2369 ctx->pc += 4;
6c5c1e20 2370 goto out;
6af0bf9c 2371 case OPC_J:
4ad40f36 2372 ctx->hflags |= MIPS_HFLAG_B;
d077b6f7 2373 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
6af0bf9c
FB
2374 break;
2375 case OPC_JAL:
2376 blink = 31;
4ad40f36 2377 ctx->hflags |= MIPS_HFLAG_B;
d077b6f7 2378 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
6af0bf9c
FB
2379 break;
2380 case OPC_JR:
4ad40f36 2381 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
2382 MIPS_DEBUG("jr %s", regnames[rs]);
2383 break;
2384 case OPC_JALR:
2385 blink = rt;
4ad40f36 2386 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
2387 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2388 break;
2389 default:
2390 MIPS_INVAL("branch/jump");
2391 generate_exception(ctx, EXCP_RI);
6c5c1e20 2392 goto out;
6af0bf9c
FB
2393 }
2394 } else {
2395 switch (opc) {
2396 case OPC_BEQ:
1ba74fb8 2397 gen_op_eq(bcond, t0, t1);
923617a3 2398 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
d077b6f7 2399 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
2400 goto not_likely;
2401 case OPC_BEQL:
1ba74fb8 2402 gen_op_eq(bcond, t0, t1);
923617a3 2403 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
d077b6f7 2404 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
2405 goto likely;
2406 case OPC_BNE:
1ba74fb8 2407 gen_op_ne(bcond, t0, t1);
923617a3 2408 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
d077b6f7 2409 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
2410 goto not_likely;
2411 case OPC_BNEL:
1ba74fb8 2412 gen_op_ne(bcond, t0, t1);
923617a3 2413 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
d077b6f7 2414 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
2415 goto likely;
2416 case OPC_BGEZ:
1ba74fb8 2417 gen_op_gez(bcond, t0);
d077b6f7 2418 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2419 goto not_likely;
2420 case OPC_BGEZL:
1ba74fb8 2421 gen_op_gez(bcond, t0);
d077b6f7 2422 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2423 goto likely;
2424 case OPC_BGEZAL:
1ba74fb8 2425 gen_op_gez(bcond, t0);
d077b6f7 2426 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2427 blink = 31;
2428 goto not_likely;
2429 case OPC_BGEZALL:
1ba74fb8 2430 gen_op_gez(bcond, t0);
6af0bf9c 2431 blink = 31;
d077b6f7 2432 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2433 goto likely;
2434 case OPC_BGTZ:
1ba74fb8 2435 gen_op_gtz(bcond, t0);
d077b6f7 2436 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2437 goto not_likely;
2438 case OPC_BGTZL:
1ba74fb8 2439 gen_op_gtz(bcond, t0);
d077b6f7 2440 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2441 goto likely;
2442 case OPC_BLEZ:
1ba74fb8 2443 gen_op_lez(bcond, t0);
d077b6f7 2444 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2445 goto not_likely;
2446 case OPC_BLEZL:
1ba74fb8 2447 gen_op_lez(bcond, t0);
d077b6f7 2448 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2449 goto likely;
2450 case OPC_BLTZ:
1ba74fb8 2451 gen_op_ltz(bcond, t0);
d077b6f7 2452 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2453 goto not_likely;
2454 case OPC_BLTZL:
1ba74fb8 2455 gen_op_ltz(bcond, t0);
d077b6f7 2456 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2457 goto likely;
2458 case OPC_BLTZAL:
1ba74fb8 2459 gen_op_ltz(bcond, t0);
6af0bf9c 2460 blink = 31;
d077b6f7 2461 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 2462 not_likely:
4ad40f36 2463 ctx->hflags |= MIPS_HFLAG_BC;
6af0bf9c
FB
2464 break;
2465 case OPC_BLTZALL:
1ba74fb8 2466 gen_op_ltz(bcond, t0);
6af0bf9c 2467 blink = 31;
d077b6f7 2468 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 2469 likely:
4ad40f36 2470 ctx->hflags |= MIPS_HFLAG_BL;
6af0bf9c 2471 break;
c53f4a62
TS
2472 default:
2473 MIPS_INVAL("conditional branch/jump");
2474 generate_exception(ctx, EXCP_RI);
6c5c1e20 2475 goto out;
6af0bf9c 2476 }
6af0bf9c 2477 }
923617a3 2478 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
d077b6f7 2479 blink, ctx->hflags, btgt);
9b9e4393 2480
d077b6f7 2481 ctx->btarget = btgt;
6af0bf9c 2482 if (blink > 0) {
1ba74fb8 2483 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + 8);
6af0bf9c 2484 }
6c5c1e20
TS
2485
2486 out:
2487 tcg_temp_free(t0);
2488 tcg_temp_free(t1);
6af0bf9c
FB
2489}
2490
7a387fff
TS
2491/* special3 bitfield operations */
2492static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
356265ae 2493 int rs, int lsb, int msb)
7a387fff 2494{
a7812ae4
PB
2495 TCGv t0 = tcg_temp_new();
2496 TCGv t1 = tcg_temp_new();
505ad7c2 2497 target_ulong mask;
6c5c1e20
TS
2498
2499 gen_load_gpr(t1, rs);
7a387fff
TS
2500 switch (opc) {
2501 case OPC_EXT:
2502 if (lsb + msb > 31)
2503 goto fail;
505ad7c2
AJ
2504 tcg_gen_shri_tl(t0, t1, lsb);
2505 if (msb != 31) {
2506 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
2507 } else {
2508 tcg_gen_ext32s_tl(t0, t0);
2509 }
7a387fff 2510 break;
c6d6dd7c 2511#if defined(TARGET_MIPS64)
7a387fff 2512 case OPC_DEXTM:
505ad7c2
AJ
2513 tcg_gen_shri_tl(t0, t1, lsb);
2514 if (msb != 31) {
2515 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
2516 }
7a387fff
TS
2517 break;
2518 case OPC_DEXTU:
505ad7c2
AJ
2519 tcg_gen_shri_tl(t0, t1, lsb + 32);
2520 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
7a387fff
TS
2521 break;
2522 case OPC_DEXT:
505ad7c2
AJ
2523 tcg_gen_shri_tl(t0, t1, lsb);
2524 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
7a387fff 2525 break;
c6d6dd7c 2526#endif
7a387fff
TS
2527 case OPC_INS:
2528 if (lsb > msb)
2529 goto fail;
505ad7c2 2530 mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
6c5c1e20 2531 gen_load_gpr(t0, rt);
505ad7c2
AJ
2532 tcg_gen_andi_tl(t0, t0, ~mask);
2533 tcg_gen_shli_tl(t1, t1, lsb);
2534 tcg_gen_andi_tl(t1, t1, mask);
2535 tcg_gen_or_tl(t0, t0, t1);
2536 tcg_gen_ext32s_tl(t0, t0);
7a387fff 2537 break;
c6d6dd7c 2538#if defined(TARGET_MIPS64)
7a387fff
TS
2539 case OPC_DINSM:
2540 if (lsb > msb)
2541 goto fail;
505ad7c2 2542 mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
6c5c1e20 2543 gen_load_gpr(t0, rt);
505ad7c2
AJ
2544 tcg_gen_andi_tl(t0, t0, ~mask);
2545 tcg_gen_shli_tl(t1, t1, lsb);
2546 tcg_gen_andi_tl(t1, t1, mask);
2547 tcg_gen_or_tl(t0, t0, t1);
7a387fff
TS
2548 break;
2549 case OPC_DINSU:
2550 if (lsb > msb)
2551 goto fail;
505ad7c2 2552 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
6c5c1e20 2553 gen_load_gpr(t0, rt);
505ad7c2
AJ
2554 tcg_gen_andi_tl(t0, t0, ~mask);
2555 tcg_gen_shli_tl(t1, t1, lsb + 32);
2556 tcg_gen_andi_tl(t1, t1, mask);
2557 tcg_gen_or_tl(t0, t0, t1);
7a387fff
TS
2558 break;
2559 case OPC_DINS:
2560 if (lsb > msb)
2561 goto fail;
6c5c1e20 2562 gen_load_gpr(t0, rt);
505ad7c2
AJ
2563 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2564 gen_load_gpr(t0, rt);
2565 tcg_gen_andi_tl(t0, t0, ~mask);
2566 tcg_gen_shli_tl(t1, t1, lsb);
2567 tcg_gen_andi_tl(t1, t1, mask);
2568 tcg_gen_or_tl(t0, t0, t1);
7a387fff 2569 break;
c6d6dd7c 2570#endif
7a387fff
TS
2571 default:
2572fail:
2573 MIPS_INVAL("bitops");
2574 generate_exception(ctx, EXCP_RI);
6c5c1e20
TS
2575 tcg_temp_free(t0);
2576 tcg_temp_free(t1);
7a387fff
TS
2577 return;
2578 }
6c5c1e20
TS
2579 gen_store_gpr(t0, rt);
2580 tcg_temp_free(t0);
2581 tcg_temp_free(t1);
7a387fff
TS
2582}
2583
49bcf33c
AJ
2584static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
2585{
3a55fa47 2586 TCGv t0;
49bcf33c 2587
3a55fa47
AJ
2588 if (rd == 0) {
2589 /* If no destination, treat it as a NOP. */
2590 MIPS_DEBUG("NOP");
2591 return;
2592 }
2593
2594 t0 = tcg_temp_new();
2595 gen_load_gpr(t0, rt);
49bcf33c
AJ
2596 switch (op2) {
2597 case OPC_WSBH:
3a55fa47
AJ
2598 {
2599 TCGv t1 = tcg_temp_new();
2600
2601 tcg_gen_shri_tl(t1, t0, 8);
2602 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
2603 tcg_gen_shli_tl(t0, t0, 8);
2604 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
2605 tcg_gen_or_tl(t0, t0, t1);
2606 tcg_temp_free(t1);
2607 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2608 }
49bcf33c
AJ
2609 break;
2610 case OPC_SEB:
3a55fa47 2611 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
2612 break;
2613 case OPC_SEH:
3a55fa47 2614 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
2615 break;
2616#if defined(TARGET_MIPS64)
2617 case OPC_DSBH:
3a55fa47
AJ
2618 {
2619 TCGv t1 = tcg_temp_new();
2620
2621 tcg_gen_shri_tl(t1, t0, 8);
2622 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
2623 tcg_gen_shli_tl(t0, t0, 8);
2624 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
2625 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2626 tcg_temp_free(t1);
2627 }
49bcf33c
AJ
2628 break;
2629 case OPC_DSHD:
3a55fa47
AJ
2630 {
2631 TCGv t1 = tcg_temp_new();
2632
2633 tcg_gen_shri_tl(t1, t0, 16);
2634 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
2635 tcg_gen_shli_tl(t0, t0, 16);
2636 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
2637 tcg_gen_or_tl(t0, t0, t1);
2638 tcg_gen_shri_tl(t1, t0, 32);
2639 tcg_gen_shli_tl(t0, t0, 32);
2640 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2641 tcg_temp_free(t1);
2642 }
49bcf33c
AJ
2643 break;
2644#endif
2645 default:
2646 MIPS_INVAL("bsfhl");
2647 generate_exception(ctx, EXCP_RI);
2648 tcg_temp_free(t0);
49bcf33c
AJ
2649 return;
2650 }
49bcf33c 2651 tcg_temp_free(t0);
49bcf33c
AJ
2652}
2653
f1aa6320 2654#ifndef CONFIG_USER_ONLY
0eaef5aa 2655/* CP0 (MMU and control) */
4f57689a
TS
2656static inline void gen_mfc0_load32 (TCGv t, target_ulong off)
2657{
a7812ae4 2658 TCGv_i32 r_tmp = tcg_temp_new_i32();
4f57689a
TS
2659
2660 tcg_gen_ld_i32(r_tmp, cpu_env, off);
2661 tcg_gen_ext_i32_tl(t, r_tmp);
a7812ae4 2662 tcg_temp_free_i32(r_tmp);
4f57689a
TS
2663}
2664
2665static inline void gen_mfc0_load64 (TCGv t, target_ulong off)
2666{
2c2435bd
TS
2667 tcg_gen_ld_tl(t, cpu_env, off);
2668 tcg_gen_ext32s_tl(t, t);
4f57689a
TS
2669}
2670
f1aa6320
TS
2671static inline void gen_mtc0_store32 (TCGv t, target_ulong off)
2672{
a7812ae4 2673 TCGv_i32 r_tmp = tcg_temp_new_i32();
f1aa6320
TS
2674
2675 tcg_gen_trunc_tl_i32(r_tmp, t);
2676 tcg_gen_st_i32(r_tmp, cpu_env, off);
a7812ae4 2677 tcg_temp_free_i32(r_tmp);
f1aa6320
TS
2678}
2679
2680static inline void gen_mtc0_store64 (TCGv t, target_ulong off)
2681{
2c2435bd
TS
2682 tcg_gen_ext32s_tl(t, t);
2683 tcg_gen_st_tl(t, cpu_env, off);
f1aa6320
TS
2684}
2685
1a3fd9c3 2686static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
873eb012 2687{
7a387fff 2688 const char *rn = "invalid";
873eb012 2689
e189e748
TS
2690 if (sel != 0)
2691 check_insn(env, ctx, ISA_MIPS32);
2692
873eb012
TS
2693 switch (reg) {
2694 case 0:
7a387fff
TS
2695 switch (sel) {
2696 case 0:
1a3fd9c3 2697 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Index));
7a387fff
TS
2698 rn = "Index";
2699 break;
2700 case 1:
7385ac0b 2701 check_insn(env, ctx, ASE_MT);
a7812ae4 2702 gen_helper_mfc0_mvpcontrol(t0);
7a387fff 2703 rn = "MVPControl";
ead9360e 2704 break;
7a387fff 2705 case 2:
7385ac0b 2706 check_insn(env, ctx, ASE_MT);
a7812ae4 2707 gen_helper_mfc0_mvpconf0(t0);
7a387fff 2708 rn = "MVPConf0";
ead9360e 2709 break;
7a387fff 2710 case 3:
7385ac0b 2711 check_insn(env, ctx, ASE_MT);
a7812ae4 2712 gen_helper_mfc0_mvpconf1(t0);
7a387fff 2713 rn = "MVPConf1";
ead9360e 2714 break;
7a387fff
TS
2715 default:
2716 goto die;
2717 }
873eb012
TS
2718 break;
2719 case 1:
7a387fff
TS
2720 switch (sel) {
2721 case 0:
a7812ae4 2722 gen_helper_mfc0_random(t0);
7a387fff 2723 rn = "Random";
2423f660 2724 break;
7a387fff 2725 case 1:
7385ac0b 2726 check_insn(env, ctx, ASE_MT);
1a3fd9c3 2727 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEControl));
7a387fff 2728 rn = "VPEControl";
ead9360e 2729 break;
7a387fff 2730 case 2:
7385ac0b 2731 check_insn(env, ctx, ASE_MT);
1a3fd9c3 2732 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf0));
7a387fff 2733 rn = "VPEConf0";
ead9360e 2734 break;
7a387fff 2735 case 3:
7385ac0b 2736 check_insn(env, ctx, ASE_MT);
1a3fd9c3 2737 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf1));
7a387fff 2738 rn = "VPEConf1";
ead9360e 2739 break;
7a387fff 2740 case 4:
7385ac0b 2741 check_insn(env, ctx, ASE_MT);
1a3fd9c3 2742 gen_mfc0_load64(t0, offsetof(CPUState, CP0_YQMask));
7a387fff 2743 rn = "YQMask";
ead9360e 2744 break;
7a387fff 2745 case 5:
7385ac0b 2746 check_insn(env, ctx, ASE_MT);
1a3fd9c3 2747 gen_mfc0_load64(t0, offsetof(CPUState, CP0_VPESchedule));
7a387fff 2748 rn = "VPESchedule";
ead9360e 2749 break;
7a387fff 2750 case 6:
7385ac0b 2751 check_insn(env, ctx, ASE_MT);
1a3fd9c3 2752 gen_mfc0_load64(t0, offsetof(CPUState, CP0_VPEScheFBack));
7a387fff 2753 rn = "VPEScheFBack";
ead9360e 2754 break;
7a387fff 2755 case 7:
7385ac0b 2756 check_insn(env, ctx, ASE_MT);
1a3fd9c3 2757 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEOpt));
7a387fff 2758 rn = "VPEOpt";
ead9360e 2759 break;
7a387fff
TS
2760 default:
2761 goto die;
2762 }
873eb012
TS
2763 break;
2764 case 2:
7a387fff
TS
2765 switch (sel) {
2766 case 0:
1a3fd9c3
TS
2767 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo0));
2768 tcg_gen_ext32s_tl(t0, t0);
2423f660
TS
2769 rn = "EntryLo0";
2770 break;
7a387fff 2771 case 1:
7385ac0b 2772 check_insn(env, ctx, ASE_MT);
a7812ae4 2773 gen_helper_mfc0_tcstatus(t0);
2423f660 2774 rn = "TCStatus";
ead9360e 2775 break;
7a387fff 2776 case 2:
7385ac0b 2777 check_insn(env, ctx, ASE_MT);
a7812ae4 2778 gen_helper_mfc0_tcbind(t0);
2423f660 2779 rn = "TCBind";
ead9360e 2780 break;
7a387fff 2781 case 3:
7385ac0b 2782 check_insn(env, ctx, ASE_MT);
a7812ae4 2783 gen_helper_mfc0_tcrestart(t0);
2423f660 2784 rn = "TCRestart";
ead9360e 2785 break;
7a387fff 2786 case 4:
7385ac0b 2787 check_insn(env, ctx, ASE_MT);
a7812ae4 2788 gen_helper_mfc0_tchalt(t0);
2423f660 2789 rn = "TCHalt";
ead9360e 2790 break;
7a387fff 2791 case 5:
7385ac0b 2792 check_insn(env, ctx, ASE_MT);
a7812ae4 2793 gen_helper_mfc0_tccontext(t0);
2423f660 2794 rn = "TCContext";
ead9360e 2795 break;
7a387fff 2796 case 6:
7385ac0b 2797 check_insn(env, ctx, ASE_MT);
a7812ae4 2798 gen_helper_mfc0_tcschedule(t0);
2423f660 2799 rn = "TCSchedule";
ead9360e 2800 break;
7a387fff 2801 case 7:
7385ac0b 2802 check_insn(env, ctx, ASE_MT);
a7812ae4 2803 gen_helper_mfc0_tcschefback(t0);
2423f660 2804 rn = "TCScheFBack";
ead9360e 2805 break;
7a387fff
TS
2806 default:
2807 goto die;
2808 }
873eb012
TS
2809 break;
2810 case 3:
7a387fff
TS
2811 switch (sel) {
2812 case 0:
1a3fd9c3
TS
2813 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo1));
2814 tcg_gen_ext32s_tl(t0, t0);
2423f660
TS
2815 rn = "EntryLo1";
2816 break;
7a387fff
TS
2817 default:
2818 goto die;
1579a72e 2819 }
873eb012
TS
2820 break;
2821 case 4:
7a387fff
TS
2822 switch (sel) {
2823 case 0:
1a3fd9c3
TS
2824 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_Context));
2825 tcg_gen_ext32s_tl(t0, t0);
2423f660
TS
2826 rn = "Context";
2827 break;
7a387fff 2828 case 1:
a7812ae4 2829// gen_helper_mfc0_contextconfig(t0); /* SmartMIPS ASE */
2423f660
TS
2830 rn = "ContextConfig";
2831// break;
7a387fff
TS
2832 default:
2833 goto die;
1579a72e 2834 }
873eb012
TS
2835 break;
2836 case 5:
7a387fff
TS
2837 switch (sel) {
2838 case 0:
1a3fd9c3 2839 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageMask));
2423f660
TS
2840 rn = "PageMask";
2841 break;
7a387fff 2842 case 1:
e189e748 2843 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 2844 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageGrain));
2423f660
TS
2845 rn = "PageGrain";
2846 break;
7a387fff
TS
2847 default:
2848 goto die;
1579a72e 2849 }
873eb012
TS
2850 break;
2851 case 6:
7a387fff
TS
2852 switch (sel) {
2853 case 0:
1a3fd9c3 2854 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Wired));
2423f660
TS
2855 rn = "Wired";
2856 break;
7a387fff 2857 case 1:
e189e748 2858 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 2859 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf0));
2423f660 2860 rn = "SRSConf0";
ead9360e 2861 break;
7a387fff 2862 case 2:
e189e748 2863 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 2864 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf1));
2423f660 2865 rn = "SRSConf1";
ead9360e 2866 break;
7a387fff 2867 case 3:
e189e748 2868 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 2869 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf2));
2423f660 2870 rn = "SRSConf2";
ead9360e 2871 break;
7a387fff 2872 case 4:
e189e748 2873 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 2874 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf3));
2423f660 2875 rn = "SRSConf3";
ead9360e 2876 break;
7a387fff 2877 case 5:
e189e748 2878 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 2879 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf4));
2423f660 2880 rn = "SRSConf4";
ead9360e 2881 break;
7a387fff
TS
2882 default:
2883 goto die;
1579a72e 2884 }
873eb012 2885 break;
8c0fdd85 2886 case 7:
7a387fff
TS
2887 switch (sel) {
2888 case 0:
e189e748 2889 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 2890 gen_mfc0_load32(t0, offsetof(CPUState, CP0_HWREna));
2423f660
TS
2891 rn = "HWREna";
2892 break;
7a387fff
TS
2893 default:
2894 goto die;
1579a72e 2895 }
8c0fdd85 2896 break;
873eb012 2897 case 8:
7a387fff
TS
2898 switch (sel) {
2899 case 0:
1a3fd9c3
TS
2900 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr));
2901 tcg_gen_ext32s_tl(t0, t0);
f0b3f3ae 2902 rn = "BadVAddr";
2423f660 2903 break;
7a387fff
TS
2904 default:
2905 goto die;
2906 }
873eb012
TS
2907 break;
2908 case 9:
7a387fff
TS
2909 switch (sel) {
2910 case 0:
2e70f6ef
PB
2911 /* Mark as an IO operation because we read the time. */
2912 if (use_icount)
2913 gen_io_start();
a7812ae4 2914 gen_helper_mfc0_count(t0);
2e70f6ef
PB
2915 if (use_icount) {
2916 gen_io_end();
2917 ctx->bstate = BS_STOP;
2918 }
2423f660
TS
2919 rn = "Count";
2920 break;
2921 /* 6,7 are implementation dependent */
7a387fff
TS
2922 default:
2923 goto die;
2423f660 2924 }
873eb012
TS
2925 break;
2926 case 10:
7a387fff
TS
2927 switch (sel) {
2928 case 0:
1a3fd9c3
TS
2929 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryHi));
2930 tcg_gen_ext32s_tl(t0, t0);
2423f660
TS
2931 rn = "EntryHi";
2932 break;
7a387fff
TS
2933 default:
2934 goto die;
1579a72e 2935 }
873eb012
TS
2936 break;
2937 case 11:
7a387fff
TS
2938 switch (sel) {
2939 case 0:
1a3fd9c3 2940 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Compare));
2423f660
TS
2941 rn = "Compare";
2942 break;
2943 /* 6,7 are implementation dependent */
7a387fff
TS
2944 default:
2945 goto die;
2423f660 2946 }
873eb012
TS
2947 break;
2948 case 12:
7a387fff
TS
2949 switch (sel) {
2950 case 0:
1a3fd9c3 2951 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Status));
2423f660
TS
2952 rn = "Status";
2953 break;
7a387fff 2954 case 1:
e189e748 2955 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 2956 gen_mfc0_load32(t0, offsetof(CPUState, CP0_IntCtl));
2423f660
TS
2957 rn = "IntCtl";
2958 break;
7a387fff 2959 case 2:
e189e748 2960 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 2961 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSCtl));
2423f660
TS
2962 rn = "SRSCtl";
2963 break;
7a387fff 2964 case 3:
e189e748 2965 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 2966 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSMap));
2423f660 2967 rn = "SRSMap";
fd88b6ab 2968 break;
7a387fff
TS
2969 default:
2970 goto die;
2971 }
873eb012
TS
2972 break;
2973 case 13:
7a387fff
TS
2974 switch (sel) {
2975 case 0:
1a3fd9c3 2976 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Cause));
2423f660
TS
2977 rn = "Cause";
2978 break;
7a387fff
TS
2979 default:
2980 goto die;
2981 }
873eb012
TS
2982 break;
2983 case 14:
7a387fff
TS
2984 switch (sel) {
2985 case 0:
1a3fd9c3
TS
2986 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
2987 tcg_gen_ext32s_tl(t0, t0);
2423f660
TS
2988 rn = "EPC";
2989 break;
7a387fff
TS
2990 default:
2991 goto die;
1579a72e 2992 }
873eb012
TS
2993 break;
2994 case 15:
7a387fff
TS
2995 switch (sel) {
2996 case 0:
1a3fd9c3 2997 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PRid));
2423f660
TS
2998 rn = "PRid";
2999 break;
7a387fff 3000 case 1:
e189e748 3001 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 3002 gen_mfc0_load32(t0, offsetof(CPUState, CP0_EBase));
2423f660
TS
3003 rn = "EBase";
3004 break;
7a387fff
TS
3005 default:
3006 goto die;
3007 }
873eb012
TS
3008 break;
3009 case 16:
3010 switch (sel) {
3011 case 0:
1a3fd9c3 3012 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config0));
873eb012
TS
3013 rn = "Config";
3014 break;
3015 case 1:
1a3fd9c3 3016 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config1));
873eb012
TS
3017 rn = "Config1";
3018 break;
7a387fff 3019 case 2:
1a3fd9c3 3020 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config2));
7a387fff
TS
3021 rn = "Config2";
3022 break;
3023 case 3:
1a3fd9c3 3024 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config3));
7a387fff
TS
3025 rn = "Config3";
3026 break;
e397ee33
TS
3027 /* 4,5 are reserved */
3028 /* 6,7 are implementation dependent */
3029 case 6:
1a3fd9c3 3030 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config6));
e397ee33
TS
3031 rn = "Config6";
3032 break;
3033 case 7:
1a3fd9c3 3034 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config7));
e397ee33
TS
3035 rn = "Config7";
3036 break;
873eb012 3037 default:
873eb012
TS
3038 goto die;
3039 }
3040 break;
3041 case 17:
7a387fff
TS
3042 switch (sel) {
3043 case 0:
a7812ae4 3044 gen_helper_mfc0_lladdr(t0);
2423f660
TS
3045 rn = "LLAddr";
3046 break;
7a387fff
TS
3047 default:
3048 goto die;
3049 }
873eb012
TS
3050 break;
3051 case 18:
7a387fff 3052 switch (sel) {
fd88b6ab 3053 case 0 ... 7:
a7812ae4 3054 gen_helper_1i(mfc0_watchlo, t0, sel);
2423f660
TS
3055 rn = "WatchLo";
3056 break;
7a387fff
TS
3057 default:
3058 goto die;
3059 }
873eb012
TS
3060 break;
3061 case 19:
7a387fff 3062 switch (sel) {
fd88b6ab 3063 case 0 ...7:
a7812ae4 3064 gen_helper_1i(mfc0_watchhi, t0, sel);
2423f660
TS
3065 rn = "WatchHi";
3066 break;
7a387fff
TS
3067 default:
3068 goto die;
3069 }
873eb012 3070 break;
8c0fdd85 3071 case 20:
7a387fff
TS
3072 switch (sel) {
3073 case 0:
d26bc211 3074#if defined(TARGET_MIPS64)
e189e748 3075 check_insn(env, ctx, ISA_MIPS3);
1a3fd9c3
TS
3076 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_XContext));
3077 tcg_gen_ext32s_tl(t0, t0);
2423f660
TS
3078 rn = "XContext";
3079 break;
703eaf37 3080#endif
7a387fff
TS
3081 default:
3082 goto die;
3083 }
8c0fdd85
TS
3084 break;
3085 case 21:
7a387fff
TS
3086 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3087 switch (sel) {
3088 case 0:
1a3fd9c3 3089 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Framemask));
2423f660
TS
3090 rn = "Framemask";
3091 break;
7a387fff
TS
3092 default:
3093 goto die;
3094 }
8c0fdd85
TS
3095 break;
3096 case 22:
da80682b 3097 tcg_gen_movi_tl(t0, 0); /* unimplemented */
2423f660
TS
3098 rn = "'Diagnostic"; /* implementation dependent */
3099 break;
873eb012 3100 case 23:
7a387fff
TS
3101 switch (sel) {
3102 case 0:
a7812ae4 3103 gen_helper_mfc0_debug(t0); /* EJTAG support */
2423f660
TS
3104 rn = "Debug";
3105 break;
7a387fff 3106 case 1:
a7812ae4 3107// gen_helper_mfc0_tracecontrol(t0); /* PDtrace support */
2423f660
TS
3108 rn = "TraceControl";
3109// break;
7a387fff 3110 case 2:
a7812ae4 3111// gen_helper_mfc0_tracecontrol2(t0); /* PDtrace support */
2423f660
TS
3112 rn = "TraceControl2";
3113// break;
7a387fff 3114 case 3:
a7812ae4 3115// gen_helper_mfc0_usertracedata(t0); /* PDtrace support */
2423f660
TS
3116 rn = "UserTraceData";
3117// break;
7a387fff 3118 case 4:
a7812ae4 3119// gen_helper_mfc0_tracebpc(t0); /* PDtrace support */
2423f660
TS
3120 rn = "TraceBPC";
3121// break;
7a387fff
TS
3122 default:
3123 goto die;
3124 }
873eb012
TS
3125 break;
3126 case 24:
7a387fff
TS
3127 switch (sel) {
3128 case 0:
f0b3f3ae 3129 /* EJTAG support */
1a3fd9c3
TS
3130 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
3131 tcg_gen_ext32s_tl(t0, t0);
2423f660
TS
3132 rn = "DEPC";
3133 break;
7a387fff
TS
3134 default:
3135 goto die;
3136 }
873eb012 3137 break;
8c0fdd85 3138 case 25:
7a387fff
TS
3139 switch (sel) {
3140 case 0:
1a3fd9c3 3141 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Performance0));
2423f660 3142 rn = "Performance0";
7a387fff
TS
3143 break;
3144 case 1:
a7812ae4 3145// gen_helper_mfc0_performance1(t0);
2423f660
TS
3146 rn = "Performance1";
3147// break;
7a387fff 3148 case 2:
a7812ae4 3149// gen_helper_mfc0_performance2(t0);
2423f660
TS
3150 rn = "Performance2";
3151// break;
7a387fff 3152 case 3:
a7812ae4 3153// gen_helper_mfc0_performance3(t0);
2423f660
TS
3154 rn = "Performance3";
3155// break;
7a387fff 3156 case 4:
a7812ae4 3157// gen_helper_mfc0_performance4(t0);
2423f660
TS
3158 rn = "Performance4";
3159// break;
7a387fff 3160 case 5:
a7812ae4 3161// gen_helper_mfc0_performance5(t0);
2423f660
TS
3162 rn = "Performance5";
3163// break;
7a387fff 3164 case 6:
a7812ae4 3165// gen_helper_mfc0_performance6(t0);
2423f660
TS
3166 rn = "Performance6";
3167// break;
7a387fff 3168 case 7:
a7812ae4 3169// gen_helper_mfc0_performance7(t0);
2423f660
TS
3170 rn = "Performance7";
3171// break;
7a387fff
TS
3172 default:
3173 goto die;
3174 }
8c0fdd85
TS
3175 break;
3176 case 26:
da80682b
AJ
3177 tcg_gen_movi_tl(t0, 0); /* unimplemented */
3178 rn = "ECC";
3179 break;
8c0fdd85 3180 case 27:
7a387fff 3181 switch (sel) {
7a387fff 3182 case 0 ... 3:
da80682b 3183 tcg_gen_movi_tl(t0, 0); /* unimplemented */
2423f660
TS
3184 rn = "CacheErr";
3185 break;
7a387fff
TS
3186 default:
3187 goto die;
3188 }
8c0fdd85 3189 break;
873eb012
TS
3190 case 28:
3191 switch (sel) {
3192 case 0:
7a387fff
TS
3193 case 2:
3194 case 4:
3195 case 6:
1a3fd9c3 3196 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagLo));
873eb012
TS
3197 rn = "TagLo";
3198 break;
3199 case 1:
7a387fff
TS
3200 case 3:
3201 case 5:
3202 case 7:
1a3fd9c3 3203 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataLo));
873eb012
TS
3204 rn = "DataLo";
3205 break;
3206 default:
873eb012
TS
3207 goto die;
3208 }
3209 break;
8c0fdd85 3210 case 29:
7a387fff
TS
3211 switch (sel) {
3212 case 0:
3213 case 2:
3214 case 4:
3215 case 6:
1a3fd9c3 3216 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagHi));
7a387fff
TS
3217 rn = "TagHi";
3218 break;
3219 case 1:
3220 case 3:
3221 case 5:
3222 case 7:
1a3fd9c3 3223 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataHi));
7a387fff
TS
3224 rn = "DataHi";
3225 break;
3226 default:
3227 goto die;
3228 }
8c0fdd85 3229 break;
873eb012 3230 case 30:
7a387fff
TS
3231 switch (sel) {
3232 case 0:
1a3fd9c3
TS
3233 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
3234 tcg_gen_ext32s_tl(t0, t0);
2423f660
TS
3235 rn = "ErrorEPC";
3236 break;
7a387fff
TS
3237 default:
3238 goto die;
3239 }
873eb012
TS
3240 break;
3241 case 31:
7a387fff
TS
3242 switch (sel) {
3243 case 0:
f0b3f3ae 3244 /* EJTAG support */
1a3fd9c3 3245 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DESAVE));
2423f660
TS
3246 rn = "DESAVE";
3247 break;
7a387fff
TS
3248 default:
3249 goto die;
3250 }
873eb012
TS
3251 break;
3252 default:
873eb012
TS
3253 goto die;
3254 }
d12d51d5 3255 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
873eb012
TS
3256 return;
3257
3258die:
d12d51d5 3259 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
873eb012
TS
3260 generate_exception(ctx, EXCP_RI);
3261}
3262
1a3fd9c3 3263static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
8c0fdd85 3264{
7a387fff
TS
3265 const char *rn = "invalid";
3266
e189e748
TS
3267 if (sel != 0)
3268 check_insn(env, ctx, ISA_MIPS32);
3269
2e70f6ef
PB
3270 if (use_icount)
3271 gen_io_start();
3272
8c0fdd85
TS
3273 switch (reg) {
3274 case 0:
7a387fff
TS
3275 switch (sel) {
3276 case 0:
a7812ae4 3277 gen_helper_mtc0_index(t0);
7a387fff
TS
3278 rn = "Index";
3279 break;
3280 case 1:
7385ac0b 3281 check_insn(env, ctx, ASE_MT);
a7812ae4 3282 gen_helper_mtc0_mvpcontrol(t0);
7a387fff 3283 rn = "MVPControl";
ead9360e 3284 break;
7a387fff 3285 case 2:
7385ac0b 3286 check_insn(env, ctx, ASE_MT);
ead9360e 3287 /* ignored */
7a387fff 3288 rn = "MVPConf0";
ead9360e 3289 break;
7a387fff 3290 case 3:
7385ac0b 3291 check_insn(env, ctx, ASE_MT);
ead9360e 3292 /* ignored */
7a387fff 3293 rn = "MVPConf1";
ead9360e 3294 break;
7a387fff
TS
3295 default:
3296 goto die;
3297 }
8c0fdd85
TS
3298 break;
3299 case 1:
7a387fff
TS
3300 switch (sel) {
3301 case 0:
2423f660 3302 /* ignored */
7a387fff 3303 rn = "Random";
2423f660 3304 break;
7a387fff 3305 case 1:
7385ac0b 3306 check_insn(env, ctx, ASE_MT);
a7812ae4 3307 gen_helper_mtc0_vpecontrol(t0);
7a387fff 3308 rn = "VPEControl";
ead9360e 3309 break;
7a387fff 3310 case 2:
7385ac0b 3311 check_insn(env, ctx, ASE_MT);
a7812ae4 3312 gen_helper_mtc0_vpeconf0(t0);
7a387fff 3313 rn = "VPEConf0";
ead9360e 3314 break;
7a387fff 3315 case 3:
7385ac0b 3316 check_insn(env, ctx, ASE_MT);
a7812ae4 3317 gen_helper_mtc0_vpeconf1(t0);
7a387fff 3318 rn = "VPEConf1";
ead9360e 3319 break;
7a387fff 3320 case 4:
7385ac0b 3321 check_insn(env, ctx, ASE_MT);
a7812ae4 3322 gen_helper_mtc0_yqmask(t0);
7a387fff 3323 rn = "YQMask";
ead9360e 3324 break;
7a387fff 3325 case 5:
7385ac0b 3326 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3327 gen_mtc0_store64(t0, offsetof(CPUState, CP0_VPESchedule));
7a387fff 3328 rn = "VPESchedule";
ead9360e 3329 break;
7a387fff 3330 case 6:
7385ac0b 3331 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3332 gen_mtc0_store64(t0, offsetof(CPUState, CP0_VPEScheFBack));
7a387fff 3333 rn = "VPEScheFBack";
ead9360e 3334 break;
7a387fff 3335 case 7:
7385ac0b 3336 check_insn(env, ctx, ASE_MT);
a7812ae4 3337 gen_helper_mtc0_vpeopt(t0);
7a387fff 3338 rn = "VPEOpt";
ead9360e 3339 break;
7a387fff
TS
3340 default:
3341 goto die;
3342 }
8c0fdd85
TS
3343 break;
3344 case 2:
7a387fff
TS
3345 switch (sel) {
3346 case 0:
a7812ae4 3347 gen_helper_mtc0_entrylo0(t0);
2423f660
TS
3348 rn = "EntryLo0";
3349 break;
7a387fff 3350 case 1:
7385ac0b 3351 check_insn(env, ctx, ASE_MT);
a7812ae4 3352 gen_helper_mtc0_tcstatus(t0);
2423f660 3353 rn = "TCStatus";
ead9360e 3354 break;
7a387fff 3355 case 2:
7385ac0b 3356 check_insn(env, ctx, ASE_MT);
a7812ae4 3357 gen_helper_mtc0_tcbind(t0);
2423f660 3358 rn = "TCBind";
ead9360e 3359 break;
7a387fff 3360 case 3:
7385ac0b 3361 check_insn(env, ctx, ASE_MT);
a7812ae4 3362 gen_helper_mtc0_tcrestart(t0);
2423f660 3363 rn = "TCRestart";
ead9360e 3364 break;
7a387fff 3365 case 4:
7385ac0b 3366 check_insn(env, ctx, ASE_MT);
a7812ae4 3367 gen_helper_mtc0_tchalt(t0);
2423f660 3368 rn = "TCHalt";
ead9360e 3369 break;
7a387fff 3370 case 5:
7385ac0b 3371 check_insn(env, ctx, ASE_MT);
a7812ae4 3372 gen_helper_mtc0_tccontext(t0);
2423f660 3373 rn = "TCContext";
ead9360e 3374 break;
7a387fff 3375 case 6:
7385ac0b 3376 check_insn(env, ctx, ASE_MT);
a7812ae4 3377 gen_helper_mtc0_tcschedule(t0);
2423f660 3378 rn = "TCSchedule";
ead9360e 3379 break;
7a387fff 3380 case 7:
7385ac0b 3381 check_insn(env, ctx, ASE_MT);
a7812ae4 3382 gen_helper_mtc0_tcschefback(t0);
2423f660 3383 rn = "TCScheFBack";
ead9360e 3384 break;
7a387fff
TS
3385 default:
3386 goto die;
3387 }
8c0fdd85
TS
3388 break;
3389 case 3:
7a387fff
TS
3390 switch (sel) {
3391 case 0:
a7812ae4 3392 gen_helper_mtc0_entrylo1(t0);
2423f660
TS
3393 rn = "EntryLo1";
3394 break;
7a387fff
TS
3395 default:
3396 goto die;
876d4b07 3397 }
8c0fdd85
TS
3398 break;
3399 case 4:
7a387fff
TS
3400 switch (sel) {
3401 case 0:
a7812ae4 3402 gen_helper_mtc0_context(t0);
2423f660
TS
3403 rn = "Context";
3404 break;
7a387fff 3405 case 1:
a7812ae4 3406// gen_helper_mtc0_contextconfig(t0); /* SmartMIPS ASE */
2423f660
TS
3407 rn = "ContextConfig";
3408// break;
7a387fff
TS
3409 default:
3410 goto die;
876d4b07 3411 }
8c0fdd85
TS
3412 break;
3413 case 5:
7a387fff
TS
3414 switch (sel) {
3415 case 0:
a7812ae4 3416 gen_helper_mtc0_pagemask(t0);
2423f660
TS
3417 rn = "PageMask";
3418 break;
7a387fff 3419 case 1:
e189e748 3420 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 3421 gen_helper_mtc0_pagegrain(t0);
2423f660
TS
3422 rn = "PageGrain";
3423 break;
7a387fff
TS
3424 default:
3425 goto die;
876d4b07 3426 }
8c0fdd85
TS
3427 break;
3428 case 6:
7a387fff
TS
3429 switch (sel) {
3430 case 0:
a7812ae4 3431 gen_helper_mtc0_wired(t0);
2423f660
TS
3432 rn = "Wired";
3433 break;
7a387fff 3434 case 1:
e189e748 3435 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 3436 gen_helper_mtc0_srsconf0(t0);
2423f660 3437 rn = "SRSConf0";
ead9360e 3438 break;
7a387fff 3439 case 2:
e189e748 3440 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 3441 gen_helper_mtc0_srsconf1(t0);
2423f660 3442 rn = "SRSConf1";
ead9360e 3443 break;
7a387fff 3444 case 3:
e189e748 3445 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 3446 gen_helper_mtc0_srsconf2(t0);
2423f660 3447 rn = "SRSConf2";
ead9360e 3448 break;
7a387fff 3449 case 4:
e189e748 3450 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 3451 gen_helper_mtc0_srsconf3(t0);
2423f660 3452 rn = "SRSConf3";
ead9360e 3453 break;
7a387fff 3454 case 5:
e189e748 3455 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 3456 gen_helper_mtc0_srsconf4(t0);
2423f660 3457 rn = "SRSConf4";
ead9360e 3458 break;
7a387fff
TS
3459 default:
3460 goto die;
876d4b07 3461 }
8c0fdd85
TS
3462 break;
3463 case 7:
7a387fff
TS
3464 switch (sel) {
3465 case 0:
e189e748 3466 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 3467 gen_helper_mtc0_hwrena(t0);
2423f660
TS
3468 rn = "HWREna";
3469 break;
7a387fff
TS
3470 default:
3471 goto die;
876d4b07 3472 }
8c0fdd85
TS
3473 break;
3474 case 8:
7a387fff 3475 /* ignored */
f0b3f3ae 3476 rn = "BadVAddr";
8c0fdd85
TS
3477 break;
3478 case 9:
7a387fff
TS
3479 switch (sel) {
3480 case 0:
a7812ae4 3481 gen_helper_mtc0_count(t0);
2423f660
TS
3482 rn = "Count";
3483 break;
876d4b07 3484 /* 6,7 are implementation dependent */
7a387fff
TS
3485 default:
3486 goto die;
876d4b07
TS
3487 }
3488 /* Stop translation as we may have switched the execution mode */
3489 ctx->bstate = BS_STOP;
8c0fdd85
TS
3490 break;
3491 case 10:
7a387fff
TS
3492 switch (sel) {
3493 case 0:
a7812ae4 3494 gen_helper_mtc0_entryhi(t0);
2423f660
TS
3495 rn = "EntryHi";
3496 break;
7a387fff
TS
3497 default:
3498 goto die;
876d4b07 3499 }
8c0fdd85
TS
3500 break;
3501 case 11:
7a387fff
TS
3502 switch (sel) {
3503 case 0:
a7812ae4 3504 gen_helper_mtc0_compare(t0);
2423f660
TS
3505 rn = "Compare";
3506 break;
3507 /* 6,7 are implementation dependent */
7a387fff
TS
3508 default:
3509 goto die;
876d4b07 3510 }
de9a95f0
AJ
3511 /* Stop translation as we may have switched the execution mode */
3512 ctx->bstate = BS_STOP;
8c0fdd85
TS
3513 break;
3514 case 12:
7a387fff
TS
3515 switch (sel) {
3516 case 0:
a7812ae4 3517 gen_helper_mtc0_status(t0);
8487327a
TS
3518 /* BS_STOP isn't good enough here, hflags may have changed. */
3519 gen_save_pc(ctx->pc + 4);
3520 ctx->bstate = BS_EXCP;
2423f660
TS
3521 rn = "Status";
3522 break;
7a387fff 3523 case 1:
e189e748 3524 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 3525 gen_helper_mtc0_intctl(t0);
8487327a
TS
3526 /* Stop translation as we may have switched the execution mode */
3527 ctx->bstate = BS_STOP;
2423f660
TS
3528 rn = "IntCtl";
3529 break;
7a387fff 3530 case 2:
e189e748 3531 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 3532 gen_helper_mtc0_srsctl(t0);
8487327a
TS
3533 /* Stop translation as we may have switched the execution mode */
3534 ctx->bstate = BS_STOP;
2423f660
TS
3535 rn = "SRSCtl";
3536 break;
7a387fff 3537 case 3:
e189e748 3538 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 3539 gen_mtc0_store32(t0, offsetof(CPUState, CP0_SRSMap));
8487327a
TS
3540 /* Stop translation as we may have switched the execution mode */
3541 ctx->bstate = BS_STOP;
2423f660 3542 rn = "SRSMap";
fd88b6ab 3543 break;
7a387fff
TS
3544 default:
3545 goto die;
876d4b07 3546 }
8c0fdd85
TS
3547 break;
3548 case 13:
7a387fff
TS
3549 switch (sel) {
3550 case 0:
a7812ae4 3551 gen_helper_mtc0_cause(t0);
2423f660
TS
3552 rn = "Cause";
3553 break;
7a387fff
TS
3554 default:
3555 goto die;
876d4b07
TS
3556 }
3557 /* Stop translation as we may have switched the execution mode */
3558 ctx->bstate = BS_STOP;
8c0fdd85
TS
3559 break;
3560 case 14:
7a387fff
TS
3561 switch (sel) {
3562 case 0:
1a3fd9c3 3563 gen_mtc0_store64(t0, offsetof(CPUState, CP0_EPC));
2423f660
TS
3564 rn = "EPC";
3565 break;
7a387fff
TS
3566 default:
3567 goto die;
876d4b07 3568 }
8c0fdd85
TS
3569 break;
3570 case 15:
7a387fff
TS
3571 switch (sel) {
3572 case 0:
2423f660
TS
3573 /* ignored */
3574 rn = "PRid";
3575 break;
7a387fff 3576 case 1:
e189e748 3577 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 3578 gen_helper_mtc0_ebase(t0);
2423f660
TS
3579 rn = "EBase";
3580 break;
7a387fff
TS
3581 default:
3582 goto die;
1579a72e 3583 }
8c0fdd85
TS
3584 break;
3585 case 16:
3586 switch (sel) {
3587 case 0:
a7812ae4 3588 gen_helper_mtc0_config0(t0);
7a387fff 3589 rn = "Config";
2423f660
TS
3590 /* Stop translation as we may have switched the execution mode */
3591 ctx->bstate = BS_STOP;
7a387fff
TS
3592 break;
3593 case 1:
e397ee33 3594 /* ignored, read only */
7a387fff
TS
3595 rn = "Config1";
3596 break;
3597 case 2:
a7812ae4 3598 gen_helper_mtc0_config2(t0);
7a387fff 3599 rn = "Config2";
2423f660
TS
3600 /* Stop translation as we may have switched the execution mode */
3601 ctx->bstate = BS_STOP;
8c0fdd85 3602 break;
7a387fff 3603 case 3:
e397ee33 3604 /* ignored, read only */
7a387fff
TS
3605 rn = "Config3";
3606 break;
e397ee33
TS
3607 /* 4,5 are reserved */
3608 /* 6,7 are implementation dependent */
3609 case 6:
3610 /* ignored */
3611 rn = "Config6";
3612 break;
3613 case 7:
3614 /* ignored */
3615 rn = "Config7";
3616 break;
8c0fdd85
TS
3617 default:
3618 rn = "Invalid config selector";
3619 goto die;
3620 }
3621 break;
3622 case 17:
7a387fff
TS
3623 switch (sel) {
3624 case 0:
2423f660
TS
3625 /* ignored */
3626 rn = "LLAddr";
3627 break;
7a387fff
TS
3628 default:
3629 goto die;
3630 }
8c0fdd85
TS
3631 break;
3632 case 18:
7a387fff 3633 switch (sel) {
fd88b6ab 3634 case 0 ... 7:
a7812ae4 3635 gen_helper_1i(mtc0_watchlo, t0, sel);
2423f660
TS
3636 rn = "WatchLo";
3637 break;
7a387fff
TS
3638 default:
3639 goto die;
3640 }
8c0fdd85
TS
3641 break;
3642 case 19:
7a387fff 3643 switch (sel) {
fd88b6ab 3644 case 0 ... 7:
a7812ae4 3645 gen_helper_1i(mtc0_watchhi, t0, sel);
2423f660
TS
3646 rn = "WatchHi";
3647 break;
7a387fff
TS
3648 default:
3649 goto die;
3650 }
8c0fdd85
TS
3651 break;
3652 case 20:
7a387fff
TS
3653 switch (sel) {
3654 case 0:
d26bc211 3655#if defined(TARGET_MIPS64)
e189e748 3656 check_insn(env, ctx, ISA_MIPS3);
a7812ae4 3657 gen_helper_mtc0_xcontext(t0);
2423f660
TS
3658 rn = "XContext";
3659 break;
703eaf37 3660#endif
7a387fff
TS
3661 default:
3662 goto die;
3663 }
8c0fdd85
TS
3664 break;
3665 case 21:
7a387fff
TS
3666 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3667 switch (sel) {
3668 case 0:
a7812ae4 3669 gen_helper_mtc0_framemask(t0);
2423f660
TS
3670 rn = "Framemask";
3671 break;
7a387fff
TS
3672 default:
3673 goto die;
3674 }
3675 break;
8c0fdd85 3676 case 22:
7a387fff
TS
3677 /* ignored */
3678 rn = "Diagnostic"; /* implementation dependent */
2423f660 3679 break;
8c0fdd85 3680 case 23:
7a387fff
TS
3681 switch (sel) {
3682 case 0:
a7812ae4 3683 gen_helper_mtc0_debug(t0); /* EJTAG support */
8487327a
TS
3684 /* BS_STOP isn't good enough here, hflags may have changed. */
3685 gen_save_pc(ctx->pc + 4);
3686 ctx->bstate = BS_EXCP;
2423f660
TS
3687 rn = "Debug";
3688 break;
7a387fff 3689 case 1:
a7812ae4 3690// gen_helper_mtc0_tracecontrol(t0); /* PDtrace support */
2423f660 3691 rn = "TraceControl";
8487327a
TS
3692 /* Stop translation as we may have switched the execution mode */
3693 ctx->bstate = BS_STOP;
2423f660 3694// break;
7a387fff 3695 case 2:
a7812ae4 3696// gen_helper_mtc0_tracecontrol2(t0); /* PDtrace support */
2423f660 3697 rn = "TraceControl2";
8487327a
TS
3698 /* Stop translation as we may have switched the execution mode */
3699 ctx->bstate = BS_STOP;
2423f660 3700// break;
7a387fff 3701 case 3:
8487327a
TS
3702 /* Stop translation as we may have switched the execution mode */
3703 ctx->bstate = BS_STOP;
a7812ae4 3704// gen_helper_mtc0_usertracedata(t0); /* PDtrace support */
2423f660 3705 rn = "UserTraceData";
8487327a
TS
3706 /* Stop translation as we may have switched the execution mode */
3707 ctx->bstate = BS_STOP;
2423f660 3708// break;
7a387fff 3709 case 4:
a7812ae4 3710// gen_helper_mtc0_tracebpc(t0); /* PDtrace support */
8487327a
TS
3711 /* Stop translation as we may have switched the execution mode */
3712 ctx->bstate = BS_STOP;
2423f660
TS
3713 rn = "TraceBPC";
3714// break;
7a387fff
TS
3715 default:
3716 goto die;
3717 }
8c0fdd85
TS
3718 break;
3719 case 24:
7a387fff
TS
3720 switch (sel) {
3721 case 0:
f1aa6320 3722 /* EJTAG support */
1a3fd9c3 3723 gen_mtc0_store64(t0, offsetof(CPUState, CP0_DEPC));
2423f660
TS
3724 rn = "DEPC";
3725 break;
7a387fff
TS
3726 default:
3727 goto die;
3728 }
8c0fdd85
TS
3729 break;
3730 case 25:
7a387fff
TS
3731 switch (sel) {
3732 case 0:
a7812ae4 3733 gen_helper_mtc0_performance0(t0);
2423f660
TS
3734 rn = "Performance0";
3735 break;
7a387fff 3736 case 1:
a7812ae4 3737// gen_helper_mtc0_performance1(t0);
2423f660
TS
3738 rn = "Performance1";
3739// break;
7a387fff 3740 case 2:
a7812ae4 3741// gen_helper_mtc0_performance2(t0);
2423f660
TS
3742 rn = "Performance2";
3743// break;
7a387fff 3744 case 3:
a7812ae4 3745// gen_helper_mtc0_performance3(t0);
2423f660
TS
3746 rn = "Performance3";
3747// break;
7a387fff 3748 case 4:
a7812ae4 3749// gen_helper_mtc0_performance4(t0);
2423f660
TS
3750 rn = "Performance4";
3751// break;
7a387fff 3752 case 5:
a7812ae4 3753// gen_helper_mtc0_performance5(t0);
2423f660
TS
3754 rn = "Performance5";
3755// break;
7a387fff 3756 case 6:
a7812ae4 3757// gen_helper_mtc0_performance6(t0);
2423f660
TS
3758 rn = "Performance6";
3759// break;
7a387fff 3760 case 7:
a7812ae4 3761// gen_helper_mtc0_performance7(t0);
2423f660
TS
3762 rn = "Performance7";
3763// break;
7a387fff
TS
3764 default:
3765 goto die;
3766 }
8c0fdd85
TS
3767 break;
3768 case 26:
2423f660 3769 /* ignored */
8c0fdd85 3770 rn = "ECC";
2423f660 3771 break;
8c0fdd85 3772 case 27:
7a387fff
TS
3773 switch (sel) {
3774 case 0 ... 3:
2423f660
TS
3775 /* ignored */
3776 rn = "CacheErr";
3777 break;
7a387fff
TS
3778 default:
3779 goto die;
3780 }
8c0fdd85
TS
3781 break;
3782 case 28:
3783 switch (sel) {
3784 case 0:
7a387fff
TS
3785 case 2:
3786 case 4:
3787 case 6:
a7812ae4 3788 gen_helper_mtc0_taglo(t0);
8c0fdd85
TS
3789 rn = "TagLo";
3790 break;
7a387fff
TS
3791 case 1:
3792 case 3:
3793 case 5:
3794 case 7:
a7812ae4 3795 gen_helper_mtc0_datalo(t0);
7a387fff
TS
3796 rn = "DataLo";
3797 break;
8c0fdd85 3798 default:
8c0fdd85
TS
3799 goto die;
3800 }
3801 break;
3802 case 29:
7a387fff
TS
3803 switch (sel) {
3804 case 0:
3805 case 2:
3806 case 4:
3807 case 6:
a7812ae4 3808 gen_helper_mtc0_taghi(t0);
7a387fff
TS
3809 rn = "TagHi";
3810 break;
3811 case 1:
3812 case 3:
3813 case 5:
3814 case 7:
a7812ae4 3815 gen_helper_mtc0_datahi(t0);
7a387fff
TS
3816 rn = "DataHi";
3817 break;
3818 default:
3819 rn = "invalid sel";
3820 goto die;
3821 }
8c0fdd85
TS
3822 break;
3823 case 30:
7a387fff
TS
3824 switch (sel) {
3825 case 0:
1a3fd9c3 3826 gen_mtc0_store64(t0, offsetof(CPUState, CP0_ErrorEPC));
2423f660
TS
3827 rn = "ErrorEPC";
3828 break;
7a387fff
TS
3829 default:
3830 goto die;
3831 }
8c0fdd85
TS
3832 break;
3833 case 31:
7a387fff
TS
3834 switch (sel) {
3835 case 0:
f1aa6320 3836 /* EJTAG support */
1a3fd9c3 3837 gen_mtc0_store32(t0, offsetof(CPUState, CP0_DESAVE));
2423f660
TS
3838 rn = "DESAVE";
3839 break;
7a387fff
TS
3840 default:
3841 goto die;
3842 }
2423f660
TS
3843 /* Stop translation as we may have switched the execution mode */
3844 ctx->bstate = BS_STOP;
8c0fdd85
TS
3845 break;
3846 default:
8c0fdd85
TS
3847 goto die;
3848 }
d12d51d5 3849 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
bf20dc07 3850 /* For simplicity assume that all writes can cause interrupts. */
2e70f6ef
PB
3851 if (use_icount) {
3852 gen_io_end();
3853 ctx->bstate = BS_STOP;
3854 }
8c0fdd85
TS
3855 return;
3856
3857die:
d12d51d5 3858 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
8c0fdd85
TS
3859 generate_exception(ctx, EXCP_RI);
3860}
3861
d26bc211 3862#if defined(TARGET_MIPS64)
1a3fd9c3 3863static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
9c2149c8
TS
3864{
3865 const char *rn = "invalid";
3866
e189e748
TS
3867 if (sel != 0)
3868 check_insn(env, ctx, ISA_MIPS64);
3869
9c2149c8
TS
3870 switch (reg) {
3871 case 0:
3872 switch (sel) {
3873 case 0:
1a3fd9c3 3874 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Index));
9c2149c8
TS
3875 rn = "Index";
3876 break;
3877 case 1:
7385ac0b 3878 check_insn(env, ctx, ASE_MT);
a7812ae4 3879 gen_helper_mfc0_mvpcontrol(t0);
9c2149c8 3880 rn = "MVPControl";
ead9360e 3881 break;
9c2149c8 3882 case 2:
7385ac0b 3883 check_insn(env, ctx, ASE_MT);
a7812ae4 3884 gen_helper_mfc0_mvpconf0(t0);
9c2149c8 3885 rn = "MVPConf0";
ead9360e 3886 break;
9c2149c8 3887 case 3:
7385ac0b 3888 check_insn(env, ctx, ASE_MT);
a7812ae4 3889 gen_helper_mfc0_mvpconf1(t0);
9c2149c8 3890 rn = "MVPConf1";
ead9360e 3891 break;
9c2149c8
TS
3892 default:
3893 goto die;
3894 }
3895 break;
3896 case 1:
3897 switch (sel) {
3898 case 0:
a7812ae4 3899 gen_helper_mfc0_random(t0);
9c2149c8 3900 rn = "Random";
2423f660 3901 break;
9c2149c8 3902 case 1:
7385ac0b 3903 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3904 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEControl));
9c2149c8 3905 rn = "VPEControl";
ead9360e 3906 break;
9c2149c8 3907 case 2:
7385ac0b 3908 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3909 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf0));
9c2149c8 3910 rn = "VPEConf0";
ead9360e 3911 break;
9c2149c8 3912 case 3:
7385ac0b 3913 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3914 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf1));
9c2149c8 3915 rn = "VPEConf1";
ead9360e 3916 break;
9c2149c8 3917 case 4:
7385ac0b 3918 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3919 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_YQMask));
9c2149c8 3920 rn = "YQMask";
ead9360e 3921 break;
9c2149c8 3922 case 5:
7385ac0b 3923 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3924 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_VPESchedule));
9c2149c8 3925 rn = "VPESchedule";
ead9360e 3926 break;
9c2149c8 3927 case 6:
7385ac0b 3928 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3929 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
9c2149c8 3930 rn = "VPEScheFBack";
ead9360e 3931 break;
9c2149c8 3932 case 7:
7385ac0b 3933 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3934 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEOpt));
9c2149c8 3935 rn = "VPEOpt";
ead9360e 3936 break;
9c2149c8
TS
3937 default:
3938 goto die;
3939 }
3940 break;
3941 case 2:
3942 switch (sel) {
3943 case 0:
1a3fd9c3 3944 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo0));
2423f660
TS
3945 rn = "EntryLo0";
3946 break;
9c2149c8 3947 case 1:
7385ac0b 3948 check_insn(env, ctx, ASE_MT);
a7812ae4 3949 gen_helper_mfc0_tcstatus(t0);
2423f660 3950 rn = "TCStatus";
ead9360e 3951 break;
9c2149c8 3952 case 2:
7385ac0b 3953 check_insn(env, ctx, ASE_MT);
a7812ae4 3954 gen_helper_mfc0_tcbind(t0);
2423f660 3955 rn = "TCBind";
ead9360e 3956 break;
9c2149c8 3957 case 3:
7385ac0b 3958 check_insn(env, ctx, ASE_MT);
a7812ae4 3959 gen_helper_dmfc0_tcrestart(t0);
2423f660 3960 rn = "TCRestart";
ead9360e 3961 break;
9c2149c8 3962 case 4:
7385ac0b 3963 check_insn(env, ctx, ASE_MT);
a7812ae4 3964 gen_helper_dmfc0_tchalt(t0);
2423f660 3965 rn = "TCHalt";
ead9360e 3966 break;
9c2149c8 3967 case 5:
7385ac0b 3968 check_insn(env, ctx, ASE_MT);
a7812ae4 3969 gen_helper_dmfc0_tccontext(t0);
2423f660 3970 rn = "TCContext";
ead9360e 3971 break;
9c2149c8 3972 case 6:
7385ac0b 3973 check_insn(env, ctx, ASE_MT);
a7812ae4 3974 gen_helper_dmfc0_tcschedule(t0);
2423f660 3975 rn = "TCSchedule";
ead9360e 3976 break;
9c2149c8 3977 case 7:
7385ac0b 3978 check_insn(env, ctx, ASE_MT);
a7812ae4 3979 gen_helper_dmfc0_tcschefback(t0);
2423f660 3980 rn = "TCScheFBack";
ead9360e 3981 break;
9c2149c8
TS
3982 default:
3983 goto die;
3984 }
3985 break;
3986 case 3:
3987 switch (sel) {
3988 case 0:
1a3fd9c3 3989 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo1));
2423f660
TS
3990 rn = "EntryLo1";
3991 break;
9c2149c8
TS
3992 default:
3993 goto die;
1579a72e 3994 }
9c2149c8
TS
3995 break;
3996 case 4:
3997 switch (sel) {
3998 case 0:
1a3fd9c3 3999 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_Context));
2423f660
TS
4000 rn = "Context";
4001 break;
9c2149c8 4002 case 1:
a7812ae4 4003// gen_helper_dmfc0_contextconfig(t0); /* SmartMIPS ASE */
2423f660
TS
4004 rn = "ContextConfig";
4005// break;
9c2149c8
TS
4006 default:
4007 goto die;
876d4b07 4008 }
9c2149c8
TS
4009 break;
4010 case 5:
4011 switch (sel) {
4012 case 0:
1a3fd9c3 4013 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageMask));
2423f660
TS
4014 rn = "PageMask";
4015 break;
9c2149c8 4016 case 1:
e189e748 4017 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4018 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageGrain));
2423f660
TS
4019 rn = "PageGrain";
4020 break;
9c2149c8
TS
4021 default:
4022 goto die;
876d4b07 4023 }
9c2149c8
TS
4024 break;
4025 case 6:
4026 switch (sel) {
4027 case 0:
1a3fd9c3 4028 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Wired));
2423f660
TS
4029 rn = "Wired";
4030 break;
9c2149c8 4031 case 1:
e189e748 4032 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4033 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf0));
2423f660 4034 rn = "SRSConf0";
ead9360e 4035 break;
9c2149c8 4036 case 2:
e189e748 4037 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4038 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf1));
2423f660 4039 rn = "SRSConf1";
ead9360e 4040 break;
9c2149c8 4041 case 3:
e189e748 4042 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4043 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf2));
2423f660 4044 rn = "SRSConf2";
ead9360e 4045 break;
9c2149c8 4046 case 4:
e189e748 4047 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4048 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf3));
2423f660 4049 rn = "SRSConf3";
ead9360e 4050 break;
9c2149c8 4051 case 5:
e189e748 4052 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4053 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf4));
2423f660 4054 rn = "SRSConf4";
ead9360e 4055 break;
9c2149c8
TS
4056 default:
4057 goto die;
876d4b07 4058 }
9c2149c8
TS
4059 break;
4060 case 7:
4061 switch (sel) {
4062 case 0:
e189e748 4063 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4064 gen_mfc0_load32(t0, offsetof(CPUState, CP0_HWREna));
2423f660
TS
4065 rn = "HWREna";
4066 break;
9c2149c8
TS
4067 default:
4068 goto die;
876d4b07 4069 }
9c2149c8
TS
4070 break;
4071 case 8:
4072 switch (sel) {
4073 case 0:
1a3fd9c3 4074 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr));
f0b3f3ae 4075 rn = "BadVAddr";
2423f660 4076 break;
9c2149c8
TS
4077 default:
4078 goto die;
876d4b07 4079 }
9c2149c8
TS
4080 break;
4081 case 9:
4082 switch (sel) {
4083 case 0:
2e70f6ef
PB
4084 /* Mark as an IO operation because we read the time. */
4085 if (use_icount)
4086 gen_io_start();
a7812ae4 4087 gen_helper_mfc0_count(t0);
2e70f6ef
PB
4088 if (use_icount) {
4089 gen_io_end();
4090 ctx->bstate = BS_STOP;
4091 }
2423f660
TS
4092 rn = "Count";
4093 break;
4094 /* 6,7 are implementation dependent */
9c2149c8
TS
4095 default:
4096 goto die;
876d4b07 4097 }
9c2149c8
TS
4098 break;
4099 case 10:
4100 switch (sel) {
4101 case 0:
1a3fd9c3 4102 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryHi));
2423f660
TS
4103 rn = "EntryHi";
4104 break;
9c2149c8
TS
4105 default:
4106 goto die;
876d4b07 4107 }
9c2149c8
TS
4108 break;
4109 case 11:
4110 switch (sel) {
4111 case 0:
1a3fd9c3 4112 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Compare));
2423f660
TS
4113 rn = "Compare";
4114 break;
876d4b07 4115 /* 6,7 are implementation dependent */
9c2149c8
TS
4116 default:
4117 goto die;
876d4b07 4118 }
9c2149c8
TS
4119 break;
4120 case 12:
4121 switch (sel) {
4122 case 0:
1a3fd9c3 4123 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Status));
2423f660
TS
4124 rn = "Status";
4125 break;
9c2149c8 4126 case 1:
e189e748 4127 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4128 gen_mfc0_load32(t0, offsetof(CPUState, CP0_IntCtl));
2423f660
TS
4129 rn = "IntCtl";
4130 break;
9c2149c8 4131 case 2:
e189e748 4132 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4133 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSCtl));
2423f660
TS
4134 rn = "SRSCtl";
4135 break;
9c2149c8 4136 case 3:
e189e748 4137 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4138 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSMap));
2423f660
TS
4139 rn = "SRSMap";
4140 break;
9c2149c8
TS
4141 default:
4142 goto die;
876d4b07 4143 }
9c2149c8
TS
4144 break;
4145 case 13:
4146 switch (sel) {
4147 case 0:
1a3fd9c3 4148 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Cause));
2423f660
TS
4149 rn = "Cause";
4150 break;
9c2149c8
TS
4151 default:
4152 goto die;
876d4b07 4153 }
9c2149c8
TS
4154 break;
4155 case 14:
4156 switch (sel) {
4157 case 0:
1a3fd9c3 4158 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
2423f660
TS
4159 rn = "EPC";
4160 break;
9c2149c8
TS
4161 default:
4162 goto die;
876d4b07 4163 }
9c2149c8
TS
4164 break;
4165 case 15:
4166 switch (sel) {
4167 case 0:
1a3fd9c3 4168 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PRid));
2423f660
TS
4169 rn = "PRid";
4170 break;
9c2149c8 4171 case 1:
e189e748 4172 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4173 gen_mfc0_load32(t0, offsetof(CPUState, CP0_EBase));
2423f660
TS
4174 rn = "EBase";
4175 break;
9c2149c8
TS
4176 default:
4177 goto die;
876d4b07 4178 }
9c2149c8
TS
4179 break;
4180 case 16:
4181 switch (sel) {
4182 case 0:
1a3fd9c3 4183 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config0));
9c2149c8
TS
4184 rn = "Config";
4185 break;
4186 case 1:
1a3fd9c3 4187 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config1));
9c2149c8
TS
4188 rn = "Config1";
4189 break;
4190 case 2:
1a3fd9c3 4191 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config2));
9c2149c8
TS
4192 rn = "Config2";
4193 break;
4194 case 3:
1a3fd9c3 4195 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config3));
9c2149c8
TS
4196 rn = "Config3";
4197 break;
4198 /* 6,7 are implementation dependent */
f0b3f3ae 4199 case 6:
1a3fd9c3 4200 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config6));
f0b3f3ae
TS
4201 rn = "Config6";
4202 break;
4203 case 7:
1a3fd9c3 4204 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config7));
f0b3f3ae
TS
4205 rn = "Config7";
4206 break;
9c2149c8
TS
4207 default:
4208 goto die;
4209 }
4210 break;
4211 case 17:
4212 switch (sel) {
4213 case 0:
a7812ae4 4214 gen_helper_dmfc0_lladdr(t0);
2423f660
TS
4215 rn = "LLAddr";
4216 break;
9c2149c8
TS
4217 default:
4218 goto die;
4219 }
4220 break;
4221 case 18:
4222 switch (sel) {
fd88b6ab 4223 case 0 ... 7:
a7812ae4 4224 gen_helper_1i(dmfc0_watchlo, t0, sel);
2423f660
TS
4225 rn = "WatchLo";
4226 break;
9c2149c8
TS
4227 default:
4228 goto die;
4229 }
4230 break;
4231 case 19:
4232 switch (sel) {
fd88b6ab 4233 case 0 ... 7:
a7812ae4 4234 gen_helper_1i(mfc0_watchhi, t0, sel);
2423f660
TS
4235 rn = "WatchHi";
4236 break;
9c2149c8
TS
4237 default:
4238 goto die;
4239 }
4240 break;
4241 case 20:
4242 switch (sel) {
4243 case 0:
e189e748 4244 check_insn(env, ctx, ISA_MIPS3);
1a3fd9c3 4245 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_XContext));
2423f660
TS
4246 rn = "XContext";
4247 break;
9c2149c8
TS
4248 default:
4249 goto die;
4250 }
4251 break;
4252 case 21:
4253 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4254 switch (sel) {
4255 case 0:
1a3fd9c3 4256 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Framemask));
2423f660
TS
4257 rn = "Framemask";
4258 break;
9c2149c8
TS
4259 default:
4260 goto die;
4261 }
4262 break;
4263 case 22:
da80682b 4264 tcg_gen_movi_tl(t0, 0); /* unimplemented */
2423f660
TS
4265 rn = "'Diagnostic"; /* implementation dependent */
4266 break;
9c2149c8
TS
4267 case 23:
4268 switch (sel) {
4269 case 0:
a7812ae4 4270 gen_helper_mfc0_debug(t0); /* EJTAG support */
2423f660
TS
4271 rn = "Debug";
4272 break;
9c2149c8 4273 case 1:
a7812ae4 4274// gen_helper_dmfc0_tracecontrol(t0); /* PDtrace support */
2423f660
TS
4275 rn = "TraceControl";
4276// break;
9c2149c8 4277 case 2:
a7812ae4 4278// gen_helper_dmfc0_tracecontrol2(t0); /* PDtrace support */
2423f660
TS
4279 rn = "TraceControl2";
4280// break;
9c2149c8 4281 case 3:
a7812ae4 4282// gen_helper_dmfc0_usertracedata(t0); /* PDtrace support */
2423f660
TS
4283 rn = "UserTraceData";
4284// break;
9c2149c8 4285 case 4:
a7812ae4 4286// gen_helper_dmfc0_tracebpc(t0); /* PDtrace support */
2423f660
TS
4287 rn = "TraceBPC";
4288// break;
9c2149c8
TS
4289 default:
4290 goto die;
4291 }
4292 break;
4293 case 24:
4294 switch (sel) {
4295 case 0:
f0b3f3ae 4296 /* EJTAG support */
1a3fd9c3 4297 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
2423f660
TS
4298 rn = "DEPC";
4299 break;
9c2149c8
TS
4300 default:
4301 goto die;
4302 }
4303 break;
4304 case 25:
4305 switch (sel) {
4306 case 0:
1a3fd9c3 4307 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Performance0));
2423f660 4308 rn = "Performance0";
9c2149c8
TS
4309 break;
4310 case 1:
a7812ae4 4311// gen_helper_dmfc0_performance1(t0);
2423f660
TS
4312 rn = "Performance1";
4313// break;
9c2149c8 4314 case 2:
a7812ae4 4315// gen_helper_dmfc0_performance2(t0);
2423f660
TS
4316 rn = "Performance2";
4317// break;
9c2149c8 4318 case 3:
a7812ae4 4319// gen_helper_dmfc0_performance3(t0);
2423f660
TS
4320 rn = "Performance3";
4321// break;
9c2149c8 4322 case 4:
a7812ae4 4323// gen_helper_dmfc0_performance4(t0);
2423f660
TS
4324 rn = "Performance4";
4325// break;
9c2149c8 4326 case 5:
a7812ae4 4327// gen_helper_dmfc0_performance5(t0);
2423f660
TS
4328 rn = "Performance5";
4329// break;
9c2149c8 4330 case 6:
a7812ae4 4331// gen_helper_dmfc0_performance6(t0);
2423f660
TS
4332 rn = "Performance6";
4333// break;
9c2149c8 4334 case 7:
a7812ae4 4335// gen_helper_dmfc0_performance7(t0);
2423f660
TS
4336 rn = "Performance7";
4337// break;
9c2149c8
TS
4338 default:
4339 goto die;
4340 }
4341 break;
4342 case 26:
da80682b
AJ
4343 tcg_gen_movi_tl(t0, 0); /* unimplemented */
4344 rn = "ECC";
4345 break;
9c2149c8
TS
4346 case 27:
4347 switch (sel) {
4348 /* ignored */
4349 case 0 ... 3:
da80682b 4350 tcg_gen_movi_tl(t0, 0); /* unimplemented */
2423f660
TS
4351 rn = "CacheErr";
4352 break;
9c2149c8
TS
4353 default:
4354 goto die;
4355 }
4356 break;
4357 case 28:
4358 switch (sel) {
4359 case 0:
4360 case 2:
4361 case 4:
4362 case 6:
1a3fd9c3 4363 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagLo));
9c2149c8
TS
4364 rn = "TagLo";
4365 break;
4366 case 1:
4367 case 3:
4368 case 5:
4369 case 7:
1a3fd9c3 4370 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataLo));
9c2149c8
TS
4371 rn = "DataLo";
4372 break;
4373 default:
4374 goto die;
4375 }
4376 break;
4377 case 29:
4378 switch (sel) {
4379 case 0:
4380 case 2:
4381 case 4:
4382 case 6:
1a3fd9c3 4383 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagHi));
9c2149c8
TS
4384 rn = "TagHi";
4385 break;
4386 case 1:
4387 case 3:
4388 case 5:
4389 case 7:
1a3fd9c3 4390 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataHi));
9c2149c8
TS
4391 rn = "DataHi";
4392 break;
4393 default:
4394 goto die;
4395 }
4396 break;
4397 case 30:
4398 switch (sel) {
4399 case 0:
1a3fd9c3 4400 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
2423f660
TS
4401 rn = "ErrorEPC";
4402 break;
9c2149c8
TS
4403 default:
4404 goto die;
4405 }
4406 break;
4407 case 31:
4408 switch (sel) {
4409 case 0:
f0b3f3ae 4410 /* EJTAG support */
1a3fd9c3 4411 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DESAVE));
2423f660
TS
4412 rn = "DESAVE";
4413 break;
9c2149c8
TS
4414 default:
4415 goto die;
4416 }
4417 break;
4418 default:
876d4b07 4419 goto die;
9c2149c8 4420 }
d12d51d5 4421 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
4422 return;
4423
4424die:
d12d51d5 4425 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
4426 generate_exception(ctx, EXCP_RI);
4427}
4428
1a3fd9c3 4429static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
9c2149c8
TS
4430{
4431 const char *rn = "invalid";
4432
e189e748
TS
4433 if (sel != 0)
4434 check_insn(env, ctx, ISA_MIPS64);
4435
2e70f6ef
PB
4436 if (use_icount)
4437 gen_io_start();
4438
9c2149c8
TS
4439 switch (reg) {
4440 case 0:
4441 switch (sel) {
4442 case 0:
a7812ae4 4443 gen_helper_mtc0_index(t0);
9c2149c8
TS
4444 rn = "Index";
4445 break;
4446 case 1:
7385ac0b 4447 check_insn(env, ctx, ASE_MT);
a7812ae4 4448 gen_helper_mtc0_mvpcontrol(t0);
9c2149c8 4449 rn = "MVPControl";
ead9360e 4450 break;
9c2149c8 4451 case 2:
7385ac0b 4452 check_insn(env, ctx, ASE_MT);
ead9360e 4453 /* ignored */
9c2149c8 4454 rn = "MVPConf0";
ead9360e 4455 break;
9c2149c8 4456 case 3:
7385ac0b 4457 check_insn(env, ctx, ASE_MT);
ead9360e 4458 /* ignored */
9c2149c8 4459 rn = "MVPConf1";
ead9360e 4460 break;
9c2149c8
TS
4461 default:
4462 goto die;
4463 }
4464 break;
4465 case 1:
4466 switch (sel) {
4467 case 0:
2423f660 4468 /* ignored */
9c2149c8 4469 rn = "Random";
2423f660 4470 break;
9c2149c8 4471 case 1:
7385ac0b 4472 check_insn(env, ctx, ASE_MT);
a7812ae4 4473 gen_helper_mtc0_vpecontrol(t0);
9c2149c8 4474 rn = "VPEControl";
ead9360e 4475 break;
9c2149c8 4476 case 2:
7385ac0b 4477 check_insn(env, ctx, ASE_MT);
a7812ae4 4478 gen_helper_mtc0_vpeconf0(t0);
9c2149c8 4479 rn = "VPEConf0";
ead9360e 4480 break;
9c2149c8 4481 case 3:
7385ac0b 4482 check_insn(env, ctx, ASE_MT);
a7812ae4 4483 gen_helper_mtc0_vpeconf1(t0);
9c2149c8 4484 rn = "VPEConf1";
ead9360e 4485 break;
9c2149c8 4486 case 4:
7385ac0b 4487 check_insn(env, ctx, ASE_MT);
a7812ae4 4488 gen_helper_mtc0_yqmask(t0);
9c2149c8 4489 rn = "YQMask";
ead9360e 4490 break;
9c2149c8 4491 case 5:
7385ac0b 4492 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4493 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_VPESchedule));
9c2149c8 4494 rn = "VPESchedule";
ead9360e 4495 break;
9c2149c8 4496 case 6:
7385ac0b 4497 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4498 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
9c2149c8 4499 rn = "VPEScheFBack";
ead9360e 4500 break;
9c2149c8 4501 case 7:
7385ac0b 4502 check_insn(env, ctx, ASE_MT);
a7812ae4 4503 gen_helper_mtc0_vpeopt(t0);
9c2149c8 4504 rn = "VPEOpt";
ead9360e 4505 break;
9c2149c8
TS
4506 default:
4507 goto die;
4508 }
4509 break;
4510 case 2:
4511 switch (sel) {
4512 case 0:
a7812ae4 4513 gen_helper_mtc0_entrylo0(t0);
2423f660
TS
4514 rn = "EntryLo0";
4515 break;
9c2149c8 4516 case 1:
7385ac0b 4517 check_insn(env, ctx, ASE_MT);
a7812ae4 4518 gen_helper_mtc0_tcstatus(t0);
2423f660 4519 rn = "TCStatus";
ead9360e 4520 break;
9c2149c8 4521 case 2:
7385ac0b 4522 check_insn(env, ctx, ASE_MT);
a7812ae4 4523 gen_helper_mtc0_tcbind(t0);
2423f660 4524 rn = "TCBind";
ead9360e 4525 break;
9c2149c8 4526 case 3:
7385ac0b 4527 check_insn(env, ctx, ASE_MT);
a7812ae4 4528 gen_helper_mtc0_tcrestart(t0);
2423f660 4529 rn = "TCRestart";
ead9360e 4530 break;
9c2149c8 4531 case 4:
7385ac0b 4532 check_insn(env, ctx, ASE_MT);
a7812ae4 4533 gen_helper_mtc0_tchalt(t0);
2423f660 4534 rn = "TCHalt";
ead9360e 4535 break;
9c2149c8 4536 case 5:
7385ac0b 4537 check_insn(env, ctx, ASE_MT);
a7812ae4 4538 gen_helper_mtc0_tccontext(t0);
2423f660 4539 rn = "TCContext";
ead9360e 4540 break;
9c2149c8 4541 case 6:
7385ac0b 4542 check_insn(env, ctx, ASE_MT);
a7812ae4 4543 gen_helper_mtc0_tcschedule(t0);
2423f660 4544 rn = "TCSchedule";
ead9360e 4545 break;
9c2149c8 4546 case 7:
7385ac0b 4547 check_insn(env, ctx, ASE_MT);
a7812ae4 4548 gen_helper_mtc0_tcschefback(t0);
2423f660 4549 rn = "TCScheFBack";
ead9360e 4550 break;
9c2149c8
TS
4551 default:
4552 goto die;
4553 }
4554 break;
4555 case 3:
4556 switch (sel) {
4557 case 0:
a7812ae4 4558 gen_helper_mtc0_entrylo1(t0);
2423f660
TS
4559 rn = "EntryLo1";
4560 break;
9c2149c8
TS
4561 default:
4562 goto die;
876d4b07 4563 }
9c2149c8
TS
4564 break;
4565 case 4:
4566 switch (sel) {
4567 case 0:
a7812ae4 4568 gen_helper_mtc0_context(t0);
2423f660
TS
4569 rn = "Context";
4570 break;
9c2149c8 4571 case 1:
a7812ae4 4572// gen_helper_mtc0_contextconfig(t0); /* SmartMIPS ASE */
2423f660
TS
4573 rn = "ContextConfig";
4574// break;
9c2149c8
TS
4575 default:
4576 goto die;
876d4b07 4577 }
9c2149c8
TS
4578 break;
4579 case 5:
4580 switch (sel) {
4581 case 0:
a7812ae4 4582 gen_helper_mtc0_pagemask(t0);
2423f660
TS
4583 rn = "PageMask";
4584 break;
9c2149c8 4585 case 1:
e189e748 4586 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 4587 gen_helper_mtc0_pagegrain(t0);
2423f660
TS
4588 rn = "PageGrain";
4589 break;
9c2149c8
TS
4590 default:
4591 goto die;
876d4b07 4592 }
9c2149c8
TS
4593 break;
4594 case 6:
4595 switch (sel) {
4596 case 0:
a7812ae4 4597 gen_helper_mtc0_wired(t0);
2423f660
TS
4598 rn = "Wired";
4599 break;
9c2149c8 4600 case 1:
e189e748 4601 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 4602 gen_helper_mtc0_srsconf0(t0);
2423f660 4603 rn = "SRSConf0";
ead9360e 4604 break;
9c2149c8 4605 case 2:
e189e748 4606 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 4607 gen_helper_mtc0_srsconf1(t0);
2423f660 4608 rn = "SRSConf1";
ead9360e 4609 break;
9c2149c8 4610 case 3:
e189e748 4611 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 4612 gen_helper_mtc0_srsconf2(t0);
2423f660 4613 rn = "SRSConf2";
ead9360e 4614 break;
9c2149c8 4615 case 4:
e189e748 4616 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 4617 gen_helper_mtc0_srsconf3(t0);
2423f660 4618 rn = "SRSConf3";
ead9360e 4619 break;
9c2149c8 4620 case 5:
e189e748 4621 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 4622 gen_helper_mtc0_srsconf4(t0);
2423f660 4623 rn = "SRSConf4";
ead9360e 4624 break;
9c2149c8
TS
4625 default:
4626 goto die;
876d4b07 4627 }
9c2149c8
TS
4628 break;
4629 case 7:
4630 switch (sel) {
4631 case 0:
e189e748 4632 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 4633 gen_helper_mtc0_hwrena(t0);
2423f660
TS
4634 rn = "HWREna";
4635 break;
9c2149c8
TS
4636 default:
4637 goto die;
876d4b07 4638 }
9c2149c8
TS
4639 break;
4640 case 8:
4641 /* ignored */
f0b3f3ae 4642 rn = "BadVAddr";
9c2149c8
TS
4643 break;
4644 case 9:
4645 switch (sel) {
4646 case 0:
a7812ae4 4647 gen_helper_mtc0_count(t0);
2423f660
TS
4648 rn = "Count";
4649 break;
876d4b07 4650 /* 6,7 are implementation dependent */
9c2149c8
TS
4651 default:
4652 goto die;
876d4b07
TS
4653 }
4654 /* Stop translation as we may have switched the execution mode */
4655 ctx->bstate = BS_STOP;
9c2149c8
TS
4656 break;
4657 case 10:
4658 switch (sel) {
4659 case 0:
a7812ae4 4660 gen_helper_mtc0_entryhi(t0);
2423f660
TS
4661 rn = "EntryHi";
4662 break;
9c2149c8
TS
4663 default:
4664 goto die;
876d4b07 4665 }
9c2149c8
TS
4666 break;
4667 case 11:
4668 switch (sel) {
4669 case 0:
a7812ae4 4670 gen_helper_mtc0_compare(t0);
2423f660
TS
4671 rn = "Compare";
4672 break;
876d4b07 4673 /* 6,7 are implementation dependent */
9c2149c8
TS
4674 default:
4675 goto die;
876d4b07 4676 }
de9a95f0
AJ
4677 /* Stop translation as we may have switched the execution mode */
4678 ctx->bstate = BS_STOP;
9c2149c8
TS
4679 break;
4680 case 12:
4681 switch (sel) {
4682 case 0:
a7812ae4 4683 gen_helper_mtc0_status(t0);
8487327a
TS
4684 /* BS_STOP isn't good enough here, hflags may have changed. */
4685 gen_save_pc(ctx->pc + 4);
4686 ctx->bstate = BS_EXCP;
2423f660
TS
4687 rn = "Status";
4688 break;
9c2149c8 4689 case 1:
e189e748 4690 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 4691 gen_helper_mtc0_intctl(t0);
8487327a
TS
4692 /* Stop translation as we may have switched the execution mode */
4693 ctx->bstate = BS_STOP;
2423f660
TS
4694 rn = "IntCtl";
4695 break;
9c2149c8 4696 case 2:
e189e748 4697 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 4698 gen_helper_mtc0_srsctl(t0);
8487327a
TS
4699 /* Stop translation as we may have switched the execution mode */
4700 ctx->bstate = BS_STOP;
2423f660
TS
4701 rn = "SRSCtl";
4702 break;
9c2149c8 4703 case 3:
e189e748 4704 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4705 gen_mtc0_store32(t0, offsetof(CPUState, CP0_SRSMap));
8487327a
TS
4706 /* Stop translation as we may have switched the execution mode */
4707 ctx->bstate = BS_STOP;
2423f660
TS
4708 rn = "SRSMap";
4709 break;
4710 default:
9c2149c8 4711 goto die;
876d4b07 4712 }
9c2149c8
TS
4713 break;
4714 case 13:
4715 switch (sel) {
4716 case 0:
a7812ae4 4717 gen_helper_mtc0_cause(t0);
2423f660
TS
4718 rn = "Cause";
4719 break;
9c2149c8
TS
4720 default:
4721 goto die;
876d4b07
TS
4722 }
4723 /* Stop translation as we may have switched the execution mode */
4724 ctx->bstate = BS_STOP;
9c2149c8
TS
4725 break;
4726 case 14:
4727 switch (sel) {
4728 case 0:
1a3fd9c3 4729 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
2423f660
TS
4730 rn = "EPC";
4731 break;
9c2149c8
TS
4732 default:
4733 goto die;
876d4b07 4734 }
9c2149c8
TS
4735 break;
4736 case 15:
4737 switch (sel) {
4738 case 0:
2423f660
TS
4739 /* ignored */
4740 rn = "PRid";
4741 break;
9c2149c8 4742 case 1:
e189e748 4743 check_insn(env, ctx, ISA_MIPS32R2);
a7812ae4 4744 gen_helper_mtc0_ebase(t0);
2423f660
TS
4745 rn = "EBase";
4746 break;
9c2149c8
TS
4747 default:
4748 goto die;
876d4b07 4749 }
9c2149c8
TS
4750 break;
4751 case 16:
4752 switch (sel) {
4753 case 0:
a7812ae4 4754 gen_helper_mtc0_config0(t0);
9c2149c8 4755 rn = "Config";
2423f660
TS
4756 /* Stop translation as we may have switched the execution mode */
4757 ctx->bstate = BS_STOP;
9c2149c8
TS
4758 break;
4759 case 1:
2423f660 4760 /* ignored */
9c2149c8
TS
4761 rn = "Config1";
4762 break;
4763 case 2:
a7812ae4 4764 gen_helper_mtc0_config2(t0);
9c2149c8 4765 rn = "Config2";
2423f660
TS
4766 /* Stop translation as we may have switched the execution mode */
4767 ctx->bstate = BS_STOP;
9c2149c8
TS
4768 break;
4769 case 3:
2423f660 4770 /* ignored */
9c2149c8
TS
4771 rn = "Config3";
4772 break;
4773 /* 6,7 are implementation dependent */
4774 default:
4775 rn = "Invalid config selector";
4776 goto die;
4777 }
9c2149c8
TS
4778 break;
4779 case 17:
4780 switch (sel) {
4781 case 0:
2423f660
TS
4782 /* ignored */
4783 rn = "LLAddr";
4784 break;
9c2149c8
TS
4785 default:
4786 goto die;
4787 }
4788 break;
4789 case 18:
4790 switch (sel) {
fd88b6ab 4791 case 0 ... 7:
a7812ae4 4792 gen_helper_1i(mtc0_watchlo, t0, sel);
2423f660
TS
4793 rn = "WatchLo";
4794 break;
9c2149c8
TS
4795 default:
4796 goto die;
4797 }
4798 break;
4799 case 19:
4800 switch (sel) {
fd88b6ab 4801 case 0 ... 7:
a7812ae4 4802 gen_helper_1i(mtc0_watchhi, t0, sel);
2423f660
TS
4803 rn = "WatchHi";
4804 break;
9c2149c8
TS
4805 default:
4806 goto die;
4807 }
4808 break;
4809 case 20:
4810 switch (sel) {
4811 case 0:
e189e748 4812 check_insn(env, ctx, ISA_MIPS3);
a7812ae4 4813 gen_helper_mtc0_xcontext(t0);
2423f660
TS
4814 rn = "XContext";
4815 break;
9c2149c8
TS
4816 default:
4817 goto die;
4818 }
4819 break;
4820 case 21:
4821 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4822 switch (sel) {
4823 case 0:
a7812ae4 4824 gen_helper_mtc0_framemask(t0);
2423f660
TS
4825 rn = "Framemask";
4826 break;
9c2149c8
TS
4827 default:
4828 goto die;
4829 }
4830 break;
4831 case 22:
4832 /* ignored */
4833 rn = "Diagnostic"; /* implementation dependent */
876d4b07 4834 break;
9c2149c8
TS
4835 case 23:
4836 switch (sel) {
4837 case 0:
a7812ae4 4838 gen_helper_mtc0_debug(t0); /* EJTAG support */
8487327a
TS
4839 /* BS_STOP isn't good enough here, hflags may have changed. */
4840 gen_save_pc(ctx->pc + 4);
4841 ctx->bstate = BS_EXCP;
2423f660
TS
4842 rn = "Debug";
4843 break;
9c2149c8 4844 case 1:
a7812ae4 4845// gen_helper_mtc0_tracecontrol(t0); /* PDtrace support */
8487327a
TS
4846 /* Stop translation as we may have switched the execution mode */
4847 ctx->bstate = BS_STOP;
2423f660
TS
4848 rn = "TraceControl";
4849// break;
9c2149c8 4850 case 2:
a7812ae4 4851// gen_helper_mtc0_tracecontrol2(t0); /* PDtrace support */
8487327a
TS
4852 /* Stop translation as we may have switched the execution mode */
4853 ctx->bstate = BS_STOP;
2423f660
TS
4854 rn = "TraceControl2";
4855// break;
9c2149c8 4856 case 3:
a7812ae4 4857// gen_helper_mtc0_usertracedata(t0); /* PDtrace support */
8487327a
TS
4858 /* Stop translation as we may have switched the execution mode */
4859 ctx->bstate = BS_STOP;
2423f660
TS
4860 rn = "UserTraceData";
4861// break;
9c2149c8 4862 case 4:
a7812ae4 4863// gen_helper_mtc0_tracebpc(t0); /* PDtrace support */
8487327a
TS
4864 /* Stop translation as we may have switched the execution mode */
4865 ctx->bstate = BS_STOP;
2423f660
TS
4866 rn = "TraceBPC";
4867// break;
9c2149c8
TS
4868 default:
4869 goto die;
4870 }
9c2149c8
TS
4871 break;
4872 case 24:
4873 switch (sel) {
4874 case 0:
f1aa6320 4875 /* EJTAG support */
1a3fd9c3 4876 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
2423f660
TS
4877 rn = "DEPC";
4878 break;
9c2149c8
TS
4879 default:
4880 goto die;
4881 }
4882 break;
4883 case 25:
4884 switch (sel) {
4885 case 0:
a7812ae4 4886 gen_helper_mtc0_performance0(t0);
2423f660
TS
4887 rn = "Performance0";
4888 break;
9c2149c8 4889 case 1:
a7812ae4 4890// gen_helper_mtc0_performance1(t0);
2423f660
TS
4891 rn = "Performance1";
4892// break;
9c2149c8 4893 case 2:
a7812ae4 4894// gen_helper_mtc0_performance2(t0);
2423f660
TS
4895 rn = "Performance2";
4896// break;
9c2149c8 4897 case 3:
a7812ae4 4898// gen_helper_mtc0_performance3(t0);
2423f660
TS
4899 rn = "Performance3";
4900// break;
9c2149c8 4901 case 4:
a7812ae4 4902// gen_helper_mtc0_performance4(t0);
2423f660
TS
4903 rn = "Performance4";
4904// break;
9c2149c8 4905 case 5:
a7812ae4 4906// gen_helper_mtc0_performance5(t0);
2423f660
TS
4907 rn = "Performance5";
4908// break;
9c2149c8 4909 case 6:
a7812ae4 4910// gen_helper_mtc0_performance6(t0);
2423f660
TS
4911 rn = "Performance6";
4912// break;
9c2149c8 4913 case 7:
a7812ae4 4914// gen_helper_mtc0_performance7(t0);
2423f660
TS
4915 rn = "Performance7";
4916// break;
9c2149c8
TS
4917 default:
4918 goto die;
4919 }
876d4b07 4920 break;
9c2149c8 4921 case 26:
876d4b07 4922 /* ignored */
9c2149c8 4923 rn = "ECC";
876d4b07 4924 break;
9c2149c8
TS
4925 case 27:
4926 switch (sel) {
4927 case 0 ... 3:
2423f660
TS
4928 /* ignored */
4929 rn = "CacheErr";
4930 break;
9c2149c8
TS
4931 default:
4932 goto die;
4933 }
876d4b07 4934 break;
9c2149c8
TS
4935 case 28:
4936 switch (sel) {
4937 case 0:
4938 case 2:
4939 case 4:
4940 case 6:
a7812ae4 4941 gen_helper_mtc0_taglo(t0);
9c2149c8
TS
4942 rn = "TagLo";
4943 break;
4944 case 1:
4945 case 3:
4946 case 5:
4947 case 7:
a7812ae4 4948 gen_helper_mtc0_datalo(t0);
9c2149c8
TS
4949 rn = "DataLo";
4950 break;
4951 default:
4952 goto die;
4953 }
4954 break;
4955 case 29:
4956 switch (sel) {
4957 case 0:
4958 case 2:
4959 case 4:
4960 case 6:
a7812ae4 4961 gen_helper_mtc0_taghi(t0);
9c2149c8
TS
4962 rn = "TagHi";
4963 break;
4964 case 1:
4965 case 3:
4966 case 5:
4967 case 7:
a7812ae4 4968 gen_helper_mtc0_datahi(t0);
9c2149c8
TS
4969 rn = "DataHi";
4970 break;
4971 default:
4972 rn = "invalid sel";
4973 goto die;
4974 }
876d4b07 4975 break;
9c2149c8
TS
4976 case 30:
4977 switch (sel) {
4978 case 0:
1a3fd9c3 4979 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
2423f660
TS
4980 rn = "ErrorEPC";
4981 break;
9c2149c8
TS
4982 default:
4983 goto die;
4984 }
4985 break;
4986 case 31:
4987 switch (sel) {
4988 case 0:
f1aa6320 4989 /* EJTAG support */
1a3fd9c3 4990 gen_mtc0_store32(t0, offsetof(CPUState, CP0_DESAVE));
2423f660
TS
4991 rn = "DESAVE";
4992 break;
9c2149c8
TS
4993 default:
4994 goto die;
4995 }
876d4b07
TS
4996 /* Stop translation as we may have switched the execution mode */
4997 ctx->bstate = BS_STOP;
9c2149c8
TS
4998 break;
4999 default:
876d4b07 5000 goto die;
9c2149c8 5001 }
d12d51d5 5002 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
bf20dc07 5003 /* For simplicity assume that all writes can cause interrupts. */
2e70f6ef
PB
5004 if (use_icount) {
5005 gen_io_end();
5006 ctx->bstate = BS_STOP;
5007 }
9c2149c8
TS
5008 return;
5009
5010die:
d12d51d5 5011 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
5012 generate_exception(ctx, EXCP_RI);
5013}
d26bc211 5014#endif /* TARGET_MIPS64 */
9c2149c8 5015
6c5c1e20 5016static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
ead9360e
TS
5017 int u, int sel, int h)
5018{
5019 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 5020 TCGv t0 = tcg_temp_local_new();
ead9360e
TS
5021
5022 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
5023 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5024 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
1a3fd9c3 5025 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
5026 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5027 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
1a3fd9c3 5028 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
5029 else if (u == 0) {
5030 switch (rt) {
5031 case 2:
5032 switch (sel) {
5033 case 1:
a7812ae4 5034 gen_helper_mftc0_tcstatus(t0);
ead9360e
TS
5035 break;
5036 case 2:
a7812ae4 5037 gen_helper_mftc0_tcbind(t0);
ead9360e
TS
5038 break;
5039 case 3:
a7812ae4 5040 gen_helper_mftc0_tcrestart(t0);
ead9360e
TS
5041 break;
5042 case 4:
a7812ae4 5043 gen_helper_mftc0_tchalt(t0);
ead9360e
TS
5044 break;
5045 case 5:
a7812ae4 5046 gen_helper_mftc0_tccontext(t0);
ead9360e
TS
5047 break;
5048 case 6:
a7812ae4 5049 gen_helper_mftc0_tcschedule(t0);
ead9360e
TS
5050 break;
5051 case 7:
a7812ae4 5052 gen_helper_mftc0_tcschefback(t0);
ead9360e
TS
5053 break;
5054 default:
1a3fd9c3 5055 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5056 break;
5057 }
5058 break;
5059 case 10:
5060 switch (sel) {
5061 case 0:
a7812ae4 5062 gen_helper_mftc0_entryhi(t0);
ead9360e
TS
5063 break;
5064 default:
1a3fd9c3 5065 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5066 break;
5067 }
5068 case 12:
5069 switch (sel) {
5070 case 0:
a7812ae4 5071 gen_helper_mftc0_status(t0);
ead9360e
TS
5072 break;
5073 default:
1a3fd9c3 5074 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5075 break;
5076 }
5077 case 23:
5078 switch (sel) {
5079 case 0:
a7812ae4 5080 gen_helper_mftc0_debug(t0);
ead9360e
TS
5081 break;
5082 default:
1a3fd9c3 5083 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5084 break;
5085 }
5086 break;
5087 default:
1a3fd9c3 5088 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5089 }
5090 } else switch (sel) {
5091 /* GPR registers. */
5092 case 0:
a7812ae4 5093 gen_helper_1i(mftgpr, t0, rt);
ead9360e
TS
5094 break;
5095 /* Auxiliary CPU registers */
5096 case 1:
5097 switch (rt) {
5098 case 0:
a7812ae4 5099 gen_helper_1i(mftlo, t0, 0);
ead9360e
TS
5100 break;
5101 case 1:
a7812ae4 5102 gen_helper_1i(mfthi, t0, 0);
ead9360e
TS
5103 break;
5104 case 2:
a7812ae4 5105 gen_helper_1i(mftacx, t0, 0);
ead9360e
TS
5106 break;
5107 case 4:
a7812ae4 5108 gen_helper_1i(mftlo, t0, 1);
ead9360e
TS
5109 break;
5110 case 5:
a7812ae4 5111 gen_helper_1i(mfthi, t0, 1);
ead9360e
TS
5112 break;
5113 case 6:
a7812ae4 5114 gen_helper_1i(mftacx, t0, 1);
ead9360e
TS
5115 break;
5116 case 8:
a7812ae4 5117 gen_helper_1i(mftlo, t0, 2);
ead9360e
TS
5118 break;
5119 case 9:
a7812ae4 5120 gen_helper_1i(mfthi, t0, 2);
ead9360e
TS
5121 break;
5122 case 10:
a7812ae4 5123 gen_helper_1i(mftacx, t0, 2);
ead9360e
TS
5124 break;
5125 case 12:
a7812ae4 5126 gen_helper_1i(mftlo, t0, 3);
ead9360e
TS
5127 break;
5128 case 13:
a7812ae4 5129 gen_helper_1i(mfthi, t0, 3);
ead9360e
TS
5130 break;
5131 case 14:
a7812ae4 5132 gen_helper_1i(mftacx, t0, 3);
ead9360e
TS
5133 break;
5134 case 16:
a7812ae4 5135 gen_helper_mftdsp(t0);
ead9360e
TS
5136 break;
5137 default:
5138 goto die;
5139 }
5140 break;
5141 /* Floating point (COP1). */
5142 case 2:
5143 /* XXX: For now we support only a single FPU context. */
5144 if (h == 0) {
a7812ae4 5145 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5146
5147 gen_load_fpr32(fp0, rt);
5148 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 5149 tcg_temp_free_i32(fp0);
ead9360e 5150 } else {
a7812ae4 5151 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5152
5153 gen_load_fpr32h(fp0, rt);
5154 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 5155 tcg_temp_free_i32(fp0);
ead9360e
TS
5156 }
5157 break;
5158 case 3:
5159 /* XXX: For now we support only a single FPU context. */
a7812ae4 5160 gen_helper_1i(cfc1, t0, rt);
ead9360e
TS
5161 break;
5162 /* COP2: Not implemented. */
5163 case 4:
5164 case 5:
5165 /* fall through */
5166 default:
5167 goto die;
5168 }
d12d51d5 5169 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
1a3fd9c3
TS
5170 gen_store_gpr(t0, rd);
5171 tcg_temp_free(t0);
ead9360e
TS
5172 return;
5173
5174die:
1a3fd9c3 5175 tcg_temp_free(t0);
d12d51d5 5176 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
ead9360e
TS
5177 generate_exception(ctx, EXCP_RI);
5178}
5179
6c5c1e20 5180static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
ead9360e
TS
5181 int u, int sel, int h)
5182{
5183 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 5184 TCGv t0 = tcg_temp_local_new();
ead9360e 5185
1a3fd9c3 5186 gen_load_gpr(t0, rt);
ead9360e 5187 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
5188 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5189 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
ead9360e
TS
5190 /* NOP */ ;
5191 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5192 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5193 /* NOP */ ;
5194 else if (u == 0) {
5195 switch (rd) {
5196 case 2:
5197 switch (sel) {
5198 case 1:
a7812ae4 5199 gen_helper_mttc0_tcstatus(t0);
ead9360e
TS
5200 break;
5201 case 2:
a7812ae4 5202 gen_helper_mttc0_tcbind(t0);
ead9360e
TS
5203 break;
5204 case 3:
a7812ae4 5205 gen_helper_mttc0_tcrestart(t0);
ead9360e
TS
5206 break;
5207 case 4:
a7812ae4 5208 gen_helper_mttc0_tchalt(t0);
ead9360e
TS
5209 break;
5210 case 5:
a7812ae4 5211 gen_helper_mttc0_tccontext(t0);
ead9360e
TS
5212 break;
5213 case 6:
a7812ae4 5214 gen_helper_mttc0_tcschedule(t0);
ead9360e
TS
5215 break;
5216 case 7:
a7812ae4 5217 gen_helper_mttc0_tcschefback(t0);
ead9360e
TS
5218 break;
5219 default:
1a3fd9c3 5220 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5221 break;
5222 }
5223 break;
5224 case 10:
5225 switch (sel) {
5226 case 0:
a7812ae4 5227 gen_helper_mttc0_entryhi(t0);
ead9360e
TS
5228 break;
5229 default:
1a3fd9c3 5230 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5231 break;
5232 }
5233 case 12:
5234 switch (sel) {
5235 case 0:
a7812ae4 5236 gen_helper_mttc0_status(t0);
ead9360e
TS
5237 break;
5238 default:
1a3fd9c3 5239 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5240 break;
5241 }
5242 case 23:
5243 switch (sel) {
5244 case 0:
a7812ae4 5245 gen_helper_mttc0_debug(t0);
ead9360e
TS
5246 break;
5247 default:
1a3fd9c3 5248 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5249 break;
5250 }
5251 break;
5252 default:
1a3fd9c3 5253 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5254 }
5255 } else switch (sel) {
5256 /* GPR registers. */
5257 case 0:
a7812ae4 5258 gen_helper_1i(mttgpr, t0, rd);
ead9360e
TS
5259 break;
5260 /* Auxiliary CPU registers */
5261 case 1:
5262 switch (rd) {
5263 case 0:
a7812ae4 5264 gen_helper_1i(mttlo, t0, 0);
ead9360e
TS
5265 break;
5266 case 1:
a7812ae4 5267 gen_helper_1i(mtthi, t0, 0);
ead9360e
TS
5268 break;
5269 case 2:
a7812ae4 5270 gen_helper_1i(mttacx, t0, 0);
ead9360e
TS
5271 break;
5272 case 4:
a7812ae4 5273 gen_helper_1i(mttlo, t0, 1);
ead9360e
TS
5274 break;
5275 case 5:
a7812ae4 5276 gen_helper_1i(mtthi, t0, 1);
ead9360e
TS
5277 break;
5278 case 6:
a7812ae4 5279 gen_helper_1i(mttacx, t0, 1);
ead9360e
TS
5280 break;
5281 case 8:
a7812ae4 5282 gen_helper_1i(mttlo, t0, 2);
ead9360e
TS
5283 break;
5284 case 9:
a7812ae4 5285 gen_helper_1i(mtthi, t0, 2);
ead9360e
TS
5286 break;
5287 case 10:
a7812ae4 5288 gen_helper_1i(mttacx, t0, 2);
ead9360e
TS
5289 break;
5290 case 12:
a7812ae4 5291 gen_helper_1i(mttlo, t0, 3);
ead9360e
TS
5292 break;
5293 case 13:
a7812ae4 5294 gen_helper_1i(mtthi, t0, 3);
ead9360e
TS
5295 break;
5296 case 14:
a7812ae4 5297 gen_helper_1i(mttacx, t0, 3);
ead9360e
TS
5298 break;
5299 case 16:
a7812ae4 5300 gen_helper_mttdsp(t0);
ead9360e
TS
5301 break;
5302 default:
5303 goto die;
5304 }
5305 break;
5306 /* Floating point (COP1). */
5307 case 2:
5308 /* XXX: For now we support only a single FPU context. */
5309 if (h == 0) {
a7812ae4 5310 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5311
5312 tcg_gen_trunc_tl_i32(fp0, t0);
5313 gen_store_fpr32(fp0, rd);
a7812ae4 5314 tcg_temp_free_i32(fp0);
ead9360e 5315 } else {
a7812ae4 5316 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5317
5318 tcg_gen_trunc_tl_i32(fp0, t0);
5319 gen_store_fpr32h(fp0, rd);
a7812ae4 5320 tcg_temp_free_i32(fp0);
ead9360e
TS
5321 }
5322 break;
5323 case 3:
5324 /* XXX: For now we support only a single FPU context. */
a7812ae4 5325 gen_helper_1i(ctc1, t0, rd);
ead9360e
TS
5326 break;
5327 /* COP2: Not implemented. */
5328 case 4:
5329 case 5:
5330 /* fall through */
5331 default:
5332 goto die;
5333 }
d12d51d5 5334 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
1a3fd9c3 5335 tcg_temp_free(t0);
ead9360e
TS
5336 return;
5337
5338die:
1a3fd9c3 5339 tcg_temp_free(t0);
d12d51d5 5340 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
ead9360e
TS
5341 generate_exception(ctx, EXCP_RI);
5342}
5343
29929e34 5344static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
6af0bf9c 5345{
287c4b84 5346 const char *opn = "ldst";
6af0bf9c 5347
6af0bf9c
FB
5348 switch (opc) {
5349 case OPC_MFC0:
5350 if (rt == 0) {
ead9360e 5351 /* Treat as NOP. */
6af0bf9c
FB
5352 return;
5353 }
1a3fd9c3 5354 {
a7812ae4 5355 TCGv t0 = tcg_temp_local_new();
1a3fd9c3
TS
5356
5357 gen_mfc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5358 gen_store_gpr(t0, rt);
5359 tcg_temp_free(t0);
5360 }
6af0bf9c
FB
5361 opn = "mfc0";
5362 break;
5363 case OPC_MTC0:
1a3fd9c3 5364 {
a7812ae4 5365 TCGv t0 = tcg_temp_local_new();
1a3fd9c3
TS
5366
5367 gen_load_gpr(t0, rt);
5368 save_cpu_state(ctx, 1);
5369 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5370 tcg_temp_free(t0);
5371 }
6af0bf9c
FB
5372 opn = "mtc0";
5373 break;
d26bc211 5374#if defined(TARGET_MIPS64)
9c2149c8 5375 case OPC_DMFC0:
e189e748 5376 check_insn(env, ctx, ISA_MIPS3);
9c2149c8 5377 if (rt == 0) {
ead9360e 5378 /* Treat as NOP. */
9c2149c8
TS
5379 return;
5380 }
1a3fd9c3 5381 {
a7812ae4 5382 TCGv t0 = tcg_temp_local_new();
1a3fd9c3
TS
5383
5384 gen_dmfc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5385 gen_store_gpr(t0, rt);
5386 tcg_temp_free(t0);
5387 }
9c2149c8
TS
5388 opn = "dmfc0";
5389 break;
5390 case OPC_DMTC0:
e189e748 5391 check_insn(env, ctx, ISA_MIPS3);
1a3fd9c3 5392 {
a7812ae4 5393 TCGv t0 = tcg_temp_local_new();
1a3fd9c3
TS
5394
5395 gen_load_gpr(t0, rt);
5396 save_cpu_state(ctx, 1);
5397 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5398 tcg_temp_free(t0);
5399 }
9c2149c8
TS
5400 opn = "dmtc0";
5401 break;
534ce69f 5402#endif
ead9360e 5403 case OPC_MFTR:
7385ac0b 5404 check_insn(env, ctx, ASE_MT);
ead9360e
TS
5405 if (rd == 0) {
5406 /* Treat as NOP. */
5407 return;
5408 }
6c5c1e20 5409 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
ead9360e 5410 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
ead9360e
TS
5411 opn = "mftr";
5412 break;
5413 case OPC_MTTR:
7385ac0b 5414 check_insn(env, ctx, ASE_MT);
6c5c1e20 5415 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
ead9360e
TS
5416 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5417 opn = "mttr";
5418 break;
6af0bf9c 5419 case OPC_TLBWI:
6af0bf9c 5420 opn = "tlbwi";
c01fccd2 5421 if (!env->tlb->helper_tlbwi)
29929e34 5422 goto die;
a7812ae4 5423 gen_helper_tlbwi();
6af0bf9c
FB
5424 break;
5425 case OPC_TLBWR:
6af0bf9c 5426 opn = "tlbwr";
c01fccd2 5427 if (!env->tlb->helper_tlbwr)
29929e34 5428 goto die;
a7812ae4 5429 gen_helper_tlbwr();
6af0bf9c
FB
5430 break;
5431 case OPC_TLBP:
6af0bf9c 5432 opn = "tlbp";
c01fccd2 5433 if (!env->tlb->helper_tlbp)
29929e34 5434 goto die;
a7812ae4 5435 gen_helper_tlbp();
6af0bf9c
FB
5436 break;
5437 case OPC_TLBR:
6af0bf9c 5438 opn = "tlbr";
c01fccd2 5439 if (!env->tlb->helper_tlbr)
29929e34 5440 goto die;
a7812ae4 5441 gen_helper_tlbr();
6af0bf9c 5442 break;
6af0bf9c
FB
5443 case OPC_ERET:
5444 opn = "eret";
e189e748 5445 check_insn(env, ctx, ISA_MIPS2);
387a8fe5 5446 save_cpu_state(ctx, 1);
a7812ae4 5447 gen_helper_eret();
6af0bf9c
FB
5448 ctx->bstate = BS_EXCP;
5449 break;
5450 case OPC_DERET:
5451 opn = "deret";
e189e748 5452 check_insn(env, ctx, ISA_MIPS32);
6af0bf9c 5453 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
923617a3 5454 MIPS_INVAL(opn);
6af0bf9c
FB
5455 generate_exception(ctx, EXCP_RI);
5456 } else {
387a8fe5 5457 save_cpu_state(ctx, 1);
a7812ae4 5458 gen_helper_deret();
6af0bf9c
FB
5459 ctx->bstate = BS_EXCP;
5460 }
5461 break;
4ad40f36
FB
5462 case OPC_WAIT:
5463 opn = "wait";
e189e748 5464 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
4ad40f36
FB
5465 /* If we get an exception, we want to restart at next instruction */
5466 ctx->pc += 4;
5467 save_cpu_state(ctx, 1);
5468 ctx->pc -= 4;
a7812ae4 5469 gen_helper_wait();
4ad40f36
FB
5470 ctx->bstate = BS_EXCP;
5471 break;
6af0bf9c 5472 default:
29929e34 5473 die:
923617a3 5474 MIPS_INVAL(opn);
6af0bf9c
FB
5475 generate_exception(ctx, EXCP_RI);
5476 return;
5477 }
5478 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5479}
f1aa6320 5480#endif /* !CONFIG_USER_ONLY */
6af0bf9c 5481
6ea83fed 5482/* CP1 Branches (before delay slot) */
e189e748 5483static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5a5012ec 5484 int32_t cc, int32_t offset)
6ea83fed
FB
5485{
5486 target_ulong btarget;
923617a3 5487 const char *opn = "cp1 cond branch";
a7812ae4 5488 TCGv_i32 t0 = tcg_temp_new_i32();
6ea83fed 5489
e189e748
TS
5490 if (cc != 0)
5491 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
5492
6ea83fed
FB
5493 btarget = ctx->pc + 4 + offset;
5494
7a387fff
TS
5495 switch (op) {
5496 case OPC_BC1F:
d94536f4
AJ
5497 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5498 tcg_gen_not_i32(t0, t0);
5499 tcg_gen_andi_i32(t0, t0, 1);
5500 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 5501 opn = "bc1f";
6ea83fed 5502 goto not_likely;
7a387fff 5503 case OPC_BC1FL:
d94536f4
AJ
5504 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5505 tcg_gen_not_i32(t0, t0);
5506 tcg_gen_andi_i32(t0, t0, 1);
5507 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 5508 opn = "bc1fl";
6ea83fed 5509 goto likely;
7a387fff 5510 case OPC_BC1T:
d94536f4
AJ
5511 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5512 tcg_gen_andi_i32(t0, t0, 1);
5513 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 5514 opn = "bc1t";
5a5012ec 5515 goto not_likely;
7a387fff 5516 case OPC_BC1TL:
d94536f4
AJ
5517 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5518 tcg_gen_andi_i32(t0, t0, 1);
5519 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 5520 opn = "bc1tl";
6ea83fed
FB
5521 likely:
5522 ctx->hflags |= MIPS_HFLAG_BL;
5523 break;
5a5012ec 5524 case OPC_BC1FANY2:
a16336e4 5525 {
d94536f4
AJ
5526 TCGv_i32 t1 = tcg_temp_new_i32();
5527 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5528 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5529 tcg_gen_or_i32(t0, t0, t1);
5530 tcg_temp_free_i32(t1);
5531 tcg_gen_not_i32(t0, t0);
5532 tcg_gen_andi_i32(t0, t0, 1);
5533 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 5534 }
fd4a04eb 5535 opn = "bc1any2f";
5a5012ec
TS
5536 goto not_likely;
5537 case OPC_BC1TANY2:
a16336e4 5538 {
d94536f4
AJ
5539 TCGv_i32 t1 = tcg_temp_new_i32();
5540 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5541 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5542 tcg_gen_or_i32(t0, t0, t1);
5543 tcg_temp_free_i32(t1);
5544 tcg_gen_andi_i32(t0, t0, 1);
5545 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 5546 }
fd4a04eb 5547 opn = "bc1any2t";
5a5012ec
TS
5548 goto not_likely;
5549 case OPC_BC1FANY4:
a16336e4 5550 {
d94536f4
AJ
5551 TCGv_i32 t1 = tcg_temp_new_i32();
5552 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5553 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5554 tcg_gen_or_i32(t0, t0, t1);
5555 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5556 tcg_gen_or_i32(t0, t0, t1);
5557 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5558 tcg_gen_or_i32(t0, t0, t1);
5559 tcg_temp_free_i32(t1);
5560 tcg_gen_not_i32(t0, t0);
5561 tcg_gen_andi_i32(t0, t0, 1);
5562 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 5563 }
fd4a04eb 5564 opn = "bc1any4f";
5a5012ec
TS
5565 goto not_likely;
5566 case OPC_BC1TANY4:
a16336e4 5567 {
d94536f4
AJ
5568 TCGv_i32 t1 = tcg_temp_new_i32();
5569 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5570 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5571 tcg_gen_or_i32(t0, t0, t1);
5572 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5573 tcg_gen_or_i32(t0, t0, t1);
5574 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5575 tcg_gen_or_i32(t0, t0, t1);
5576 tcg_temp_free_i32(t1);
5577 tcg_gen_andi_i32(t0, t0, 1);
5578 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 5579 }
fd4a04eb 5580 opn = "bc1any4t";
5a5012ec
TS
5581 not_likely:
5582 ctx->hflags |= MIPS_HFLAG_BC;
5a5012ec
TS
5583 break;
5584 default:
923617a3 5585 MIPS_INVAL(opn);
e397ee33 5586 generate_exception (ctx, EXCP_RI);
6c5c1e20 5587 goto out;
6ea83fed 5588 }
923617a3 5589 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
6ea83fed
FB
5590 ctx->hflags, btarget);
5591 ctx->btarget = btarget;
6c5c1e20
TS
5592
5593 out:
a7812ae4 5594 tcg_temp_free_i32(t0);
6ea83fed
FB
5595}
5596
6af0bf9c 5597/* Coprocessor 1 (FPU) */
5a5012ec 5598
5a5012ec
TS
5599#define FOP(func, fmt) (((fmt) << 21) | (func))
5600
7a387fff 5601static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6ea83fed 5602{
923617a3 5603 const char *opn = "cp1 move";
a7812ae4 5604 TCGv t0 = tcg_temp_local_new();
6ea83fed
FB
5605
5606 switch (opc) {
5607 case OPC_MFC1:
b6d96bed 5608 {
a7812ae4 5609 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5610
5611 gen_load_fpr32(fp0, fs);
5612 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 5613 tcg_temp_free_i32(fp0);
6958549d 5614 }
6c5c1e20 5615 gen_store_gpr(t0, rt);
6ea83fed
FB
5616 opn = "mfc1";
5617 break;
5618 case OPC_MTC1:
6c5c1e20 5619 gen_load_gpr(t0, rt);
b6d96bed 5620 {
a7812ae4 5621 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5622
5623 tcg_gen_trunc_tl_i32(fp0, t0);
5624 gen_store_fpr32(fp0, fs);
a7812ae4 5625 tcg_temp_free_i32(fp0);
6958549d 5626 }
6ea83fed
FB
5627 opn = "mtc1";
5628 break;
5629 case OPC_CFC1:
a7812ae4 5630 gen_helper_1i(cfc1, t0, fs);
6c5c1e20 5631 gen_store_gpr(t0, rt);
6ea83fed
FB
5632 opn = "cfc1";
5633 break;
5634 case OPC_CTC1:
6c5c1e20 5635 gen_load_gpr(t0, rt);
a7812ae4 5636 gen_helper_1i(ctc1, t0, fs);
6ea83fed
FB
5637 opn = "ctc1";
5638 break;
9c2149c8 5639 case OPC_DMFC1:
b6d96bed 5640 {
a7812ae4 5641 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
5642
5643 gen_load_fpr64(ctx, fp0, fs);
a7812ae4
PB
5644 tcg_gen_trunc_i64_tl(t0, fp0);
5645 tcg_temp_free_i64(fp0);
6958549d 5646 }
6c5c1e20 5647 gen_store_gpr(t0, rt);
5a5012ec
TS
5648 opn = "dmfc1";
5649 break;
9c2149c8 5650 case OPC_DMTC1:
6c5c1e20 5651 gen_load_gpr(t0, rt);
b6d96bed 5652 {
a7812ae4 5653 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 5654
a7812ae4 5655 tcg_gen_extu_tl_i64(fp0, t0);
b6d96bed 5656 gen_store_fpr64(ctx, fp0, fs);
a7812ae4 5657 tcg_temp_free_i64(fp0);
6958549d 5658 }
5a5012ec
TS
5659 opn = "dmtc1";
5660 break;
5661 case OPC_MFHC1:
b6d96bed 5662 {
a7812ae4 5663 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5664
5665 gen_load_fpr32h(fp0, fs);
5666 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 5667 tcg_temp_free_i32(fp0);
6958549d 5668 }
6c5c1e20 5669 gen_store_gpr(t0, rt);
5a5012ec
TS
5670 opn = "mfhc1";
5671 break;
5672 case OPC_MTHC1:
6c5c1e20 5673 gen_load_gpr(t0, rt);
b6d96bed 5674 {
a7812ae4 5675 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5676
5677 tcg_gen_trunc_tl_i32(fp0, t0);
5678 gen_store_fpr32h(fp0, fs);
a7812ae4 5679 tcg_temp_free_i32(fp0);
6958549d 5680 }
5a5012ec
TS
5681 opn = "mthc1";
5682 break;
6ea83fed 5683 default:
923617a3 5684 MIPS_INVAL(opn);
e397ee33 5685 generate_exception (ctx, EXCP_RI);
6c5c1e20 5686 goto out;
6ea83fed
FB
5687 }
5688 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
6c5c1e20
TS
5689
5690 out:
5691 tcg_temp_free(t0);
6ea83fed
FB
5692}
5693
5a5012ec
TS
5694static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
5695{
af58f9ca 5696 int l1;
e214b9bb 5697 TCGCond cond;
af58f9ca
AJ
5698 TCGv_i32 t0;
5699
5700 if (rd == 0) {
5701 /* Treat as NOP. */
5702 return;
5703 }
6ea83fed 5704
e214b9bb 5705 if (tf)
e214b9bb 5706 cond = TCG_COND_EQ;
27848470
TS
5707 else
5708 cond = TCG_COND_NE;
5709
af58f9ca
AJ
5710 l1 = gen_new_label();
5711 t0 = tcg_temp_new_i32();
5712 tcg_gen_andi_i32(t0, fpu_fcr31, get_fp_bit(cc));
5713 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5714 if (rs == 0) {
5715 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5716 } else {
5717 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
5718 }
e214b9bb 5719 gen_set_label(l1);
af58f9ca 5720 tcg_temp_free_i32(t0);
5a5012ec
TS
5721}
5722
b6d96bed 5723static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
a16336e4
TS
5724{
5725 uint32_t ccbit;
5726 int cond;
a7812ae4
PB
5727 TCGv_i32 r_tmp1 = tcg_temp_new_i32();
5728 TCGv_i32 fp0 = tcg_temp_local_new_i32();
a16336e4
TS
5729 int l1 = gen_new_label();
5730
5731 if (cc)
5732 ccbit = 1 << (24 + cc);
5733 else
5734 ccbit = 1 << 23;
5735
5736 if (tf)
5737 cond = TCG_COND_EQ;
5738 else
5739 cond = TCG_COND_NE;
5740
9bf3eb2c 5741 gen_load_fpr32(fp0, fd);
f01be154 5742 tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit);
a16336e4 5743 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
a7812ae4 5744 tcg_temp_free_i32(r_tmp1);
9bf3eb2c 5745 gen_load_fpr32(fp0, fs);
a16336e4 5746 gen_set_label(l1);
9bf3eb2c 5747 gen_store_fpr32(fp0, fd);
a7812ae4 5748 tcg_temp_free_i32(fp0);
5a5012ec 5749}
a16336e4 5750
b6d96bed 5751static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
a16336e4
TS
5752{
5753 uint32_t ccbit;
5754 int cond;
a7812ae4
PB
5755 TCGv_i32 r_tmp1 = tcg_temp_new_i32();
5756 TCGv_i64 fp0 = tcg_temp_local_new_i64();
a16336e4
TS
5757 int l1 = gen_new_label();
5758
5759 if (cc)
5760 ccbit = 1 << (24 + cc);
5761 else
5762 ccbit = 1 << 23;
5763
5764 if (tf)
5765 cond = TCG_COND_EQ;
5766 else
5767 cond = TCG_COND_NE;
5768
9bf3eb2c 5769 gen_load_fpr64(ctx, fp0, fd);
f01be154 5770 tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit);
a16336e4 5771 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
a7812ae4 5772 tcg_temp_free_i32(r_tmp1);
9bf3eb2c 5773 gen_load_fpr64(ctx, fp0, fs);
a16336e4 5774 gen_set_label(l1);
9bf3eb2c 5775 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 5776 tcg_temp_free_i64(fp0);
a16336e4
TS
5777}
5778
b6d96bed 5779static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
a16336e4 5780{
9bf3eb2c 5781 uint32_t ccbit1, ccbit2;
a16336e4 5782 int cond;
a7812ae4
PB
5783 TCGv_i32 r_tmp1 = tcg_temp_new_i32();
5784 TCGv_i32 fp0 = tcg_temp_local_new_i32();
a16336e4
TS
5785 int l1 = gen_new_label();
5786 int l2 = gen_new_label();
5787
9bf3eb2c
AJ
5788 if (cc) {
5789 ccbit1 = 1 << (24 + cc);
5790 ccbit2 = 1 << (25 + cc);
5791 } else {
5792 ccbit1 = 1 << 23;
5793 ccbit2 = 1 << 25;
5794 }
5795
a16336e4
TS
5796 if (tf)
5797 cond = TCG_COND_EQ;
5798 else
5799 cond = TCG_COND_NE;
5800
9bf3eb2c
AJ
5801 gen_load_fpr32(fp0, fd);
5802 tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit1);
5803 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
b6d96bed 5804 gen_load_fpr32(fp0, fs);
a16336e4 5805 gen_set_label(l1);
9bf3eb2c
AJ
5806 gen_store_fpr32(fp0, fd);
5807
5808 gen_load_fpr32h(fp0, fd);
5809 tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit2);
5810 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l2);
5811 gen_load_fpr32h(fp0, fs);
a16336e4 5812 gen_set_label(l2);
9bf3eb2c
AJ
5813 gen_store_fpr32h(fp0, fd);
5814
a7812ae4
PB
5815 tcg_temp_free_i32(r_tmp1);
5816 tcg_temp_free_i32(fp0);
a16336e4
TS
5817}
5818
6ea83fed 5819
5e755519
TS
5820static void gen_farith (DisasContext *ctx, uint32_t op1,
5821 int ft, int fs, int fd, int cc)
6ea83fed 5822{
923617a3 5823 const char *opn = "farith";
6ea83fed
FB
5824 const char *condnames[] = {
5825 "c.f",
5826 "c.un",
5827 "c.eq",
5828 "c.ueq",
5829 "c.olt",
5830 "c.ult",
5831 "c.ole",
5832 "c.ule",
5833 "c.sf",
5834 "c.ngle",
5835 "c.seq",
5836 "c.ngl",
5837 "c.lt",
5838 "c.nge",
5839 "c.le",
5840 "c.ngt",
5841 };
5a1e8ffb
TS
5842 const char *condnames_abs[] = {
5843 "cabs.f",
5844 "cabs.un",
5845 "cabs.eq",
5846 "cabs.ueq",
5847 "cabs.olt",
5848 "cabs.ult",
5849 "cabs.ole",
5850 "cabs.ule",
5851 "cabs.sf",
5852 "cabs.ngle",
5853 "cabs.seq",
5854 "cabs.ngl",
5855 "cabs.lt",
5856 "cabs.nge",
5857 "cabs.le",
5858 "cabs.ngt",
5859 };
5860 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
7a387fff
TS
5861 uint32_t func = ctx->opcode & 0x3f;
5862
6ea83fed 5863 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
5a5012ec 5864 case FOP(0, 16):
b6d96bed 5865 {
a7812ae4
PB
5866 TCGv_i32 fp0 = tcg_temp_new_i32();
5867 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
5868
5869 gen_load_fpr32(fp0, fs);
5870 gen_load_fpr32(fp1, ft);
a7812ae4
PB
5871 gen_helper_float_add_s(fp0, fp0, fp1);
5872 tcg_temp_free_i32(fp1);
b6d96bed 5873 gen_store_fpr32(fp0, fd);
a7812ae4 5874 tcg_temp_free_i32(fp0);
b6d96bed 5875 }
5a5012ec 5876 opn = "add.s";
5a1e8ffb 5877 optype = BINOP;
5a5012ec
TS
5878 break;
5879 case FOP(1, 16):
b6d96bed 5880 {
a7812ae4
PB
5881 TCGv_i32 fp0 = tcg_temp_new_i32();
5882 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
5883
5884 gen_load_fpr32(fp0, fs);
5885 gen_load_fpr32(fp1, ft);
a7812ae4
PB
5886 gen_helper_float_sub_s(fp0, fp0, fp1);
5887 tcg_temp_free_i32(fp1);
b6d96bed 5888 gen_store_fpr32(fp0, fd);
a7812ae4 5889 tcg_temp_free_i32(fp0);
b6d96bed 5890 }
5a5012ec 5891 opn = "sub.s";
5a1e8ffb 5892 optype = BINOP;
5a5012ec
TS
5893 break;
5894 case FOP(2, 16):
b6d96bed 5895 {
a7812ae4
PB
5896 TCGv_i32 fp0 = tcg_temp_new_i32();
5897 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
5898
5899 gen_load_fpr32(fp0, fs);
5900 gen_load_fpr32(fp1, ft);
a7812ae4
PB
5901 gen_helper_float_mul_s(fp0, fp0, fp1);
5902 tcg_temp_free_i32(fp1);
b6d96bed 5903 gen_store_fpr32(fp0, fd);
a7812ae4 5904 tcg_temp_free_i32(fp0);
b6d96bed 5905 }
5a5012ec 5906 opn = "mul.s";
5a1e8ffb 5907 optype = BINOP;
5a5012ec
TS
5908 break;
5909 case FOP(3, 16):
b6d96bed 5910 {
a7812ae4
PB
5911 TCGv_i32 fp0 = tcg_temp_new_i32();
5912 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
5913
5914 gen_load_fpr32(fp0, fs);
5915 gen_load_fpr32(fp1, ft);
a7812ae4
PB
5916 gen_helper_float_div_s(fp0, fp0, fp1);
5917 tcg_temp_free_i32(fp1);
b6d96bed 5918 gen_store_fpr32(fp0, fd);
a7812ae4 5919 tcg_temp_free_i32(fp0);
b6d96bed 5920 }
5a5012ec 5921 opn = "div.s";
5a1e8ffb 5922 optype = BINOP;
5a5012ec
TS
5923 break;
5924 case FOP(4, 16):
b6d96bed 5925 {
a7812ae4 5926 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5927
5928 gen_load_fpr32(fp0, fs);
a7812ae4 5929 gen_helper_float_sqrt_s(fp0, fp0);
b6d96bed 5930 gen_store_fpr32(fp0, fd);
a7812ae4 5931 tcg_temp_free_i32(fp0);
b6d96bed 5932 }
5a5012ec
TS
5933 opn = "sqrt.s";
5934 break;
5935 case FOP(5, 16):
b6d96bed 5936 {
a7812ae4 5937 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5938
5939 gen_load_fpr32(fp0, fs);
a7812ae4 5940 gen_helper_float_abs_s(fp0, fp0);
b6d96bed 5941 gen_store_fpr32(fp0, fd);
a7812ae4 5942 tcg_temp_free_i32(fp0);
b6d96bed 5943 }
5a5012ec
TS
5944 opn = "abs.s";
5945 break;
5946 case FOP(6, 16):
b6d96bed 5947 {
a7812ae4 5948 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5949
5950 gen_load_fpr32(fp0, fs);
5951 gen_store_fpr32(fp0, fd);
a7812ae4 5952 tcg_temp_free_i32(fp0);
b6d96bed 5953 }
5a5012ec
TS
5954 opn = "mov.s";
5955 break;
5956 case FOP(7, 16):
b6d96bed 5957 {
a7812ae4 5958 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5959
5960 gen_load_fpr32(fp0, fs);
a7812ae4 5961 gen_helper_float_chs_s(fp0, fp0);
b6d96bed 5962 gen_store_fpr32(fp0, fd);
a7812ae4 5963 tcg_temp_free_i32(fp0);
b6d96bed 5964 }
5a5012ec
TS
5965 opn = "neg.s";
5966 break;
5967 case FOP(8, 16):
5e755519 5968 check_cp1_64bitmode(ctx);
b6d96bed 5969 {
a7812ae4
PB
5970 TCGv_i32 fp32 = tcg_temp_new_i32();
5971 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
5972
5973 gen_load_fpr32(fp32, fs);
a7812ae4
PB
5974 gen_helper_float_roundl_s(fp64, fp32);
5975 tcg_temp_free_i32(fp32);
b6d96bed 5976 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 5977 tcg_temp_free_i64(fp64);
b6d96bed 5978 }
5a5012ec
TS
5979 opn = "round.l.s";
5980 break;
5981 case FOP(9, 16):
5e755519 5982 check_cp1_64bitmode(ctx);
b6d96bed 5983 {
a7812ae4
PB
5984 TCGv_i32 fp32 = tcg_temp_new_i32();
5985 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
5986
5987 gen_load_fpr32(fp32, fs);
a7812ae4
PB
5988 gen_helper_float_truncl_s(fp64, fp32);
5989 tcg_temp_free_i32(fp32);
b6d96bed 5990 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 5991 tcg_temp_free_i64(fp64);
b6d96bed 5992 }
5a5012ec
TS
5993 opn = "trunc.l.s";
5994 break;
5995 case FOP(10, 16):
5e755519 5996 check_cp1_64bitmode(ctx);
b6d96bed 5997 {
a7812ae4
PB
5998 TCGv_i32 fp32 = tcg_temp_new_i32();
5999 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6000
6001 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6002 gen_helper_float_ceill_s(fp64, fp32);
6003 tcg_temp_free_i32(fp32);
b6d96bed 6004 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6005 tcg_temp_free_i64(fp64);
b6d96bed 6006 }
5a5012ec
TS
6007 opn = "ceil.l.s";
6008 break;
6009 case FOP(11, 16):
5e755519 6010 check_cp1_64bitmode(ctx);
b6d96bed 6011 {
a7812ae4
PB
6012 TCGv_i32 fp32 = tcg_temp_new_i32();
6013 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6014
6015 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6016 gen_helper_float_floorl_s(fp64, fp32);
6017 tcg_temp_free_i32(fp32);
b6d96bed 6018 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6019 tcg_temp_free_i64(fp64);
b6d96bed 6020 }
5a5012ec
TS
6021 opn = "floor.l.s";
6022 break;
6023 case FOP(12, 16):
b6d96bed 6024 {
a7812ae4 6025 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6026
6027 gen_load_fpr32(fp0, fs);
a7812ae4 6028 gen_helper_float_roundw_s(fp0, fp0);
b6d96bed 6029 gen_store_fpr32(fp0, fd);
a7812ae4 6030 tcg_temp_free_i32(fp0);
b6d96bed 6031 }
5a5012ec
TS
6032 opn = "round.w.s";
6033 break;
6034 case FOP(13, 16):
b6d96bed 6035 {
a7812ae4 6036 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6037
6038 gen_load_fpr32(fp0, fs);
a7812ae4 6039 gen_helper_float_truncw_s(fp0, fp0);
b6d96bed 6040 gen_store_fpr32(fp0, fd);
a7812ae4 6041 tcg_temp_free_i32(fp0);
b6d96bed 6042 }
5a5012ec
TS
6043 opn = "trunc.w.s";
6044 break;
6045 case FOP(14, 16):
b6d96bed 6046 {
a7812ae4 6047 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6048
6049 gen_load_fpr32(fp0, fs);
a7812ae4 6050 gen_helper_float_ceilw_s(fp0, fp0);
b6d96bed 6051 gen_store_fpr32(fp0, fd);
a7812ae4 6052 tcg_temp_free_i32(fp0);
b6d96bed 6053 }
5a5012ec
TS
6054 opn = "ceil.w.s";
6055 break;
6056 case FOP(15, 16):
b6d96bed 6057 {
a7812ae4 6058 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6059
6060 gen_load_fpr32(fp0, fs);
a7812ae4 6061 gen_helper_float_floorw_s(fp0, fp0);
b6d96bed 6062 gen_store_fpr32(fp0, fd);
a7812ae4 6063 tcg_temp_free_i32(fp0);
b6d96bed 6064 }
5a5012ec
TS
6065 opn = "floor.w.s";
6066 break;
6067 case FOP(17, 16):
b6d96bed 6068 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec
TS
6069 opn = "movcf.s";
6070 break;
6071 case FOP(18, 16):
a16336e4
TS
6072 {
6073 int l1 = gen_new_label();
a7812ae4
PB
6074 TCGv t0 = tcg_temp_new();
6075 TCGv_i32 fp0 = tcg_temp_local_new_i32();
a16336e4 6076
6c5c1e20
TS
6077 gen_load_gpr(t0, ft);
6078 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
b6d96bed
TS
6079 gen_load_fpr32(fp0, fs);
6080 gen_store_fpr32(fp0, fd);
a7812ae4 6081 tcg_temp_free_i32(fp0);
a16336e4 6082 gen_set_label(l1);
2a0ab998 6083 tcg_temp_free(t0);
a16336e4 6084 }
5a5012ec
TS
6085 opn = "movz.s";
6086 break;
6087 case FOP(19, 16):
a16336e4
TS
6088 {
6089 int l1 = gen_new_label();
a7812ae4
PB
6090 TCGv t0 = tcg_temp_new();
6091 TCGv_i32 fp0 = tcg_temp_local_new_i32();
a16336e4 6092
6c5c1e20
TS
6093 gen_load_gpr(t0, ft);
6094 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
b6d96bed
TS
6095 gen_load_fpr32(fp0, fs);
6096 gen_store_fpr32(fp0, fd);
a7812ae4 6097 tcg_temp_free_i32(fp0);
a16336e4 6098 gen_set_label(l1);
2a0ab998 6099 tcg_temp_free(t0);
a16336e4 6100 }
5a5012ec
TS
6101 opn = "movn.s";
6102 break;
57fa1fb3 6103 case FOP(21, 16):
b8aa4598 6104 check_cop1x(ctx);
b6d96bed 6105 {
a7812ae4 6106 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6107
6108 gen_load_fpr32(fp0, fs);
a7812ae4 6109 gen_helper_float_recip_s(fp0, fp0);
b6d96bed 6110 gen_store_fpr32(fp0, fd);
a7812ae4 6111 tcg_temp_free_i32(fp0);
b6d96bed 6112 }
57fa1fb3
TS
6113 opn = "recip.s";
6114 break;
6115 case FOP(22, 16):
b8aa4598 6116 check_cop1x(ctx);
b6d96bed 6117 {
a7812ae4 6118 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6119
6120 gen_load_fpr32(fp0, fs);
a7812ae4 6121 gen_helper_float_rsqrt_s(fp0, fp0);
b6d96bed 6122 gen_store_fpr32(fp0, fd);
a7812ae4 6123 tcg_temp_free_i32(fp0);
b6d96bed 6124 }
57fa1fb3
TS
6125 opn = "rsqrt.s";
6126 break;
6127 case FOP(28, 16):
5e755519 6128 check_cp1_64bitmode(ctx);
b6d96bed 6129 {
a7812ae4
PB
6130 TCGv_i32 fp0 = tcg_temp_new_i32();
6131 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6132
6133 gen_load_fpr32(fp0, fs);
6134 gen_load_fpr32(fp1, fd);
a7812ae4
PB
6135 gen_helper_float_recip2_s(fp0, fp0, fp1);
6136 tcg_temp_free_i32(fp1);
b6d96bed 6137 gen_store_fpr32(fp0, fd);
a7812ae4 6138 tcg_temp_free_i32(fp0);
b6d96bed 6139 }
57fa1fb3
TS
6140 opn = "recip2.s";
6141 break;
6142 case FOP(29, 16):
5e755519 6143 check_cp1_64bitmode(ctx);
b6d96bed 6144 {
a7812ae4 6145 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6146
6147 gen_load_fpr32(fp0, fs);
a7812ae4 6148 gen_helper_float_recip1_s(fp0, fp0);
b6d96bed 6149 gen_store_fpr32(fp0, fd);
a7812ae4 6150 tcg_temp_free_i32(fp0);
b6d96bed 6151 }
57fa1fb3
TS
6152 opn = "recip1.s";
6153 break;
6154 case FOP(30, 16):
5e755519 6155 check_cp1_64bitmode(ctx);
b6d96bed 6156 {
a7812ae4 6157 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6158
6159 gen_load_fpr32(fp0, fs);
a7812ae4 6160 gen_helper_float_rsqrt1_s(fp0, fp0);
b6d96bed 6161 gen_store_fpr32(fp0, fd);
a7812ae4 6162 tcg_temp_free_i32(fp0);
b6d96bed 6163 }
57fa1fb3
TS
6164 opn = "rsqrt1.s";
6165 break;
6166 case FOP(31, 16):
5e755519 6167 check_cp1_64bitmode(ctx);
b6d96bed 6168 {
a7812ae4
PB
6169 TCGv_i32 fp0 = tcg_temp_new_i32();
6170 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6171
6172 gen_load_fpr32(fp0, fs);
6173 gen_load_fpr32(fp1, ft);
a7812ae4
PB
6174 gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
6175 tcg_temp_free_i32(fp1);
b6d96bed 6176 gen_store_fpr32(fp0, fd);
a7812ae4 6177 tcg_temp_free_i32(fp0);
b6d96bed 6178 }
57fa1fb3
TS
6179 opn = "rsqrt2.s";
6180 break;
5a5012ec 6181 case FOP(33, 16):
5e755519 6182 check_cp1_registers(ctx, fd);
b6d96bed 6183 {
a7812ae4
PB
6184 TCGv_i32 fp32 = tcg_temp_new_i32();
6185 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6186
6187 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6188 gen_helper_float_cvtd_s(fp64, fp32);
6189 tcg_temp_free_i32(fp32);
b6d96bed 6190 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6191 tcg_temp_free_i64(fp64);
b6d96bed 6192 }
5a5012ec
TS
6193 opn = "cvt.d.s";
6194 break;
6195 case FOP(36, 16):
b6d96bed 6196 {
a7812ae4 6197 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6198
6199 gen_load_fpr32(fp0, fs);
a7812ae4 6200 gen_helper_float_cvtw_s(fp0, fp0);
b6d96bed 6201 gen_store_fpr32(fp0, fd);
a7812ae4 6202 tcg_temp_free_i32(fp0);
b6d96bed 6203 }
5a5012ec
TS
6204 opn = "cvt.w.s";
6205 break;
6206 case FOP(37, 16):
5e755519 6207 check_cp1_64bitmode(ctx);
b6d96bed 6208 {
a7812ae4
PB
6209 TCGv_i32 fp32 = tcg_temp_new_i32();
6210 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6211
6212 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6213 gen_helper_float_cvtl_s(fp64, fp32);
6214 tcg_temp_free_i32(fp32);
b6d96bed 6215 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6216 tcg_temp_free_i64(fp64);
b6d96bed 6217 }
5a5012ec
TS
6218 opn = "cvt.l.s";
6219 break;
6220 case FOP(38, 16):
5e755519 6221 check_cp1_64bitmode(ctx);
b6d96bed 6222 {
a7812ae4
PB
6223 TCGv_i64 fp64 = tcg_temp_new_i64();
6224 TCGv_i32 fp32_0 = tcg_temp_new_i32();
6225 TCGv_i32 fp32_1 = tcg_temp_new_i32();
b6d96bed
TS
6226
6227 gen_load_fpr32(fp32_0, fs);
6228 gen_load_fpr32(fp32_1, ft);
36aa55dc 6229 tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
a7812ae4
PB
6230 tcg_temp_free_i32(fp32_1);
6231 tcg_temp_free_i32(fp32_0);
36aa55dc 6232 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6233 tcg_temp_free_i64(fp64);
b6d96bed 6234 }
5a5012ec
TS
6235 opn = "cvt.ps.s";
6236 break;
6237 case FOP(48, 16):
6238 case FOP(49, 16):
6239 case FOP(50, 16):
6240 case FOP(51, 16):
6241 case FOP(52, 16):
6242 case FOP(53, 16):
6243 case FOP(54, 16):
6244 case FOP(55, 16):
6245 case FOP(56, 16):
6246 case FOP(57, 16):
6247 case FOP(58, 16):
6248 case FOP(59, 16):
6249 case FOP(60, 16):
6250 case FOP(61, 16):
6251 case FOP(62, 16):
6252 case FOP(63, 16):
b6d96bed 6253 {
a7812ae4
PB
6254 TCGv_i32 fp0 = tcg_temp_new_i32();
6255 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6256
6257 gen_load_fpr32(fp0, fs);
6258 gen_load_fpr32(fp1, ft);
6259 if (ctx->opcode & (1 << 6)) {
6260 check_cop1x(ctx);
6261 gen_cmpabs_s(func-48, fp0, fp1, cc);
6262 opn = condnames_abs[func-48];
6263 } else {
6264 gen_cmp_s(func-48, fp0, fp1, cc);
6265 opn = condnames[func-48];
6266 }
a7812ae4
PB
6267 tcg_temp_free_i32(fp0);
6268 tcg_temp_free_i32(fp1);
5a1e8ffb 6269 }
5a5012ec 6270 break;
6ea83fed 6271 case FOP(0, 17):
5e755519 6272 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6273 {
a7812ae4
PB
6274 TCGv_i64 fp0 = tcg_temp_new_i64();
6275 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6276
6277 gen_load_fpr64(ctx, fp0, fs);
6278 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6279 gen_helper_float_add_d(fp0, fp0, fp1);
6280 tcg_temp_free_i64(fp1);
b6d96bed 6281 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6282 tcg_temp_free_i64(fp0);
b6d96bed 6283 }
6ea83fed 6284 opn = "add.d";
5a1e8ffb 6285 optype = BINOP;
6ea83fed
FB
6286 break;
6287 case FOP(1, 17):
5e755519 6288 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6289 {
a7812ae4
PB
6290 TCGv_i64 fp0 = tcg_temp_new_i64();
6291 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6292
6293 gen_load_fpr64(ctx, fp0, fs);
6294 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6295 gen_helper_float_sub_d(fp0, fp0, fp1);
6296 tcg_temp_free_i64(fp1);
b6d96bed 6297 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6298 tcg_temp_free_i64(fp0);
b6d96bed 6299 }
6ea83fed 6300 opn = "sub.d";
5a1e8ffb 6301 optype = BINOP;
6ea83fed
FB
6302 break;
6303 case FOP(2, 17):
5e755519 6304 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6305 {
a7812ae4
PB
6306 TCGv_i64 fp0 = tcg_temp_new_i64();
6307 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6308
6309 gen_load_fpr64(ctx, fp0, fs);
6310 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6311 gen_helper_float_mul_d(fp0, fp0, fp1);
6312 tcg_temp_free_i64(fp1);
b6d96bed 6313 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6314 tcg_temp_free_i64(fp0);
b6d96bed 6315 }
6ea83fed 6316 opn = "mul.d";
5a1e8ffb 6317 optype = BINOP;
6ea83fed
FB
6318 break;
6319 case FOP(3, 17):
5e755519 6320 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6321 {
a7812ae4
PB
6322 TCGv_i64 fp0 = tcg_temp_new_i64();
6323 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6324
6325 gen_load_fpr64(ctx, fp0, fs);
6326 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6327 gen_helper_float_div_d(fp0, fp0, fp1);
6328 tcg_temp_free_i64(fp1);
b6d96bed 6329 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6330 tcg_temp_free_i64(fp0);
b6d96bed 6331 }
6ea83fed 6332 opn = "div.d";
5a1e8ffb 6333 optype = BINOP;
6ea83fed
FB
6334 break;
6335 case FOP(4, 17):
5e755519 6336 check_cp1_registers(ctx, fs | fd);
b6d96bed 6337 {
a7812ae4 6338 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6339
6340 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6341 gen_helper_float_sqrt_d(fp0, fp0);
b6d96bed 6342 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6343 tcg_temp_free_i64(fp0);
b6d96bed 6344 }
6ea83fed
FB
6345 opn = "sqrt.d";
6346 break;
6347 case FOP(5, 17):
5e755519 6348 check_cp1_registers(ctx, fs | fd);
b6d96bed 6349 {
a7812ae4 6350 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6351
6352 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6353 gen_helper_float_abs_d(fp0, fp0);
b6d96bed 6354 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6355 tcg_temp_free_i64(fp0);
b6d96bed 6356 }
6ea83fed
FB
6357 opn = "abs.d";
6358 break;
6359 case FOP(6, 17):
5e755519 6360 check_cp1_registers(ctx, fs | fd);
b6d96bed 6361 {
a7812ae4 6362 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6363
6364 gen_load_fpr64(ctx, fp0, fs);
6365 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6366 tcg_temp_free_i64(fp0);
b6d96bed 6367 }
6ea83fed
FB
6368 opn = "mov.d";
6369 break;
6370 case FOP(7, 17):
5e755519 6371 check_cp1_registers(ctx, fs | fd);
b6d96bed 6372 {
a7812ae4 6373 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6374
6375 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6376 gen_helper_float_chs_d(fp0, fp0);
b6d96bed 6377 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6378 tcg_temp_free_i64(fp0);
b6d96bed 6379 }
6ea83fed
FB
6380 opn = "neg.d";
6381 break;
5a5012ec 6382 case FOP(8, 17):
5e755519 6383 check_cp1_64bitmode(ctx);
b6d96bed 6384 {
a7812ae4 6385 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6386
6387 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6388 gen_helper_float_roundl_d(fp0, fp0);
b6d96bed 6389 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6390 tcg_temp_free_i64(fp0);
b6d96bed 6391 }
5a5012ec
TS
6392 opn = "round.l.d";
6393 break;
6394 case FOP(9, 17):
5e755519 6395 check_cp1_64bitmode(ctx);
b6d96bed 6396 {
a7812ae4 6397 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6398
6399 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6400 gen_helper_float_truncl_d(fp0, fp0);
b6d96bed 6401 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6402 tcg_temp_free_i64(fp0);
b6d96bed 6403 }
5a5012ec
TS
6404 opn = "trunc.l.d";
6405 break;
6406 case FOP(10, 17):
5e755519 6407 check_cp1_64bitmode(ctx);
b6d96bed 6408 {
a7812ae4 6409 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6410
6411 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6412 gen_helper_float_ceill_d(fp0, fp0);
b6d96bed 6413 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6414 tcg_temp_free_i64(fp0);
b6d96bed 6415 }
5a5012ec
TS
6416 opn = "ceil.l.d";
6417 break;
6418 case FOP(11, 17):
5e755519 6419 check_cp1_64bitmode(ctx);
b6d96bed 6420 {
a7812ae4 6421 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6422
6423 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6424 gen_helper_float_floorl_d(fp0, fp0);
b6d96bed 6425 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6426 tcg_temp_free_i64(fp0);
b6d96bed 6427 }
5a5012ec
TS
6428 opn = "floor.l.d";
6429 break;
6ea83fed 6430 case FOP(12, 17):
5e755519 6431 check_cp1_registers(ctx, fs);
b6d96bed 6432 {
a7812ae4
PB
6433 TCGv_i32 fp32 = tcg_temp_new_i32();
6434 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6435
6436 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6437 gen_helper_float_roundw_d(fp32, fp64);
6438 tcg_temp_free_i64(fp64);
b6d96bed 6439 gen_store_fpr32(fp32, fd);
a7812ae4 6440 tcg_temp_free_i32(fp32);
b6d96bed 6441 }
6ea83fed
FB
6442 opn = "round.w.d";
6443 break;
6444 case FOP(13, 17):
5e755519 6445 check_cp1_registers(ctx, fs);
b6d96bed 6446 {
a7812ae4
PB
6447 TCGv_i32 fp32 = tcg_temp_new_i32();
6448 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6449
6450 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6451 gen_helper_float_truncw_d(fp32, fp64);
6452 tcg_temp_free_i64(fp64);
b6d96bed 6453 gen_store_fpr32(fp32, fd);
a7812ae4 6454 tcg_temp_free_i32(fp32);
b6d96bed 6455 }
6ea83fed
FB
6456 opn = "trunc.w.d";
6457 break;
6458 case FOP(14, 17):
5e755519 6459 check_cp1_registers(ctx, fs);
b6d96bed 6460 {
a7812ae4
PB
6461 TCGv_i32 fp32 = tcg_temp_new_i32();
6462 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6463
6464 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6465 gen_helper_float_ceilw_d(fp32, fp64);
6466 tcg_temp_free_i64(fp64);
b6d96bed 6467 gen_store_fpr32(fp32, fd);
a7812ae4 6468 tcg_temp_free_i32(fp32);
b6d96bed 6469 }
6ea83fed
FB
6470 opn = "ceil.w.d";
6471 break;
6472 case FOP(15, 17):
5e755519 6473 check_cp1_registers(ctx, fs);
b6d96bed 6474 {
a7812ae4
PB
6475 TCGv_i32 fp32 = tcg_temp_new_i32();
6476 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6477
6478 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6479 gen_helper_float_floorw_d(fp32, fp64);
6480 tcg_temp_free_i64(fp64);
b6d96bed 6481 gen_store_fpr32(fp32, fd);
a7812ae4 6482 tcg_temp_free_i32(fp32);
b6d96bed 6483 }
7a387fff 6484 opn = "floor.w.d";
6ea83fed 6485 break;
5a5012ec 6486 case FOP(17, 17):
b6d96bed 6487 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 6488 opn = "movcf.d";
dd016883 6489 break;
5a5012ec 6490 case FOP(18, 17):
a16336e4
TS
6491 {
6492 int l1 = gen_new_label();
a7812ae4
PB
6493 TCGv t0 = tcg_temp_new();
6494 TCGv_i64 fp0 = tcg_temp_local_new_i64();
a16336e4 6495
6c5c1e20
TS
6496 gen_load_gpr(t0, ft);
6497 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
b6d96bed
TS
6498 gen_load_fpr64(ctx, fp0, fs);
6499 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6500 tcg_temp_free_i64(fp0);
a16336e4 6501 gen_set_label(l1);
2a0ab998 6502 tcg_temp_free(t0);
a16336e4 6503 }
5a5012ec
TS
6504 opn = "movz.d";
6505 break;
6506 case FOP(19, 17):
a16336e4
TS
6507 {
6508 int l1 = gen_new_label();
a7812ae4
PB
6509 TCGv t0 = tcg_temp_new();
6510 TCGv_i64 fp0 = tcg_temp_local_new_i64();
a16336e4 6511
6c5c1e20
TS
6512 gen_load_gpr(t0, ft);
6513 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
b6d96bed
TS
6514 gen_load_fpr64(ctx, fp0, fs);
6515 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6516 tcg_temp_free_i64(fp0);
a16336e4 6517 gen_set_label(l1);
2a0ab998 6518 tcg_temp_free(t0);
a16336e4 6519 }
5a5012ec 6520 opn = "movn.d";
6ea83fed 6521 break;
57fa1fb3 6522 case FOP(21, 17):
b8aa4598 6523 check_cp1_64bitmode(ctx);
b6d96bed 6524 {
a7812ae4 6525 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6526
6527 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6528 gen_helper_float_recip_d(fp0, fp0);
b6d96bed 6529 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6530 tcg_temp_free_i64(fp0);
b6d96bed 6531 }
57fa1fb3
TS
6532 opn = "recip.d";
6533 break;
6534 case FOP(22, 17):
b8aa4598 6535 check_cp1_64bitmode(ctx);
b6d96bed 6536 {
a7812ae4 6537 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6538
6539 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6540 gen_helper_float_rsqrt_d(fp0, fp0);
b6d96bed 6541 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6542 tcg_temp_free_i64(fp0);
b6d96bed 6543 }
57fa1fb3
TS
6544 opn = "rsqrt.d";
6545 break;
6546 case FOP(28, 17):
5e755519 6547 check_cp1_64bitmode(ctx);
b6d96bed 6548 {
a7812ae4
PB
6549 TCGv_i64 fp0 = tcg_temp_new_i64();
6550 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6551
6552 gen_load_fpr64(ctx, fp0, fs);
6553 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6554 gen_helper_float_recip2_d(fp0, fp0, fp1);
6555 tcg_temp_free_i64(fp1);
b6d96bed 6556 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6557 tcg_temp_free_i64(fp0);
b6d96bed 6558 }
57fa1fb3
TS
6559 opn = "recip2.d";
6560 break;
6561 case FOP(29, 17):
5e755519 6562 check_cp1_64bitmode(ctx);
b6d96bed 6563 {
a7812ae4 6564 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6565
6566 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6567 gen_helper_float_recip1_d(fp0, fp0);
b6d96bed 6568 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6569 tcg_temp_free_i64(fp0);
b6d96bed 6570 }
57fa1fb3
TS
6571 opn = "recip1.d";
6572 break;
6573 case FOP(30, 17):
5e755519 6574 check_cp1_64bitmode(ctx);
b6d96bed 6575 {
a7812ae4 6576 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6577
6578 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6579 gen_helper_float_rsqrt1_d(fp0, fp0);
b6d96bed 6580 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6581 tcg_temp_free_i64(fp0);
b6d96bed 6582 }
57fa1fb3
TS
6583 opn = "rsqrt1.d";
6584 break;
6585 case FOP(31, 17):
5e755519 6586 check_cp1_64bitmode(ctx);
b6d96bed 6587 {
a7812ae4
PB
6588 TCGv_i64 fp0 = tcg_temp_new_i64();
6589 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6590
6591 gen_load_fpr64(ctx, fp0, fs);
6592 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6593 gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
6594 tcg_temp_free_i64(fp1);
b6d96bed 6595 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6596 tcg_temp_free_i64(fp0);
b6d96bed 6597 }
57fa1fb3
TS
6598 opn = "rsqrt2.d";
6599 break;
6ea83fed
FB
6600 case FOP(48, 17):
6601 case FOP(49, 17):
6602 case FOP(50, 17):
6603 case FOP(51, 17):
6604 case FOP(52, 17):
6605 case FOP(53, 17):
6606 case FOP(54, 17):
6607 case FOP(55, 17):
6608 case FOP(56, 17):
6609 case FOP(57, 17):
6610 case FOP(58, 17):
6611 case FOP(59, 17):
6612 case FOP(60, 17):
6613 case FOP(61, 17):
6614 case FOP(62, 17):
6615 case FOP(63, 17):
b6d96bed 6616 {
a7812ae4
PB
6617 TCGv_i64 fp0 = tcg_temp_new_i64();
6618 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6619
6620 gen_load_fpr64(ctx, fp0, fs);
6621 gen_load_fpr64(ctx, fp1, ft);
6622 if (ctx->opcode & (1 << 6)) {
6623 check_cop1x(ctx);
6624 check_cp1_registers(ctx, fs | ft);
6625 gen_cmpabs_d(func-48, fp0, fp1, cc);
6626 opn = condnames_abs[func-48];
6627 } else {
6628 check_cp1_registers(ctx, fs | ft);
6629 gen_cmp_d(func-48, fp0, fp1, cc);
6630 opn = condnames[func-48];
6631 }
a7812ae4
PB
6632 tcg_temp_free_i64(fp0);
6633 tcg_temp_free_i64(fp1);
5a1e8ffb 6634 }
6ea83fed 6635 break;
5a5012ec 6636 case FOP(32, 17):
5e755519 6637 check_cp1_registers(ctx, fs);
b6d96bed 6638 {
a7812ae4
PB
6639 TCGv_i32 fp32 = tcg_temp_new_i32();
6640 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6641
6642 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6643 gen_helper_float_cvts_d(fp32, fp64);
6644 tcg_temp_free_i64(fp64);
b6d96bed 6645 gen_store_fpr32(fp32, fd);
a7812ae4 6646 tcg_temp_free_i32(fp32);
b6d96bed 6647 }
5a5012ec
TS
6648 opn = "cvt.s.d";
6649 break;
6650 case FOP(36, 17):
5e755519 6651 check_cp1_registers(ctx, fs);
b6d96bed 6652 {
a7812ae4
PB
6653 TCGv_i32 fp32 = tcg_temp_new_i32();
6654 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6655
6656 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6657 gen_helper_float_cvtw_d(fp32, fp64);
6658 tcg_temp_free_i64(fp64);
b6d96bed 6659 gen_store_fpr32(fp32, fd);
a7812ae4 6660 tcg_temp_free_i32(fp32);
b6d96bed 6661 }
5a5012ec
TS
6662 opn = "cvt.w.d";
6663 break;
6664 case FOP(37, 17):
5e755519 6665 check_cp1_64bitmode(ctx);
b6d96bed 6666 {
a7812ae4 6667 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6668
6669 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6670 gen_helper_float_cvtl_d(fp0, fp0);
b6d96bed 6671 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6672 tcg_temp_free_i64(fp0);
b6d96bed 6673 }
5a5012ec
TS
6674 opn = "cvt.l.d";
6675 break;
6676 case FOP(32, 20):
b6d96bed 6677 {
a7812ae4 6678 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6679
6680 gen_load_fpr32(fp0, fs);
a7812ae4 6681 gen_helper_float_cvts_w(fp0, fp0);
b6d96bed 6682 gen_store_fpr32(fp0, fd);
a7812ae4 6683 tcg_temp_free_i32(fp0);
b6d96bed 6684 }
5a5012ec 6685 opn = "cvt.s.w";
6ea83fed 6686 break;
5a5012ec 6687 case FOP(33, 20):
5e755519 6688 check_cp1_registers(ctx, fd);
b6d96bed 6689 {
a7812ae4
PB
6690 TCGv_i32 fp32 = tcg_temp_new_i32();
6691 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6692
6693 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6694 gen_helper_float_cvtd_w(fp64, fp32);
6695 tcg_temp_free_i32(fp32);
b6d96bed 6696 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6697 tcg_temp_free_i64(fp64);
b6d96bed 6698 }
5a5012ec
TS
6699 opn = "cvt.d.w";
6700 break;
6701 case FOP(32, 21):
5e755519 6702 check_cp1_64bitmode(ctx);
b6d96bed 6703 {
a7812ae4
PB
6704 TCGv_i32 fp32 = tcg_temp_new_i32();
6705 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6706
6707 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6708 gen_helper_float_cvts_l(fp32, fp64);
6709 tcg_temp_free_i64(fp64);
b6d96bed 6710 gen_store_fpr32(fp32, fd);
a7812ae4 6711 tcg_temp_free_i32(fp32);
b6d96bed 6712 }
5a5012ec
TS
6713 opn = "cvt.s.l";
6714 break;
6715 case FOP(33, 21):
5e755519 6716 check_cp1_64bitmode(ctx);
b6d96bed 6717 {
a7812ae4 6718 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6719
6720 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6721 gen_helper_float_cvtd_l(fp0, fp0);
b6d96bed 6722 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6723 tcg_temp_free_i64(fp0);
b6d96bed 6724 }
5a5012ec
TS
6725 opn = "cvt.d.l";
6726 break;
6727 case FOP(38, 20):
5e755519 6728 check_cp1_64bitmode(ctx);
b6d96bed 6729 {
a7812ae4 6730 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6731
6732 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6733 gen_helper_float_cvtps_pw(fp0, fp0);
b6d96bed 6734 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6735 tcg_temp_free_i64(fp0);
b6d96bed 6736 }
5a5012ec
TS
6737 opn = "cvt.ps.pw";
6738 break;
6739 case FOP(0, 22):
5e755519 6740 check_cp1_64bitmode(ctx);
b6d96bed 6741 {
a7812ae4
PB
6742 TCGv_i64 fp0 = tcg_temp_new_i64();
6743 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6744
6745 gen_load_fpr64(ctx, fp0, fs);
6746 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6747 gen_helper_float_add_ps(fp0, fp0, fp1);
6748 tcg_temp_free_i64(fp1);
b6d96bed 6749 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6750 tcg_temp_free_i64(fp0);
b6d96bed 6751 }
5a5012ec 6752 opn = "add.ps";
6ea83fed 6753 break;
5a5012ec 6754 case FOP(1, 22):
5e755519 6755 check_cp1_64bitmode(ctx);
b6d96bed 6756 {
a7812ae4
PB
6757 TCGv_i64 fp0 = tcg_temp_new_i64();
6758 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6759
6760 gen_load_fpr64(ctx, fp0, fs);
6761 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6762 gen_helper_float_sub_ps(fp0, fp0, fp1);
6763 tcg_temp_free_i64(fp1);
b6d96bed 6764 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6765 tcg_temp_free_i64(fp0);
b6d96bed 6766 }
5a5012ec 6767 opn = "sub.ps";
6ea83fed 6768 break;
5a5012ec 6769 case FOP(2, 22):
5e755519 6770 check_cp1_64bitmode(ctx);
b6d96bed 6771 {
a7812ae4
PB
6772 TCGv_i64 fp0 = tcg_temp_new_i64();
6773 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6774
6775 gen_load_fpr64(ctx, fp0, fs);
6776 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6777 gen_helper_float_mul_ps(fp0, fp0, fp1);
6778 tcg_temp_free_i64(fp1);
b6d96bed 6779 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6780 tcg_temp_free_i64(fp0);
b6d96bed 6781 }
5a5012ec 6782 opn = "mul.ps";
6ea83fed 6783 break;
5a5012ec 6784 case FOP(5, 22):
5e755519 6785 check_cp1_64bitmode(ctx);
b6d96bed 6786 {
a7812ae4 6787 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6788
6789 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6790 gen_helper_float_abs_ps(fp0, fp0);
b6d96bed 6791 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6792 tcg_temp_free_i64(fp0);
b6d96bed 6793 }
5a5012ec 6794 opn = "abs.ps";
6ea83fed 6795 break;
5a5012ec 6796 case FOP(6, 22):
5e755519 6797 check_cp1_64bitmode(ctx);
b6d96bed 6798 {
a7812ae4 6799 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6800
6801 gen_load_fpr64(ctx, fp0, fs);
6802 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6803 tcg_temp_free_i64(fp0);
b6d96bed 6804 }
5a5012ec 6805 opn = "mov.ps";
6ea83fed 6806 break;
5a5012ec 6807 case FOP(7, 22):
5e755519 6808 check_cp1_64bitmode(ctx);
b6d96bed 6809 {
a7812ae4 6810 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6811
6812 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6813 gen_helper_float_chs_ps(fp0, fp0);
b6d96bed 6814 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6815 tcg_temp_free_i64(fp0);
b6d96bed 6816 }
5a5012ec 6817 opn = "neg.ps";
6ea83fed 6818 break;
5a5012ec 6819 case FOP(17, 22):
5e755519 6820 check_cp1_64bitmode(ctx);
b6d96bed 6821 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 6822 opn = "movcf.ps";
6ea83fed 6823 break;
5a5012ec 6824 case FOP(18, 22):
5e755519 6825 check_cp1_64bitmode(ctx);
a16336e4
TS
6826 {
6827 int l1 = gen_new_label();
a7812ae4
PB
6828 TCGv t0 = tcg_temp_new();
6829 TCGv_i32 fp0 = tcg_temp_local_new_i32();
6830 TCGv_i32 fph0 = tcg_temp_local_new_i32();
a16336e4 6831
6c5c1e20
TS
6832 gen_load_gpr(t0, ft);
6833 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
b6d96bed
TS
6834 gen_load_fpr32(fp0, fs);
6835 gen_load_fpr32h(fph0, fs);
6836 gen_store_fpr32(fp0, fd);
6837 gen_store_fpr32h(fph0, fd);
a7812ae4
PB
6838 tcg_temp_free_i32(fp0);
6839 tcg_temp_free_i32(fph0);
a16336e4 6840 gen_set_label(l1);
2a0ab998 6841 tcg_temp_free(t0);
a16336e4 6842 }
5a5012ec 6843 opn = "movz.ps";
6ea83fed 6844 break;
5a5012ec 6845 case FOP(19, 22):
5e755519 6846 check_cp1_64bitmode(ctx);
a16336e4
TS
6847 {
6848 int l1 = gen_new_label();
a7812ae4
PB
6849 TCGv t0 = tcg_temp_new();
6850 TCGv_i32 fp0 = tcg_temp_local_new_i32();
6851 TCGv_i32 fph0 = tcg_temp_local_new_i32();
a16336e4 6852
6c5c1e20
TS
6853 gen_load_gpr(t0, ft);
6854 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
b6d96bed
TS
6855 gen_load_fpr32(fp0, fs);
6856 gen_load_fpr32h(fph0, fs);
6857 gen_store_fpr32(fp0, fd);
6858 gen_store_fpr32h(fph0, fd);
a7812ae4
PB
6859 tcg_temp_free_i32(fp0);
6860 tcg_temp_free_i32(fph0);
a16336e4 6861 gen_set_label(l1);
2a0ab998 6862 tcg_temp_free(t0);
a16336e4 6863 }
5a5012ec 6864 opn = "movn.ps";
6ea83fed 6865 break;
fbcc6828 6866 case FOP(24, 22):
5e755519 6867 check_cp1_64bitmode(ctx);
b6d96bed 6868 {
a7812ae4
PB
6869 TCGv_i64 fp0 = tcg_temp_new_i64();
6870 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6871
6872 gen_load_fpr64(ctx, fp0, ft);
6873 gen_load_fpr64(ctx, fp1, fs);
a7812ae4
PB
6874 gen_helper_float_addr_ps(fp0, fp0, fp1);
6875 tcg_temp_free_i64(fp1);
b6d96bed 6876 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6877 tcg_temp_free_i64(fp0);
b6d96bed 6878 }
fbcc6828
TS
6879 opn = "addr.ps";
6880 break;
57fa1fb3 6881 case FOP(26, 22):
5e755519 6882 check_cp1_64bitmode(ctx);
b6d96bed 6883 {
a7812ae4
PB
6884 TCGv_i64 fp0 = tcg_temp_new_i64();
6885 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6886
6887 gen_load_fpr64(ctx, fp0, ft);
6888 gen_load_fpr64(ctx, fp1, fs);
a7812ae4
PB
6889 gen_helper_float_mulr_ps(fp0, fp0, fp1);
6890 tcg_temp_free_i64(fp1);
b6d96bed 6891 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6892 tcg_temp_free_i64(fp0);
b6d96bed 6893 }
57fa1fb3
TS
6894 opn = "mulr.ps";
6895 break;
6896 case FOP(28, 22):
5e755519 6897 check_cp1_64bitmode(ctx);
b6d96bed 6898 {
a7812ae4
PB
6899 TCGv_i64 fp0 = tcg_temp_new_i64();
6900 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6901
6902 gen_load_fpr64(ctx, fp0, fs);
6903 gen_load_fpr64(ctx, fp1, fd);
a7812ae4
PB
6904 gen_helper_float_recip2_ps(fp0, fp0, fp1);
6905 tcg_temp_free_i64(fp1);
b6d96bed 6906 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6907 tcg_temp_free_i64(fp0);
b6d96bed 6908 }
57fa1fb3
TS
6909 opn = "recip2.ps";
6910 break;
6911 case FOP(29, 22):
5e755519 6912 check_cp1_64bitmode(ctx);
b6d96bed 6913 {
a7812ae4 6914 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6915
6916 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6917 gen_helper_float_recip1_ps(fp0, fp0);
b6d96bed 6918 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6919 tcg_temp_free_i64(fp0);
b6d96bed 6920 }
57fa1fb3
TS
6921 opn = "recip1.ps";
6922 break;
6923 case FOP(30, 22):
5e755519 6924 check_cp1_64bitmode(ctx);
b6d96bed 6925 {
a7812ae4 6926 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6927
6928 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6929 gen_helper_float_rsqrt1_ps(fp0, fp0);
b6d96bed 6930 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6931 tcg_temp_free_i64(fp0);
b6d96bed 6932 }
57fa1fb3
TS
6933 opn = "rsqrt1.ps";
6934 break;
6935 case FOP(31, 22):
5e755519 6936 check_cp1_64bitmode(ctx);
b6d96bed 6937 {
a7812ae4
PB
6938 TCGv_i64 fp0 = tcg_temp_new_i64();
6939 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6940
6941 gen_load_fpr64(ctx, fp0, fs);
6942 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6943 gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
6944 tcg_temp_free_i64(fp1);
b6d96bed 6945 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6946 tcg_temp_free_i64(fp0);
b6d96bed 6947 }
57fa1fb3
TS
6948 opn = "rsqrt2.ps";
6949 break;
5a5012ec 6950 case FOP(32, 22):
5e755519 6951 check_cp1_64bitmode(ctx);
b6d96bed 6952 {
a7812ae4 6953 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6954
6955 gen_load_fpr32h(fp0, fs);
a7812ae4 6956 gen_helper_float_cvts_pu(fp0, fp0);
b6d96bed 6957 gen_store_fpr32(fp0, fd);
a7812ae4 6958 tcg_temp_free_i32(fp0);
b6d96bed 6959 }
5a5012ec 6960 opn = "cvt.s.pu";
dd016883 6961 break;
5a5012ec 6962 case FOP(36, 22):
5e755519 6963 check_cp1_64bitmode(ctx);
b6d96bed 6964 {
a7812ae4 6965 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6966
6967 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6968 gen_helper_float_cvtpw_ps(fp0, fp0);
b6d96bed 6969 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6970 tcg_temp_free_i64(fp0);
b6d96bed 6971 }
5a5012ec 6972 opn = "cvt.pw.ps";
6ea83fed 6973 break;
5a5012ec 6974 case FOP(40, 22):
5e755519 6975 check_cp1_64bitmode(ctx);
b6d96bed 6976 {
a7812ae4 6977 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6978
6979 gen_load_fpr32(fp0, fs);
a7812ae4 6980 gen_helper_float_cvts_pl(fp0, fp0);
b6d96bed 6981 gen_store_fpr32(fp0, fd);
a7812ae4 6982 tcg_temp_free_i32(fp0);
b6d96bed 6983 }
5a5012ec 6984 opn = "cvt.s.pl";
6ea83fed 6985 break;
5a5012ec 6986 case FOP(44, 22):
5e755519 6987 check_cp1_64bitmode(ctx);
b6d96bed 6988 {
a7812ae4
PB
6989 TCGv_i32 fp0 = tcg_temp_new_i32();
6990 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6991
6992 gen_load_fpr32(fp0, fs);
6993 gen_load_fpr32(fp1, ft);
6994 gen_store_fpr32h(fp0, fd);
6995 gen_store_fpr32(fp1, fd);
a7812ae4
PB
6996 tcg_temp_free_i32(fp0);
6997 tcg_temp_free_i32(fp1);
b6d96bed 6998 }
5a5012ec 6999 opn = "pll.ps";
6ea83fed 7000 break;
5a5012ec 7001 case FOP(45, 22):
5e755519 7002 check_cp1_64bitmode(ctx);
b6d96bed 7003 {
a7812ae4
PB
7004 TCGv_i32 fp0 = tcg_temp_new_i32();
7005 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7006
7007 gen_load_fpr32(fp0, fs);
7008 gen_load_fpr32h(fp1, ft);
7009 gen_store_fpr32(fp1, fd);
7010 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
7011 tcg_temp_free_i32(fp0);
7012 tcg_temp_free_i32(fp1);
b6d96bed 7013 }
5a5012ec
TS
7014 opn = "plu.ps";
7015 break;
7016 case FOP(46, 22):
5e755519 7017 check_cp1_64bitmode(ctx);
b6d96bed 7018 {
a7812ae4
PB
7019 TCGv_i32 fp0 = tcg_temp_new_i32();
7020 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7021
7022 gen_load_fpr32h(fp0, fs);
7023 gen_load_fpr32(fp1, ft);
7024 gen_store_fpr32(fp1, fd);
7025 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
7026 tcg_temp_free_i32(fp0);
7027 tcg_temp_free_i32(fp1);
b6d96bed 7028 }
5a5012ec
TS
7029 opn = "pul.ps";
7030 break;
7031 case FOP(47, 22):
5e755519 7032 check_cp1_64bitmode(ctx);
b6d96bed 7033 {
a7812ae4
PB
7034 TCGv_i32 fp0 = tcg_temp_new_i32();
7035 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7036
7037 gen_load_fpr32h(fp0, fs);
7038 gen_load_fpr32h(fp1, ft);
7039 gen_store_fpr32(fp1, fd);
7040 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
7041 tcg_temp_free_i32(fp0);
7042 tcg_temp_free_i32(fp1);
b6d96bed 7043 }
5a5012ec
TS
7044 opn = "puu.ps";
7045 break;
7046 case FOP(48, 22):
7047 case FOP(49, 22):
7048 case FOP(50, 22):
7049 case FOP(51, 22):
7050 case FOP(52, 22):
7051 case FOP(53, 22):
7052 case FOP(54, 22):
7053 case FOP(55, 22):
7054 case FOP(56, 22):
7055 case FOP(57, 22):
7056 case FOP(58, 22):
7057 case FOP(59, 22):
7058 case FOP(60, 22):
7059 case FOP(61, 22):
7060 case FOP(62, 22):
7061 case FOP(63, 22):
5e755519 7062 check_cp1_64bitmode(ctx);
b6d96bed 7063 {
a7812ae4
PB
7064 TCGv_i64 fp0 = tcg_temp_new_i64();
7065 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7066
7067 gen_load_fpr64(ctx, fp0, fs);
7068 gen_load_fpr64(ctx, fp1, ft);
7069 if (ctx->opcode & (1 << 6)) {
7070 gen_cmpabs_ps(func-48, fp0, fp1, cc);
7071 opn = condnames_abs[func-48];
7072 } else {
7073 gen_cmp_ps(func-48, fp0, fp1, cc);
7074 opn = condnames[func-48];
7075 }
a7812ae4
PB
7076 tcg_temp_free_i64(fp0);
7077 tcg_temp_free_i64(fp1);
5a1e8ffb 7078 }
6ea83fed 7079 break;
5a5012ec 7080 default:
923617a3 7081 MIPS_INVAL(opn);
e397ee33 7082 generate_exception (ctx, EXCP_RI);
6ea83fed
FB
7083 return;
7084 }
5a1e8ffb
TS
7085 switch (optype) {
7086 case BINOP:
6ea83fed 7087 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
5a1e8ffb
TS
7088 break;
7089 case CMPOP:
7090 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7091 break;
7092 default:
6ea83fed 7093 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
5a1e8ffb
TS
7094 break;
7095 }
6ea83fed 7096}
6af0bf9c 7097
5a5012ec 7098/* Coprocessor 3 (FPU) */
5e755519
TS
7099static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7100 int fd, int fs, int base, int index)
7a387fff 7101{
923617a3 7102 const char *opn = "extended float load/store";
93b12ccc 7103 int store = 0;
a7812ae4
PB
7104 TCGv t0 = tcg_temp_local_new();
7105 TCGv t1 = tcg_temp_local_new();
7a387fff 7106
93b12ccc 7107 if (base == 0) {
6c5c1e20 7108 gen_load_gpr(t0, index);
93b12ccc 7109 } else if (index == 0) {
6c5c1e20 7110 gen_load_gpr(t0, base);
93b12ccc 7111 } else {
e9203484
AJ
7112 gen_load_gpr(t0, index);
7113 gen_op_addr_add(ctx, t0, cpu_gpr[base]);
93b12ccc 7114 }
5a5012ec 7115 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 7116 memory access. */
5a5012ec
TS
7117 switch (opc) {
7118 case OPC_LWXC1:
b8aa4598 7119 check_cop1x(ctx);
b6d96bed 7120 {
a7812ae4 7121 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 7122
a7812ae4
PB
7123 tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx);
7124 tcg_gen_trunc_tl_i32(fp0, t1);
b6d96bed 7125 gen_store_fpr32(fp0, fd);
a7812ae4 7126 tcg_temp_free_i32(fp0);
b6d96bed 7127 }
5a5012ec
TS
7128 opn = "lwxc1";
7129 break;
7130 case OPC_LDXC1:
b8aa4598
TS
7131 check_cop1x(ctx);
7132 check_cp1_registers(ctx, fd);
b6d96bed 7133 {
a7812ae4 7134 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7135
7136 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7137 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7138 tcg_temp_free_i64(fp0);
b6d96bed 7139 }
5a5012ec
TS
7140 opn = "ldxc1";
7141 break;
7142 case OPC_LUXC1:
b8aa4598 7143 check_cp1_64bitmode(ctx);
6c5c1e20 7144 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 7145 {
a7812ae4 7146 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7147
7148 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7149 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7150 tcg_temp_free_i64(fp0);
b6d96bed 7151 }
5a5012ec
TS
7152 opn = "luxc1";
7153 break;
7154 case OPC_SWXC1:
b8aa4598 7155 check_cop1x(ctx);
b6d96bed 7156 {
a7812ae4 7157 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7158
7159 gen_load_fpr32(fp0, fs);
a7812ae4
PB
7160 tcg_gen_extu_i32_tl(t1, fp0);
7161 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7162 tcg_temp_free_i32(fp0);
b6d96bed 7163 }
5a5012ec 7164 opn = "swxc1";
93b12ccc 7165 store = 1;
5a5012ec
TS
7166 break;
7167 case OPC_SDXC1:
b8aa4598
TS
7168 check_cop1x(ctx);
7169 check_cp1_registers(ctx, fs);
b6d96bed 7170 {
a7812ae4 7171 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7172
7173 gen_load_fpr64(ctx, fp0, fs);
7174 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 7175 tcg_temp_free_i64(fp0);
b6d96bed 7176 }
5a5012ec 7177 opn = "sdxc1";
93b12ccc 7178 store = 1;
5a5012ec
TS
7179 break;
7180 case OPC_SUXC1:
b8aa4598 7181 check_cp1_64bitmode(ctx);
6c5c1e20 7182 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 7183 {
a7812ae4 7184 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7185
7186 gen_load_fpr64(ctx, fp0, fs);
7187 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 7188 tcg_temp_free_i64(fp0);
b6d96bed 7189 }
5a5012ec 7190 opn = "suxc1";
93b12ccc 7191 store = 1;
5a5012ec
TS
7192 break;
7193 default:
923617a3 7194 MIPS_INVAL(opn);
5a5012ec 7195 generate_exception(ctx, EXCP_RI);
6c5c1e20
TS
7196 tcg_temp_free(t0);
7197 tcg_temp_free(t1);
5a5012ec
TS
7198 return;
7199 }
6c5c1e20
TS
7200 tcg_temp_free(t0);
7201 tcg_temp_free(t1);
93b12ccc
TS
7202 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7203 regnames[index], regnames[base]);
5a5012ec
TS
7204}
7205
5e755519
TS
7206static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7207 int fd, int fr, int fs, int ft)
5a5012ec 7208{
923617a3 7209 const char *opn = "flt3_arith";
5a5012ec 7210
5a5012ec
TS
7211 switch (opc) {
7212 case OPC_ALNV_PS:
b8aa4598 7213 check_cp1_64bitmode(ctx);
a16336e4 7214 {
a7812ae4
PB
7215 TCGv t0 = tcg_temp_local_new();
7216 TCGv_i32 fp0 = tcg_temp_local_new_i32();
7217 TCGv_i32 fph0 = tcg_temp_local_new_i32();
7218 TCGv_i32 fp1 = tcg_temp_local_new_i32();
7219 TCGv_i32 fph1 = tcg_temp_local_new_i32();
a16336e4
TS
7220 int l1 = gen_new_label();
7221 int l2 = gen_new_label();
7222
6c5c1e20
TS
7223 gen_load_gpr(t0, fr);
7224 tcg_gen_andi_tl(t0, t0, 0x7);
b6d96bed
TS
7225 gen_load_fpr32(fp0, fs);
7226 gen_load_fpr32h(fph0, fs);
7227 gen_load_fpr32(fp1, ft);
7228 gen_load_fpr32h(fph1, ft);
6c5c1e20
TS
7229
7230 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
b6d96bed
TS
7231 gen_store_fpr32(fp0, fd);
7232 gen_store_fpr32h(fph0, fd);
a16336e4
TS
7233 tcg_gen_br(l2);
7234 gen_set_label(l1);
6c5c1e20
TS
7235 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7236 tcg_temp_free(t0);
a16336e4 7237#ifdef TARGET_WORDS_BIGENDIAN
b6d96bed
TS
7238 gen_store_fpr32(fph1, fd);
7239 gen_store_fpr32h(fp0, fd);
a16336e4 7240#else
b6d96bed
TS
7241 gen_store_fpr32(fph0, fd);
7242 gen_store_fpr32h(fp1, fd);
a16336e4
TS
7243#endif
7244 gen_set_label(l2);
a7812ae4
PB
7245 tcg_temp_free_i32(fp0);
7246 tcg_temp_free_i32(fph0);
7247 tcg_temp_free_i32(fp1);
7248 tcg_temp_free_i32(fph1);
a16336e4 7249 }
5a5012ec
TS
7250 opn = "alnv.ps";
7251 break;
7252 case OPC_MADD_S:
b8aa4598 7253 check_cop1x(ctx);
b6d96bed 7254 {
a7812ae4
PB
7255 TCGv_i32 fp0 = tcg_temp_new_i32();
7256 TCGv_i32 fp1 = tcg_temp_new_i32();
7257 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7258
7259 gen_load_fpr32(fp0, fs);
7260 gen_load_fpr32(fp1, ft);
7261 gen_load_fpr32(fp2, fr);
a7812ae4
PB
7262 gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
7263 tcg_temp_free_i32(fp0);
7264 tcg_temp_free_i32(fp1);
b6d96bed 7265 gen_store_fpr32(fp2, fd);
a7812ae4 7266 tcg_temp_free_i32(fp2);
b6d96bed 7267 }
5a5012ec
TS
7268 opn = "madd.s";
7269 break;
7270 case OPC_MADD_D:
b8aa4598
TS
7271 check_cop1x(ctx);
7272 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 7273 {
a7812ae4
PB
7274 TCGv_i64 fp0 = tcg_temp_new_i64();
7275 TCGv_i64 fp1 = tcg_temp_new_i64();
7276 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7277
7278 gen_load_fpr64(ctx, fp0, fs);
7279 gen_load_fpr64(ctx, fp1, ft);
7280 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7281 gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
7282 tcg_temp_free_i64(fp0);
7283 tcg_temp_free_i64(fp1);
b6d96bed 7284 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7285 tcg_temp_free_i64(fp2);
b6d96bed 7286 }
5a5012ec
TS
7287 opn = "madd.d";
7288 break;
7289 case OPC_MADD_PS:
b8aa4598 7290 check_cp1_64bitmode(ctx);
b6d96bed 7291 {
a7812ae4
PB
7292 TCGv_i64 fp0 = tcg_temp_new_i64();
7293 TCGv_i64 fp1 = tcg_temp_new_i64();
7294 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7295
7296 gen_load_fpr64(ctx, fp0, fs);
7297 gen_load_fpr64(ctx, fp1, ft);
7298 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7299 gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
7300 tcg_temp_free_i64(fp0);
7301 tcg_temp_free_i64(fp1);
b6d96bed 7302 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7303 tcg_temp_free_i64(fp2);
b6d96bed 7304 }
5a5012ec
TS
7305 opn = "madd.ps";
7306 break;
7307 case OPC_MSUB_S:
b8aa4598 7308 check_cop1x(ctx);
b6d96bed 7309 {
a7812ae4
PB
7310 TCGv_i32 fp0 = tcg_temp_new_i32();
7311 TCGv_i32 fp1 = tcg_temp_new_i32();
7312 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7313
7314 gen_load_fpr32(fp0, fs);
7315 gen_load_fpr32(fp1, ft);
7316 gen_load_fpr32(fp2, fr);
a7812ae4
PB
7317 gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
7318 tcg_temp_free_i32(fp0);
7319 tcg_temp_free_i32(fp1);
b6d96bed 7320 gen_store_fpr32(fp2, fd);
a7812ae4 7321 tcg_temp_free_i32(fp2);
b6d96bed 7322 }
5a5012ec
TS
7323 opn = "msub.s";
7324 break;
7325 case OPC_MSUB_D:
b8aa4598
TS
7326 check_cop1x(ctx);
7327 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 7328 {
a7812ae4
PB
7329 TCGv_i64 fp0 = tcg_temp_new_i64();
7330 TCGv_i64 fp1 = tcg_temp_new_i64();
7331 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7332
7333 gen_load_fpr64(ctx, fp0, fs);
7334 gen_load_fpr64(ctx, fp1, ft);
7335 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7336 gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
7337 tcg_temp_free_i64(fp0);
7338 tcg_temp_free_i64(fp1);
b6d96bed 7339 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7340 tcg_temp_free_i64(fp2);
b6d96bed 7341 }
5a5012ec
TS
7342 opn = "msub.d";
7343 break;
7344 case OPC_MSUB_PS:
b8aa4598 7345 check_cp1_64bitmode(ctx);
b6d96bed 7346 {
a7812ae4
PB
7347 TCGv_i64 fp0 = tcg_temp_new_i64();
7348 TCGv_i64 fp1 = tcg_temp_new_i64();
7349 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7350
7351 gen_load_fpr64(ctx, fp0, fs);
7352 gen_load_fpr64(ctx, fp1, ft);
7353 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7354 gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
7355 tcg_temp_free_i64(fp0);
7356 tcg_temp_free_i64(fp1);
b6d96bed 7357 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7358 tcg_temp_free_i64(fp2);
b6d96bed 7359 }
5a5012ec
TS
7360 opn = "msub.ps";
7361 break;
7362 case OPC_NMADD_S:
b8aa4598 7363 check_cop1x(ctx);
b6d96bed 7364 {
a7812ae4
PB
7365 TCGv_i32 fp0 = tcg_temp_new_i32();
7366 TCGv_i32 fp1 = tcg_temp_new_i32();
7367 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7368
7369 gen_load_fpr32(fp0, fs);
7370 gen_load_fpr32(fp1, ft);
7371 gen_load_fpr32(fp2, fr);
a7812ae4
PB
7372 gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
7373 tcg_temp_free_i32(fp0);
7374 tcg_temp_free_i32(fp1);
b6d96bed 7375 gen_store_fpr32(fp2, fd);
a7812ae4 7376 tcg_temp_free_i32(fp2);
b6d96bed 7377 }
5a5012ec
TS
7378 opn = "nmadd.s";
7379 break;
7380 case OPC_NMADD_D:
b8aa4598
TS
7381 check_cop1x(ctx);
7382 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 7383 {
a7812ae4
PB
7384 TCGv_i64 fp0 = tcg_temp_new_i64();
7385 TCGv_i64 fp1 = tcg_temp_new_i64();
7386 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7387
7388 gen_load_fpr64(ctx, fp0, fs);
7389 gen_load_fpr64(ctx, fp1, ft);
7390 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7391 gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
7392 tcg_temp_free_i64(fp0);
7393 tcg_temp_free_i64(fp1);
b6d96bed 7394 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7395 tcg_temp_free_i64(fp2);
b6d96bed 7396 }
5a5012ec
TS
7397 opn = "nmadd.d";
7398 break;
7399 case OPC_NMADD_PS:
b8aa4598 7400 check_cp1_64bitmode(ctx);
b6d96bed 7401 {
a7812ae4
PB
7402 TCGv_i64 fp0 = tcg_temp_new_i64();
7403 TCGv_i64 fp1 = tcg_temp_new_i64();
7404 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7405
7406 gen_load_fpr64(ctx, fp0, fs);
7407 gen_load_fpr64(ctx, fp1, ft);
7408 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7409 gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
7410 tcg_temp_free_i64(fp0);
7411 tcg_temp_free_i64(fp1);
b6d96bed 7412 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7413 tcg_temp_free_i64(fp2);
b6d96bed 7414 }
5a5012ec
TS
7415 opn = "nmadd.ps";
7416 break;
7417 case OPC_NMSUB_S:
b8aa4598 7418 check_cop1x(ctx);
b6d96bed 7419 {
a7812ae4
PB
7420 TCGv_i32 fp0 = tcg_temp_new_i32();
7421 TCGv_i32 fp1 = tcg_temp_new_i32();
7422 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7423
7424 gen_load_fpr32(fp0, fs);
7425 gen_load_fpr32(fp1, ft);
7426 gen_load_fpr32(fp2, fr);
a7812ae4
PB
7427 gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
7428 tcg_temp_free_i32(fp0);
7429 tcg_temp_free_i32(fp1);
b6d96bed 7430 gen_store_fpr32(fp2, fd);
a7812ae4 7431 tcg_temp_free_i32(fp2);
b6d96bed 7432 }
5a5012ec
TS
7433 opn = "nmsub.s";
7434 break;
7435 case OPC_NMSUB_D:
b8aa4598
TS
7436 check_cop1x(ctx);
7437 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 7438 {
a7812ae4
PB
7439 TCGv_i64 fp0 = tcg_temp_new_i64();
7440 TCGv_i64 fp1 = tcg_temp_new_i64();
7441 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7442
7443 gen_load_fpr64(ctx, fp0, fs);
7444 gen_load_fpr64(ctx, fp1, ft);
7445 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7446 gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
7447 tcg_temp_free_i64(fp0);
7448 tcg_temp_free_i64(fp1);
b6d96bed 7449 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7450 tcg_temp_free_i64(fp2);
b6d96bed 7451 }
5a5012ec
TS
7452 opn = "nmsub.d";
7453 break;
7454 case OPC_NMSUB_PS:
b8aa4598 7455 check_cp1_64bitmode(ctx);
b6d96bed 7456 {
a7812ae4
PB
7457 TCGv_i64 fp0 = tcg_temp_new_i64();
7458 TCGv_i64 fp1 = tcg_temp_new_i64();
7459 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7460
7461 gen_load_fpr64(ctx, fp0, fs);
7462 gen_load_fpr64(ctx, fp1, ft);
7463 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7464 gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
7465 tcg_temp_free_i64(fp0);
7466 tcg_temp_free_i64(fp1);
b6d96bed 7467 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7468 tcg_temp_free_i64(fp2);
b6d96bed 7469 }
5a5012ec
TS
7470 opn = "nmsub.ps";
7471 break;
923617a3
TS
7472 default:
7473 MIPS_INVAL(opn);
5a5012ec
TS
7474 generate_exception (ctx, EXCP_RI);
7475 return;
7476 }
7477 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
7478 fregnames[fs], fregnames[ft]);
7a387fff
TS
7479}
7480
7481/* ISA extensions (ASEs) */
6af0bf9c
FB
7482/* MIPS16 extension to MIPS32 */
7483/* SmartMIPS extension to MIPS32 */
7484
d26bc211 7485#if defined(TARGET_MIPS64)
6af0bf9c
FB
7486
7487/* MDMX extension to MIPS64 */
6af0bf9c
FB
7488
7489#endif
7490
36d23958 7491static void decode_opc (CPUState *env, DisasContext *ctx)
6af0bf9c
FB
7492{
7493 int32_t offset;
7494 int rs, rt, rd, sa;
7a387fff 7495 uint32_t op, op1, op2;
6af0bf9c
FB
7496 int16_t imm;
7497
d796321b
FB
7498 /* make sure instructions are on a word boundary */
7499 if (ctx->pc & 0x3) {
cbeb0857 7500 env->CP0_BadVAddr = ctx->pc;
d796321b
FB
7501 generate_exception(ctx, EXCP_AdEL);
7502 return;
7503 }
7504
8e9ade68 7505 /* Handle blikely not taken case */
4ad40f36 7506 if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
8e9ade68
TS
7507 int l1 = gen_new_label();
7508
3594c774 7509 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
1ba74fb8 7510 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
41db4607 7511 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
5a5012ec
TS
7512 gen_goto_tb(ctx, 1, ctx->pc + 4);
7513 gen_set_label(l1);
6af0bf9c 7514 }
7a387fff
TS
7515 op = MASK_OP_MAJOR(ctx->opcode);
7516 rs = (ctx->opcode >> 21) & 0x1f;
7517 rt = (ctx->opcode >> 16) & 0x1f;
7518 rd = (ctx->opcode >> 11) & 0x1f;
7519 sa = (ctx->opcode >> 6) & 0x1f;
6af0bf9c
FB
7520 imm = (int16_t)ctx->opcode;
7521 switch (op) {
7a387fff
TS
7522 case OPC_SPECIAL:
7523 op1 = MASK_SPECIAL(ctx->opcode);
6af0bf9c 7524 switch (op1) {
7a387fff
TS
7525 case OPC_SLL: /* Arithmetic with immediate */
7526 case OPC_SRL ... OPC_SRA:
e189e748 7527 gen_arith_imm(env, ctx, op1, rd, rt, sa);
7a387fff 7528 break;
e189e748
TS
7529 case OPC_MOVZ ... OPC_MOVN:
7530 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7a387fff
TS
7531 case OPC_SLLV: /* Arithmetic */
7532 case OPC_SRLV ... OPC_SRAV:
7a387fff
TS
7533 case OPC_ADD ... OPC_NOR:
7534 case OPC_SLT ... OPC_SLTU:
e189e748 7535 gen_arith(env, ctx, op1, rd, rs, rt);
7a387fff
TS
7536 break;
7537 case OPC_MULT ... OPC_DIVU:
e9c71dd1
TS
7538 if (sa) {
7539 check_insn(env, ctx, INSN_VR54XX);
7540 op1 = MASK_MUL_VR54XX(ctx->opcode);
7541 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
7542 } else
7543 gen_muldiv(ctx, op1, rs, rt);
7a387fff
TS
7544 break;
7545 case OPC_JR ... OPC_JALR:
7546 gen_compute_branch(ctx, op1, rs, rd, sa);
6af0bf9c 7547 return;
7a387fff
TS
7548 case OPC_TGE ... OPC_TEQ: /* Traps */
7549 case OPC_TNE:
7550 gen_trap(ctx, op1, rs, rt, -1);
6af0bf9c 7551 break;
7a387fff
TS
7552 case OPC_MFHI: /* Move from HI/LO */
7553 case OPC_MFLO:
7554 gen_HILO(ctx, op1, rd);
6af0bf9c 7555 break;
7a387fff
TS
7556 case OPC_MTHI:
7557 case OPC_MTLO: /* Move to HI/LO */
7558 gen_HILO(ctx, op1, rs);
6af0bf9c 7559 break;
b48cfdff
TS
7560 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
7561#ifdef MIPS_STRICT_STANDARD
7562 MIPS_INVAL("PMON / selsl");
7563 generate_exception(ctx, EXCP_RI);
7564#else
a7812ae4 7565 gen_helper_0i(pmon, sa);
b48cfdff 7566#endif
7a387fff
TS
7567 break;
7568 case OPC_SYSCALL:
6af0bf9c
FB
7569 generate_exception(ctx, EXCP_SYSCALL);
7570 break;
7a387fff 7571 case OPC_BREAK:
6af0bf9c
FB
7572 generate_exception(ctx, EXCP_BREAK);
7573 break;
b48cfdff
TS
7574 case OPC_SPIM:
7575#ifdef MIPS_STRICT_STANDARD
7576 MIPS_INVAL("SPIM");
7577 generate_exception(ctx, EXCP_RI);
7578#else
7a387fff
TS
7579 /* Implemented as RI exception for now. */
7580 MIPS_INVAL("spim (unofficial)");
7581 generate_exception(ctx, EXCP_RI);
b48cfdff 7582#endif
6af0bf9c 7583 break;
7a387fff 7584 case OPC_SYNC:
ead9360e 7585 /* Treat as NOP. */
6af0bf9c 7586 break;
4ad40f36 7587
7a387fff 7588 case OPC_MOVCI:
e189e748 7589 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
36d23958 7590 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
e397ee33 7591 save_cpu_state(ctx, 1);
5e755519 7592 check_cp1_enabled(ctx);
36d23958
TS
7593 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
7594 (ctx->opcode >> 16) & 1);
7595 } else {
e397ee33 7596 generate_exception_err(ctx, EXCP_CpU, 1);
36d23958 7597 }
4ad40f36
FB
7598 break;
7599
d26bc211 7600#if defined(TARGET_MIPS64)
7a387fff
TS
7601 /* MIPS64 specific opcodes */
7602 case OPC_DSLL:
7603 case OPC_DSRL ... OPC_DSRA:
7604 case OPC_DSLL32:
7605 case OPC_DSRL32 ... OPC_DSRA32:
e189e748
TS
7606 check_insn(env, ctx, ISA_MIPS3);
7607 check_mips_64(ctx);
7608 gen_arith_imm(env, ctx, op1, rd, rt, sa);
7a387fff
TS
7609 break;
7610 case OPC_DSLLV:
7611 case OPC_DSRLV ... OPC_DSRAV:
7612 case OPC_DADD ... OPC_DSUBU:
e189e748
TS
7613 check_insn(env, ctx, ISA_MIPS3);
7614 check_mips_64(ctx);
7615 gen_arith(env, ctx, op1, rd, rs, rt);
7a387fff
TS
7616 break;
7617 case OPC_DMULT ... OPC_DDIVU:
e189e748
TS
7618 check_insn(env, ctx, ISA_MIPS3);
7619 check_mips_64(ctx);
7a387fff
TS
7620 gen_muldiv(ctx, op1, rs, rt);
7621 break;
6af0bf9c
FB
7622#endif
7623 default: /* Invalid */
7624 MIPS_INVAL("special");
7625 generate_exception(ctx, EXCP_RI);
7626 break;
7627 }
7628 break;
7a387fff
TS
7629 case OPC_SPECIAL2:
7630 op1 = MASK_SPECIAL2(ctx->opcode);
6af0bf9c 7631 switch (op1) {
7a387fff
TS
7632 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
7633 case OPC_MSUB ... OPC_MSUBU:
e189e748 7634 check_insn(env, ctx, ISA_MIPS32);
7a387fff 7635 gen_muldiv(ctx, op1, rs, rt);
6af0bf9c 7636 break;
7a387fff 7637 case OPC_MUL:
e189e748 7638 gen_arith(env, ctx, op1, rd, rs, rt);
6af0bf9c 7639 break;
20e1fb52
AJ
7640 case OPC_CLO:
7641 case OPC_CLZ:
e189e748 7642 check_insn(env, ctx, ISA_MIPS32);
7a387fff 7643 gen_cl(ctx, op1, rd, rs);
6af0bf9c 7644 break;
7a387fff 7645 case OPC_SDBBP:
6af0bf9c
FB
7646 /* XXX: not clear which exception should be raised
7647 * when in debug mode...
7648 */
e189e748 7649 check_insn(env, ctx, ISA_MIPS32);
6af0bf9c
FB
7650 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
7651 generate_exception(ctx, EXCP_DBp);
7652 } else {
7653 generate_exception(ctx, EXCP_DBp);
7654 }
ead9360e 7655 /* Treat as NOP. */
6af0bf9c 7656 break;
d26bc211 7657#if defined(TARGET_MIPS64)
20e1fb52
AJ
7658 case OPC_DCLO:
7659 case OPC_DCLZ:
e189e748
TS
7660 check_insn(env, ctx, ISA_MIPS64);
7661 check_mips_64(ctx);
7a387fff
TS
7662 gen_cl(ctx, op1, rd, rs);
7663 break;
7664#endif
6af0bf9c
FB
7665 default: /* Invalid */
7666 MIPS_INVAL("special2");
7667 generate_exception(ctx, EXCP_RI);
7668 break;
7669 }
7670 break;
7a387fff 7671 case OPC_SPECIAL3:
2b0233ab
TS
7672 op1 = MASK_SPECIAL3(ctx->opcode);
7673 switch (op1) {
7674 case OPC_EXT:
7675 case OPC_INS:
7676 check_insn(env, ctx, ISA_MIPS32R2);
7677 gen_bitops(ctx, op1, rt, rs, sa, rd);
7678 break;
7679 case OPC_BSHFL:
7680 check_insn(env, ctx, ISA_MIPS32R2);
7681 op2 = MASK_BSHFL(ctx->opcode);
49bcf33c 7682 gen_bshfl(ctx, op2, rt, rd);
7a387fff 7683 break;
1579a72e 7684 case OPC_RDHWR:
e189e748 7685 check_insn(env, ctx, ISA_MIPS32R2);
6c5c1e20 7686 {
a7812ae4 7687 TCGv t0 = tcg_temp_local_new();
6c5c1e20
TS
7688
7689 switch (rd) {
7690 case 0:
7691 save_cpu_state(ctx, 1);
a7812ae4 7692 gen_helper_rdhwr_cpunum(t0);
6c5c1e20
TS
7693 break;
7694 case 1:
7695 save_cpu_state(ctx, 1);
a7812ae4 7696 gen_helper_rdhwr_synci_step(t0);
6c5c1e20
TS
7697 break;
7698 case 2:
7699 save_cpu_state(ctx, 1);
a7812ae4 7700 gen_helper_rdhwr_cc(t0);
6c5c1e20
TS
7701 break;
7702 case 3:
7703 save_cpu_state(ctx, 1);
a7812ae4 7704 gen_helper_rdhwr_ccres(t0);
6c5c1e20
TS
7705 break;
7706 case 29:
932e71cd
AJ
7707#if defined(CONFIG_USER_ONLY)
7708 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
7709 break;
7710#else
7711 /* XXX: Some CPUs implement this in hardware.
7712 Not supported yet. */
7713#endif
6c5c1e20
TS
7714 default: /* Invalid */
7715 MIPS_INVAL("rdhwr");
7716 generate_exception(ctx, EXCP_RI);
7717 break;
7718 }
7719 gen_store_gpr(t0, rt);
7720 tcg_temp_free(t0);
1579a72e 7721 }
1579a72e 7722 break;
ead9360e 7723 case OPC_FORK:
7385ac0b 7724 check_insn(env, ctx, ASE_MT);
6c5c1e20 7725 {
a7812ae4
PB
7726 TCGv t0 = tcg_temp_local_new();
7727 TCGv t1 = tcg_temp_local_new();
6c5c1e20
TS
7728
7729 gen_load_gpr(t0, rt);
7730 gen_load_gpr(t1, rs);
a7812ae4 7731 gen_helper_fork(t0, t1);
6c5c1e20
TS
7732 tcg_temp_free(t0);
7733 tcg_temp_free(t1);
7734 }
ead9360e
TS
7735 break;
7736 case OPC_YIELD:
7385ac0b 7737 check_insn(env, ctx, ASE_MT);
6c5c1e20 7738 {
a7812ae4 7739 TCGv t0 = tcg_temp_local_new();
6c5c1e20
TS
7740
7741 gen_load_gpr(t0, rs);
a7812ae4 7742 gen_helper_yield(t0, t0);
6c5c1e20
TS
7743 gen_store_gpr(t0, rd);
7744 tcg_temp_free(t0);
7745 }
ead9360e 7746 break;
d26bc211 7747#if defined(TARGET_MIPS64)
1579a72e
TS
7748 case OPC_DEXTM ... OPC_DEXT:
7749 case OPC_DINSM ... OPC_DINS:
e189e748
TS
7750 check_insn(env, ctx, ISA_MIPS64R2);
7751 check_mips_64(ctx);
1579a72e 7752 gen_bitops(ctx, op1, rt, rs, sa, rd);
7a387fff 7753 break;
1579a72e 7754 case OPC_DBSHFL:
e189e748
TS
7755 check_insn(env, ctx, ISA_MIPS64R2);
7756 check_mips_64(ctx);
1579a72e 7757 op2 = MASK_DBSHFL(ctx->opcode);
49bcf33c 7758 gen_bshfl(ctx, op2, rt, rd);
c6d6dd7c 7759 break;
7a387fff
TS
7760#endif
7761 default: /* Invalid */
7762 MIPS_INVAL("special3");
7763 generate_exception(ctx, EXCP_RI);
7764 break;
7765 }
7766 break;
7767 case OPC_REGIMM:
7768 op1 = MASK_REGIMM(ctx->opcode);
7769 switch (op1) {
7770 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
7771 case OPC_BLTZAL ... OPC_BGEZALL:
7772 gen_compute_branch(ctx, op1, rs, -1, imm << 2);
6af0bf9c 7773 return;
7a387fff
TS
7774 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
7775 case OPC_TNEI:
7776 gen_trap(ctx, op1, rs, -1, imm);
7777 break;
7778 case OPC_SYNCI:
e189e748 7779 check_insn(env, ctx, ISA_MIPS32R2);
ead9360e 7780 /* Treat as NOP. */
6af0bf9c
FB
7781 break;
7782 default: /* Invalid */
923617a3 7783 MIPS_INVAL("regimm");
6af0bf9c
FB
7784 generate_exception(ctx, EXCP_RI);
7785 break;
7786 }
7787 break;
7a387fff 7788 case OPC_CP0:
387a8fe5 7789 check_cp0_enabled(ctx);
7a387fff 7790 op1 = MASK_CP0(ctx->opcode);
6af0bf9c 7791 switch (op1) {
7a387fff
TS
7792 case OPC_MFC0:
7793 case OPC_MTC0:
ead9360e
TS
7794 case OPC_MFTR:
7795 case OPC_MTTR:
d26bc211 7796#if defined(TARGET_MIPS64)
7a387fff
TS
7797 case OPC_DMFC0:
7798 case OPC_DMTC0:
7799#endif
f1aa6320 7800#ifndef CONFIG_USER_ONLY
932e71cd 7801 gen_cp0(env, ctx, op1, rt, rd);
0eaef5aa 7802#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
7803 break;
7804 case OPC_C0_FIRST ... OPC_C0_LAST:
f1aa6320 7805#ifndef CONFIG_USER_ONLY
932e71cd 7806 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
0eaef5aa 7807#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
7808 break;
7809 case OPC_MFMC0:
8706c382 7810#ifndef CONFIG_USER_ONLY
932e71cd 7811 {
a7812ae4 7812 TCGv t0 = tcg_temp_local_new();
6c5c1e20 7813
0eaef5aa 7814 op2 = MASK_MFMC0(ctx->opcode);
6c5c1e20
TS
7815 switch (op2) {
7816 case OPC_DMT:
7817 check_insn(env, ctx, ASE_MT);
a7812ae4 7818 gen_helper_dmt(t0, t0);
6c5c1e20
TS
7819 break;
7820 case OPC_EMT:
7821 check_insn(env, ctx, ASE_MT);
a7812ae4 7822 gen_helper_emt(t0, t0);
da80682b 7823 break;
6c5c1e20
TS
7824 case OPC_DVPE:
7825 check_insn(env, ctx, ASE_MT);
a7812ae4 7826 gen_helper_dvpe(t0, t0);
6c5c1e20
TS
7827 break;
7828 case OPC_EVPE:
7829 check_insn(env, ctx, ASE_MT);
a7812ae4 7830 gen_helper_evpe(t0, t0);
6c5c1e20
TS
7831 break;
7832 case OPC_DI:
7833 check_insn(env, ctx, ISA_MIPS32R2);
7834 save_cpu_state(ctx, 1);
a7812ae4 7835 gen_helper_di(t0);
6c5c1e20
TS
7836 /* Stop translation as we may have switched the execution mode */
7837 ctx->bstate = BS_STOP;
7838 break;
7839 case OPC_EI:
7840 check_insn(env, ctx, ISA_MIPS32R2);
7841 save_cpu_state(ctx, 1);
a7812ae4 7842 gen_helper_ei(t0);
6c5c1e20
TS
7843 /* Stop translation as we may have switched the execution mode */
7844 ctx->bstate = BS_STOP;
7845 break;
7846 default: /* Invalid */
7847 MIPS_INVAL("mfmc0");
7848 generate_exception(ctx, EXCP_RI);
7849 break;
7850 }
7851 gen_store_gpr(t0, rt);
7852 tcg_temp_free(t0);
7a387fff 7853 }
0eaef5aa 7854#endif /* !CONFIG_USER_ONLY */
6af0bf9c 7855 break;
7a387fff 7856 case OPC_RDPGPR:
e189e748 7857 check_insn(env, ctx, ISA_MIPS32R2);
be24bb4f 7858 gen_load_srsgpr(rt, rd);
ead9360e 7859 break;
7a387fff 7860 case OPC_WRPGPR:
e189e748 7861 check_insn(env, ctx, ISA_MIPS32R2);
be24bb4f 7862 gen_store_srsgpr(rt, rd);
38121543 7863 break;
6af0bf9c 7864 default:
923617a3 7865 MIPS_INVAL("cp0");
7a387fff 7866 generate_exception(ctx, EXCP_RI);
6af0bf9c
FB
7867 break;
7868 }
7869 break;
7a387fff 7870 case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
e189e748 7871 gen_arith_imm(env, ctx, op, rt, rs, imm);
7a387fff
TS
7872 break;
7873 case OPC_J ... OPC_JAL: /* Jump */
7874 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
7875 gen_compute_branch(ctx, op, rs, rt, offset);
7876 return;
7877 case OPC_BEQ ... OPC_BGTZ: /* Branch */
7878 case OPC_BEQL ... OPC_BGTZL:
7879 gen_compute_branch(ctx, op, rs, rt, imm << 2);
7880 return;
7881 case OPC_LB ... OPC_LWR: /* Load and stores */
7882 case OPC_SB ... OPC_SW:
7883 case OPC_SWR:
7884 case OPC_LL:
7885 case OPC_SC:
7886 gen_ldst(ctx, op, rt, rs, imm);
7887 break;
7888 case OPC_CACHE:
e189e748 7889 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
ead9360e 7890 /* Treat as NOP. */
34ae7b51 7891 break;
7a387fff 7892 case OPC_PREF:
e189e748 7893 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
ead9360e 7894 /* Treat as NOP. */
6af0bf9c 7895 break;
4ad40f36 7896
923617a3 7897 /* Floating point (COP1). */
7a387fff
TS
7898 case OPC_LWC1:
7899 case OPC_LDC1:
7900 case OPC_SWC1:
7901 case OPC_SDC1:
36d23958
TS
7902 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7903 save_cpu_state(ctx, 1);
5e755519 7904 check_cp1_enabled(ctx);
36d23958
TS
7905 gen_flt_ldst(ctx, op, rt, rs, imm);
7906 } else {
7907 generate_exception_err(ctx, EXCP_CpU, 1);
7908 }
6ea83fed
FB
7909 break;
7910
7a387fff 7911 case OPC_CP1:
36d23958
TS
7912 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7913 save_cpu_state(ctx, 1);
5e755519 7914 check_cp1_enabled(ctx);
36d23958
TS
7915 op1 = MASK_CP1(ctx->opcode);
7916 switch (op1) {
3a95e3a7
TS
7917 case OPC_MFHC1:
7918 case OPC_MTHC1:
e189e748 7919 check_insn(env, ctx, ISA_MIPS32R2);
36d23958
TS
7920 case OPC_MFC1:
7921 case OPC_CFC1:
7922 case OPC_MTC1:
7923 case OPC_CTC1:
e189e748
TS
7924 gen_cp1(ctx, op1, rt, rd);
7925 break;
d26bc211 7926#if defined(TARGET_MIPS64)
36d23958
TS
7927 case OPC_DMFC1:
7928 case OPC_DMTC1:
e189e748 7929 check_insn(env, ctx, ISA_MIPS3);
36d23958
TS
7930 gen_cp1(ctx, op1, rt, rd);
7931 break;
e189e748 7932#endif
fbcc6828
TS
7933 case OPC_BC1ANY2:
7934 case OPC_BC1ANY4:
b8aa4598 7935 check_cop1x(ctx);
7385ac0b 7936 check_insn(env, ctx, ASE_MIPS3D);
d8a5950a
TS
7937 /* fall through */
7938 case OPC_BC1:
e189e748 7939 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
5a5012ec 7940 (rt >> 2) & 0x7, imm << 2);
36d23958
TS
7941 return;
7942 case OPC_S_FMT:
7943 case OPC_D_FMT:
7944 case OPC_W_FMT:
7945 case OPC_L_FMT:
5a5012ec
TS
7946 case OPC_PS_FMT:
7947 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
7948 (imm >> 8) & 0x7);
36d23958
TS
7949 break;
7950 default:
923617a3 7951 MIPS_INVAL("cp1");
e397ee33 7952 generate_exception (ctx, EXCP_RI);
36d23958
TS
7953 break;
7954 }
7955 } else {
7956 generate_exception_err(ctx, EXCP_CpU, 1);
6ea83fed 7957 }
4ad40f36
FB
7958 break;
7959
7960 /* COP2. */
7a387fff
TS
7961 case OPC_LWC2:
7962 case OPC_LDC2:
7963 case OPC_SWC2:
7964 case OPC_SDC2:
7965 case OPC_CP2:
7966 /* COP2: Not implemented. */
4ad40f36
FB
7967 generate_exception_err(ctx, EXCP_CpU, 2);
7968 break;
7969
7a387fff 7970 case OPC_CP3:
36d23958 7971 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
e397ee33 7972 save_cpu_state(ctx, 1);
5e755519 7973 check_cp1_enabled(ctx);
36d23958
TS
7974 op1 = MASK_CP3(ctx->opcode);
7975 switch (op1) {
5a5012ec
TS
7976 case OPC_LWXC1:
7977 case OPC_LDXC1:
7978 case OPC_LUXC1:
7979 case OPC_SWXC1:
7980 case OPC_SDXC1:
7981 case OPC_SUXC1:
93b12ccc 7982 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
5a5012ec 7983 break;
e0c84da7 7984 case OPC_PREFX:
ead9360e 7985 /* Treat as NOP. */
e0c84da7 7986 break;
5a5012ec
TS
7987 case OPC_ALNV_PS:
7988 case OPC_MADD_S:
7989 case OPC_MADD_D:
7990 case OPC_MADD_PS:
7991 case OPC_MSUB_S:
7992 case OPC_MSUB_D:
7993 case OPC_MSUB_PS:
7994 case OPC_NMADD_S:
7995 case OPC_NMADD_D:
7996 case OPC_NMADD_PS:
7997 case OPC_NMSUB_S:
7998 case OPC_NMSUB_D:
7999 case OPC_NMSUB_PS:
8000 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
8001 break;
36d23958 8002 default:
923617a3 8003 MIPS_INVAL("cp3");
e397ee33 8004 generate_exception (ctx, EXCP_RI);
36d23958
TS
8005 break;
8006 }
8007 } else {
e397ee33 8008 generate_exception_err(ctx, EXCP_CpU, 1);
7a387fff 8009 }
4ad40f36
FB
8010 break;
8011
d26bc211 8012#if defined(TARGET_MIPS64)
7a387fff
TS
8013 /* MIPS64 opcodes */
8014 case OPC_LWU:
8015 case OPC_LDL ... OPC_LDR:
8016 case OPC_SDL ... OPC_SDR:
8017 case OPC_LLD:
8018 case OPC_LD:
8019 case OPC_SCD:
8020 case OPC_SD:
e189e748
TS
8021 check_insn(env, ctx, ISA_MIPS3);
8022 check_mips_64(ctx);
7a387fff
TS
8023 gen_ldst(ctx, op, rt, rs, imm);
8024 break;
8025 case OPC_DADDI ... OPC_DADDIU:
e189e748
TS
8026 check_insn(env, ctx, ISA_MIPS3);
8027 check_mips_64(ctx);
8028 gen_arith_imm(env, ctx, op, rt, rs, imm);
7a387fff 8029 break;
6af0bf9c 8030#endif
7a387fff 8031 case OPC_JALX:
e189e748 8032 check_insn(env, ctx, ASE_MIPS16);
7a387fff 8033 /* MIPS16: Not implemented. */
7a387fff 8034 case OPC_MDMX:
e189e748 8035 check_insn(env, ctx, ASE_MDMX);
7a387fff 8036 /* MDMX: Not implemented. */
6af0bf9c 8037 default: /* Invalid */
923617a3 8038 MIPS_INVAL("major opcode");
6af0bf9c
FB
8039 generate_exception(ctx, EXCP_RI);
8040 break;
8041 }
4ad40f36 8042 if (ctx->hflags & MIPS_HFLAG_BMASK) {
c53f4a62 8043 int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
6af0bf9c 8044 /* Branches completion */
4ad40f36 8045 ctx->hflags &= ~MIPS_HFLAG_BMASK;
6af0bf9c
FB
8046 ctx->bstate = BS_BRANCH;
8047 save_cpu_state(ctx, 0);
2e70f6ef 8048 /* FIXME: Need to clear can_do_io. */
5a5012ec 8049 switch (hflags) {
6af0bf9c
FB
8050 case MIPS_HFLAG_B:
8051 /* unconditional branch */
8052 MIPS_DEBUG("unconditional branch");
6e256c93 8053 gen_goto_tb(ctx, 0, ctx->btarget);
6af0bf9c
FB
8054 break;
8055 case MIPS_HFLAG_BL:
8056 /* blikely taken case */
8057 MIPS_DEBUG("blikely branch taken");
6e256c93 8058 gen_goto_tb(ctx, 0, ctx->btarget);
6af0bf9c
FB
8059 break;
8060 case MIPS_HFLAG_BC:
8061 /* Conditional branch */
8062 MIPS_DEBUG("conditional branch");
c53be334 8063 {
8e9ade68
TS
8064 int l1 = gen_new_label();
8065
1ba74fb8 8066 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8e9ade68
TS
8067 gen_goto_tb(ctx, 1, ctx->pc + 4);
8068 gen_set_label(l1);
8069 gen_goto_tb(ctx, 0, ctx->btarget);
c53be334 8070 }
6af0bf9c
FB
8071 break;
8072 case MIPS_HFLAG_BR:
8073 /* unconditional branch to register */
8074 MIPS_DEBUG("branch to register");
4b2eb8d2 8075 tcg_gen_mov_tl(cpu_PC, btarget);
57fec1fe 8076 tcg_gen_exit_tb(0);
6af0bf9c
FB
8077 break;
8078 default:
8079 MIPS_DEBUG("unknown branch");
8080 break;
8081 }
8082 }
8083}
8084
2cfc5f17 8085static inline void
820e00f2
TS
8086gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
8087 int search_pc)
6af0bf9c 8088{
278d0702 8089 DisasContext ctx;
6af0bf9c
FB
8090 target_ulong pc_start;
8091 uint16_t *gen_opc_end;
a1d1bb31 8092 CPUBreakpoint *bp;
6af0bf9c 8093 int j, lj = -1;
2e70f6ef
PB
8094 int num_insns;
8095 int max_insns;
6af0bf9c 8096
93fcfe39
AL
8097 if (search_pc)
8098 qemu_log("search pc %d\n", search_pc);
4ad40f36 8099
6af0bf9c 8100 pc_start = tb->pc;
faf7aaa9
TS
8101 /* Leave some spare opc slots for branch handling. */
8102 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE - 16;
6af0bf9c 8103 ctx.pc = pc_start;
4ad40f36 8104 ctx.saved_pc = -1;
6af0bf9c
FB
8105 ctx.tb = tb;
8106 ctx.bstate = BS_NONE;
4ad40f36 8107 /* Restore delay slot state from the tb context. */
c068688b 8108 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
fd4a04eb 8109 restore_cpu_state(env, &ctx);
932e71cd 8110#ifdef CONFIG_USER_ONLY
0eaef5aa 8111 ctx.mem_idx = MIPS_HFLAG_UM;
932e71cd 8112#else
0eaef5aa 8113 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
932e71cd 8114#endif
2e70f6ef
PB
8115 num_insns = 0;
8116 max_insns = tb->cflags & CF_COUNT_MASK;
8117 if (max_insns == 0)
8118 max_insns = CF_COUNT_MASK;
6af0bf9c 8119#ifdef DEBUG_DISAS
93fcfe39
AL
8120 qemu_log_mask(CPU_LOG_TB_CPU, "------------------------------------------------\n");
8121 /* FIXME: This may print out stale hflags from env... */
8122 log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
6af0bf9c 8123#endif
d12d51d5 8124 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
2e70f6ef 8125 gen_icount_start();
faf7aaa9 8126 while (ctx.bstate == BS_NONE) {
c0ce998e
AL
8127 if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
8128 TAILQ_FOREACH(bp, &env->breakpoints, entry) {
a1d1bb31 8129 if (bp->pc == ctx.pc) {
278d0702 8130 save_cpu_state(&ctx, 1);
4ad40f36 8131 ctx.bstate = BS_BRANCH;
a7812ae4 8132 gen_helper_0i(raise_exception, EXCP_DEBUG);
ce62e5ba
TS
8133 /* Include the breakpoint location or the tb won't
8134 * be flushed when it must be. */
8135 ctx.pc += 4;
4ad40f36
FB
8136 goto done_generating;
8137 }
8138 }
8139 }
8140
6af0bf9c
FB
8141 if (search_pc) {
8142 j = gen_opc_ptr - gen_opc_buf;
6af0bf9c
FB
8143 if (lj < j) {
8144 lj++;
8145 while (lj < j)
8146 gen_opc_instr_start[lj++] = 0;
6af0bf9c 8147 }
4ad40f36
FB
8148 gen_opc_pc[lj] = ctx.pc;
8149 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
8150 gen_opc_instr_start[lj] = 1;
2e70f6ef 8151 gen_opc_icount[lj] = num_insns;
6af0bf9c 8152 }
2e70f6ef
PB
8153 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8154 gen_io_start();
6af0bf9c 8155 ctx.opcode = ldl_code(ctx.pc);
36d23958 8156 decode_opc(env, &ctx);
6af0bf9c 8157 ctx.pc += 4;
2e70f6ef 8158 num_insns++;
4ad40f36
FB
8159
8160 if (env->singlestep_enabled)
8161 break;
8162
6af0bf9c
FB
8163 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
8164 break;
4ad40f36 8165
faf7aaa9
TS
8166 if (gen_opc_ptr >= gen_opc_end)
8167 break;
8168
2e70f6ef
PB
8169 if (num_insns >= max_insns)
8170 break;
6af0bf9c
FB
8171#if defined (MIPS_SINGLE_STEP)
8172 break;
8173#endif
8174 }
2e70f6ef
PB
8175 if (tb->cflags & CF_LAST_IO)
8176 gen_io_end();
4ad40f36 8177 if (env->singlestep_enabled) {
278d0702 8178 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
a7812ae4 8179 gen_helper_0i(raise_exception, EXCP_DEBUG);
16c00cb2 8180 } else {
6958549d 8181 switch (ctx.bstate) {
16c00cb2 8182 case BS_STOP:
a7812ae4 8183 gen_helper_interrupt_restart();
df1561e2
TS
8184 gen_goto_tb(&ctx, 0, ctx.pc);
8185 break;
16c00cb2 8186 case BS_NONE:
278d0702 8187 save_cpu_state(&ctx, 0);
16c00cb2
TS
8188 gen_goto_tb(&ctx, 0, ctx.pc);
8189 break;
5a5012ec 8190 case BS_EXCP:
a7812ae4 8191 gen_helper_interrupt_restart();
57fec1fe 8192 tcg_gen_exit_tb(0);
16c00cb2 8193 break;
5a5012ec
TS
8194 case BS_BRANCH:
8195 default:
8196 break;
6958549d 8197 }
6af0bf9c 8198 }
4ad40f36 8199done_generating:
2e70f6ef 8200 gen_icount_end(tb, num_insns);
6af0bf9c
FB
8201 *gen_opc_ptr = INDEX_op_end;
8202 if (search_pc) {
8203 j = gen_opc_ptr - gen_opc_buf;
8204 lj++;
8205 while (lj <= j)
8206 gen_opc_instr_start[lj++] = 0;
6af0bf9c
FB
8207 } else {
8208 tb->size = ctx.pc - pc_start;
2e70f6ef 8209 tb->icount = num_insns;
6af0bf9c
FB
8210 }
8211#ifdef DEBUG_DISAS
d12d51d5 8212 LOG_DISAS("\n");
8fec2b8c 8213 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
93fcfe39
AL
8214 qemu_log("IN: %s\n", lookup_symbol(pc_start));
8215 log_target_disas(pc_start, ctx.pc - pc_start, 0);
8216 qemu_log("\n");
6af0bf9c 8217 }
93fcfe39 8218 qemu_log_mask(CPU_LOG_TB_CPU, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
6af0bf9c 8219#endif
6af0bf9c
FB
8220}
8221
2cfc5f17 8222void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
6af0bf9c 8223{
2cfc5f17 8224 gen_intermediate_code_internal(env, tb, 0);
6af0bf9c
FB
8225}
8226
2cfc5f17 8227void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
6af0bf9c 8228{
2cfc5f17 8229 gen_intermediate_code_internal(env, tb, 1);
6af0bf9c
FB
8230}
8231
8706c382
TS
8232static void fpu_dump_state(CPUState *env, FILE *f,
8233 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
8234 int flags)
6ea83fed
FB
8235{
8236 int i;
5e755519 8237 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
5a5012ec
TS
8238
8239#define printfpr(fp) \
8240 do { \
8241 if (is_fpu64) \
8242 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n", \
8243 (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd, \
8244 (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
8245 else { \
8246 fpr_t tmp; \
8247 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
8248 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
8249 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n", \
8250 tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd, \
8251 tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]); \
8252 } \
6ea83fed
FB
8253 } while(0)
8254
5a5012ec
TS
8255
8256 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
f01be154
TS
8257 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
8258 get_float_exception_flags(&env->active_fpu.fp_status));
5a5012ec
TS
8259 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
8260 fpu_fprintf(f, "%3s: ", fregnames[i]);
f01be154 8261 printfpr(&env->active_fpu.fpr[i]);
6ea83fed
FB
8262 }
8263
8264#undef printfpr
8265}
8266
d26bc211 8267#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16 8268/* Debug help: The architecture requires 32bit code to maintain proper
c7e8a937 8269 sign-extended values on 64bit machines. */
c570fd16
TS
8270
8271#define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
8272
8706c382
TS
8273static void
8274cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
8275 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8276 int flags)
c570fd16
TS
8277{
8278 int i;
8279
b5dc7732
TS
8280 if (!SIGN_EXT_P(env->active_tc.PC))
8281 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
8282 if (!SIGN_EXT_P(env->active_tc.HI[0]))
8283 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
8284 if (!SIGN_EXT_P(env->active_tc.LO[0]))
8285 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
c570fd16 8286 if (!SIGN_EXT_P(env->btarget))
3594c774 8287 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
c570fd16
TS
8288
8289 for (i = 0; i < 32; i++) {
b5dc7732
TS
8290 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
8291 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
c570fd16
TS
8292 }
8293
8294 if (!SIGN_EXT_P(env->CP0_EPC))
3594c774 8295 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
c570fd16 8296 if (!SIGN_EXT_P(env->CP0_LLAddr))
3594c774 8297 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
c570fd16
TS
8298}
8299#endif
8300
5fafdf24 8301void cpu_dump_state (CPUState *env, FILE *f,
6af0bf9c
FB
8302 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8303 int flags)
8304{
8305 int i;
3b46e624 8306
3594c774 8307 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx " %d\n",
3d5be870
TS
8308 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
8309 env->hflags, env->btarget, env->bcond);
6af0bf9c
FB
8310 for (i = 0; i < 32; i++) {
8311 if ((i & 3) == 0)
8312 cpu_fprintf(f, "GPR%02d:", i);
b5dc7732 8313 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
6af0bf9c
FB
8314 if ((i & 3) == 3)
8315 cpu_fprintf(f, "\n");
8316 }
568b600d 8317
3594c774 8318 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
5e755519 8319 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
3594c774 8320 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
6af0bf9c 8321 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
5e755519 8322 if (env->hflags & MIPS_HFLAG_FPU)
7a387fff 8323 fpu_dump_state(env, f, cpu_fprintf, flags);
d26bc211 8324#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16
TS
8325 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
8326#endif
6af0bf9c
FB
8327}
8328
39454628
TS
8329static void mips_tcg_init(void)
8330{
f01be154 8331 int i;
39454628
TS
8332 static int inited;
8333
8334 /* Initialize various static tables. */
8335 if (inited)
6958549d 8336 return;
39454628 8337
a7812ae4 8338 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
4b2eb8d2 8339 for (i = 0; i < 32; i++)
a7812ae4 8340 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
8341 offsetof(CPUState, active_tc.gpr[i]),
8342 regnames[i]);
a7812ae4 8343 cpu_PC = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
8344 offsetof(CPUState, active_tc.PC), "PC");
8345 for (i = 0; i < MIPS_DSP_ACC; i++) {
a7812ae4 8346 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
8347 offsetof(CPUState, active_tc.HI[i]),
8348 regnames_HI[i]);
a7812ae4 8349 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
8350 offsetof(CPUState, active_tc.LO[i]),
8351 regnames_LO[i]);
a7812ae4 8352 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
8353 offsetof(CPUState, active_tc.ACX[i]),
8354 regnames_ACX[i]);
8355 }
a7812ae4 8356 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
8357 offsetof(CPUState, active_tc.DSPControl),
8358 "DSPControl");
1ba74fb8
AJ
8359 bcond = tcg_global_mem_new(TCG_AREG0,
8360 offsetof(CPUState, bcond), "bcond");
a7812ae4 8361 btarget = tcg_global_mem_new(TCG_AREG0,
d077b6f7 8362 offsetof(CPUState, btarget), "btarget");
41db4607
AJ
8363 hflags = tcg_global_mem_new_i32(TCG_AREG0,
8364 offsetof(CPUState, hflags), "hflags");
8365
a7812ae4
PB
8366 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
8367 offsetof(CPUState, active_fpu.fcr0),
8368 "fcr0");
8369 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
8370 offsetof(CPUState, active_fpu.fcr31),
8371 "fcr31");
39454628 8372
7dd9e556 8373 /* register helpers */
a7812ae4 8374#define GEN_HELPER 2
7dd9e556
TS
8375#include "helper.h"
8376
39454628
TS
8377 inited = 1;
8378}
8379
aaed909a
FB
8380#include "translate_init.c"
8381
8382CPUMIPSState *cpu_mips_init (const char *cpu_model)
6af0bf9c
FB
8383{
8384 CPUMIPSState *env;
aaed909a 8385 const mips_def_t *def;
6af0bf9c 8386
aaed909a
FB
8387 def = cpu_mips_find_by_name(cpu_model);
8388 if (!def)
8389 return NULL;
6af0bf9c 8390 env = qemu_mallocz(sizeof(CPUMIPSState));
aaed909a
FB
8391 env->cpu_model = def;
8392
173d6cfe 8393 cpu_exec_init(env);
01ba9816 8394 env->cpu_model_str = cpu_model;
39454628 8395 mips_tcg_init();
6ae81775
TS
8396 cpu_reset(env);
8397 return env;
8398}
8399
8400void cpu_reset (CPUMIPSState *env)
8401{
eca1bdf4
AL
8402 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
8403 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
8404 log_cpu_state(env, 0);
8405 }
8406
6ae81775
TS
8407 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
8408
6af0bf9c 8409 tlb_flush(env, 1);
6ae81775 8410
6af0bf9c 8411 /* Minimal init */
0eaef5aa 8412#if defined(CONFIG_USER_ONLY)
932e71cd
AJ
8413 env->hflags = MIPS_HFLAG_UM;
8414#else
8415 if (env->hflags & MIPS_HFLAG_BMASK) {
8416 /* If the exception was raised from a delay slot,
8417 come back to the jump. */
8418 env->CP0_ErrorEPC = env->active_tc.PC - 4;
aa328add 8419 } else {
932e71cd
AJ
8420 env->CP0_ErrorEPC = env->active_tc.PC;
8421 }
8422 env->active_tc.PC = (int32_t)0xBFC00000;
8423 env->CP0_Wired = 0;
8424 /* SMP not implemented */
8425 env->CP0_EBase = 0x80000000;
8426 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
8427 /* vectored interrupts not implemented, timer on int 7,
8428 no performance counters. */
8429 env->CP0_IntCtl = 0xe0000000;
8430 {
8431 int i;
8432
8433 for (i = 0; i < 7; i++) {
8434 env->CP0_WatchLo[i] = 0;
8435 env->CP0_WatchHi[i] = 0x80000000;
fd88b6ab 8436 }
932e71cd
AJ
8437 env->CP0_WatchLo[7] = 0;
8438 env->CP0_WatchHi[7] = 0;
fd88b6ab 8439 }
932e71cd
AJ
8440 /* Count register increments in debug mode, EJTAG version 1 */
8441 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
8442 env->hflags = MIPS_HFLAG_CP0;
8443#endif
6af0bf9c 8444 env->exception_index = EXCP_NONE;
aaed909a 8445 cpu_mips_register(env, env->cpu_model);
6af0bf9c 8446}
d2856f1a
AJ
8447
8448void gen_pc_load(CPUState *env, TranslationBlock *tb,
8449 unsigned long searched_pc, int pc_pos, void *puc)
8450{
b5dc7732 8451 env->active_tc.PC = gen_opc_pc[pc_pos];
d2856f1a
AJ
8452 env->hflags &= ~MIPS_HFLAG_BMASK;
8453 env->hflags |= gen_opc_hflags[pc_pos];
8454}
This page took 1.708235 seconds and 4 git commands to generate.