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