]> git.proxmox.com Git - mirror_qemu.git/blame - target-mips/translate.c
target-i386: fix helper_pmovmskb_mmx helper
[mirror_qemu.git] / target-mips / translate.c
CommitLineData
6af0bf9c
FB
1/*
2 * MIPS32 emulation for qemu: main translation routines.
5fafdf24 3 *
6af0bf9c 4 * Copyright (c) 2004-2005 Jocelyn Mayer
6ea83fed 5 * Copyright (c) 2006 Marius Groeger (FPU operations)
bb8a53ad 6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
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:
da80682b 3189 tcg_gen_movi_tl(t0, 0); /* unimplemented */
2423f660
TS
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:
da80682b
AJ
3269 tcg_gen_movi_tl(t0, 0); /* unimplemented */
3270 rn = "ECC";
3271 break;
8c0fdd85 3272 case 27:
7a387fff 3273 switch (sel) {
7a387fff 3274 case 0 ... 3:
da80682b 3275 tcg_gen_movi_tl(t0, 0); /* unimplemented */
2423f660
TS
3276 rn = "CacheErr";
3277 break;
7a387fff
TS
3278 default:
3279 goto die;
3280 }
8c0fdd85 3281 break;
873eb012
TS
3282 case 28:
3283 switch (sel) {
3284 case 0:
7a387fff
TS
3285 case 2:
3286 case 4:
3287 case 6:
1a3fd9c3 3288 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagLo));
873eb012
TS
3289 rn = "TagLo";
3290 break;
3291 case 1:
7a387fff
TS
3292 case 3:
3293 case 5:
3294 case 7:
1a3fd9c3 3295 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataLo));
873eb012
TS
3296 rn = "DataLo";
3297 break;
3298 default:
873eb012
TS
3299 goto die;
3300 }
3301 break;
8c0fdd85 3302 case 29:
7a387fff
TS
3303 switch (sel) {
3304 case 0:
3305 case 2:
3306 case 4:
3307 case 6:
1a3fd9c3 3308 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagHi));
7a387fff
TS
3309 rn = "TagHi";
3310 break;
3311 case 1:
3312 case 3:
3313 case 5:
3314 case 7:
1a3fd9c3 3315 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataHi));
7a387fff
TS
3316 rn = "DataHi";
3317 break;
3318 default:
3319 goto die;
3320 }
8c0fdd85 3321 break;
873eb012 3322 case 30:
7a387fff
TS
3323 switch (sel) {
3324 case 0:
1a3fd9c3
TS
3325 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
3326 tcg_gen_ext32s_tl(t0, t0);
2423f660
TS
3327 rn = "ErrorEPC";
3328 break;
7a387fff
TS
3329 default:
3330 goto die;
3331 }
873eb012
TS
3332 break;
3333 case 31:
7a387fff
TS
3334 switch (sel) {
3335 case 0:
f0b3f3ae 3336 /* EJTAG support */
1a3fd9c3 3337 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DESAVE));
2423f660
TS
3338 rn = "DESAVE";
3339 break;
7a387fff
TS
3340 default:
3341 goto die;
3342 }
873eb012
TS
3343 break;
3344 default:
873eb012
TS
3345 goto die;
3346 }
3347#if defined MIPS_DEBUG_DISAS
3348 if (loglevel & CPU_LOG_TB_IN_ASM) {
7a387fff
TS
3349 fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
3350 rn, reg, sel);
873eb012
TS
3351 }
3352#endif
3353 return;
3354
3355die:
3356#if defined MIPS_DEBUG_DISAS
3357 if (loglevel & CPU_LOG_TB_IN_ASM) {
7a387fff
TS
3358 fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
3359 rn, reg, sel);
873eb012
TS
3360 }
3361#endif
3362 generate_exception(ctx, EXCP_RI);
3363}
3364
1a3fd9c3 3365static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
8c0fdd85 3366{
7a387fff
TS
3367 const char *rn = "invalid";
3368
e189e748
TS
3369 if (sel != 0)
3370 check_insn(env, ctx, ISA_MIPS32);
3371
2e70f6ef
PB
3372 if (use_icount)
3373 gen_io_start();
3374
8c0fdd85
TS
3375 switch (reg) {
3376 case 0:
7a387fff
TS
3377 switch (sel) {
3378 case 0:
1a3fd9c3 3379 tcg_gen_helper_0_1(do_mtc0_index, t0);
7a387fff
TS
3380 rn = "Index";
3381 break;
3382 case 1:
7385ac0b 3383 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3384 tcg_gen_helper_0_1(do_mtc0_mvpcontrol, t0);
7a387fff 3385 rn = "MVPControl";
ead9360e 3386 break;
7a387fff 3387 case 2:
7385ac0b 3388 check_insn(env, ctx, ASE_MT);
ead9360e 3389 /* ignored */
7a387fff 3390 rn = "MVPConf0";
ead9360e 3391 break;
7a387fff 3392 case 3:
7385ac0b 3393 check_insn(env, ctx, ASE_MT);
ead9360e 3394 /* ignored */
7a387fff 3395 rn = "MVPConf1";
ead9360e 3396 break;
7a387fff
TS
3397 default:
3398 goto die;
3399 }
8c0fdd85
TS
3400 break;
3401 case 1:
7a387fff
TS
3402 switch (sel) {
3403 case 0:
2423f660 3404 /* ignored */
7a387fff 3405 rn = "Random";
2423f660 3406 break;
7a387fff 3407 case 1:
7385ac0b 3408 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3409 tcg_gen_helper_0_1(do_mtc0_vpecontrol, t0);
7a387fff 3410 rn = "VPEControl";
ead9360e 3411 break;
7a387fff 3412 case 2:
7385ac0b 3413 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3414 tcg_gen_helper_0_1(do_mtc0_vpeconf0, t0);
7a387fff 3415 rn = "VPEConf0";
ead9360e 3416 break;
7a387fff 3417 case 3:
7385ac0b 3418 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3419 tcg_gen_helper_0_1(do_mtc0_vpeconf1, t0);
7a387fff 3420 rn = "VPEConf1";
ead9360e 3421 break;
7a387fff 3422 case 4:
7385ac0b 3423 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3424 tcg_gen_helper_0_1(do_mtc0_yqmask, t0);
7a387fff 3425 rn = "YQMask";
ead9360e 3426 break;
7a387fff 3427 case 5:
7385ac0b 3428 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3429 gen_mtc0_store64(t0, offsetof(CPUState, CP0_VPESchedule));
7a387fff 3430 rn = "VPESchedule";
ead9360e 3431 break;
7a387fff 3432 case 6:
7385ac0b 3433 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3434 gen_mtc0_store64(t0, offsetof(CPUState, CP0_VPEScheFBack));
7a387fff 3435 rn = "VPEScheFBack";
ead9360e 3436 break;
7a387fff 3437 case 7:
7385ac0b 3438 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3439 tcg_gen_helper_0_1(do_mtc0_vpeopt, t0);
7a387fff 3440 rn = "VPEOpt";
ead9360e 3441 break;
7a387fff
TS
3442 default:
3443 goto die;
3444 }
8c0fdd85
TS
3445 break;
3446 case 2:
7a387fff
TS
3447 switch (sel) {
3448 case 0:
1a3fd9c3 3449 tcg_gen_helper_0_1(do_mtc0_entrylo0, t0);
2423f660
TS
3450 rn = "EntryLo0";
3451 break;
7a387fff 3452 case 1:
7385ac0b 3453 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3454 tcg_gen_helper_0_1(do_mtc0_tcstatus, t0);
2423f660 3455 rn = "TCStatus";
ead9360e 3456 break;
7a387fff 3457 case 2:
7385ac0b 3458 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3459 tcg_gen_helper_0_1(do_mtc0_tcbind, t0);
2423f660 3460 rn = "TCBind";
ead9360e 3461 break;
7a387fff 3462 case 3:
7385ac0b 3463 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3464 tcg_gen_helper_0_1(do_mtc0_tcrestart, t0);
2423f660 3465 rn = "TCRestart";
ead9360e 3466 break;
7a387fff 3467 case 4:
7385ac0b 3468 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3469 tcg_gen_helper_0_1(do_mtc0_tchalt, t0);
2423f660 3470 rn = "TCHalt";
ead9360e 3471 break;
7a387fff 3472 case 5:
7385ac0b 3473 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3474 tcg_gen_helper_0_1(do_mtc0_tccontext, t0);
2423f660 3475 rn = "TCContext";
ead9360e 3476 break;
7a387fff 3477 case 6:
7385ac0b 3478 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3479 tcg_gen_helper_0_1(do_mtc0_tcschedule, t0);
2423f660 3480 rn = "TCSchedule";
ead9360e 3481 break;
7a387fff 3482 case 7:
7385ac0b 3483 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3484 tcg_gen_helper_0_1(do_mtc0_tcschefback, t0);
2423f660 3485 rn = "TCScheFBack";
ead9360e 3486 break;
7a387fff
TS
3487 default:
3488 goto die;
3489 }
8c0fdd85
TS
3490 break;
3491 case 3:
7a387fff
TS
3492 switch (sel) {
3493 case 0:
1a3fd9c3 3494 tcg_gen_helper_0_1(do_mtc0_entrylo1, t0);
2423f660
TS
3495 rn = "EntryLo1";
3496 break;
7a387fff
TS
3497 default:
3498 goto die;
876d4b07 3499 }
8c0fdd85
TS
3500 break;
3501 case 4:
7a387fff
TS
3502 switch (sel) {
3503 case 0:
1a3fd9c3 3504 tcg_gen_helper_0_1(do_mtc0_context, t0);
2423f660
TS
3505 rn = "Context";
3506 break;
7a387fff 3507 case 1:
1a3fd9c3 3508// tcg_gen_helper_0_1(do_mtc0_contextconfig, t0); /* SmartMIPS ASE */
2423f660
TS
3509 rn = "ContextConfig";
3510// break;
7a387fff
TS
3511 default:
3512 goto die;
876d4b07 3513 }
8c0fdd85
TS
3514 break;
3515 case 5:
7a387fff
TS
3516 switch (sel) {
3517 case 0:
1a3fd9c3 3518 tcg_gen_helper_0_1(do_mtc0_pagemask, t0);
2423f660
TS
3519 rn = "PageMask";
3520 break;
7a387fff 3521 case 1:
e189e748 3522 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 3523 tcg_gen_helper_0_1(do_mtc0_pagegrain, t0);
2423f660
TS
3524 rn = "PageGrain";
3525 break;
7a387fff
TS
3526 default:
3527 goto die;
876d4b07 3528 }
8c0fdd85
TS
3529 break;
3530 case 6:
7a387fff
TS
3531 switch (sel) {
3532 case 0:
1a3fd9c3 3533 tcg_gen_helper_0_1(do_mtc0_wired, t0);
2423f660
TS
3534 rn = "Wired";
3535 break;
7a387fff 3536 case 1:
e189e748 3537 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 3538 tcg_gen_helper_0_1(do_mtc0_srsconf0, t0);
2423f660 3539 rn = "SRSConf0";
ead9360e 3540 break;
7a387fff 3541 case 2:
e189e748 3542 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 3543 tcg_gen_helper_0_1(do_mtc0_srsconf1, t0);
2423f660 3544 rn = "SRSConf1";
ead9360e 3545 break;
7a387fff 3546 case 3:
e189e748 3547 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 3548 tcg_gen_helper_0_1(do_mtc0_srsconf2, t0);
2423f660 3549 rn = "SRSConf2";
ead9360e 3550 break;
7a387fff 3551 case 4:
e189e748 3552 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 3553 tcg_gen_helper_0_1(do_mtc0_srsconf3, t0);
2423f660 3554 rn = "SRSConf3";
ead9360e 3555 break;
7a387fff 3556 case 5:
e189e748 3557 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 3558 tcg_gen_helper_0_1(do_mtc0_srsconf4, t0);
2423f660 3559 rn = "SRSConf4";
ead9360e 3560 break;
7a387fff
TS
3561 default:
3562 goto die;
876d4b07 3563 }
8c0fdd85
TS
3564 break;
3565 case 7:
7a387fff
TS
3566 switch (sel) {
3567 case 0:
e189e748 3568 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 3569 tcg_gen_helper_0_1(do_mtc0_hwrena, t0);
2423f660
TS
3570 rn = "HWREna";
3571 break;
7a387fff
TS
3572 default:
3573 goto die;
876d4b07 3574 }
8c0fdd85
TS
3575 break;
3576 case 8:
7a387fff 3577 /* ignored */
f0b3f3ae 3578 rn = "BadVAddr";
8c0fdd85
TS
3579 break;
3580 case 9:
7a387fff
TS
3581 switch (sel) {
3582 case 0:
1a3fd9c3 3583 tcg_gen_helper_0_1(do_mtc0_count, t0);
2423f660
TS
3584 rn = "Count";
3585 break;
876d4b07 3586 /* 6,7 are implementation dependent */
7a387fff
TS
3587 default:
3588 goto die;
876d4b07
TS
3589 }
3590 /* Stop translation as we may have switched the execution mode */
3591 ctx->bstate = BS_STOP;
8c0fdd85
TS
3592 break;
3593 case 10:
7a387fff
TS
3594 switch (sel) {
3595 case 0:
1a3fd9c3 3596 tcg_gen_helper_0_1(do_mtc0_entryhi, t0);
2423f660
TS
3597 rn = "EntryHi";
3598 break;
7a387fff
TS
3599 default:
3600 goto die;
876d4b07 3601 }
8c0fdd85
TS
3602 break;
3603 case 11:
7a387fff
TS
3604 switch (sel) {
3605 case 0:
1a3fd9c3 3606 tcg_gen_helper_0_1(do_mtc0_compare, t0);
2423f660
TS
3607 rn = "Compare";
3608 break;
3609 /* 6,7 are implementation dependent */
7a387fff
TS
3610 default:
3611 goto die;
876d4b07 3612 }
de9a95f0
AJ
3613 /* Stop translation as we may have switched the execution mode */
3614 ctx->bstate = BS_STOP;
8c0fdd85
TS
3615 break;
3616 case 12:
7a387fff
TS
3617 switch (sel) {
3618 case 0:
1a3fd9c3 3619 tcg_gen_helper_0_1(do_mtc0_status, t0);
8487327a
TS
3620 /* BS_STOP isn't good enough here, hflags may have changed. */
3621 gen_save_pc(ctx->pc + 4);
3622 ctx->bstate = BS_EXCP;
2423f660
TS
3623 rn = "Status";
3624 break;
7a387fff 3625 case 1:
e189e748 3626 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 3627 tcg_gen_helper_0_1(do_mtc0_intctl, t0);
8487327a
TS
3628 /* Stop translation as we may have switched the execution mode */
3629 ctx->bstate = BS_STOP;
2423f660
TS
3630 rn = "IntCtl";
3631 break;
7a387fff 3632 case 2:
e189e748 3633 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 3634 tcg_gen_helper_0_1(do_mtc0_srsctl, t0);
8487327a
TS
3635 /* Stop translation as we may have switched the execution mode */
3636 ctx->bstate = BS_STOP;
2423f660
TS
3637 rn = "SRSCtl";
3638 break;
7a387fff 3639 case 3:
e189e748 3640 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 3641 gen_mtc0_store32(t0, offsetof(CPUState, CP0_SRSMap));
8487327a
TS
3642 /* Stop translation as we may have switched the execution mode */
3643 ctx->bstate = BS_STOP;
2423f660 3644 rn = "SRSMap";
fd88b6ab 3645 break;
7a387fff
TS
3646 default:
3647 goto die;
876d4b07 3648 }
8c0fdd85
TS
3649 break;
3650 case 13:
7a387fff
TS
3651 switch (sel) {
3652 case 0:
1a3fd9c3 3653 tcg_gen_helper_0_1(do_mtc0_cause, t0);
2423f660
TS
3654 rn = "Cause";
3655 break;
7a387fff
TS
3656 default:
3657 goto die;
876d4b07
TS
3658 }
3659 /* Stop translation as we may have switched the execution mode */
3660 ctx->bstate = BS_STOP;
8c0fdd85
TS
3661 break;
3662 case 14:
7a387fff
TS
3663 switch (sel) {
3664 case 0:
1a3fd9c3 3665 gen_mtc0_store64(t0, offsetof(CPUState, CP0_EPC));
2423f660
TS
3666 rn = "EPC";
3667 break;
7a387fff
TS
3668 default:
3669 goto die;
876d4b07 3670 }
8c0fdd85
TS
3671 break;
3672 case 15:
7a387fff
TS
3673 switch (sel) {
3674 case 0:
2423f660
TS
3675 /* ignored */
3676 rn = "PRid";
3677 break;
7a387fff 3678 case 1:
e189e748 3679 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 3680 tcg_gen_helper_0_1(do_mtc0_ebase, t0);
2423f660
TS
3681 rn = "EBase";
3682 break;
7a387fff
TS
3683 default:
3684 goto die;
1579a72e 3685 }
8c0fdd85
TS
3686 break;
3687 case 16:
3688 switch (sel) {
3689 case 0:
1a3fd9c3 3690 tcg_gen_helper_0_1(do_mtc0_config0, t0);
7a387fff 3691 rn = "Config";
2423f660
TS
3692 /* Stop translation as we may have switched the execution mode */
3693 ctx->bstate = BS_STOP;
7a387fff
TS
3694 break;
3695 case 1:
e397ee33 3696 /* ignored, read only */
7a387fff
TS
3697 rn = "Config1";
3698 break;
3699 case 2:
1a3fd9c3 3700 tcg_gen_helper_0_1(do_mtc0_config2, t0);
7a387fff 3701 rn = "Config2";
2423f660
TS
3702 /* Stop translation as we may have switched the execution mode */
3703 ctx->bstate = BS_STOP;
8c0fdd85 3704 break;
7a387fff 3705 case 3:
e397ee33 3706 /* ignored, read only */
7a387fff
TS
3707 rn = "Config3";
3708 break;
e397ee33
TS
3709 /* 4,5 are reserved */
3710 /* 6,7 are implementation dependent */
3711 case 6:
3712 /* ignored */
3713 rn = "Config6";
3714 break;
3715 case 7:
3716 /* ignored */
3717 rn = "Config7";
3718 break;
8c0fdd85
TS
3719 default:
3720 rn = "Invalid config selector";
3721 goto die;
3722 }
3723 break;
3724 case 17:
7a387fff
TS
3725 switch (sel) {
3726 case 0:
2423f660
TS
3727 /* ignored */
3728 rn = "LLAddr";
3729 break;
7a387fff
TS
3730 default:
3731 goto die;
3732 }
8c0fdd85
TS
3733 break;
3734 case 18:
7a387fff 3735 switch (sel) {
fd88b6ab 3736 case 0 ... 7:
1a3fd9c3 3737 tcg_gen_helper_0_1i(do_mtc0_watchlo, t0, sel);
2423f660
TS
3738 rn = "WatchLo";
3739 break;
7a387fff
TS
3740 default:
3741 goto die;
3742 }
8c0fdd85
TS
3743 break;
3744 case 19:
7a387fff 3745 switch (sel) {
fd88b6ab 3746 case 0 ... 7:
1a3fd9c3 3747 tcg_gen_helper_0_1i(do_mtc0_watchhi, t0, sel);
2423f660
TS
3748 rn = "WatchHi";
3749 break;
7a387fff
TS
3750 default:
3751 goto die;
3752 }
8c0fdd85
TS
3753 break;
3754 case 20:
7a387fff
TS
3755 switch (sel) {
3756 case 0:
d26bc211 3757#if defined(TARGET_MIPS64)
e189e748 3758 check_insn(env, ctx, ISA_MIPS3);
1a3fd9c3 3759 tcg_gen_helper_0_1(do_mtc0_xcontext, t0);
2423f660
TS
3760 rn = "XContext";
3761 break;
703eaf37 3762#endif
7a387fff
TS
3763 default:
3764 goto die;
3765 }
8c0fdd85
TS
3766 break;
3767 case 21:
7a387fff
TS
3768 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3769 switch (sel) {
3770 case 0:
1a3fd9c3 3771 tcg_gen_helper_0_1(do_mtc0_framemask, t0);
2423f660
TS
3772 rn = "Framemask";
3773 break;
7a387fff
TS
3774 default:
3775 goto die;
3776 }
3777 break;
8c0fdd85 3778 case 22:
7a387fff
TS
3779 /* ignored */
3780 rn = "Diagnostic"; /* implementation dependent */
2423f660 3781 break;
8c0fdd85 3782 case 23:
7a387fff
TS
3783 switch (sel) {
3784 case 0:
1a3fd9c3 3785 tcg_gen_helper_0_1(do_mtc0_debug, t0); /* EJTAG support */
8487327a
TS
3786 /* BS_STOP isn't good enough here, hflags may have changed. */
3787 gen_save_pc(ctx->pc + 4);
3788 ctx->bstate = BS_EXCP;
2423f660
TS
3789 rn = "Debug";
3790 break;
7a387fff 3791 case 1:
1a3fd9c3 3792// tcg_gen_helper_0_1(do_mtc0_tracecontrol, t0); /* PDtrace support */
2423f660 3793 rn = "TraceControl";
8487327a
TS
3794 /* Stop translation as we may have switched the execution mode */
3795 ctx->bstate = BS_STOP;
2423f660 3796// break;
7a387fff 3797 case 2:
1a3fd9c3 3798// tcg_gen_helper_0_1(do_mtc0_tracecontrol2, t0); /* PDtrace support */
2423f660 3799 rn = "TraceControl2";
8487327a
TS
3800 /* Stop translation as we may have switched the execution mode */
3801 ctx->bstate = BS_STOP;
2423f660 3802// break;
7a387fff 3803 case 3:
8487327a
TS
3804 /* Stop translation as we may have switched the execution mode */
3805 ctx->bstate = BS_STOP;
1a3fd9c3 3806// tcg_gen_helper_0_1(do_mtc0_usertracedata, t0); /* PDtrace support */
2423f660 3807 rn = "UserTraceData";
8487327a
TS
3808 /* Stop translation as we may have switched the execution mode */
3809 ctx->bstate = BS_STOP;
2423f660 3810// break;
7a387fff 3811 case 4:
1a3fd9c3 3812// tcg_gen_helper_0_1(do_mtc0_tracebpc, t0); /* PDtrace support */
8487327a
TS
3813 /* Stop translation as we may have switched the execution mode */
3814 ctx->bstate = BS_STOP;
2423f660
TS
3815 rn = "TraceBPC";
3816// break;
7a387fff
TS
3817 default:
3818 goto die;
3819 }
8c0fdd85
TS
3820 break;
3821 case 24:
7a387fff
TS
3822 switch (sel) {
3823 case 0:
f1aa6320 3824 /* EJTAG support */
1a3fd9c3 3825 gen_mtc0_store64(t0, offsetof(CPUState, CP0_DEPC));
2423f660
TS
3826 rn = "DEPC";
3827 break;
7a387fff
TS
3828 default:
3829 goto die;
3830 }
8c0fdd85
TS
3831 break;
3832 case 25:
7a387fff
TS
3833 switch (sel) {
3834 case 0:
1a3fd9c3 3835 tcg_gen_helper_0_1(do_mtc0_performance0, t0);
2423f660
TS
3836 rn = "Performance0";
3837 break;
7a387fff 3838 case 1:
1a3fd9c3 3839// tcg_gen_helper_0_1(do_mtc0_performance1, t0);
2423f660
TS
3840 rn = "Performance1";
3841// break;
7a387fff 3842 case 2:
1a3fd9c3 3843// tcg_gen_helper_0_1(do_mtc0_performance2, t0);
2423f660
TS
3844 rn = "Performance2";
3845// break;
7a387fff 3846 case 3:
1a3fd9c3 3847// tcg_gen_helper_0_1(do_mtc0_performance3, t0);
2423f660
TS
3848 rn = "Performance3";
3849// break;
7a387fff 3850 case 4:
1a3fd9c3 3851// tcg_gen_helper_0_1(do_mtc0_performance4, t0);
2423f660
TS
3852 rn = "Performance4";
3853// break;
7a387fff 3854 case 5:
1a3fd9c3 3855// tcg_gen_helper_0_1(do_mtc0_performance5, t0);
2423f660
TS
3856 rn = "Performance5";
3857// break;
7a387fff 3858 case 6:
1a3fd9c3 3859// tcg_gen_helper_0_1(do_mtc0_performance6, t0);
2423f660
TS
3860 rn = "Performance6";
3861// break;
7a387fff 3862 case 7:
1a3fd9c3 3863// tcg_gen_helper_0_1(do_mtc0_performance7, t0);
2423f660
TS
3864 rn = "Performance7";
3865// break;
7a387fff
TS
3866 default:
3867 goto die;
3868 }
8c0fdd85
TS
3869 break;
3870 case 26:
2423f660 3871 /* ignored */
8c0fdd85 3872 rn = "ECC";
2423f660 3873 break;
8c0fdd85 3874 case 27:
7a387fff
TS
3875 switch (sel) {
3876 case 0 ... 3:
2423f660
TS
3877 /* ignored */
3878 rn = "CacheErr";
3879 break;
7a387fff
TS
3880 default:
3881 goto die;
3882 }
8c0fdd85
TS
3883 break;
3884 case 28:
3885 switch (sel) {
3886 case 0:
7a387fff
TS
3887 case 2:
3888 case 4:
3889 case 6:
1a3fd9c3 3890 tcg_gen_helper_0_1(do_mtc0_taglo, t0);
8c0fdd85
TS
3891 rn = "TagLo";
3892 break;
7a387fff
TS
3893 case 1:
3894 case 3:
3895 case 5:
3896 case 7:
1a3fd9c3 3897 tcg_gen_helper_0_1(do_mtc0_datalo, t0);
7a387fff
TS
3898 rn = "DataLo";
3899 break;
8c0fdd85 3900 default:
8c0fdd85
TS
3901 goto die;
3902 }
3903 break;
3904 case 29:
7a387fff
TS
3905 switch (sel) {
3906 case 0:
3907 case 2:
3908 case 4:
3909 case 6:
1a3fd9c3 3910 tcg_gen_helper_0_1(do_mtc0_taghi, t0);
7a387fff
TS
3911 rn = "TagHi";
3912 break;
3913 case 1:
3914 case 3:
3915 case 5:
3916 case 7:
1a3fd9c3 3917 tcg_gen_helper_0_1(do_mtc0_datahi, t0);
7a387fff
TS
3918 rn = "DataHi";
3919 break;
3920 default:
3921 rn = "invalid sel";
3922 goto die;
3923 }
8c0fdd85
TS
3924 break;
3925 case 30:
7a387fff
TS
3926 switch (sel) {
3927 case 0:
1a3fd9c3 3928 gen_mtc0_store64(t0, offsetof(CPUState, CP0_ErrorEPC));
2423f660
TS
3929 rn = "ErrorEPC";
3930 break;
7a387fff
TS
3931 default:
3932 goto die;
3933 }
8c0fdd85
TS
3934 break;
3935 case 31:
7a387fff
TS
3936 switch (sel) {
3937 case 0:
f1aa6320 3938 /* EJTAG support */
1a3fd9c3 3939 gen_mtc0_store32(t0, offsetof(CPUState, CP0_DESAVE));
2423f660
TS
3940 rn = "DESAVE";
3941 break;
7a387fff
TS
3942 default:
3943 goto die;
3944 }
2423f660
TS
3945 /* Stop translation as we may have switched the execution mode */
3946 ctx->bstate = BS_STOP;
8c0fdd85
TS
3947 break;
3948 default:
8c0fdd85
TS
3949 goto die;
3950 }
3951#if defined MIPS_DEBUG_DISAS
3952 if (loglevel & CPU_LOG_TB_IN_ASM) {
7a387fff
TS
3953 fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
3954 rn, reg, sel);
8c0fdd85
TS
3955 }
3956#endif
bf20dc07 3957 /* For simplicity assume that all writes can cause interrupts. */
2e70f6ef
PB
3958 if (use_icount) {
3959 gen_io_end();
3960 ctx->bstate = BS_STOP;
3961 }
8c0fdd85
TS
3962 return;
3963
3964die:
3965#if defined MIPS_DEBUG_DISAS
3966 if (loglevel & CPU_LOG_TB_IN_ASM) {
7a387fff
TS
3967 fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
3968 rn, reg, sel);
8c0fdd85
TS
3969 }
3970#endif
3971 generate_exception(ctx, EXCP_RI);
3972}
3973
d26bc211 3974#if defined(TARGET_MIPS64)
1a3fd9c3 3975static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
9c2149c8
TS
3976{
3977 const char *rn = "invalid";
3978
e189e748
TS
3979 if (sel != 0)
3980 check_insn(env, ctx, ISA_MIPS64);
3981
9c2149c8
TS
3982 switch (reg) {
3983 case 0:
3984 switch (sel) {
3985 case 0:
1a3fd9c3 3986 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Index));
9c2149c8
TS
3987 rn = "Index";
3988 break;
3989 case 1:
7385ac0b 3990 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3991 tcg_gen_helper_1_0(do_mfc0_mvpcontrol, t0);
9c2149c8 3992 rn = "MVPControl";
ead9360e 3993 break;
9c2149c8 3994 case 2:
7385ac0b 3995 check_insn(env, ctx, ASE_MT);
1a3fd9c3 3996 tcg_gen_helper_1_0(do_mfc0_mvpconf0, t0);
9c2149c8 3997 rn = "MVPConf0";
ead9360e 3998 break;
9c2149c8 3999 case 3:
7385ac0b 4000 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4001 tcg_gen_helper_1_0(do_mfc0_mvpconf1, t0);
9c2149c8 4002 rn = "MVPConf1";
ead9360e 4003 break;
9c2149c8
TS
4004 default:
4005 goto die;
4006 }
4007 break;
4008 case 1:
4009 switch (sel) {
4010 case 0:
1a3fd9c3 4011 tcg_gen_helper_1_0(do_mfc0_random, t0);
9c2149c8 4012 rn = "Random";
2423f660 4013 break;
9c2149c8 4014 case 1:
7385ac0b 4015 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4016 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEControl));
9c2149c8 4017 rn = "VPEControl";
ead9360e 4018 break;
9c2149c8 4019 case 2:
7385ac0b 4020 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4021 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf0));
9c2149c8 4022 rn = "VPEConf0";
ead9360e 4023 break;
9c2149c8 4024 case 3:
7385ac0b 4025 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4026 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEConf1));
9c2149c8 4027 rn = "VPEConf1";
ead9360e 4028 break;
9c2149c8 4029 case 4:
7385ac0b 4030 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4031 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_YQMask));
9c2149c8 4032 rn = "YQMask";
ead9360e 4033 break;
9c2149c8 4034 case 5:
7385ac0b 4035 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4036 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_VPESchedule));
9c2149c8 4037 rn = "VPESchedule";
ead9360e 4038 break;
9c2149c8 4039 case 6:
7385ac0b 4040 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4041 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
9c2149c8 4042 rn = "VPEScheFBack";
ead9360e 4043 break;
9c2149c8 4044 case 7:
7385ac0b 4045 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4046 gen_mfc0_load32(t0, offsetof(CPUState, CP0_VPEOpt));
9c2149c8 4047 rn = "VPEOpt";
ead9360e 4048 break;
9c2149c8
TS
4049 default:
4050 goto die;
4051 }
4052 break;
4053 case 2:
4054 switch (sel) {
4055 case 0:
1a3fd9c3 4056 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo0));
2423f660
TS
4057 rn = "EntryLo0";
4058 break;
9c2149c8 4059 case 1:
7385ac0b 4060 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4061 tcg_gen_helper_1_0(do_mfc0_tcstatus, t0);
2423f660 4062 rn = "TCStatus";
ead9360e 4063 break;
9c2149c8 4064 case 2:
7385ac0b 4065 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4066 tcg_gen_helper_1_0(do_mfc0_tcbind, t0);
2423f660 4067 rn = "TCBind";
ead9360e 4068 break;
9c2149c8 4069 case 3:
7385ac0b 4070 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4071 tcg_gen_helper_1_0(do_dmfc0_tcrestart, t0);
2423f660 4072 rn = "TCRestart";
ead9360e 4073 break;
9c2149c8 4074 case 4:
7385ac0b 4075 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4076 tcg_gen_helper_1_0(do_dmfc0_tchalt, t0);
2423f660 4077 rn = "TCHalt";
ead9360e 4078 break;
9c2149c8 4079 case 5:
7385ac0b 4080 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4081 tcg_gen_helper_1_0(do_dmfc0_tccontext, t0);
2423f660 4082 rn = "TCContext";
ead9360e 4083 break;
9c2149c8 4084 case 6:
7385ac0b 4085 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4086 tcg_gen_helper_1_0(do_dmfc0_tcschedule, t0);
2423f660 4087 rn = "TCSchedule";
ead9360e 4088 break;
9c2149c8 4089 case 7:
7385ac0b 4090 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4091 tcg_gen_helper_1_0(do_dmfc0_tcschefback, t0);
2423f660 4092 rn = "TCScheFBack";
ead9360e 4093 break;
9c2149c8
TS
4094 default:
4095 goto die;
4096 }
4097 break;
4098 case 3:
4099 switch (sel) {
4100 case 0:
1a3fd9c3 4101 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryLo1));
2423f660
TS
4102 rn = "EntryLo1";
4103 break;
9c2149c8
TS
4104 default:
4105 goto die;
1579a72e 4106 }
9c2149c8
TS
4107 break;
4108 case 4:
4109 switch (sel) {
4110 case 0:
1a3fd9c3 4111 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_Context));
2423f660
TS
4112 rn = "Context";
4113 break;
9c2149c8 4114 case 1:
1a3fd9c3 4115// tcg_gen_helper_1_0(do_dmfc0_contextconfig, t0); /* SmartMIPS ASE */
2423f660
TS
4116 rn = "ContextConfig";
4117// break;
9c2149c8
TS
4118 default:
4119 goto die;
876d4b07 4120 }
9c2149c8
TS
4121 break;
4122 case 5:
4123 switch (sel) {
4124 case 0:
1a3fd9c3 4125 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageMask));
2423f660
TS
4126 rn = "PageMask";
4127 break;
9c2149c8 4128 case 1:
e189e748 4129 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4130 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PageGrain));
2423f660
TS
4131 rn = "PageGrain";
4132 break;
9c2149c8
TS
4133 default:
4134 goto die;
876d4b07 4135 }
9c2149c8
TS
4136 break;
4137 case 6:
4138 switch (sel) {
4139 case 0:
1a3fd9c3 4140 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Wired));
2423f660
TS
4141 rn = "Wired";
4142 break;
9c2149c8 4143 case 1:
e189e748 4144 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4145 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf0));
2423f660 4146 rn = "SRSConf0";
ead9360e 4147 break;
9c2149c8 4148 case 2:
e189e748 4149 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4150 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf1));
2423f660 4151 rn = "SRSConf1";
ead9360e 4152 break;
9c2149c8 4153 case 3:
e189e748 4154 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4155 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf2));
2423f660 4156 rn = "SRSConf2";
ead9360e 4157 break;
9c2149c8 4158 case 4:
e189e748 4159 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4160 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf3));
2423f660 4161 rn = "SRSConf3";
ead9360e 4162 break;
9c2149c8 4163 case 5:
e189e748 4164 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4165 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSConf4));
2423f660 4166 rn = "SRSConf4";
ead9360e 4167 break;
9c2149c8
TS
4168 default:
4169 goto die;
876d4b07 4170 }
9c2149c8
TS
4171 break;
4172 case 7:
4173 switch (sel) {
4174 case 0:
e189e748 4175 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4176 gen_mfc0_load32(t0, offsetof(CPUState, CP0_HWREna));
2423f660
TS
4177 rn = "HWREna";
4178 break;
9c2149c8
TS
4179 default:
4180 goto die;
876d4b07 4181 }
9c2149c8
TS
4182 break;
4183 case 8:
4184 switch (sel) {
4185 case 0:
1a3fd9c3 4186 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_BadVAddr));
f0b3f3ae 4187 rn = "BadVAddr";
2423f660 4188 break;
9c2149c8
TS
4189 default:
4190 goto die;
876d4b07 4191 }
9c2149c8
TS
4192 break;
4193 case 9:
4194 switch (sel) {
4195 case 0:
2e70f6ef
PB
4196 /* Mark as an IO operation because we read the time. */
4197 if (use_icount)
4198 gen_io_start();
1a3fd9c3 4199 tcg_gen_helper_1_0(do_mfc0_count, t0);
2e70f6ef
PB
4200 if (use_icount) {
4201 gen_io_end();
4202 ctx->bstate = BS_STOP;
4203 }
2423f660
TS
4204 rn = "Count";
4205 break;
4206 /* 6,7 are implementation dependent */
9c2149c8
TS
4207 default:
4208 goto die;
876d4b07 4209 }
9c2149c8
TS
4210 break;
4211 case 10:
4212 switch (sel) {
4213 case 0:
1a3fd9c3 4214 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EntryHi));
2423f660
TS
4215 rn = "EntryHi";
4216 break;
9c2149c8
TS
4217 default:
4218 goto die;
876d4b07 4219 }
9c2149c8
TS
4220 break;
4221 case 11:
4222 switch (sel) {
4223 case 0:
1a3fd9c3 4224 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Compare));
2423f660
TS
4225 rn = "Compare";
4226 break;
876d4b07 4227 /* 6,7 are implementation dependent */
9c2149c8
TS
4228 default:
4229 goto die;
876d4b07 4230 }
9c2149c8
TS
4231 break;
4232 case 12:
4233 switch (sel) {
4234 case 0:
1a3fd9c3 4235 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Status));
2423f660
TS
4236 rn = "Status";
4237 break;
9c2149c8 4238 case 1:
e189e748 4239 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4240 gen_mfc0_load32(t0, offsetof(CPUState, CP0_IntCtl));
2423f660
TS
4241 rn = "IntCtl";
4242 break;
9c2149c8 4243 case 2:
e189e748 4244 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4245 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSCtl));
2423f660
TS
4246 rn = "SRSCtl";
4247 break;
9c2149c8 4248 case 3:
e189e748 4249 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4250 gen_mfc0_load32(t0, offsetof(CPUState, CP0_SRSMap));
2423f660
TS
4251 rn = "SRSMap";
4252 break;
9c2149c8
TS
4253 default:
4254 goto die;
876d4b07 4255 }
9c2149c8
TS
4256 break;
4257 case 13:
4258 switch (sel) {
4259 case 0:
1a3fd9c3 4260 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Cause));
2423f660
TS
4261 rn = "Cause";
4262 break;
9c2149c8
TS
4263 default:
4264 goto die;
876d4b07 4265 }
9c2149c8
TS
4266 break;
4267 case 14:
4268 switch (sel) {
4269 case 0:
1a3fd9c3 4270 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
2423f660
TS
4271 rn = "EPC";
4272 break;
9c2149c8
TS
4273 default:
4274 goto die;
876d4b07 4275 }
9c2149c8
TS
4276 break;
4277 case 15:
4278 switch (sel) {
4279 case 0:
1a3fd9c3 4280 gen_mfc0_load32(t0, offsetof(CPUState, CP0_PRid));
2423f660
TS
4281 rn = "PRid";
4282 break;
9c2149c8 4283 case 1:
e189e748 4284 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4285 gen_mfc0_load32(t0, offsetof(CPUState, CP0_EBase));
2423f660
TS
4286 rn = "EBase";
4287 break;
9c2149c8
TS
4288 default:
4289 goto die;
876d4b07 4290 }
9c2149c8
TS
4291 break;
4292 case 16:
4293 switch (sel) {
4294 case 0:
1a3fd9c3 4295 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config0));
9c2149c8
TS
4296 rn = "Config";
4297 break;
4298 case 1:
1a3fd9c3 4299 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config1));
9c2149c8
TS
4300 rn = "Config1";
4301 break;
4302 case 2:
1a3fd9c3 4303 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config2));
9c2149c8
TS
4304 rn = "Config2";
4305 break;
4306 case 3:
1a3fd9c3 4307 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config3));
9c2149c8
TS
4308 rn = "Config3";
4309 break;
4310 /* 6,7 are implementation dependent */
f0b3f3ae 4311 case 6:
1a3fd9c3 4312 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config6));
f0b3f3ae
TS
4313 rn = "Config6";
4314 break;
4315 case 7:
1a3fd9c3 4316 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Config7));
f0b3f3ae
TS
4317 rn = "Config7";
4318 break;
9c2149c8
TS
4319 default:
4320 goto die;
4321 }
4322 break;
4323 case 17:
4324 switch (sel) {
4325 case 0:
1a3fd9c3 4326 tcg_gen_helper_1_0(do_dmfc0_lladdr, t0);
2423f660
TS
4327 rn = "LLAddr";
4328 break;
9c2149c8
TS
4329 default:
4330 goto die;
4331 }
4332 break;
4333 case 18:
4334 switch (sel) {
fd88b6ab 4335 case 0 ... 7:
1a3fd9c3 4336 tcg_gen_helper_1_i(do_dmfc0_watchlo, t0, sel);
2423f660
TS
4337 rn = "WatchLo";
4338 break;
9c2149c8
TS
4339 default:
4340 goto die;
4341 }
4342 break;
4343 case 19:
4344 switch (sel) {
fd88b6ab 4345 case 0 ... 7:
1a3fd9c3 4346 tcg_gen_helper_1_i(do_mfc0_watchhi, t0, sel);
2423f660
TS
4347 rn = "WatchHi";
4348 break;
9c2149c8
TS
4349 default:
4350 goto die;
4351 }
4352 break;
4353 case 20:
4354 switch (sel) {
4355 case 0:
e189e748 4356 check_insn(env, ctx, ISA_MIPS3);
1a3fd9c3 4357 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_XContext));
2423f660
TS
4358 rn = "XContext";
4359 break;
9c2149c8
TS
4360 default:
4361 goto die;
4362 }
4363 break;
4364 case 21:
4365 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4366 switch (sel) {
4367 case 0:
1a3fd9c3 4368 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Framemask));
2423f660
TS
4369 rn = "Framemask";
4370 break;
9c2149c8
TS
4371 default:
4372 goto die;
4373 }
4374 break;
4375 case 22:
da80682b 4376 tcg_gen_movi_tl(t0, 0); /* unimplemented */
2423f660
TS
4377 rn = "'Diagnostic"; /* implementation dependent */
4378 break;
9c2149c8
TS
4379 case 23:
4380 switch (sel) {
4381 case 0:
1a3fd9c3 4382 tcg_gen_helper_1_0(do_mfc0_debug, t0); /* EJTAG support */
2423f660
TS
4383 rn = "Debug";
4384 break;
9c2149c8 4385 case 1:
1a3fd9c3 4386// tcg_gen_helper_1_0(do_dmfc0_tracecontrol, t0); /* PDtrace support */
2423f660
TS
4387 rn = "TraceControl";
4388// break;
9c2149c8 4389 case 2:
1a3fd9c3 4390// tcg_gen_helper_1_0(do_dmfc0_tracecontrol2, t0); /* PDtrace support */
2423f660
TS
4391 rn = "TraceControl2";
4392// break;
9c2149c8 4393 case 3:
1a3fd9c3 4394// tcg_gen_helper_1_0(do_dmfc0_usertracedata, t0); /* PDtrace support */
2423f660
TS
4395 rn = "UserTraceData";
4396// break;
9c2149c8 4397 case 4:
1a3fd9c3 4398// tcg_gen_helper_1_0(do_dmfc0_tracebpc, t0); /* PDtrace support */
2423f660
TS
4399 rn = "TraceBPC";
4400// break;
9c2149c8
TS
4401 default:
4402 goto die;
4403 }
4404 break;
4405 case 24:
4406 switch (sel) {
4407 case 0:
f0b3f3ae 4408 /* EJTAG support */
1a3fd9c3 4409 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
2423f660
TS
4410 rn = "DEPC";
4411 break;
9c2149c8
TS
4412 default:
4413 goto die;
4414 }
4415 break;
4416 case 25:
4417 switch (sel) {
4418 case 0:
1a3fd9c3 4419 gen_mfc0_load32(t0, offsetof(CPUState, CP0_Performance0));
2423f660 4420 rn = "Performance0";
9c2149c8
TS
4421 break;
4422 case 1:
1a3fd9c3 4423// tcg_gen_helper_1_0(do_dmfc0_performance1, t0);
2423f660
TS
4424 rn = "Performance1";
4425// break;
9c2149c8 4426 case 2:
1a3fd9c3 4427// tcg_gen_helper_1_0(do_dmfc0_performance2, t0);
2423f660
TS
4428 rn = "Performance2";
4429// break;
9c2149c8 4430 case 3:
1a3fd9c3 4431// tcg_gen_helper_1_0(do_dmfc0_performance3, t0);
2423f660
TS
4432 rn = "Performance3";
4433// break;
9c2149c8 4434 case 4:
1a3fd9c3 4435// tcg_gen_helper_1_0(do_dmfc0_performance4, t0);
2423f660
TS
4436 rn = "Performance4";
4437// break;
9c2149c8 4438 case 5:
1a3fd9c3 4439// tcg_gen_helper_1_0(do_dmfc0_performance5, t0);
2423f660
TS
4440 rn = "Performance5";
4441// break;
9c2149c8 4442 case 6:
1a3fd9c3 4443// tcg_gen_helper_1_0(do_dmfc0_performance6, t0);
2423f660
TS
4444 rn = "Performance6";
4445// break;
9c2149c8 4446 case 7:
1a3fd9c3 4447// tcg_gen_helper_1_0(do_dmfc0_performance7, t0);
2423f660
TS
4448 rn = "Performance7";
4449// break;
9c2149c8
TS
4450 default:
4451 goto die;
4452 }
4453 break;
4454 case 26:
da80682b
AJ
4455 tcg_gen_movi_tl(t0, 0); /* unimplemented */
4456 rn = "ECC";
4457 break;
9c2149c8
TS
4458 case 27:
4459 switch (sel) {
4460 /* ignored */
4461 case 0 ... 3:
da80682b 4462 tcg_gen_movi_tl(t0, 0); /* unimplemented */
2423f660
TS
4463 rn = "CacheErr";
4464 break;
9c2149c8
TS
4465 default:
4466 goto die;
4467 }
4468 break;
4469 case 28:
4470 switch (sel) {
4471 case 0:
4472 case 2:
4473 case 4:
4474 case 6:
1a3fd9c3 4475 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagLo));
9c2149c8
TS
4476 rn = "TagLo";
4477 break;
4478 case 1:
4479 case 3:
4480 case 5:
4481 case 7:
1a3fd9c3 4482 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataLo));
9c2149c8
TS
4483 rn = "DataLo";
4484 break;
4485 default:
4486 goto die;
4487 }
4488 break;
4489 case 29:
4490 switch (sel) {
4491 case 0:
4492 case 2:
4493 case 4:
4494 case 6:
1a3fd9c3 4495 gen_mfc0_load32(t0, offsetof(CPUState, CP0_TagHi));
9c2149c8
TS
4496 rn = "TagHi";
4497 break;
4498 case 1:
4499 case 3:
4500 case 5:
4501 case 7:
1a3fd9c3 4502 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DataHi));
9c2149c8
TS
4503 rn = "DataHi";
4504 break;
4505 default:
4506 goto die;
4507 }
4508 break;
4509 case 30:
4510 switch (sel) {
4511 case 0:
1a3fd9c3 4512 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
2423f660
TS
4513 rn = "ErrorEPC";
4514 break;
9c2149c8
TS
4515 default:
4516 goto die;
4517 }
4518 break;
4519 case 31:
4520 switch (sel) {
4521 case 0:
f0b3f3ae 4522 /* EJTAG support */
1a3fd9c3 4523 gen_mfc0_load32(t0, offsetof(CPUState, CP0_DESAVE));
2423f660
TS
4524 rn = "DESAVE";
4525 break;
9c2149c8
TS
4526 default:
4527 goto die;
4528 }
4529 break;
4530 default:
876d4b07 4531 goto die;
9c2149c8
TS
4532 }
4533#if defined MIPS_DEBUG_DISAS
4534 if (loglevel & CPU_LOG_TB_IN_ASM) {
4535 fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
4536 rn, reg, sel);
4537 }
4538#endif
4539 return;
4540
4541die:
4542#if defined MIPS_DEBUG_DISAS
4543 if (loglevel & CPU_LOG_TB_IN_ASM) {
4544 fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
4545 rn, reg, sel);
4546 }
4547#endif
4548 generate_exception(ctx, EXCP_RI);
4549}
4550
1a3fd9c3 4551static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int sel)
9c2149c8
TS
4552{
4553 const char *rn = "invalid";
4554
e189e748
TS
4555 if (sel != 0)
4556 check_insn(env, ctx, ISA_MIPS64);
4557
2e70f6ef
PB
4558 if (use_icount)
4559 gen_io_start();
4560
9c2149c8
TS
4561 switch (reg) {
4562 case 0:
4563 switch (sel) {
4564 case 0:
1a3fd9c3 4565 tcg_gen_helper_0_1(do_mtc0_index, t0);
9c2149c8
TS
4566 rn = "Index";
4567 break;
4568 case 1:
7385ac0b 4569 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4570 tcg_gen_helper_0_1(do_mtc0_mvpcontrol, t0);
9c2149c8 4571 rn = "MVPControl";
ead9360e 4572 break;
9c2149c8 4573 case 2:
7385ac0b 4574 check_insn(env, ctx, ASE_MT);
ead9360e 4575 /* ignored */
9c2149c8 4576 rn = "MVPConf0";
ead9360e 4577 break;
9c2149c8 4578 case 3:
7385ac0b 4579 check_insn(env, ctx, ASE_MT);
ead9360e 4580 /* ignored */
9c2149c8 4581 rn = "MVPConf1";
ead9360e 4582 break;
9c2149c8
TS
4583 default:
4584 goto die;
4585 }
4586 break;
4587 case 1:
4588 switch (sel) {
4589 case 0:
2423f660 4590 /* ignored */
9c2149c8 4591 rn = "Random";
2423f660 4592 break;
9c2149c8 4593 case 1:
7385ac0b 4594 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4595 tcg_gen_helper_0_1(do_mtc0_vpecontrol, t0);
9c2149c8 4596 rn = "VPEControl";
ead9360e 4597 break;
9c2149c8 4598 case 2:
7385ac0b 4599 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4600 tcg_gen_helper_0_1(do_mtc0_vpeconf0, t0);
9c2149c8 4601 rn = "VPEConf0";
ead9360e 4602 break;
9c2149c8 4603 case 3:
7385ac0b 4604 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4605 tcg_gen_helper_0_1(do_mtc0_vpeconf1, t0);
9c2149c8 4606 rn = "VPEConf1";
ead9360e 4607 break;
9c2149c8 4608 case 4:
7385ac0b 4609 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4610 tcg_gen_helper_0_1(do_mtc0_yqmask, t0);
9c2149c8 4611 rn = "YQMask";
ead9360e 4612 break;
9c2149c8 4613 case 5:
7385ac0b 4614 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4615 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_VPESchedule));
9c2149c8 4616 rn = "VPESchedule";
ead9360e 4617 break;
9c2149c8 4618 case 6:
7385ac0b 4619 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4620 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
9c2149c8 4621 rn = "VPEScheFBack";
ead9360e 4622 break;
9c2149c8 4623 case 7:
7385ac0b 4624 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4625 tcg_gen_helper_0_1(do_mtc0_vpeopt, t0);
9c2149c8 4626 rn = "VPEOpt";
ead9360e 4627 break;
9c2149c8
TS
4628 default:
4629 goto die;
4630 }
4631 break;
4632 case 2:
4633 switch (sel) {
4634 case 0:
1a3fd9c3 4635 tcg_gen_helper_0_1(do_mtc0_entrylo0, t0);
2423f660
TS
4636 rn = "EntryLo0";
4637 break;
9c2149c8 4638 case 1:
7385ac0b 4639 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4640 tcg_gen_helper_0_1(do_mtc0_tcstatus, t0);
2423f660 4641 rn = "TCStatus";
ead9360e 4642 break;
9c2149c8 4643 case 2:
7385ac0b 4644 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4645 tcg_gen_helper_0_1(do_mtc0_tcbind, t0);
2423f660 4646 rn = "TCBind";
ead9360e 4647 break;
9c2149c8 4648 case 3:
7385ac0b 4649 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4650 tcg_gen_helper_0_1(do_mtc0_tcrestart, t0);
2423f660 4651 rn = "TCRestart";
ead9360e 4652 break;
9c2149c8 4653 case 4:
7385ac0b 4654 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4655 tcg_gen_helper_0_1(do_mtc0_tchalt, t0);
2423f660 4656 rn = "TCHalt";
ead9360e 4657 break;
9c2149c8 4658 case 5:
7385ac0b 4659 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4660 tcg_gen_helper_0_1(do_mtc0_tccontext, t0);
2423f660 4661 rn = "TCContext";
ead9360e 4662 break;
9c2149c8 4663 case 6:
7385ac0b 4664 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4665 tcg_gen_helper_0_1(do_mtc0_tcschedule, t0);
2423f660 4666 rn = "TCSchedule";
ead9360e 4667 break;
9c2149c8 4668 case 7:
7385ac0b 4669 check_insn(env, ctx, ASE_MT);
1a3fd9c3 4670 tcg_gen_helper_0_1(do_mtc0_tcschefback, t0);
2423f660 4671 rn = "TCScheFBack";
ead9360e 4672 break;
9c2149c8
TS
4673 default:
4674 goto die;
4675 }
4676 break;
4677 case 3:
4678 switch (sel) {
4679 case 0:
1a3fd9c3 4680 tcg_gen_helper_0_1(do_mtc0_entrylo1, t0);
2423f660
TS
4681 rn = "EntryLo1";
4682 break;
9c2149c8
TS
4683 default:
4684 goto die;
876d4b07 4685 }
9c2149c8
TS
4686 break;
4687 case 4:
4688 switch (sel) {
4689 case 0:
1a3fd9c3 4690 tcg_gen_helper_0_1(do_mtc0_context, t0);
2423f660
TS
4691 rn = "Context";
4692 break;
9c2149c8 4693 case 1:
1a3fd9c3 4694// tcg_gen_helper_0_1(do_mtc0_contextconfig, t0); /* SmartMIPS ASE */
2423f660
TS
4695 rn = "ContextConfig";
4696// break;
9c2149c8
TS
4697 default:
4698 goto die;
876d4b07 4699 }
9c2149c8
TS
4700 break;
4701 case 5:
4702 switch (sel) {
4703 case 0:
1a3fd9c3 4704 tcg_gen_helper_0_1(do_mtc0_pagemask, t0);
2423f660
TS
4705 rn = "PageMask";
4706 break;
9c2149c8 4707 case 1:
e189e748 4708 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4709 tcg_gen_helper_0_1(do_mtc0_pagegrain, t0);
2423f660
TS
4710 rn = "PageGrain";
4711 break;
9c2149c8
TS
4712 default:
4713 goto die;
876d4b07 4714 }
9c2149c8
TS
4715 break;
4716 case 6:
4717 switch (sel) {
4718 case 0:
1a3fd9c3 4719 tcg_gen_helper_0_1(do_mtc0_wired, t0);
2423f660
TS
4720 rn = "Wired";
4721 break;
9c2149c8 4722 case 1:
e189e748 4723 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4724 tcg_gen_helper_0_1(do_mtc0_srsconf0, t0);
2423f660 4725 rn = "SRSConf0";
ead9360e 4726 break;
9c2149c8 4727 case 2:
e189e748 4728 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4729 tcg_gen_helper_0_1(do_mtc0_srsconf1, t0);
2423f660 4730 rn = "SRSConf1";
ead9360e 4731 break;
9c2149c8 4732 case 3:
e189e748 4733 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4734 tcg_gen_helper_0_1(do_mtc0_srsconf2, t0);
2423f660 4735 rn = "SRSConf2";
ead9360e 4736 break;
9c2149c8 4737 case 4:
e189e748 4738 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4739 tcg_gen_helper_0_1(do_mtc0_srsconf3, t0);
2423f660 4740 rn = "SRSConf3";
ead9360e 4741 break;
9c2149c8 4742 case 5:
e189e748 4743 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4744 tcg_gen_helper_0_1(do_mtc0_srsconf4, t0);
2423f660 4745 rn = "SRSConf4";
ead9360e 4746 break;
9c2149c8
TS
4747 default:
4748 goto die;
876d4b07 4749 }
9c2149c8
TS
4750 break;
4751 case 7:
4752 switch (sel) {
4753 case 0:
e189e748 4754 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4755 tcg_gen_helper_0_1(do_mtc0_hwrena, t0);
2423f660
TS
4756 rn = "HWREna";
4757 break;
9c2149c8
TS
4758 default:
4759 goto die;
876d4b07 4760 }
9c2149c8
TS
4761 break;
4762 case 8:
4763 /* ignored */
f0b3f3ae 4764 rn = "BadVAddr";
9c2149c8
TS
4765 break;
4766 case 9:
4767 switch (sel) {
4768 case 0:
1a3fd9c3 4769 tcg_gen_helper_0_1(do_mtc0_count, t0);
2423f660
TS
4770 rn = "Count";
4771 break;
876d4b07 4772 /* 6,7 are implementation dependent */
9c2149c8
TS
4773 default:
4774 goto die;
876d4b07
TS
4775 }
4776 /* Stop translation as we may have switched the execution mode */
4777 ctx->bstate = BS_STOP;
9c2149c8
TS
4778 break;
4779 case 10:
4780 switch (sel) {
4781 case 0:
1a3fd9c3 4782 tcg_gen_helper_0_1(do_mtc0_entryhi, t0);
2423f660
TS
4783 rn = "EntryHi";
4784 break;
9c2149c8
TS
4785 default:
4786 goto die;
876d4b07 4787 }
9c2149c8
TS
4788 break;
4789 case 11:
4790 switch (sel) {
4791 case 0:
1a3fd9c3 4792 tcg_gen_helper_0_1(do_mtc0_compare, t0);
2423f660
TS
4793 rn = "Compare";
4794 break;
876d4b07 4795 /* 6,7 are implementation dependent */
9c2149c8
TS
4796 default:
4797 goto die;
876d4b07 4798 }
de9a95f0
AJ
4799 /* Stop translation as we may have switched the execution mode */
4800 ctx->bstate = BS_STOP;
9c2149c8
TS
4801 break;
4802 case 12:
4803 switch (sel) {
4804 case 0:
1a3fd9c3 4805 tcg_gen_helper_0_1(do_mtc0_status, t0);
8487327a
TS
4806 /* BS_STOP isn't good enough here, hflags may have changed. */
4807 gen_save_pc(ctx->pc + 4);
4808 ctx->bstate = BS_EXCP;
2423f660
TS
4809 rn = "Status";
4810 break;
9c2149c8 4811 case 1:
e189e748 4812 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4813 tcg_gen_helper_0_1(do_mtc0_intctl, t0);
8487327a
TS
4814 /* Stop translation as we may have switched the execution mode */
4815 ctx->bstate = BS_STOP;
2423f660
TS
4816 rn = "IntCtl";
4817 break;
9c2149c8 4818 case 2:
e189e748 4819 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4820 tcg_gen_helper_0_1(do_mtc0_srsctl, t0);
8487327a
TS
4821 /* Stop translation as we may have switched the execution mode */
4822 ctx->bstate = BS_STOP;
2423f660
TS
4823 rn = "SRSCtl";
4824 break;
9c2149c8 4825 case 3:
e189e748 4826 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4827 gen_mtc0_store32(t0, offsetof(CPUState, CP0_SRSMap));
8487327a
TS
4828 /* Stop translation as we may have switched the execution mode */
4829 ctx->bstate = BS_STOP;
2423f660
TS
4830 rn = "SRSMap";
4831 break;
4832 default:
9c2149c8 4833 goto die;
876d4b07 4834 }
9c2149c8
TS
4835 break;
4836 case 13:
4837 switch (sel) {
4838 case 0:
1a3fd9c3 4839 tcg_gen_helper_0_1(do_mtc0_cause, t0);
2423f660
TS
4840 rn = "Cause";
4841 break;
9c2149c8
TS
4842 default:
4843 goto die;
876d4b07
TS
4844 }
4845 /* Stop translation as we may have switched the execution mode */
4846 ctx->bstate = BS_STOP;
9c2149c8
TS
4847 break;
4848 case 14:
4849 switch (sel) {
4850 case 0:
1a3fd9c3 4851 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_EPC));
2423f660
TS
4852 rn = "EPC";
4853 break;
9c2149c8
TS
4854 default:
4855 goto die;
876d4b07 4856 }
9c2149c8
TS
4857 break;
4858 case 15:
4859 switch (sel) {
4860 case 0:
2423f660
TS
4861 /* ignored */
4862 rn = "PRid";
4863 break;
9c2149c8 4864 case 1:
e189e748 4865 check_insn(env, ctx, ISA_MIPS32R2);
1a3fd9c3 4866 tcg_gen_helper_0_1(do_mtc0_ebase, t0);
2423f660
TS
4867 rn = "EBase";
4868 break;
9c2149c8
TS
4869 default:
4870 goto die;
876d4b07 4871 }
9c2149c8
TS
4872 break;
4873 case 16:
4874 switch (sel) {
4875 case 0:
1a3fd9c3 4876 tcg_gen_helper_0_1(do_mtc0_config0, t0);
9c2149c8 4877 rn = "Config";
2423f660
TS
4878 /* Stop translation as we may have switched the execution mode */
4879 ctx->bstate = BS_STOP;
9c2149c8
TS
4880 break;
4881 case 1:
2423f660 4882 /* ignored */
9c2149c8
TS
4883 rn = "Config1";
4884 break;
4885 case 2:
1a3fd9c3 4886 tcg_gen_helper_0_1(do_mtc0_config2, t0);
9c2149c8 4887 rn = "Config2";
2423f660
TS
4888 /* Stop translation as we may have switched the execution mode */
4889 ctx->bstate = BS_STOP;
9c2149c8
TS
4890 break;
4891 case 3:
2423f660 4892 /* ignored */
9c2149c8
TS
4893 rn = "Config3";
4894 break;
4895 /* 6,7 are implementation dependent */
4896 default:
4897 rn = "Invalid config selector";
4898 goto die;
4899 }
9c2149c8
TS
4900 break;
4901 case 17:
4902 switch (sel) {
4903 case 0:
2423f660
TS
4904 /* ignored */
4905 rn = "LLAddr";
4906 break;
9c2149c8
TS
4907 default:
4908 goto die;
4909 }
4910 break;
4911 case 18:
4912 switch (sel) {
fd88b6ab 4913 case 0 ... 7:
1a3fd9c3 4914 tcg_gen_helper_0_1i(do_mtc0_watchlo, t0, sel);
2423f660
TS
4915 rn = "WatchLo";
4916 break;
9c2149c8
TS
4917 default:
4918 goto die;
4919 }
4920 break;
4921 case 19:
4922 switch (sel) {
fd88b6ab 4923 case 0 ... 7:
1a3fd9c3 4924 tcg_gen_helper_0_1i(do_mtc0_watchhi, t0, sel);
2423f660
TS
4925 rn = "WatchHi";
4926 break;
9c2149c8
TS
4927 default:
4928 goto die;
4929 }
4930 break;
4931 case 20:
4932 switch (sel) {
4933 case 0:
e189e748 4934 check_insn(env, ctx, ISA_MIPS3);
1a3fd9c3 4935 tcg_gen_helper_0_1(do_mtc0_xcontext, t0);
2423f660
TS
4936 rn = "XContext";
4937 break;
9c2149c8
TS
4938 default:
4939 goto die;
4940 }
4941 break;
4942 case 21:
4943 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4944 switch (sel) {
4945 case 0:
1a3fd9c3 4946 tcg_gen_helper_0_1(do_mtc0_framemask, t0);
2423f660
TS
4947 rn = "Framemask";
4948 break;
9c2149c8
TS
4949 default:
4950 goto die;
4951 }
4952 break;
4953 case 22:
4954 /* ignored */
4955 rn = "Diagnostic"; /* implementation dependent */
876d4b07 4956 break;
9c2149c8
TS
4957 case 23:
4958 switch (sel) {
4959 case 0:
1a3fd9c3 4960 tcg_gen_helper_0_1(do_mtc0_debug, t0); /* EJTAG support */
8487327a
TS
4961 /* BS_STOP isn't good enough here, hflags may have changed. */
4962 gen_save_pc(ctx->pc + 4);
4963 ctx->bstate = BS_EXCP;
2423f660
TS
4964 rn = "Debug";
4965 break;
9c2149c8 4966 case 1:
1a3fd9c3 4967// tcg_gen_helper_0_1(do_mtc0_tracecontrol, t0); /* PDtrace support */
8487327a
TS
4968 /* Stop translation as we may have switched the execution mode */
4969 ctx->bstate = BS_STOP;
2423f660
TS
4970 rn = "TraceControl";
4971// break;
9c2149c8 4972 case 2:
1a3fd9c3 4973// tcg_gen_helper_0_1(do_mtc0_tracecontrol2, t0); /* PDtrace support */
8487327a
TS
4974 /* Stop translation as we may have switched the execution mode */
4975 ctx->bstate = BS_STOP;
2423f660
TS
4976 rn = "TraceControl2";
4977// break;
9c2149c8 4978 case 3:
1a3fd9c3 4979// tcg_gen_helper_0_1(do_mtc0_usertracedata, t0); /* PDtrace support */
8487327a
TS
4980 /* Stop translation as we may have switched the execution mode */
4981 ctx->bstate = BS_STOP;
2423f660
TS
4982 rn = "UserTraceData";
4983// break;
9c2149c8 4984 case 4:
1a3fd9c3 4985// tcg_gen_helper_0_1(do_mtc0_tracebpc, t0); /* PDtrace support */
8487327a
TS
4986 /* Stop translation as we may have switched the execution mode */
4987 ctx->bstate = BS_STOP;
2423f660
TS
4988 rn = "TraceBPC";
4989// break;
9c2149c8
TS
4990 default:
4991 goto die;
4992 }
9c2149c8
TS
4993 break;
4994 case 24:
4995 switch (sel) {
4996 case 0:
f1aa6320 4997 /* EJTAG support */
1a3fd9c3 4998 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_DEPC));
2423f660
TS
4999 rn = "DEPC";
5000 break;
9c2149c8
TS
5001 default:
5002 goto die;
5003 }
5004 break;
5005 case 25:
5006 switch (sel) {
5007 case 0:
1a3fd9c3 5008 tcg_gen_helper_0_1(do_mtc0_performance0, t0);
2423f660
TS
5009 rn = "Performance0";
5010 break;
9c2149c8 5011 case 1:
1a3fd9c3 5012// tcg_gen_helper_0_1(do_mtc0_performance1, t0);
2423f660
TS
5013 rn = "Performance1";
5014// break;
9c2149c8 5015 case 2:
1a3fd9c3 5016// tcg_gen_helper_0_1(do_mtc0_performance2, t0);
2423f660
TS
5017 rn = "Performance2";
5018// break;
9c2149c8 5019 case 3:
1a3fd9c3 5020// tcg_gen_helper_0_1(do_mtc0_performance3, t0);
2423f660
TS
5021 rn = "Performance3";
5022// break;
9c2149c8 5023 case 4:
1a3fd9c3 5024// tcg_gen_helper_0_1(do_mtc0_performance4, t0);
2423f660
TS
5025 rn = "Performance4";
5026// break;
9c2149c8 5027 case 5:
1a3fd9c3 5028// tcg_gen_helper_0_1(do_mtc0_performance5, t0);
2423f660
TS
5029 rn = "Performance5";
5030// break;
9c2149c8 5031 case 6:
1a3fd9c3 5032// tcg_gen_helper_0_1(do_mtc0_performance6, t0);
2423f660
TS
5033 rn = "Performance6";
5034// break;
9c2149c8 5035 case 7:
1a3fd9c3 5036// tcg_gen_helper_0_1(do_mtc0_performance7, t0);
2423f660
TS
5037 rn = "Performance7";
5038// break;
9c2149c8
TS
5039 default:
5040 goto die;
5041 }
876d4b07 5042 break;
9c2149c8 5043 case 26:
876d4b07 5044 /* ignored */
9c2149c8 5045 rn = "ECC";
876d4b07 5046 break;
9c2149c8
TS
5047 case 27:
5048 switch (sel) {
5049 case 0 ... 3:
2423f660
TS
5050 /* ignored */
5051 rn = "CacheErr";
5052 break;
9c2149c8
TS
5053 default:
5054 goto die;
5055 }
876d4b07 5056 break;
9c2149c8
TS
5057 case 28:
5058 switch (sel) {
5059 case 0:
5060 case 2:
5061 case 4:
5062 case 6:
1a3fd9c3 5063 tcg_gen_helper_0_1(do_mtc0_taglo, t0);
9c2149c8
TS
5064 rn = "TagLo";
5065 break;
5066 case 1:
5067 case 3:
5068 case 5:
5069 case 7:
1a3fd9c3 5070 tcg_gen_helper_0_1(do_mtc0_datalo, t0);
9c2149c8
TS
5071 rn = "DataLo";
5072 break;
5073 default:
5074 goto die;
5075 }
5076 break;
5077 case 29:
5078 switch (sel) {
5079 case 0:
5080 case 2:
5081 case 4:
5082 case 6:
1a3fd9c3 5083 tcg_gen_helper_0_1(do_mtc0_taghi, t0);
9c2149c8
TS
5084 rn = "TagHi";
5085 break;
5086 case 1:
5087 case 3:
5088 case 5:
5089 case 7:
1a3fd9c3 5090 tcg_gen_helper_0_1(do_mtc0_datahi, t0);
9c2149c8
TS
5091 rn = "DataHi";
5092 break;
5093 default:
5094 rn = "invalid sel";
5095 goto die;
5096 }
876d4b07 5097 break;
9c2149c8
TS
5098 case 30:
5099 switch (sel) {
5100 case 0:
1a3fd9c3 5101 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
2423f660
TS
5102 rn = "ErrorEPC";
5103 break;
9c2149c8
TS
5104 default:
5105 goto die;
5106 }
5107 break;
5108 case 31:
5109 switch (sel) {
5110 case 0:
f1aa6320 5111 /* EJTAG support */
1a3fd9c3 5112 gen_mtc0_store32(t0, offsetof(CPUState, CP0_DESAVE));
2423f660
TS
5113 rn = "DESAVE";
5114 break;
9c2149c8
TS
5115 default:
5116 goto die;
5117 }
876d4b07
TS
5118 /* Stop translation as we may have switched the execution mode */
5119 ctx->bstate = BS_STOP;
9c2149c8
TS
5120 break;
5121 default:
876d4b07 5122 goto die;
9c2149c8
TS
5123 }
5124#if defined MIPS_DEBUG_DISAS
5125 if (loglevel & CPU_LOG_TB_IN_ASM) {
5126 fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
5127 rn, reg, sel);
5128 }
5129#endif
bf20dc07 5130 /* For simplicity assume that all writes can cause interrupts. */
2e70f6ef
PB
5131 if (use_icount) {
5132 gen_io_end();
5133 ctx->bstate = BS_STOP;
5134 }
9c2149c8
TS
5135 return;
5136
5137die:
5138#if defined MIPS_DEBUG_DISAS
5139 if (loglevel & CPU_LOG_TB_IN_ASM) {
5140 fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
5141 rn, reg, sel);
5142 }
5143#endif
5144 generate_exception(ctx, EXCP_RI);
5145}
d26bc211 5146#endif /* TARGET_MIPS64 */
9c2149c8 5147
6c5c1e20 5148static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
ead9360e
TS
5149 int u, int sel, int h)
5150{
5151 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1a3fd9c3 5152 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
ead9360e
TS
5153
5154 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
5155 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5156 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
1a3fd9c3 5157 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
5158 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5159 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
1a3fd9c3 5160 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
5161 else if (u == 0) {
5162 switch (rt) {
5163 case 2:
5164 switch (sel) {
5165 case 1:
add69063 5166 tcg_gen_helper_1_0(do_mftc0_tcstatus, t0);
ead9360e
TS
5167 break;
5168 case 2:
add69063 5169 tcg_gen_helper_1_0(do_mftc0_tcbind, t0);
ead9360e
TS
5170 break;
5171 case 3:
add69063 5172 tcg_gen_helper_1_0(do_mftc0_tcrestart, t0);
ead9360e
TS
5173 break;
5174 case 4:
add69063 5175 tcg_gen_helper_1_0(do_mftc0_tchalt, t0);
ead9360e
TS
5176 break;
5177 case 5:
add69063 5178 tcg_gen_helper_1_0(do_mftc0_tccontext, t0);
ead9360e
TS
5179 break;
5180 case 6:
add69063 5181 tcg_gen_helper_1_0(do_mftc0_tcschedule, t0);
ead9360e
TS
5182 break;
5183 case 7:
add69063 5184 tcg_gen_helper_1_0(do_mftc0_tcschefback, t0);
ead9360e
TS
5185 break;
5186 default:
1a3fd9c3 5187 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5188 break;
5189 }
5190 break;
5191 case 10:
5192 switch (sel) {
5193 case 0:
add69063 5194 tcg_gen_helper_1_0(do_mftc0_entryhi, t0);
ead9360e
TS
5195 break;
5196 default:
1a3fd9c3 5197 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5198 break;
5199 }
5200 case 12:
5201 switch (sel) {
5202 case 0:
add69063 5203 tcg_gen_helper_1_0(do_mftc0_status, t0);
ead9360e
TS
5204 break;
5205 default:
1a3fd9c3 5206 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5207 break;
5208 }
5209 case 23:
5210 switch (sel) {
5211 case 0:
add69063 5212 tcg_gen_helper_1_0(do_mftc0_debug, t0);
ead9360e
TS
5213 break;
5214 default:
1a3fd9c3 5215 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5216 break;
5217 }
5218 break;
5219 default:
1a3fd9c3 5220 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5221 }
5222 } else switch (sel) {
5223 /* GPR registers. */
5224 case 0:
add69063 5225 tcg_gen_helper_1_i(do_mftgpr, t0, rt);
ead9360e
TS
5226 break;
5227 /* Auxiliary CPU registers */
5228 case 1:
5229 switch (rt) {
5230 case 0:
add69063 5231 tcg_gen_helper_1_i(do_mftlo, t0, 0);
ead9360e
TS
5232 break;
5233 case 1:
add69063 5234 tcg_gen_helper_1_i(do_mfthi, t0, 0);
ead9360e
TS
5235 break;
5236 case 2:
add69063 5237 tcg_gen_helper_1_i(do_mftacx, t0, 0);
ead9360e
TS
5238 break;
5239 case 4:
add69063 5240 tcg_gen_helper_1_i(do_mftlo, t0, 1);
ead9360e
TS
5241 break;
5242 case 5:
add69063 5243 tcg_gen_helper_1_i(do_mfthi, t0, 1);
ead9360e
TS
5244 break;
5245 case 6:
add69063 5246 tcg_gen_helper_1_i(do_mftacx, t0, 1);
ead9360e
TS
5247 break;
5248 case 8:
add69063 5249 tcg_gen_helper_1_i(do_mftlo, t0, 2);
ead9360e
TS
5250 break;
5251 case 9:
add69063 5252 tcg_gen_helper_1_i(do_mfthi, t0, 2);
ead9360e
TS
5253 break;
5254 case 10:
add69063 5255 tcg_gen_helper_1_i(do_mftacx, t0, 2);
ead9360e
TS
5256 break;
5257 case 12:
add69063 5258 tcg_gen_helper_1_i(do_mftlo, t0, 3);
ead9360e
TS
5259 break;
5260 case 13:
add69063 5261 tcg_gen_helper_1_i(do_mfthi, t0, 3);
ead9360e
TS
5262 break;
5263 case 14:
add69063 5264 tcg_gen_helper_1_i(do_mftacx, t0, 3);
ead9360e
TS
5265 break;
5266 case 16:
add69063 5267 tcg_gen_helper_1_0(do_mftdsp, t0);
ead9360e
TS
5268 break;
5269 default:
5270 goto die;
5271 }
5272 break;
5273 /* Floating point (COP1). */
5274 case 2:
5275 /* XXX: For now we support only a single FPU context. */
5276 if (h == 0) {
b6d96bed
TS
5277 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5278
5279 gen_load_fpr32(fp0, rt);
5280 tcg_gen_ext_i32_tl(t0, fp0);
5281 tcg_temp_free(fp0);
ead9360e 5282 } else {
b6d96bed
TS
5283 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5284
5285 gen_load_fpr32h(fp0, rt);
5286 tcg_gen_ext_i32_tl(t0, fp0);
5287 tcg_temp_free(fp0);
ead9360e
TS
5288 }
5289 break;
5290 case 3:
5291 /* XXX: For now we support only a single FPU context. */
1a3fd9c3 5292 tcg_gen_helper_1_1i(do_cfc1, t0, t0, rt);
ead9360e
TS
5293 break;
5294 /* COP2: Not implemented. */
5295 case 4:
5296 case 5:
5297 /* fall through */
5298 default:
5299 goto die;
5300 }
5301#if defined MIPS_DEBUG_DISAS
5302 if (loglevel & CPU_LOG_TB_IN_ASM) {
5303 fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n",
5304 rt, u, sel, h);
5305 }
5306#endif
1a3fd9c3
TS
5307 gen_store_gpr(t0, rd);
5308 tcg_temp_free(t0);
ead9360e
TS
5309 return;
5310
5311die:
1a3fd9c3 5312 tcg_temp_free(t0);
ead9360e
TS
5313#if defined MIPS_DEBUG_DISAS
5314 if (loglevel & CPU_LOG_TB_IN_ASM) {
5315 fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n",
5316 rt, u, sel, h);
5317 }
5318#endif
5319 generate_exception(ctx, EXCP_RI);
5320}
5321
6c5c1e20 5322static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
ead9360e
TS
5323 int u, int sel, int h)
5324{
5325 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1a3fd9c3 5326 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
ead9360e 5327
1a3fd9c3 5328 gen_load_gpr(t0, rt);
ead9360e 5329 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
5330 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5331 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
ead9360e
TS
5332 /* NOP */ ;
5333 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5334 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5335 /* NOP */ ;
5336 else if (u == 0) {
5337 switch (rd) {
5338 case 2:
5339 switch (sel) {
5340 case 1:
1a3fd9c3 5341 tcg_gen_helper_0_1(do_mttc0_tcstatus, t0);
ead9360e
TS
5342 break;
5343 case 2:
1a3fd9c3 5344 tcg_gen_helper_0_1(do_mttc0_tcbind, t0);
ead9360e
TS
5345 break;
5346 case 3:
1a3fd9c3 5347 tcg_gen_helper_0_1(do_mttc0_tcrestart, t0);
ead9360e
TS
5348 break;
5349 case 4:
1a3fd9c3 5350 tcg_gen_helper_0_1(do_mttc0_tchalt, t0);
ead9360e
TS
5351 break;
5352 case 5:
1a3fd9c3 5353 tcg_gen_helper_0_1(do_mttc0_tccontext, t0);
ead9360e
TS
5354 break;
5355 case 6:
1a3fd9c3 5356 tcg_gen_helper_0_1(do_mttc0_tcschedule, t0);
ead9360e
TS
5357 break;
5358 case 7:
1a3fd9c3 5359 tcg_gen_helper_0_1(do_mttc0_tcschefback, t0);
ead9360e
TS
5360 break;
5361 default:
1a3fd9c3 5362 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5363 break;
5364 }
5365 break;
5366 case 10:
5367 switch (sel) {
5368 case 0:
1a3fd9c3 5369 tcg_gen_helper_0_1(do_mttc0_entryhi, t0);
ead9360e
TS
5370 break;
5371 default:
1a3fd9c3 5372 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5373 break;
5374 }
5375 case 12:
5376 switch (sel) {
5377 case 0:
1a3fd9c3 5378 tcg_gen_helper_0_1(do_mttc0_status, t0);
ead9360e
TS
5379 break;
5380 default:
1a3fd9c3 5381 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5382 break;
5383 }
5384 case 23:
5385 switch (sel) {
5386 case 0:
1a3fd9c3 5387 tcg_gen_helper_0_1(do_mttc0_debug, t0);
ead9360e
TS
5388 break;
5389 default:
1a3fd9c3 5390 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5391 break;
5392 }
5393 break;
5394 default:
1a3fd9c3 5395 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5396 }
5397 } else switch (sel) {
5398 /* GPR registers. */
5399 case 0:
1a3fd9c3 5400 tcg_gen_helper_0_1i(do_mttgpr, t0, rd);
ead9360e
TS
5401 break;
5402 /* Auxiliary CPU registers */
5403 case 1:
5404 switch (rd) {
5405 case 0:
1a3fd9c3 5406 tcg_gen_helper_0_1i(do_mttlo, t0, 0);
ead9360e
TS
5407 break;
5408 case 1:
1a3fd9c3 5409 tcg_gen_helper_0_1i(do_mtthi, t0, 0);
ead9360e
TS
5410 break;
5411 case 2:
1a3fd9c3 5412 tcg_gen_helper_0_1i(do_mttacx, t0, 0);
ead9360e
TS
5413 break;
5414 case 4:
1a3fd9c3 5415 tcg_gen_helper_0_1i(do_mttlo, t0, 1);
ead9360e
TS
5416 break;
5417 case 5:
1a3fd9c3 5418 tcg_gen_helper_0_1i(do_mtthi, t0, 1);
ead9360e
TS
5419 break;
5420 case 6:
1a3fd9c3 5421 tcg_gen_helper_0_1i(do_mttacx, t0, 1);
ead9360e
TS
5422 break;
5423 case 8:
1a3fd9c3 5424 tcg_gen_helper_0_1i(do_mttlo, t0, 2);
ead9360e
TS
5425 break;
5426 case 9:
1a3fd9c3 5427 tcg_gen_helper_0_1i(do_mtthi, t0, 2);
ead9360e
TS
5428 break;
5429 case 10:
1a3fd9c3 5430 tcg_gen_helper_0_1i(do_mttacx, t0, 2);
ead9360e
TS
5431 break;
5432 case 12:
1a3fd9c3 5433 tcg_gen_helper_0_1i(do_mttlo, t0, 3);
ead9360e
TS
5434 break;
5435 case 13:
1a3fd9c3 5436 tcg_gen_helper_0_1i(do_mtthi, t0, 3);
ead9360e
TS
5437 break;
5438 case 14:
1a3fd9c3 5439 tcg_gen_helper_0_1i(do_mttacx, t0, 3);
ead9360e
TS
5440 break;
5441 case 16:
1a3fd9c3 5442 tcg_gen_helper_0_1(do_mttdsp, t0);
ead9360e
TS
5443 break;
5444 default:
5445 goto die;
5446 }
5447 break;
5448 /* Floating point (COP1). */
5449 case 2:
5450 /* XXX: For now we support only a single FPU context. */
5451 if (h == 0) {
b6d96bed
TS
5452 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5453
5454 tcg_gen_trunc_tl_i32(fp0, t0);
5455 gen_store_fpr32(fp0, rd);
5456 tcg_temp_free(fp0);
ead9360e 5457 } else {
b6d96bed
TS
5458 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5459
5460 tcg_gen_trunc_tl_i32(fp0, t0);
5461 gen_store_fpr32h(fp0, rd);
5462 tcg_temp_free(fp0);
ead9360e
TS
5463 }
5464 break;
5465 case 3:
5466 /* XXX: For now we support only a single FPU context. */
1a3fd9c3 5467 tcg_gen_helper_0_1i(do_ctc1, t0, rd);
ead9360e
TS
5468 break;
5469 /* COP2: Not implemented. */
5470 case 4:
5471 case 5:
5472 /* fall through */
5473 default:
5474 goto die;
5475 }
5476#if defined MIPS_DEBUG_DISAS
5477 if (loglevel & CPU_LOG_TB_IN_ASM) {
5478 fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n",
5479 rd, u, sel, h);
5480 }
5481#endif
1a3fd9c3 5482 tcg_temp_free(t0);
ead9360e
TS
5483 return;
5484
5485die:
1a3fd9c3 5486 tcg_temp_free(t0);
ead9360e
TS
5487#if defined MIPS_DEBUG_DISAS
5488 if (loglevel & CPU_LOG_TB_IN_ASM) {
5489 fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n",
5490 rd, u, sel, h);
5491 }
5492#endif
5493 generate_exception(ctx, EXCP_RI);
5494}
5495
29929e34 5496static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
6af0bf9c 5497{
287c4b84 5498 const char *opn = "ldst";
6af0bf9c 5499
6af0bf9c
FB
5500 switch (opc) {
5501 case OPC_MFC0:
5502 if (rt == 0) {
ead9360e 5503 /* Treat as NOP. */
6af0bf9c
FB
5504 return;
5505 }
1a3fd9c3
TS
5506 {
5507 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5508
5509 gen_mfc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5510 gen_store_gpr(t0, rt);
5511 tcg_temp_free(t0);
5512 }
6af0bf9c
FB
5513 opn = "mfc0";
5514 break;
5515 case OPC_MTC0:
1a3fd9c3
TS
5516 {
5517 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5518
5519 gen_load_gpr(t0, rt);
5520 save_cpu_state(ctx, 1);
5521 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5522 tcg_temp_free(t0);
5523 }
6af0bf9c
FB
5524 opn = "mtc0";
5525 break;
d26bc211 5526#if defined(TARGET_MIPS64)
9c2149c8 5527 case OPC_DMFC0:
e189e748 5528 check_insn(env, ctx, ISA_MIPS3);
9c2149c8 5529 if (rt == 0) {
ead9360e 5530 /* Treat as NOP. */
9c2149c8
TS
5531 return;
5532 }
1a3fd9c3
TS
5533 {
5534 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5535
5536 gen_dmfc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5537 gen_store_gpr(t0, rt);
5538 tcg_temp_free(t0);
5539 }
9c2149c8
TS
5540 opn = "dmfc0";
5541 break;
5542 case OPC_DMTC0:
e189e748 5543 check_insn(env, ctx, ISA_MIPS3);
1a3fd9c3
TS
5544 {
5545 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
5546
5547 gen_load_gpr(t0, rt);
5548 save_cpu_state(ctx, 1);
5549 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5550 tcg_temp_free(t0);
5551 }
9c2149c8
TS
5552 opn = "dmtc0";
5553 break;
534ce69f 5554#endif
ead9360e 5555 case OPC_MFTR:
7385ac0b 5556 check_insn(env, ctx, ASE_MT);
ead9360e
TS
5557 if (rd == 0) {
5558 /* Treat as NOP. */
5559 return;
5560 }
6c5c1e20 5561 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
ead9360e 5562 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
ead9360e
TS
5563 opn = "mftr";
5564 break;
5565 case OPC_MTTR:
7385ac0b 5566 check_insn(env, ctx, ASE_MT);
6c5c1e20 5567 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
ead9360e
TS
5568 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5569 opn = "mttr";
5570 break;
6af0bf9c 5571 case OPC_TLBWI:
6af0bf9c 5572 opn = "tlbwi";
ead9360e 5573 if (!env->tlb->do_tlbwi)
29929e34 5574 goto die;
08ba7963 5575 tcg_gen_helper_0_0(env->tlb->do_tlbwi);
6af0bf9c
FB
5576 break;
5577 case OPC_TLBWR:
6af0bf9c 5578 opn = "tlbwr";
ead9360e 5579 if (!env->tlb->do_tlbwr)
29929e34 5580 goto die;
08ba7963 5581 tcg_gen_helper_0_0(env->tlb->do_tlbwr);
6af0bf9c
FB
5582 break;
5583 case OPC_TLBP:
6af0bf9c 5584 opn = "tlbp";
ead9360e 5585 if (!env->tlb->do_tlbp)
29929e34 5586 goto die;
08ba7963 5587 tcg_gen_helper_0_0(env->tlb->do_tlbp);
6af0bf9c
FB
5588 break;
5589 case OPC_TLBR:
6af0bf9c 5590 opn = "tlbr";
ead9360e 5591 if (!env->tlb->do_tlbr)
29929e34 5592 goto die;
08ba7963 5593 tcg_gen_helper_0_0(env->tlb->do_tlbr);
6af0bf9c 5594 break;
6af0bf9c
FB
5595 case OPC_ERET:
5596 opn = "eret";
e189e748 5597 check_insn(env, ctx, ISA_MIPS2);
387a8fe5 5598 save_cpu_state(ctx, 1);
6c5c1e20 5599 tcg_gen_helper_0_0(do_eret);
6af0bf9c
FB
5600 ctx->bstate = BS_EXCP;
5601 break;
5602 case OPC_DERET:
5603 opn = "deret";
e189e748 5604 check_insn(env, ctx, ISA_MIPS32);
6af0bf9c 5605 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
923617a3 5606 MIPS_INVAL(opn);
6af0bf9c
FB
5607 generate_exception(ctx, EXCP_RI);
5608 } else {
387a8fe5 5609 save_cpu_state(ctx, 1);
6c5c1e20 5610 tcg_gen_helper_0_0(do_deret);
6af0bf9c
FB
5611 ctx->bstate = BS_EXCP;
5612 }
5613 break;
4ad40f36
FB
5614 case OPC_WAIT:
5615 opn = "wait";
e189e748 5616 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
4ad40f36
FB
5617 /* If we get an exception, we want to restart at next instruction */
5618 ctx->pc += 4;
5619 save_cpu_state(ctx, 1);
5620 ctx->pc -= 4;
08ba7963 5621 tcg_gen_helper_0_0(do_wait);
4ad40f36
FB
5622 ctx->bstate = BS_EXCP;
5623 break;
6af0bf9c 5624 default:
29929e34 5625 die:
923617a3 5626 MIPS_INVAL(opn);
6af0bf9c
FB
5627 generate_exception(ctx, EXCP_RI);
5628 return;
5629 }
5630 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5631}
f1aa6320 5632#endif /* !CONFIG_USER_ONLY */
6af0bf9c 5633
6ea83fed 5634/* CP1 Branches (before delay slot) */
e189e748 5635static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5a5012ec 5636 int32_t cc, int32_t offset)
6ea83fed
FB
5637{
5638 target_ulong btarget;
923617a3 5639 const char *opn = "cp1 cond branch";
a6e92a65 5640 TCGv t0 = tcg_temp_new(TCG_TYPE_TL);
6ea83fed 5641
e189e748
TS
5642 if (cc != 0)
5643 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
5644
6ea83fed
FB
5645 btarget = ctx->pc + 4 + offset;
5646
7a387fff
TS
5647 switch (op) {
5648 case OPC_BC1F:
a16336e4
TS
5649 {
5650 int l1 = gen_new_label();
5651 int l2 = gen_new_label();
a16336e4 5652
a6e92a65
AJ
5653 get_fp_cond(t0);
5654 tcg_gen_andi_i32(t0, t0, 0x1 << cc);
5655 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
5656 tcg_gen_movi_i32(bcond, 0);
a16336e4
TS
5657 tcg_gen_br(l2);
5658 gen_set_label(l1);
a6e92a65 5659 tcg_gen_movi_i32(bcond, 1);
a16336e4
TS
5660 gen_set_label(l2);
5661 }
923617a3 5662 opn = "bc1f";
6ea83fed 5663 goto not_likely;
7a387fff 5664 case OPC_BC1FL:
a16336e4
TS
5665 {
5666 int l1 = gen_new_label();
5667 int l2 = gen_new_label();
a16336e4 5668
a6e92a65
AJ
5669 get_fp_cond(t0);
5670 tcg_gen_andi_i32(t0, t0, 0x1 << cc);
5671 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
5672 tcg_gen_movi_i32(bcond, 0);
a16336e4
TS
5673 tcg_gen_br(l2);
5674 gen_set_label(l1);
a6e92a65 5675 tcg_gen_movi_i32(bcond, 1);
a16336e4
TS
5676 gen_set_label(l2);
5677 }
923617a3 5678 opn = "bc1fl";
6ea83fed 5679 goto likely;
7a387fff 5680 case OPC_BC1T:
a16336e4
TS
5681 {
5682 int l1 = gen_new_label();
5683 int l2 = gen_new_label();
a16336e4 5684
a6e92a65
AJ
5685 get_fp_cond(t0);
5686 tcg_gen_andi_i32(t0, t0, 0x1 << cc);
5687 tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, l1);
5688 tcg_gen_movi_i32(bcond, 0);
a16336e4
TS
5689 tcg_gen_br(l2);
5690 gen_set_label(l1);
a6e92a65 5691 tcg_gen_movi_i32(bcond, 1);
a16336e4
TS
5692 gen_set_label(l2);
5693 }
923617a3 5694 opn = "bc1t";
5a5012ec 5695 goto not_likely;
7a387fff 5696 case OPC_BC1TL:
a16336e4
TS
5697 {
5698 int l1 = gen_new_label();
5699 int l2 = gen_new_label();
a16336e4 5700
a6e92a65
AJ
5701 get_fp_cond(t0);
5702 tcg_gen_andi_i32(t0, t0, 0x1 << cc);
5703 tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, l1);
5704 tcg_gen_movi_i32(bcond, 0);
a16336e4
TS
5705 tcg_gen_br(l2);
5706 gen_set_label(l1);
a6e92a65 5707 tcg_gen_movi_i32(bcond, 1);
a16336e4
TS
5708 gen_set_label(l2);
5709 }
923617a3 5710 opn = "bc1tl";
6ea83fed
FB
5711 likely:
5712 ctx->hflags |= MIPS_HFLAG_BL;
5713 break;
5a5012ec 5714 case OPC_BC1FANY2:
a16336e4
TS
5715 {
5716 int l1 = gen_new_label();
5717 int l2 = gen_new_label();
a16336e4 5718
a6e92a65
AJ
5719 get_fp_cond(t0);
5720 tcg_gen_andi_i32(t0, t0, 0x3 << cc);
5721 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
5722 tcg_gen_movi_i32(bcond, 0);
a16336e4
TS
5723 tcg_gen_br(l2);
5724 gen_set_label(l1);
a6e92a65 5725 tcg_gen_movi_i32(bcond, 1);
a16336e4
TS
5726 gen_set_label(l2);
5727 }
fd4a04eb 5728 opn = "bc1any2f";
5a5012ec
TS
5729 goto not_likely;
5730 case OPC_BC1TANY2:
a16336e4
TS
5731 {
5732 int l1 = gen_new_label();
5733 int l2 = gen_new_label();
a16336e4 5734
a6e92a65
AJ
5735 get_fp_cond(t0);
5736 tcg_gen_andi_i32(t0, t0, 0x3 << cc);
5737 tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, l1);
5738 tcg_gen_movi_i32(bcond, 0);
a16336e4
TS
5739 tcg_gen_br(l2);
5740 gen_set_label(l1);
a6e92a65 5741 tcg_gen_movi_i32(bcond, 1);
a16336e4
TS
5742 gen_set_label(l2);
5743 }
fd4a04eb 5744 opn = "bc1any2t";
5a5012ec
TS
5745 goto not_likely;
5746 case OPC_BC1FANY4:
a16336e4
TS
5747 {
5748 int l1 = gen_new_label();
5749 int l2 = gen_new_label();
a16336e4 5750
a6e92a65
AJ
5751 get_fp_cond(t0);
5752 tcg_gen_andi_i32(t0, t0, 0xf << cc);
5753 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
5754 tcg_gen_movi_i32(bcond, 0);
a16336e4
TS
5755 tcg_gen_br(l2);
5756 gen_set_label(l1);
a6e92a65 5757 tcg_gen_movi_i32(bcond, 1);
a16336e4
TS
5758 gen_set_label(l2);
5759 }
fd4a04eb 5760 opn = "bc1any4f";
5a5012ec
TS
5761 goto not_likely;
5762 case OPC_BC1TANY4:
a16336e4
TS
5763 {
5764 int l1 = gen_new_label();
5765 int l2 = gen_new_label();
a16336e4 5766
a6e92a65
AJ
5767 get_fp_cond(t0);
5768 tcg_gen_andi_i32(t0, t0, 0xf << cc);
5769 tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, l1);
5770 tcg_gen_movi_i32(bcond, 0);
a16336e4
TS
5771 tcg_gen_br(l2);
5772 gen_set_label(l1);
a6e92a65 5773 tcg_gen_movi_i32(bcond, 1);
a16336e4
TS
5774 gen_set_label(l2);
5775 }
fd4a04eb 5776 opn = "bc1any4t";
5a5012ec
TS
5777 not_likely:
5778 ctx->hflags |= MIPS_HFLAG_BC;
5a5012ec
TS
5779 break;
5780 default:
923617a3 5781 MIPS_INVAL(opn);
e397ee33 5782 generate_exception (ctx, EXCP_RI);
6c5c1e20 5783 goto out;
6ea83fed 5784 }
923617a3 5785 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
6ea83fed
FB
5786 ctx->hflags, btarget);
5787 ctx->btarget = btarget;
6c5c1e20
TS
5788
5789 out:
5790 tcg_temp_free(t0);
6ea83fed
FB
5791}
5792
6af0bf9c 5793/* Coprocessor 1 (FPU) */
5a5012ec 5794
5a5012ec
TS
5795#define FOP(func, fmt) (((fmt) << 21) | (func))
5796
7a387fff 5797static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6ea83fed 5798{
923617a3 5799 const char *opn = "cp1 move";
6c5c1e20 5800 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
6ea83fed
FB
5801
5802 switch (opc) {
5803 case OPC_MFC1:
b6d96bed
TS
5804 {
5805 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5806
5807 gen_load_fpr32(fp0, fs);
5808 tcg_gen_ext_i32_tl(t0, fp0);
5809 tcg_temp_free(fp0);
5810 }
6c5c1e20 5811 gen_store_gpr(t0, rt);
6ea83fed
FB
5812 opn = "mfc1";
5813 break;
5814 case OPC_MTC1:
6c5c1e20 5815 gen_load_gpr(t0, rt);
b6d96bed
TS
5816 {
5817 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5818
5819 tcg_gen_trunc_tl_i32(fp0, t0);
5820 gen_store_fpr32(fp0, fs);
5821 tcg_temp_free(fp0);
5822 }
6ea83fed
FB
5823 opn = "mtc1";
5824 break;
5825 case OPC_CFC1:
6c5c1e20
TS
5826 tcg_gen_helper_1_i(do_cfc1, t0, fs);
5827 gen_store_gpr(t0, rt);
6ea83fed
FB
5828 opn = "cfc1";
5829 break;
5830 case OPC_CTC1:
6c5c1e20
TS
5831 gen_load_gpr(t0, rt);
5832 tcg_gen_helper_0_1i(do_ctc1, t0, fs);
6ea83fed
FB
5833 opn = "ctc1";
5834 break;
9c2149c8 5835 case OPC_DMFC1:
b6d96bed
TS
5836 {
5837 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
5838
5839 gen_load_fpr64(ctx, fp0, fs);
5840 tcg_gen_mov_tl(t0, fp0);
5841 tcg_temp_free(fp0);
5842 }
6c5c1e20 5843 gen_store_gpr(t0, rt);
5a5012ec
TS
5844 opn = "dmfc1";
5845 break;
9c2149c8 5846 case OPC_DMTC1:
6c5c1e20 5847 gen_load_gpr(t0, rt);
b6d96bed
TS
5848 {
5849 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
5850
5851 tcg_gen_mov_tl(fp0, t0);
5852 gen_store_fpr64(ctx, fp0, fs);
5853 tcg_temp_free(fp0);
5854 }
5a5012ec
TS
5855 opn = "dmtc1";
5856 break;
5857 case OPC_MFHC1:
b6d96bed
TS
5858 {
5859 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5860
5861 gen_load_fpr32h(fp0, fs);
5862 tcg_gen_ext_i32_tl(t0, fp0);
5863 tcg_temp_free(fp0);
5864 }
6c5c1e20 5865 gen_store_gpr(t0, rt);
5a5012ec
TS
5866 opn = "mfhc1";
5867 break;
5868 case OPC_MTHC1:
6c5c1e20 5869 gen_load_gpr(t0, rt);
b6d96bed
TS
5870 {
5871 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
5872
5873 tcg_gen_trunc_tl_i32(fp0, t0);
5874 gen_store_fpr32h(fp0, fs);
5875 tcg_temp_free(fp0);
5876 }
5a5012ec
TS
5877 opn = "mthc1";
5878 break;
6ea83fed 5879 default:
923617a3 5880 MIPS_INVAL(opn);
e397ee33 5881 generate_exception (ctx, EXCP_RI);
6c5c1e20 5882 goto out;
6ea83fed
FB
5883 }
5884 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
6c5c1e20
TS
5885
5886 out:
5887 tcg_temp_free(t0);
6ea83fed
FB
5888}
5889
5a5012ec
TS
5890static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
5891{
e214b9bb 5892 int l1 = gen_new_label();
5a5012ec 5893 uint32_t ccbit;
e214b9bb 5894 TCGCond cond;
6c5c1e20 5895 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
9bf3eb2c 5896 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
6ea83fed 5897
e214b9bb 5898 if (cc)
5a5012ec 5899 ccbit = 1 << (24 + cc);
e214b9bb 5900 else
5a5012ec 5901 ccbit = 1 << 23;
e214b9bb 5902 if (tf)
e214b9bb 5903 cond = TCG_COND_EQ;
27848470
TS
5904 else
5905 cond = TCG_COND_NE;
5906
6c5c1e20 5907 gen_load_gpr(t0, rd);
f01be154 5908 tcg_gen_andi_i32(r_tmp, fpu_fcr31, ccbit);
920c608e 5909 tcg_gen_brcondi_i32(cond, r_tmp, 0, l1);
9bf3eb2c 5910 gen_load_gpr(t0, rs);
e214b9bb 5911 gen_set_label(l1);
6c5c1e20
TS
5912 gen_store_gpr(t0, rd);
5913 tcg_temp_free(t0);
5a5012ec
TS
5914}
5915
b6d96bed 5916static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
a16336e4
TS
5917{
5918 uint32_t ccbit;
5919 int cond;
9bf3eb2c 5920 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
b6d96bed 5921 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
a16336e4
TS
5922 int l1 = gen_new_label();
5923
5924 if (cc)
5925 ccbit = 1 << (24 + cc);
5926 else
5927 ccbit = 1 << 23;
5928
5929 if (tf)
5930 cond = TCG_COND_EQ;
5931 else
5932 cond = TCG_COND_NE;
5933
9bf3eb2c 5934 gen_load_fpr32(fp0, fd);
f01be154 5935 tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit);
a16336e4 5936 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
9bf3eb2c 5937 gen_load_fpr32(fp0, fs);
a16336e4 5938 gen_set_label(l1);
9bf3eb2c
AJ
5939 gen_store_fpr32(fp0, fd);
5940 tcg_temp_free(fp0);
5a5012ec 5941}
a16336e4 5942
b6d96bed 5943static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
a16336e4
TS
5944{
5945 uint32_t ccbit;
5946 int cond;
9bf3eb2c 5947 TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
b6d96bed 5948 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I64);
a16336e4
TS
5949 int l1 = gen_new_label();
5950
5951 if (cc)
5952 ccbit = 1 << (24 + cc);
5953 else
5954 ccbit = 1 << 23;
5955
5956 if (tf)
5957 cond = TCG_COND_EQ;
5958 else
5959 cond = TCG_COND_NE;
5960
9bf3eb2c 5961 gen_load_fpr64(ctx, fp0, fd);
f01be154 5962 tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit);
a16336e4 5963 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
9bf3eb2c 5964 gen_load_fpr64(ctx, fp0, fs);
a16336e4 5965 gen_set_label(l1);
9bf3eb2c
AJ
5966 gen_store_fpr64(ctx, fp0, fd);
5967 tcg_temp_free(fp0);
a16336e4
TS
5968}
5969
b6d96bed 5970static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
a16336e4 5971{
9bf3eb2c 5972 uint32_t ccbit1, ccbit2;
a16336e4
TS
5973 int cond;
5974 TCGv r_tmp1 = tcg_temp_local_new(TCG_TYPE_I32);
b6d96bed 5975 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
a16336e4
TS
5976 int l1 = gen_new_label();
5977 int l2 = gen_new_label();
5978
9bf3eb2c
AJ
5979 if (cc) {
5980 ccbit1 = 1 << (24 + cc);
5981 ccbit2 = 1 << (25 + cc);
5982 } else {
5983 ccbit1 = 1 << 23;
5984 ccbit2 = 1 << 25;
5985 }
5986
a16336e4
TS
5987 if (tf)
5988 cond = TCG_COND_EQ;
5989 else
5990 cond = TCG_COND_NE;
5991
9bf3eb2c
AJ
5992 gen_load_fpr32(fp0, fd);
5993 tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit1);
5994 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
b6d96bed 5995 gen_load_fpr32(fp0, fs);
a16336e4 5996 gen_set_label(l1);
9bf3eb2c
AJ
5997 gen_store_fpr32(fp0, fd);
5998
5999 gen_load_fpr32h(fp0, fd);
6000 tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit2);
6001 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l2);
6002 gen_load_fpr32h(fp0, fs);
a16336e4 6003 gen_set_label(l2);
9bf3eb2c
AJ
6004 gen_store_fpr32h(fp0, fd);
6005
a16336e4 6006 tcg_temp_free(r_tmp1);
9bf3eb2c 6007 tcg_temp_free(fp0);
a16336e4
TS
6008}
6009
6ea83fed 6010
5e755519
TS
6011static void gen_farith (DisasContext *ctx, uint32_t op1,
6012 int ft, int fs, int fd, int cc)
6ea83fed 6013{
923617a3 6014 const char *opn = "farith";
6ea83fed
FB
6015 const char *condnames[] = {
6016 "c.f",
6017 "c.un",
6018 "c.eq",
6019 "c.ueq",
6020 "c.olt",
6021 "c.ult",
6022 "c.ole",
6023 "c.ule",
6024 "c.sf",
6025 "c.ngle",
6026 "c.seq",
6027 "c.ngl",
6028 "c.lt",
6029 "c.nge",
6030 "c.le",
6031 "c.ngt",
6032 };
5a1e8ffb
TS
6033 const char *condnames_abs[] = {
6034 "cabs.f",
6035 "cabs.un",
6036 "cabs.eq",
6037 "cabs.ueq",
6038 "cabs.olt",
6039 "cabs.ult",
6040 "cabs.ole",
6041 "cabs.ule",
6042 "cabs.sf",
6043 "cabs.ngle",
6044 "cabs.seq",
6045 "cabs.ngl",
6046 "cabs.lt",
6047 "cabs.nge",
6048 "cabs.le",
6049 "cabs.ngt",
6050 };
6051 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
7a387fff
TS
6052 uint32_t func = ctx->opcode & 0x3f;
6053
6ea83fed 6054 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
5a5012ec 6055 case FOP(0, 16):
b6d96bed
TS
6056 {
6057 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6058 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6059
6060 gen_load_fpr32(fp0, fs);
6061 gen_load_fpr32(fp1, ft);
6062 tcg_gen_helper_1_2(do_float_add_s, fp0, fp0, fp1);
6063 tcg_temp_free(fp1);
6064 gen_store_fpr32(fp0, fd);
6065 tcg_temp_free(fp0);
6066 }
5a5012ec 6067 opn = "add.s";
5a1e8ffb 6068 optype = BINOP;
5a5012ec
TS
6069 break;
6070 case FOP(1, 16):
b6d96bed
TS
6071 {
6072 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6073 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6074
6075 gen_load_fpr32(fp0, fs);
6076 gen_load_fpr32(fp1, ft);
6077 tcg_gen_helper_1_2(do_float_sub_s, fp0, fp0, fp1);
6078 tcg_temp_free(fp1);
6079 gen_store_fpr32(fp0, fd);
6080 tcg_temp_free(fp0);
6081 }
5a5012ec 6082 opn = "sub.s";
5a1e8ffb 6083 optype = BINOP;
5a5012ec
TS
6084 break;
6085 case FOP(2, 16):
b6d96bed
TS
6086 {
6087 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6088 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6089
6090 gen_load_fpr32(fp0, fs);
6091 gen_load_fpr32(fp1, ft);
6092 tcg_gen_helper_1_2(do_float_mul_s, fp0, fp0, fp1);
6093 tcg_temp_free(fp1);
6094 gen_store_fpr32(fp0, fd);
6095 tcg_temp_free(fp0);
6096 }
5a5012ec 6097 opn = "mul.s";
5a1e8ffb 6098 optype = BINOP;
5a5012ec
TS
6099 break;
6100 case FOP(3, 16):
b6d96bed
TS
6101 {
6102 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6103 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6104
6105 gen_load_fpr32(fp0, fs);
6106 gen_load_fpr32(fp1, ft);
6107 tcg_gen_helper_1_2(do_float_div_s, fp0, fp0, fp1);
6108 tcg_temp_free(fp1);
6109 gen_store_fpr32(fp0, fd);
6110 tcg_temp_free(fp0);
6111 }
5a5012ec 6112 opn = "div.s";
5a1e8ffb 6113 optype = BINOP;
5a5012ec
TS
6114 break;
6115 case FOP(4, 16):
b6d96bed
TS
6116 {
6117 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6118
6119 gen_load_fpr32(fp0, fs);
6120 tcg_gen_helper_1_1(do_float_sqrt_s, fp0, fp0);
6121 gen_store_fpr32(fp0, fd);
6122 tcg_temp_free(fp0);
6123 }
5a5012ec
TS
6124 opn = "sqrt.s";
6125 break;
6126 case FOP(5, 16):
b6d96bed
TS
6127 {
6128 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6129
6130 gen_load_fpr32(fp0, fs);
6131 tcg_gen_helper_1_1(do_float_abs_s, fp0, fp0);
6132 gen_store_fpr32(fp0, fd);
6133 tcg_temp_free(fp0);
6134 }
5a5012ec
TS
6135 opn = "abs.s";
6136 break;
6137 case FOP(6, 16):
b6d96bed
TS
6138 {
6139 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6140
6141 gen_load_fpr32(fp0, fs);
6142 gen_store_fpr32(fp0, fd);
6143 tcg_temp_free(fp0);
6144 }
5a5012ec
TS
6145 opn = "mov.s";
6146 break;
6147 case FOP(7, 16):
b6d96bed
TS
6148 {
6149 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6150
6151 gen_load_fpr32(fp0, fs);
6152 tcg_gen_helper_1_1(do_float_chs_s, fp0, fp0);
6153 gen_store_fpr32(fp0, fd);
6154 tcg_temp_free(fp0);
6155 }
5a5012ec
TS
6156 opn = "neg.s";
6157 break;
6158 case FOP(8, 16):
5e755519 6159 check_cp1_64bitmode(ctx);
b6d96bed
TS
6160 {
6161 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6162 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6163
6164 gen_load_fpr32(fp32, fs);
6165 tcg_gen_helper_1_1(do_float_roundl_s, fp64, fp32);
6166 tcg_temp_free(fp32);
6167 gen_store_fpr64(ctx, fp64, fd);
6168 tcg_temp_free(fp64);
6169 }
5a5012ec
TS
6170 opn = "round.l.s";
6171 break;
6172 case FOP(9, 16):
5e755519 6173 check_cp1_64bitmode(ctx);
b6d96bed
TS
6174 {
6175 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6176 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6177
6178 gen_load_fpr32(fp32, fs);
6179 tcg_gen_helper_1_1(do_float_truncl_s, fp64, fp32);
6180 tcg_temp_free(fp32);
6181 gen_store_fpr64(ctx, fp64, fd);
6182 tcg_temp_free(fp64);
6183 }
5a5012ec
TS
6184 opn = "trunc.l.s";
6185 break;
6186 case FOP(10, 16):
5e755519 6187 check_cp1_64bitmode(ctx);
b6d96bed
TS
6188 {
6189 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6190 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6191
6192 gen_load_fpr32(fp32, fs);
6193 tcg_gen_helper_1_1(do_float_ceill_s, fp64, fp32);
6194 tcg_temp_free(fp32);
6195 gen_store_fpr64(ctx, fp64, fd);
6196 tcg_temp_free(fp64);
6197 }
5a5012ec
TS
6198 opn = "ceil.l.s";
6199 break;
6200 case FOP(11, 16):
5e755519 6201 check_cp1_64bitmode(ctx);
b6d96bed
TS
6202 {
6203 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6204 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6205
6206 gen_load_fpr32(fp32, fs);
6207 tcg_gen_helper_1_1(do_float_floorl_s, fp64, fp32);
6208 tcg_temp_free(fp32);
6209 gen_store_fpr64(ctx, fp64, fd);
6210 tcg_temp_free(fp64);
6211 }
5a5012ec
TS
6212 opn = "floor.l.s";
6213 break;
6214 case FOP(12, 16):
b6d96bed
TS
6215 {
6216 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6217
6218 gen_load_fpr32(fp0, fs);
6219 tcg_gen_helper_1_1(do_float_roundw_s, fp0, fp0);
6220 gen_store_fpr32(fp0, fd);
6221 tcg_temp_free(fp0);
6222 }
5a5012ec
TS
6223 opn = "round.w.s";
6224 break;
6225 case FOP(13, 16):
b6d96bed
TS
6226 {
6227 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6228
6229 gen_load_fpr32(fp0, fs);
6230 tcg_gen_helper_1_1(do_float_truncw_s, fp0, fp0);
6231 gen_store_fpr32(fp0, fd);
6232 tcg_temp_free(fp0);
6233 }
5a5012ec
TS
6234 opn = "trunc.w.s";
6235 break;
6236 case FOP(14, 16):
b6d96bed
TS
6237 {
6238 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6239
6240 gen_load_fpr32(fp0, fs);
6241 tcg_gen_helper_1_1(do_float_ceilw_s, fp0, fp0);
6242 gen_store_fpr32(fp0, fd);
6243 tcg_temp_free(fp0);
6244 }
5a5012ec
TS
6245 opn = "ceil.w.s";
6246 break;
6247 case FOP(15, 16):
b6d96bed
TS
6248 {
6249 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6250
6251 gen_load_fpr32(fp0, fs);
6252 tcg_gen_helper_1_1(do_float_floorw_s, fp0, fp0);
6253 gen_store_fpr32(fp0, fd);
6254 tcg_temp_free(fp0);
6255 }
5a5012ec
TS
6256 opn = "floor.w.s";
6257 break;
6258 case FOP(17, 16):
b6d96bed 6259 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec
TS
6260 opn = "movcf.s";
6261 break;
6262 case FOP(18, 16):
a16336e4
TS
6263 {
6264 int l1 = gen_new_label();
2a0ab998 6265 TCGv t0 = tcg_temp_new(TCG_TYPE_TL);
b6d96bed 6266 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
a16336e4 6267
6c5c1e20
TS
6268 gen_load_gpr(t0, ft);
6269 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
b6d96bed
TS
6270 gen_load_fpr32(fp0, fs);
6271 gen_store_fpr32(fp0, fd);
6272 tcg_temp_free(fp0);
a16336e4 6273 gen_set_label(l1);
2a0ab998 6274 tcg_temp_free(t0);
a16336e4 6275 }
5a5012ec
TS
6276 opn = "movz.s";
6277 break;
6278 case FOP(19, 16):
a16336e4
TS
6279 {
6280 int l1 = gen_new_label();
2a0ab998 6281 TCGv t0 = tcg_temp_new(TCG_TYPE_TL);
b6d96bed 6282 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
a16336e4 6283
6c5c1e20
TS
6284 gen_load_gpr(t0, ft);
6285 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
b6d96bed
TS
6286 gen_load_fpr32(fp0, fs);
6287 gen_store_fpr32(fp0, fd);
6288 tcg_temp_free(fp0);
a16336e4 6289 gen_set_label(l1);
2a0ab998 6290 tcg_temp_free(t0);
a16336e4 6291 }
5a5012ec
TS
6292 opn = "movn.s";
6293 break;
57fa1fb3 6294 case FOP(21, 16):
b8aa4598 6295 check_cop1x(ctx);
b6d96bed
TS
6296 {
6297 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6298
6299 gen_load_fpr32(fp0, fs);
6300 tcg_gen_helper_1_1(do_float_recip_s, fp0, fp0);
6301 gen_store_fpr32(fp0, fd);
6302 tcg_temp_free(fp0);
6303 }
57fa1fb3
TS
6304 opn = "recip.s";
6305 break;
6306 case FOP(22, 16):
b8aa4598 6307 check_cop1x(ctx);
b6d96bed
TS
6308 {
6309 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6310
6311 gen_load_fpr32(fp0, fs);
6312 tcg_gen_helper_1_1(do_float_rsqrt_s, fp0, fp0);
6313 gen_store_fpr32(fp0, fd);
6314 tcg_temp_free(fp0);
6315 }
57fa1fb3
TS
6316 opn = "rsqrt.s";
6317 break;
6318 case FOP(28, 16):
5e755519 6319 check_cp1_64bitmode(ctx);
b6d96bed
TS
6320 {
6321 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6322 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6323
6324 gen_load_fpr32(fp0, fs);
6325 gen_load_fpr32(fp1, fd);
6326 tcg_gen_helper_1_2(do_float_recip2_s, fp0, fp0, fp1);
6327 tcg_temp_free(fp1);
6328 gen_store_fpr32(fp0, fd);
6329 tcg_temp_free(fp0);
6330 }
57fa1fb3
TS
6331 opn = "recip2.s";
6332 break;
6333 case FOP(29, 16):
5e755519 6334 check_cp1_64bitmode(ctx);
b6d96bed
TS
6335 {
6336 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6337
6338 gen_load_fpr32(fp0, fs);
6339 tcg_gen_helper_1_1(do_float_recip1_s, fp0, fp0);
6340 gen_store_fpr32(fp0, fd);
6341 tcg_temp_free(fp0);
6342 }
57fa1fb3
TS
6343 opn = "recip1.s";
6344 break;
6345 case FOP(30, 16):
5e755519 6346 check_cp1_64bitmode(ctx);
b6d96bed
TS
6347 {
6348 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6349
6350 gen_load_fpr32(fp0, fs);
6351 tcg_gen_helper_1_1(do_float_rsqrt1_s, fp0, fp0);
6352 gen_store_fpr32(fp0, fd);
6353 tcg_temp_free(fp0);
6354 }
57fa1fb3
TS
6355 opn = "rsqrt1.s";
6356 break;
6357 case FOP(31, 16):
5e755519 6358 check_cp1_64bitmode(ctx);
b6d96bed
TS
6359 {
6360 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6361 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6362
6363 gen_load_fpr32(fp0, fs);
6364 gen_load_fpr32(fp1, ft);
6365 tcg_gen_helper_1_2(do_float_rsqrt2_s, fp0, fp0, fp1);
6366 tcg_temp_free(fp1);
6367 gen_store_fpr32(fp0, fd);
6368 tcg_temp_free(fp0);
6369 }
57fa1fb3
TS
6370 opn = "rsqrt2.s";
6371 break;
5a5012ec 6372 case FOP(33, 16):
5e755519 6373 check_cp1_registers(ctx, fd);
b6d96bed
TS
6374 {
6375 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6376 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6377
6378 gen_load_fpr32(fp32, fs);
6379 tcg_gen_helper_1_1(do_float_cvtd_s, fp64, fp32);
6380 tcg_temp_free(fp32);
6381 gen_store_fpr64(ctx, fp64, fd);
6382 tcg_temp_free(fp64);
6383 }
5a5012ec
TS
6384 opn = "cvt.d.s";
6385 break;
6386 case FOP(36, 16):
b6d96bed
TS
6387 {
6388 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6389
6390 gen_load_fpr32(fp0, fs);
6391 tcg_gen_helper_1_1(do_float_cvtw_s, fp0, fp0);
6392 gen_store_fpr32(fp0, fd);
6393 tcg_temp_free(fp0);
6394 }
5a5012ec
TS
6395 opn = "cvt.w.s";
6396 break;
6397 case FOP(37, 16):
5e755519 6398 check_cp1_64bitmode(ctx);
b6d96bed
TS
6399 {
6400 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6401 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6402
6403 gen_load_fpr32(fp32, fs);
6404 tcg_gen_helper_1_1(do_float_cvtl_s, fp64, fp32);
6405 tcg_temp_free(fp32);
6406 gen_store_fpr64(ctx, fp64, fd);
6407 tcg_temp_free(fp64);
6408 }
5a5012ec
TS
6409 opn = "cvt.l.s";
6410 break;
6411 case FOP(38, 16):
5e755519 6412 check_cp1_64bitmode(ctx);
b6d96bed 6413 {
36aa55dc 6414 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
b6d96bed
TS
6415 TCGv fp32_0 = tcg_temp_new(TCG_TYPE_I32);
6416 TCGv fp32_1 = tcg_temp_new(TCG_TYPE_I32);
6417
6418 gen_load_fpr32(fp32_0, fs);
6419 gen_load_fpr32(fp32_1, ft);
36aa55dc 6420 tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
b6d96bed 6421 tcg_temp_free(fp32_1);
36aa55dc
PB
6422 tcg_temp_free(fp32_0);
6423 gen_store_fpr64(ctx, fp64, fd);
6424 tcg_temp_free(fp64);
b6d96bed 6425 }
5a5012ec
TS
6426 opn = "cvt.ps.s";
6427 break;
6428 case FOP(48, 16):
6429 case FOP(49, 16):
6430 case FOP(50, 16):
6431 case FOP(51, 16):
6432 case FOP(52, 16):
6433 case FOP(53, 16):
6434 case FOP(54, 16):
6435 case FOP(55, 16):
6436 case FOP(56, 16):
6437 case FOP(57, 16):
6438 case FOP(58, 16):
6439 case FOP(59, 16):
6440 case FOP(60, 16):
6441 case FOP(61, 16):
6442 case FOP(62, 16):
6443 case FOP(63, 16):
b6d96bed
TS
6444 {
6445 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6446 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
6447
6448 gen_load_fpr32(fp0, fs);
6449 gen_load_fpr32(fp1, ft);
6450 if (ctx->opcode & (1 << 6)) {
6451 check_cop1x(ctx);
6452 gen_cmpabs_s(func-48, fp0, fp1, cc);
6453 opn = condnames_abs[func-48];
6454 } else {
6455 gen_cmp_s(func-48, fp0, fp1, cc);
6456 opn = condnames[func-48];
6457 }
6458 tcg_temp_free(fp0);
6459 tcg_temp_free(fp1);
5a1e8ffb 6460 }
5a5012ec 6461 break;
6ea83fed 6462 case FOP(0, 17):
5e755519 6463 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed
TS
6464 {
6465 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6466 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6467
6468 gen_load_fpr64(ctx, fp0, fs);
6469 gen_load_fpr64(ctx, fp1, ft);
6470 tcg_gen_helper_1_2(do_float_add_d, fp0, fp0, fp1);
6471 tcg_temp_free(fp1);
6472 gen_store_fpr64(ctx, fp0, fd);
6473 tcg_temp_free(fp0);
6474 }
6ea83fed 6475 opn = "add.d";
5a1e8ffb 6476 optype = BINOP;
6ea83fed
FB
6477 break;
6478 case FOP(1, 17):
5e755519 6479 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed
TS
6480 {
6481 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6482 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6483
6484 gen_load_fpr64(ctx, fp0, fs);
6485 gen_load_fpr64(ctx, fp1, ft);
6486 tcg_gen_helper_1_2(do_float_sub_d, fp0, fp0, fp1);
6487 tcg_temp_free(fp1);
6488 gen_store_fpr64(ctx, fp0, fd);
6489 tcg_temp_free(fp0);
6490 }
6ea83fed 6491 opn = "sub.d";
5a1e8ffb 6492 optype = BINOP;
6ea83fed
FB
6493 break;
6494 case FOP(2, 17):
5e755519 6495 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed
TS
6496 {
6497 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6498 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6499
6500 gen_load_fpr64(ctx, fp0, fs);
6501 gen_load_fpr64(ctx, fp1, ft);
6502 tcg_gen_helper_1_2(do_float_mul_d, fp0, fp0, fp1);
6503 tcg_temp_free(fp1);
6504 gen_store_fpr64(ctx, fp0, fd);
6505 tcg_temp_free(fp0);
6506 }
6ea83fed 6507 opn = "mul.d";
5a1e8ffb 6508 optype = BINOP;
6ea83fed
FB
6509 break;
6510 case FOP(3, 17):
5e755519 6511 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed
TS
6512 {
6513 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6514 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6515
6516 gen_load_fpr64(ctx, fp0, fs);
6517 gen_load_fpr64(ctx, fp1, ft);
6518 tcg_gen_helper_1_2(do_float_div_d, fp0, fp0, fp1);
6519 tcg_temp_free(fp1);
6520 gen_store_fpr64(ctx, fp0, fd);
6521 tcg_temp_free(fp0);
6522 }
6ea83fed 6523 opn = "div.d";
5a1e8ffb 6524 optype = BINOP;
6ea83fed
FB
6525 break;
6526 case FOP(4, 17):
5e755519 6527 check_cp1_registers(ctx, fs | fd);
b6d96bed
TS
6528 {
6529 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6530
6531 gen_load_fpr64(ctx, fp0, fs);
6532 tcg_gen_helper_1_1(do_float_sqrt_d, fp0, fp0);
6533 gen_store_fpr64(ctx, fp0, fd);
6534 tcg_temp_free(fp0);
6535 }
6ea83fed
FB
6536 opn = "sqrt.d";
6537 break;
6538 case FOP(5, 17):
5e755519 6539 check_cp1_registers(ctx, fs | fd);
b6d96bed
TS
6540 {
6541 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6542
6543 gen_load_fpr64(ctx, fp0, fs);
6544 tcg_gen_helper_1_1(do_float_abs_d, fp0, fp0);
6545 gen_store_fpr64(ctx, fp0, fd);
6546 tcg_temp_free(fp0);
6547 }
6ea83fed
FB
6548 opn = "abs.d";
6549 break;
6550 case FOP(6, 17):
5e755519 6551 check_cp1_registers(ctx, fs | fd);
b6d96bed
TS
6552 {
6553 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6554
6555 gen_load_fpr64(ctx, fp0, fs);
6556 gen_store_fpr64(ctx, fp0, fd);
6557 tcg_temp_free(fp0);
6558 }
6ea83fed
FB
6559 opn = "mov.d";
6560 break;
6561 case FOP(7, 17):
5e755519 6562 check_cp1_registers(ctx, fs | fd);
b6d96bed
TS
6563 {
6564 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6565
6566 gen_load_fpr64(ctx, fp0, fs);
6567 tcg_gen_helper_1_1(do_float_chs_d, fp0, fp0);
6568 gen_store_fpr64(ctx, fp0, fd);
6569 tcg_temp_free(fp0);
6570 }
6ea83fed
FB
6571 opn = "neg.d";
6572 break;
5a5012ec 6573 case FOP(8, 17):
5e755519 6574 check_cp1_64bitmode(ctx);
b6d96bed
TS
6575 {
6576 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6577
6578 gen_load_fpr64(ctx, fp0, fs);
6579 tcg_gen_helper_1_1(do_float_roundl_d, fp0, fp0);
6580 gen_store_fpr64(ctx, fp0, fd);
6581 tcg_temp_free(fp0);
6582 }
5a5012ec
TS
6583 opn = "round.l.d";
6584 break;
6585 case FOP(9, 17):
5e755519 6586 check_cp1_64bitmode(ctx);
b6d96bed
TS
6587 {
6588 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6589
6590 gen_load_fpr64(ctx, fp0, fs);
6591 tcg_gen_helper_1_1(do_float_truncl_d, fp0, fp0);
6592 gen_store_fpr64(ctx, fp0, fd);
6593 tcg_temp_free(fp0);
6594 }
5a5012ec
TS
6595 opn = "trunc.l.d";
6596 break;
6597 case FOP(10, 17):
5e755519 6598 check_cp1_64bitmode(ctx);
b6d96bed
TS
6599 {
6600 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6601
6602 gen_load_fpr64(ctx, fp0, fs);
6603 tcg_gen_helper_1_1(do_float_ceill_d, fp0, fp0);
6604 gen_store_fpr64(ctx, fp0, fd);
6605 tcg_temp_free(fp0);
6606 }
5a5012ec
TS
6607 opn = "ceil.l.d";
6608 break;
6609 case FOP(11, 17):
5e755519 6610 check_cp1_64bitmode(ctx);
b6d96bed
TS
6611 {
6612 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6613
6614 gen_load_fpr64(ctx, fp0, fs);
6615 tcg_gen_helper_1_1(do_float_floorl_d, fp0, fp0);
6616 gen_store_fpr64(ctx, fp0, fd);
6617 tcg_temp_free(fp0);
6618 }
5a5012ec
TS
6619 opn = "floor.l.d";
6620 break;
6ea83fed 6621 case FOP(12, 17):
5e755519 6622 check_cp1_registers(ctx, fs);
b6d96bed
TS
6623 {
6624 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6625 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6626
6627 gen_load_fpr64(ctx, fp64, fs);
6628 tcg_gen_helper_1_1(do_float_roundw_d, fp32, fp64);
6629 tcg_temp_free(fp64);
6630 gen_store_fpr32(fp32, fd);
6631 tcg_temp_free(fp32);
6632 }
6ea83fed
FB
6633 opn = "round.w.d";
6634 break;
6635 case FOP(13, 17):
5e755519 6636 check_cp1_registers(ctx, fs);
b6d96bed
TS
6637 {
6638 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6639 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6640
6641 gen_load_fpr64(ctx, fp64, fs);
6642 tcg_gen_helper_1_1(do_float_truncw_d, fp32, fp64);
6643 tcg_temp_free(fp64);
6644 gen_store_fpr32(fp32, fd);
6645 tcg_temp_free(fp32);
6646 }
6ea83fed
FB
6647 opn = "trunc.w.d";
6648 break;
6649 case FOP(14, 17):
5e755519 6650 check_cp1_registers(ctx, fs);
b6d96bed
TS
6651 {
6652 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6653 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6654
6655 gen_load_fpr64(ctx, fp64, fs);
6656 tcg_gen_helper_1_1(do_float_ceilw_d, fp32, fp64);
6657 tcg_temp_free(fp64);
6658 gen_store_fpr32(fp32, fd);
6659 tcg_temp_free(fp32);
6660 }
6ea83fed
FB
6661 opn = "ceil.w.d";
6662 break;
6663 case FOP(15, 17):
5e755519 6664 check_cp1_registers(ctx, fs);
b6d96bed
TS
6665 {
6666 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6667 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6668
6669 gen_load_fpr64(ctx, fp64, fs);
6670 tcg_gen_helper_1_1(do_float_floorw_d, fp32, fp64);
6671 tcg_temp_free(fp64);
6672 gen_store_fpr32(fp32, fd);
6673 tcg_temp_free(fp32);
6674 }
7a387fff 6675 opn = "floor.w.d";
6ea83fed 6676 break;
5a5012ec 6677 case FOP(17, 17):
b6d96bed 6678 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 6679 opn = "movcf.d";
dd016883 6680 break;
5a5012ec 6681 case FOP(18, 17):
a16336e4
TS
6682 {
6683 int l1 = gen_new_label();
2a0ab998 6684 TCGv t0 = tcg_temp_new(TCG_TYPE_TL);
b6d96bed 6685 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I64);
a16336e4 6686
6c5c1e20
TS
6687 gen_load_gpr(t0, ft);
6688 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
b6d96bed
TS
6689 gen_load_fpr64(ctx, fp0, fs);
6690 gen_store_fpr64(ctx, fp0, fd);
6691 tcg_temp_free(fp0);
a16336e4 6692 gen_set_label(l1);
2a0ab998 6693 tcg_temp_free(t0);
a16336e4 6694 }
5a5012ec
TS
6695 opn = "movz.d";
6696 break;
6697 case FOP(19, 17):
a16336e4
TS
6698 {
6699 int l1 = gen_new_label();
2a0ab998 6700 TCGv t0 = tcg_temp_new(TCG_TYPE_TL);
b6d96bed 6701 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I64);
a16336e4 6702
6c5c1e20
TS
6703 gen_load_gpr(t0, ft);
6704 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
b6d96bed
TS
6705 gen_load_fpr64(ctx, fp0, fs);
6706 gen_store_fpr64(ctx, fp0, fd);
6707 tcg_temp_free(fp0);
a16336e4 6708 gen_set_label(l1);
2a0ab998 6709 tcg_temp_free(t0);
a16336e4 6710 }
5a5012ec 6711 opn = "movn.d";
6ea83fed 6712 break;
57fa1fb3 6713 case FOP(21, 17):
b8aa4598 6714 check_cp1_64bitmode(ctx);
b6d96bed
TS
6715 {
6716 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6717
6718 gen_load_fpr64(ctx, fp0, fs);
6719 tcg_gen_helper_1_1(do_float_recip_d, fp0, fp0);
6720 gen_store_fpr64(ctx, fp0, fd);
6721 tcg_temp_free(fp0);
6722 }
57fa1fb3
TS
6723 opn = "recip.d";
6724 break;
6725 case FOP(22, 17):
b8aa4598 6726 check_cp1_64bitmode(ctx);
b6d96bed
TS
6727 {
6728 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6729
6730 gen_load_fpr64(ctx, fp0, fs);
6731 tcg_gen_helper_1_1(do_float_rsqrt_d, fp0, fp0);
6732 gen_store_fpr64(ctx, fp0, fd);
6733 tcg_temp_free(fp0);
6734 }
57fa1fb3
TS
6735 opn = "rsqrt.d";
6736 break;
6737 case FOP(28, 17):
5e755519 6738 check_cp1_64bitmode(ctx);
b6d96bed
TS
6739 {
6740 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6741 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6742
6743 gen_load_fpr64(ctx, fp0, fs);
6744 gen_load_fpr64(ctx, fp1, ft);
6745 tcg_gen_helper_1_2(do_float_recip2_d, fp0, fp0, fp1);
6746 tcg_temp_free(fp1);
6747 gen_store_fpr64(ctx, fp0, fd);
6748 tcg_temp_free(fp0);
6749 }
57fa1fb3
TS
6750 opn = "recip2.d";
6751 break;
6752 case FOP(29, 17):
5e755519 6753 check_cp1_64bitmode(ctx);
b6d96bed
TS
6754 {
6755 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6756
6757 gen_load_fpr64(ctx, fp0, fs);
6758 tcg_gen_helper_1_1(do_float_recip1_d, fp0, fp0);
6759 gen_store_fpr64(ctx, fp0, fd);
6760 tcg_temp_free(fp0);
6761 }
57fa1fb3
TS
6762 opn = "recip1.d";
6763 break;
6764 case FOP(30, 17):
5e755519 6765 check_cp1_64bitmode(ctx);
b6d96bed
TS
6766 {
6767 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6768
6769 gen_load_fpr64(ctx, fp0, fs);
6770 tcg_gen_helper_1_1(do_float_rsqrt1_d, fp0, fp0);
6771 gen_store_fpr64(ctx, fp0, fd);
6772 tcg_temp_free(fp0);
6773 }
57fa1fb3
TS
6774 opn = "rsqrt1.d";
6775 break;
6776 case FOP(31, 17):
5e755519 6777 check_cp1_64bitmode(ctx);
b6d96bed
TS
6778 {
6779 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6780 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6781
6782 gen_load_fpr64(ctx, fp0, fs);
6783 gen_load_fpr64(ctx, fp1, ft);
6784 tcg_gen_helper_1_2(do_float_rsqrt2_d, fp0, fp0, fp1);
6785 tcg_temp_free(fp1);
6786 gen_store_fpr64(ctx, fp0, fd);
6787 tcg_temp_free(fp0);
6788 }
57fa1fb3
TS
6789 opn = "rsqrt2.d";
6790 break;
6ea83fed
FB
6791 case FOP(48, 17):
6792 case FOP(49, 17):
6793 case FOP(50, 17):
6794 case FOP(51, 17):
6795 case FOP(52, 17):
6796 case FOP(53, 17):
6797 case FOP(54, 17):
6798 case FOP(55, 17):
6799 case FOP(56, 17):
6800 case FOP(57, 17):
6801 case FOP(58, 17):
6802 case FOP(59, 17):
6803 case FOP(60, 17):
6804 case FOP(61, 17):
6805 case FOP(62, 17):
6806 case FOP(63, 17):
b6d96bed
TS
6807 {
6808 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6809 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6810
6811 gen_load_fpr64(ctx, fp0, fs);
6812 gen_load_fpr64(ctx, fp1, ft);
6813 if (ctx->opcode & (1 << 6)) {
6814 check_cop1x(ctx);
6815 check_cp1_registers(ctx, fs | ft);
6816 gen_cmpabs_d(func-48, fp0, fp1, cc);
6817 opn = condnames_abs[func-48];
6818 } else {
6819 check_cp1_registers(ctx, fs | ft);
6820 gen_cmp_d(func-48, fp0, fp1, cc);
6821 opn = condnames[func-48];
6822 }
6823 tcg_temp_free(fp0);
6824 tcg_temp_free(fp1);
5a1e8ffb 6825 }
6ea83fed 6826 break;
5a5012ec 6827 case FOP(32, 17):
5e755519 6828 check_cp1_registers(ctx, fs);
b6d96bed
TS
6829 {
6830 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6831 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6832
6833 gen_load_fpr64(ctx, fp64, fs);
6834 tcg_gen_helper_1_1(do_float_cvts_d, fp32, fp64);
6835 tcg_temp_free(fp64);
6836 gen_store_fpr32(fp32, fd);
6837 tcg_temp_free(fp32);
6838 }
5a5012ec
TS
6839 opn = "cvt.s.d";
6840 break;
6841 case FOP(36, 17):
5e755519 6842 check_cp1_registers(ctx, fs);
b6d96bed
TS
6843 {
6844 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6845 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6846
6847 gen_load_fpr64(ctx, fp64, fs);
6848 tcg_gen_helper_1_1(do_float_cvtw_d, fp32, fp64);
6849 tcg_temp_free(fp64);
6850 gen_store_fpr32(fp32, fd);
6851 tcg_temp_free(fp32);
6852 }
5a5012ec
TS
6853 opn = "cvt.w.d";
6854 break;
6855 case FOP(37, 17):
5e755519 6856 check_cp1_64bitmode(ctx);
b6d96bed
TS
6857 {
6858 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6859
6860 gen_load_fpr64(ctx, fp0, fs);
6861 tcg_gen_helper_1_1(do_float_cvtl_d, fp0, fp0);
6862 gen_store_fpr64(ctx, fp0, fd);
6863 tcg_temp_free(fp0);
6864 }
5a5012ec
TS
6865 opn = "cvt.l.d";
6866 break;
6867 case FOP(32, 20):
b6d96bed
TS
6868 {
6869 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
6870
6871 gen_load_fpr32(fp0, fs);
6872 tcg_gen_helper_1_1(do_float_cvts_w, fp0, fp0);
6873 gen_store_fpr32(fp0, fd);
6874 tcg_temp_free(fp0);
6875 }
5a5012ec 6876 opn = "cvt.s.w";
6ea83fed 6877 break;
5a5012ec 6878 case FOP(33, 20):
5e755519 6879 check_cp1_registers(ctx, fd);
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_fpr32(fp32, fs);
6885 tcg_gen_helper_1_1(do_float_cvtd_w, fp64, fp32);
6886 tcg_temp_free(fp32);
6887 gen_store_fpr64(ctx, fp64, fd);
6888 tcg_temp_free(fp64);
6889 }
5a5012ec
TS
6890 opn = "cvt.d.w";
6891 break;
6892 case FOP(32, 21):
5e755519 6893 check_cp1_64bitmode(ctx);
b6d96bed
TS
6894 {
6895 TCGv fp32 = tcg_temp_new(TCG_TYPE_I32);
6896 TCGv fp64 = tcg_temp_new(TCG_TYPE_I64);
6897
6898 gen_load_fpr64(ctx, fp64, fs);
6899 tcg_gen_helper_1_1(do_float_cvts_l, fp32, fp64);
6900 tcg_temp_free(fp64);
6901 gen_store_fpr32(fp32, fd);
6902 tcg_temp_free(fp32);
6903 }
5a5012ec
TS
6904 opn = "cvt.s.l";
6905 break;
6906 case FOP(33, 21):
5e755519 6907 check_cp1_64bitmode(ctx);
b6d96bed
TS
6908 {
6909 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6910
6911 gen_load_fpr64(ctx, fp0, fs);
6912 tcg_gen_helper_1_1(do_float_cvtd_l, fp0, fp0);
6913 gen_store_fpr64(ctx, fp0, fd);
6914 tcg_temp_free(fp0);
6915 }
5a5012ec
TS
6916 opn = "cvt.d.l";
6917 break;
6918 case FOP(38, 20):
5e755519 6919 check_cp1_64bitmode(ctx);
b6d96bed
TS
6920 {
6921 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6922
6923 gen_load_fpr64(ctx, fp0, fs);
6924 tcg_gen_helper_1_1(do_float_cvtps_pw, fp0, fp0);
6925 gen_store_fpr64(ctx, fp0, fd);
6926 tcg_temp_free(fp0);
6927 }
5a5012ec
TS
6928 opn = "cvt.ps.pw";
6929 break;
6930 case FOP(0, 22):
5e755519 6931 check_cp1_64bitmode(ctx);
b6d96bed
TS
6932 {
6933 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6934 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6935
6936 gen_load_fpr64(ctx, fp0, fs);
6937 gen_load_fpr64(ctx, fp1, ft);
6938 tcg_gen_helper_1_2(do_float_add_ps, fp0, fp0, fp1);
6939 tcg_temp_free(fp1);
6940 gen_store_fpr64(ctx, fp0, fd);
6941 tcg_temp_free(fp0);
6942 }
5a5012ec 6943 opn = "add.ps";
6ea83fed 6944 break;
5a5012ec 6945 case FOP(1, 22):
5e755519 6946 check_cp1_64bitmode(ctx);
b6d96bed
TS
6947 {
6948 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6949 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6950
6951 gen_load_fpr64(ctx, fp0, fs);
6952 gen_load_fpr64(ctx, fp1, ft);
6953 tcg_gen_helper_1_2(do_float_sub_ps, fp0, fp0, fp1);
6954 tcg_temp_free(fp1);
6955 gen_store_fpr64(ctx, fp0, fd);
6956 tcg_temp_free(fp0);
6957 }
5a5012ec 6958 opn = "sub.ps";
6ea83fed 6959 break;
5a5012ec 6960 case FOP(2, 22):
5e755519 6961 check_cp1_64bitmode(ctx);
b6d96bed
TS
6962 {
6963 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6964 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
6965
6966 gen_load_fpr64(ctx, fp0, fs);
6967 gen_load_fpr64(ctx, fp1, ft);
6968 tcg_gen_helper_1_2(do_float_mul_ps, fp0, fp0, fp1);
6969 tcg_temp_free(fp1);
6970 gen_store_fpr64(ctx, fp0, fd);
6971 tcg_temp_free(fp0);
6972 }
5a5012ec 6973 opn = "mul.ps";
6ea83fed 6974 break;
5a5012ec 6975 case FOP(5, 22):
5e755519 6976 check_cp1_64bitmode(ctx);
b6d96bed
TS
6977 {
6978 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6979
6980 gen_load_fpr64(ctx, fp0, fs);
6981 tcg_gen_helper_1_1(do_float_abs_ps, fp0, fp0);
6982 gen_store_fpr64(ctx, fp0, fd);
6983 tcg_temp_free(fp0);
6984 }
5a5012ec 6985 opn = "abs.ps";
6ea83fed 6986 break;
5a5012ec 6987 case FOP(6, 22):
5e755519 6988 check_cp1_64bitmode(ctx);
b6d96bed
TS
6989 {
6990 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
6991
6992 gen_load_fpr64(ctx, fp0, fs);
6993 gen_store_fpr64(ctx, fp0, fd);
6994 tcg_temp_free(fp0);
6995 }
5a5012ec 6996 opn = "mov.ps";
6ea83fed 6997 break;
5a5012ec 6998 case FOP(7, 22):
5e755519 6999 check_cp1_64bitmode(ctx);
b6d96bed
TS
7000 {
7001 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7002
7003 gen_load_fpr64(ctx, fp0, fs);
7004 tcg_gen_helper_1_1(do_float_chs_ps, fp0, fp0);
7005 gen_store_fpr64(ctx, fp0, fd);
7006 tcg_temp_free(fp0);
7007 }
5a5012ec 7008 opn = "neg.ps";
6ea83fed 7009 break;
5a5012ec 7010 case FOP(17, 22):
5e755519 7011 check_cp1_64bitmode(ctx);
b6d96bed 7012 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 7013 opn = "movcf.ps";
6ea83fed 7014 break;
5a5012ec 7015 case FOP(18, 22):
5e755519 7016 check_cp1_64bitmode(ctx);
a16336e4
TS
7017 {
7018 int l1 = gen_new_label();
2a0ab998 7019 TCGv t0 = tcg_temp_new(TCG_TYPE_TL);
b6d96bed
TS
7020 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
7021 TCGv fph0 = tcg_temp_local_new(TCG_TYPE_I32);
a16336e4 7022
6c5c1e20
TS
7023 gen_load_gpr(t0, ft);
7024 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
b6d96bed
TS
7025 gen_load_fpr32(fp0, fs);
7026 gen_load_fpr32h(fph0, fs);
7027 gen_store_fpr32(fp0, fd);
7028 gen_store_fpr32h(fph0, fd);
7029 tcg_temp_free(fp0);
7030 tcg_temp_free(fph0);
a16336e4 7031 gen_set_label(l1);
2a0ab998 7032 tcg_temp_free(t0);
a16336e4 7033 }
5a5012ec 7034 opn = "movz.ps";
6ea83fed 7035 break;
5a5012ec 7036 case FOP(19, 22):
5e755519 7037 check_cp1_64bitmode(ctx);
a16336e4
TS
7038 {
7039 int l1 = gen_new_label();
2a0ab998 7040 TCGv t0 = tcg_temp_new(TCG_TYPE_TL);
b6d96bed
TS
7041 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
7042 TCGv fph0 = tcg_temp_local_new(TCG_TYPE_I32);
a16336e4 7043
6c5c1e20
TS
7044 gen_load_gpr(t0, ft);
7045 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
b6d96bed
TS
7046 gen_load_fpr32(fp0, fs);
7047 gen_load_fpr32h(fph0, fs);
7048 gen_store_fpr32(fp0, fd);
7049 gen_store_fpr32h(fph0, fd);
7050 tcg_temp_free(fp0);
7051 tcg_temp_free(fph0);
a16336e4 7052 gen_set_label(l1);
2a0ab998 7053 tcg_temp_free(t0);
a16336e4 7054 }
5a5012ec 7055 opn = "movn.ps";
6ea83fed 7056 break;
fbcc6828 7057 case FOP(24, 22):
5e755519 7058 check_cp1_64bitmode(ctx);
b6d96bed
TS
7059 {
7060 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7061 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7062
7063 gen_load_fpr64(ctx, fp0, ft);
7064 gen_load_fpr64(ctx, fp1, fs);
7065 tcg_gen_helper_1_2(do_float_addr_ps, fp0, fp0, fp1);
7066 tcg_temp_free(fp1);
7067 gen_store_fpr64(ctx, fp0, fd);
7068 tcg_temp_free(fp0);
7069 }
fbcc6828
TS
7070 opn = "addr.ps";
7071 break;
57fa1fb3 7072 case FOP(26, 22):
5e755519 7073 check_cp1_64bitmode(ctx);
b6d96bed
TS
7074 {
7075 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7076 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7077
7078 gen_load_fpr64(ctx, fp0, ft);
7079 gen_load_fpr64(ctx, fp1, fs);
7080 tcg_gen_helper_1_2(do_float_mulr_ps, fp0, fp0, fp1);
7081 tcg_temp_free(fp1);
7082 gen_store_fpr64(ctx, fp0, fd);
7083 tcg_temp_free(fp0);
7084 }
57fa1fb3
TS
7085 opn = "mulr.ps";
7086 break;
7087 case FOP(28, 22):
5e755519 7088 check_cp1_64bitmode(ctx);
b6d96bed
TS
7089 {
7090 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7091 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7092
7093 gen_load_fpr64(ctx, fp0, fs);
7094 gen_load_fpr64(ctx, fp1, fd);
7095 tcg_gen_helper_1_2(do_float_recip2_ps, fp0, fp0, fp1);
7096 tcg_temp_free(fp1);
7097 gen_store_fpr64(ctx, fp0, fd);
7098 tcg_temp_free(fp0);
7099 }
57fa1fb3
TS
7100 opn = "recip2.ps";
7101 break;
7102 case FOP(29, 22):
5e755519 7103 check_cp1_64bitmode(ctx);
b6d96bed
TS
7104 {
7105 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7106
7107 gen_load_fpr64(ctx, fp0, fs);
7108 tcg_gen_helper_1_1(do_float_recip1_ps, fp0, fp0);
7109 gen_store_fpr64(ctx, fp0, fd);
7110 tcg_temp_free(fp0);
7111 }
57fa1fb3
TS
7112 opn = "recip1.ps";
7113 break;
7114 case FOP(30, 22):
5e755519 7115 check_cp1_64bitmode(ctx);
b6d96bed
TS
7116 {
7117 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7118
7119 gen_load_fpr64(ctx, fp0, fs);
7120 tcg_gen_helper_1_1(do_float_rsqrt1_ps, fp0, fp0);
7121 gen_store_fpr64(ctx, fp0, fd);
7122 tcg_temp_free(fp0);
7123 }
57fa1fb3
TS
7124 opn = "rsqrt1.ps";
7125 break;
7126 case FOP(31, 22):
5e755519 7127 check_cp1_64bitmode(ctx);
b6d96bed
TS
7128 {
7129 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7130 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7131
7132 gen_load_fpr64(ctx, fp0, fs);
7133 gen_load_fpr64(ctx, fp1, ft);
7134 tcg_gen_helper_1_2(do_float_rsqrt2_ps, fp0, fp0, fp1);
7135 tcg_temp_free(fp1);
7136 gen_store_fpr64(ctx, fp0, fd);
7137 tcg_temp_free(fp0);
7138 }
57fa1fb3
TS
7139 opn = "rsqrt2.ps";
7140 break;
5a5012ec 7141 case FOP(32, 22):
5e755519 7142 check_cp1_64bitmode(ctx);
b6d96bed
TS
7143 {
7144 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7145
7146 gen_load_fpr32h(fp0, fs);
7147 tcg_gen_helper_1_1(do_float_cvts_pu, fp0, fp0);
7148 gen_store_fpr32(fp0, fd);
7149 tcg_temp_free(fp0);
7150 }
5a5012ec 7151 opn = "cvt.s.pu";
dd016883 7152 break;
5a5012ec 7153 case FOP(36, 22):
5e755519 7154 check_cp1_64bitmode(ctx);
b6d96bed
TS
7155 {
7156 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7157
7158 gen_load_fpr64(ctx, fp0, fs);
7159 tcg_gen_helper_1_1(do_float_cvtpw_ps, fp0, fp0);
7160 gen_store_fpr64(ctx, fp0, fd);
7161 tcg_temp_free(fp0);
7162 }
5a5012ec 7163 opn = "cvt.pw.ps";
6ea83fed 7164 break;
5a5012ec 7165 case FOP(40, 22):
5e755519 7166 check_cp1_64bitmode(ctx);
b6d96bed
TS
7167 {
7168 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7169
7170 gen_load_fpr32(fp0, fs);
7171 tcg_gen_helper_1_1(do_float_cvts_pl, fp0, fp0);
7172 gen_store_fpr32(fp0, fd);
7173 tcg_temp_free(fp0);
7174 }
5a5012ec 7175 opn = "cvt.s.pl";
6ea83fed 7176 break;
5a5012ec 7177 case FOP(44, 22):
5e755519 7178 check_cp1_64bitmode(ctx);
b6d96bed
TS
7179 {
7180 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7181 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7182
7183 gen_load_fpr32(fp0, fs);
7184 gen_load_fpr32(fp1, ft);
7185 gen_store_fpr32h(fp0, fd);
7186 gen_store_fpr32(fp1, fd);
7187 tcg_temp_free(fp0);
7188 tcg_temp_free(fp1);
7189 }
5a5012ec 7190 opn = "pll.ps";
6ea83fed 7191 break;
5a5012ec 7192 case FOP(45, 22):
5e755519 7193 check_cp1_64bitmode(ctx);
b6d96bed
TS
7194 {
7195 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7196 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7197
7198 gen_load_fpr32(fp0, fs);
7199 gen_load_fpr32h(fp1, ft);
7200 gen_store_fpr32(fp1, fd);
7201 gen_store_fpr32h(fp0, fd);
7202 tcg_temp_free(fp0);
7203 tcg_temp_free(fp1);
7204 }
5a5012ec
TS
7205 opn = "plu.ps";
7206 break;
7207 case FOP(46, 22):
5e755519 7208 check_cp1_64bitmode(ctx);
b6d96bed
TS
7209 {
7210 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7211 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7212
7213 gen_load_fpr32h(fp0, fs);
7214 gen_load_fpr32(fp1, ft);
7215 gen_store_fpr32(fp1, fd);
7216 gen_store_fpr32h(fp0, fd);
7217 tcg_temp_free(fp0);
7218 tcg_temp_free(fp1);
7219 }
5a5012ec
TS
7220 opn = "pul.ps";
7221 break;
7222 case FOP(47, 22):
5e755519 7223 check_cp1_64bitmode(ctx);
b6d96bed
TS
7224 {
7225 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7226 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7227
7228 gen_load_fpr32h(fp0, fs);
7229 gen_load_fpr32h(fp1, ft);
7230 gen_store_fpr32(fp1, fd);
7231 gen_store_fpr32h(fp0, fd);
7232 tcg_temp_free(fp0);
7233 tcg_temp_free(fp1);
7234 }
5a5012ec
TS
7235 opn = "puu.ps";
7236 break;
7237 case FOP(48, 22):
7238 case FOP(49, 22):
7239 case FOP(50, 22):
7240 case FOP(51, 22):
7241 case FOP(52, 22):
7242 case FOP(53, 22):
7243 case FOP(54, 22):
7244 case FOP(55, 22):
7245 case FOP(56, 22):
7246 case FOP(57, 22):
7247 case FOP(58, 22):
7248 case FOP(59, 22):
7249 case FOP(60, 22):
7250 case FOP(61, 22):
7251 case FOP(62, 22):
7252 case FOP(63, 22):
5e755519 7253 check_cp1_64bitmode(ctx);
b6d96bed
TS
7254 {
7255 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7256 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7257
7258 gen_load_fpr64(ctx, fp0, fs);
7259 gen_load_fpr64(ctx, fp1, ft);
7260 if (ctx->opcode & (1 << 6)) {
7261 gen_cmpabs_ps(func-48, fp0, fp1, cc);
7262 opn = condnames_abs[func-48];
7263 } else {
7264 gen_cmp_ps(func-48, fp0, fp1, cc);
7265 opn = condnames[func-48];
7266 }
7267 tcg_temp_free(fp0);
7268 tcg_temp_free(fp1);
5a1e8ffb 7269 }
6ea83fed 7270 break;
5a5012ec 7271 default:
923617a3 7272 MIPS_INVAL(opn);
e397ee33 7273 generate_exception (ctx, EXCP_RI);
6ea83fed
FB
7274 return;
7275 }
5a1e8ffb
TS
7276 switch (optype) {
7277 case BINOP:
6ea83fed 7278 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
5a1e8ffb
TS
7279 break;
7280 case CMPOP:
7281 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7282 break;
7283 default:
6ea83fed 7284 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
5a1e8ffb
TS
7285 break;
7286 }
6ea83fed 7287}
6af0bf9c 7288
5a5012ec 7289/* Coprocessor 3 (FPU) */
5e755519
TS
7290static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7291 int fd, int fs, int base, int index)
7a387fff 7292{
923617a3 7293 const char *opn = "extended float load/store";
93b12ccc 7294 int store = 0;
6c5c1e20
TS
7295 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
7296 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
7a387fff 7297
93b12ccc 7298 if (base == 0) {
6c5c1e20 7299 gen_load_gpr(t0, index);
93b12ccc 7300 } else if (index == 0) {
6c5c1e20 7301 gen_load_gpr(t0, base);
93b12ccc 7302 } else {
6c5c1e20
TS
7303 gen_load_gpr(t0, base);
7304 gen_load_gpr(t1, index);
d144d1d9 7305 gen_op_addr_add(ctx, t0, t1);
93b12ccc 7306 }
5a5012ec 7307 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 7308 memory access. */
5a5012ec
TS
7309 switch (opc) {
7310 case OPC_LWXC1:
b8aa4598 7311 check_cop1x(ctx);
b6d96bed
TS
7312 {
7313 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7314
7315 tcg_gen_qemu_ld32s(fp0, t0, ctx->mem_idx);
7316 gen_store_fpr32(fp0, fd);
7317 tcg_temp_free(fp0);
7318 }
5a5012ec
TS
7319 opn = "lwxc1";
7320 break;
7321 case OPC_LDXC1:
b8aa4598
TS
7322 check_cop1x(ctx);
7323 check_cp1_registers(ctx, fd);
b6d96bed
TS
7324 {
7325 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7326
7327 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7328 gen_store_fpr64(ctx, fp0, fd);
7329 tcg_temp_free(fp0);
7330 }
5a5012ec
TS
7331 opn = "ldxc1";
7332 break;
7333 case OPC_LUXC1:
b8aa4598 7334 check_cp1_64bitmode(ctx);
6c5c1e20 7335 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed
TS
7336 {
7337 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7338
7339 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7340 gen_store_fpr64(ctx, fp0, fd);
7341 tcg_temp_free(fp0);
7342 }
5a5012ec
TS
7343 opn = "luxc1";
7344 break;
7345 case OPC_SWXC1:
b8aa4598 7346 check_cop1x(ctx);
b6d96bed
TS
7347 {
7348 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7349
7350 gen_load_fpr32(fp0, fs);
7351 tcg_gen_qemu_st32(fp0, t0, ctx->mem_idx);
7352 tcg_temp_free(fp0);
7353 }
5a5012ec 7354 opn = "swxc1";
93b12ccc 7355 store = 1;
5a5012ec
TS
7356 break;
7357 case OPC_SDXC1:
b8aa4598
TS
7358 check_cop1x(ctx);
7359 check_cp1_registers(ctx, fs);
b6d96bed
TS
7360 {
7361 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7362
7363 gen_load_fpr64(ctx, fp0, fs);
7364 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7365 tcg_temp_free(fp0);
7366 }
5a5012ec 7367 opn = "sdxc1";
93b12ccc 7368 store = 1;
5a5012ec
TS
7369 break;
7370 case OPC_SUXC1:
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 gen_load_fpr64(ctx, fp0, fs);
7377 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7378 tcg_temp_free(fp0);
7379 }
5a5012ec 7380 opn = "suxc1";
93b12ccc 7381 store = 1;
5a5012ec
TS
7382 break;
7383 default:
923617a3 7384 MIPS_INVAL(opn);
5a5012ec 7385 generate_exception(ctx, EXCP_RI);
6c5c1e20
TS
7386 tcg_temp_free(t0);
7387 tcg_temp_free(t1);
5a5012ec
TS
7388 return;
7389 }
6c5c1e20
TS
7390 tcg_temp_free(t0);
7391 tcg_temp_free(t1);
93b12ccc
TS
7392 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7393 regnames[index], regnames[base]);
5a5012ec
TS
7394}
7395
5e755519
TS
7396static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7397 int fd, int fr, int fs, int ft)
5a5012ec 7398{
923617a3 7399 const char *opn = "flt3_arith";
5a5012ec 7400
5a5012ec
TS
7401 switch (opc) {
7402 case OPC_ALNV_PS:
b8aa4598 7403 check_cp1_64bitmode(ctx);
a16336e4 7404 {
6c5c1e20 7405 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
b6d96bed
TS
7406 TCGv fp0 = tcg_temp_local_new(TCG_TYPE_I32);
7407 TCGv fph0 = tcg_temp_local_new(TCG_TYPE_I32);
7408 TCGv fp1 = tcg_temp_local_new(TCG_TYPE_I32);
7409 TCGv fph1 = tcg_temp_local_new(TCG_TYPE_I32);
a16336e4
TS
7410 int l1 = gen_new_label();
7411 int l2 = gen_new_label();
7412
6c5c1e20
TS
7413 gen_load_gpr(t0, fr);
7414 tcg_gen_andi_tl(t0, t0, 0x7);
b6d96bed
TS
7415 gen_load_fpr32(fp0, fs);
7416 gen_load_fpr32h(fph0, fs);
7417 gen_load_fpr32(fp1, ft);
7418 gen_load_fpr32h(fph1, ft);
6c5c1e20
TS
7419
7420 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
b6d96bed
TS
7421 gen_store_fpr32(fp0, fd);
7422 gen_store_fpr32h(fph0, fd);
a16336e4
TS
7423 tcg_gen_br(l2);
7424 gen_set_label(l1);
6c5c1e20
TS
7425 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7426 tcg_temp_free(t0);
a16336e4 7427#ifdef TARGET_WORDS_BIGENDIAN
b6d96bed
TS
7428 gen_store_fpr32(fph1, fd);
7429 gen_store_fpr32h(fp0, fd);
a16336e4 7430#else
b6d96bed
TS
7431 gen_store_fpr32(fph0, fd);
7432 gen_store_fpr32h(fp1, fd);
a16336e4
TS
7433#endif
7434 gen_set_label(l2);
b6d96bed
TS
7435 tcg_temp_free(fp0);
7436 tcg_temp_free(fph0);
7437 tcg_temp_free(fp1);
7438 tcg_temp_free(fph1);
a16336e4 7439 }
5a5012ec
TS
7440 opn = "alnv.ps";
7441 break;
7442 case OPC_MADD_S:
b8aa4598 7443 check_cop1x(ctx);
b6d96bed
TS
7444 {
7445 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7446 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7447 TCGv fp2 = tcg_temp_new(TCG_TYPE_I32);
7448
7449 gen_load_fpr32(fp0, fs);
7450 gen_load_fpr32(fp1, ft);
7451 gen_load_fpr32(fp2, fr);
7452 tcg_gen_helper_1_3(do_float_muladd_s, fp2, fp0, fp1, fp2);
7453 tcg_temp_free(fp0);
7454 tcg_temp_free(fp1);
7455 gen_store_fpr32(fp2, fd);
7456 tcg_temp_free(fp2);
7457 }
5a5012ec
TS
7458 opn = "madd.s";
7459 break;
7460 case OPC_MADD_D:
b8aa4598
TS
7461 check_cop1x(ctx);
7462 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed
TS
7463 {
7464 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7465 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7466 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7467
7468 gen_load_fpr64(ctx, fp0, fs);
7469 gen_load_fpr64(ctx, fp1, ft);
7470 gen_load_fpr64(ctx, fp2, fr);
7471 tcg_gen_helper_1_3(do_float_muladd_d, fp2, fp0, fp1, fp2);
7472 tcg_temp_free(fp0);
7473 tcg_temp_free(fp1);
7474 gen_store_fpr64(ctx, fp2, fd);
7475 tcg_temp_free(fp2);
7476 }
5a5012ec
TS
7477 opn = "madd.d";
7478 break;
7479 case OPC_MADD_PS:
b8aa4598 7480 check_cp1_64bitmode(ctx);
b6d96bed
TS
7481 {
7482 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7483 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7484 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7485
7486 gen_load_fpr64(ctx, fp0, fs);
7487 gen_load_fpr64(ctx, fp1, ft);
7488 gen_load_fpr64(ctx, fp2, fr);
7489 tcg_gen_helper_1_3(do_float_muladd_ps, fp2, fp0, fp1, fp2);
7490 tcg_temp_free(fp0);
7491 tcg_temp_free(fp1);
7492 gen_store_fpr64(ctx, fp2, fd);
7493 tcg_temp_free(fp2);
7494 }
5a5012ec
TS
7495 opn = "madd.ps";
7496 break;
7497 case OPC_MSUB_S:
b8aa4598 7498 check_cop1x(ctx);
b6d96bed
TS
7499 {
7500 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7501 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7502 TCGv fp2 = tcg_temp_new(TCG_TYPE_I32);
7503
7504 gen_load_fpr32(fp0, fs);
7505 gen_load_fpr32(fp1, ft);
7506 gen_load_fpr32(fp2, fr);
7507 tcg_gen_helper_1_3(do_float_mulsub_s, fp2, fp0, fp1, fp2);
7508 tcg_temp_free(fp0);
7509 tcg_temp_free(fp1);
7510 gen_store_fpr32(fp2, fd);
7511 tcg_temp_free(fp2);
7512 }
5a5012ec
TS
7513 opn = "msub.s";
7514 break;
7515 case OPC_MSUB_D:
b8aa4598
TS
7516 check_cop1x(ctx);
7517 check_cp1_registers(ctx, fd | fs | ft | fr);
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_mulsub_d, 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 = "msub.d";
7533 break;
7534 case OPC_MSUB_PS:
b8aa4598 7535 check_cp1_64bitmode(ctx);
b6d96bed
TS
7536 {
7537 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7538 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7539 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7540
7541 gen_load_fpr64(ctx, fp0, fs);
7542 gen_load_fpr64(ctx, fp1, ft);
7543 gen_load_fpr64(ctx, fp2, fr);
7544 tcg_gen_helper_1_3(do_float_mulsub_ps, fp2, fp0, fp1, fp2);
7545 tcg_temp_free(fp0);
7546 tcg_temp_free(fp1);
7547 gen_store_fpr64(ctx, fp2, fd);
7548 tcg_temp_free(fp2);
7549 }
5a5012ec
TS
7550 opn = "msub.ps";
7551 break;
7552 case OPC_NMADD_S:
b8aa4598 7553 check_cop1x(ctx);
b6d96bed
TS
7554 {
7555 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7556 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7557 TCGv fp2 = tcg_temp_new(TCG_TYPE_I32);
7558
7559 gen_load_fpr32(fp0, fs);
7560 gen_load_fpr32(fp1, ft);
7561 gen_load_fpr32(fp2, fr);
7562 tcg_gen_helper_1_3(do_float_nmuladd_s, fp2, fp0, fp1, fp2);
7563 tcg_temp_free(fp0);
7564 tcg_temp_free(fp1);
7565 gen_store_fpr32(fp2, fd);
7566 tcg_temp_free(fp2);
7567 }
5a5012ec
TS
7568 opn = "nmadd.s";
7569 break;
7570 case OPC_NMADD_D:
b8aa4598
TS
7571 check_cop1x(ctx);
7572 check_cp1_registers(ctx, fd | fs | ft | fr);
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_nmuladd_d, 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 = "nmadd.d";
7588 break;
7589 case OPC_NMADD_PS:
b8aa4598 7590 check_cp1_64bitmode(ctx);
b6d96bed
TS
7591 {
7592 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7593 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7594 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7595
7596 gen_load_fpr64(ctx, fp0, fs);
7597 gen_load_fpr64(ctx, fp1, ft);
7598 gen_load_fpr64(ctx, fp2, fr);
7599 tcg_gen_helper_1_3(do_float_nmuladd_ps, fp2, fp0, fp1, fp2);
7600 tcg_temp_free(fp0);
7601 tcg_temp_free(fp1);
7602 gen_store_fpr64(ctx, fp2, fd);
7603 tcg_temp_free(fp2);
7604 }
5a5012ec
TS
7605 opn = "nmadd.ps";
7606 break;
7607 case OPC_NMSUB_S:
b8aa4598 7608 check_cop1x(ctx);
b6d96bed
TS
7609 {
7610 TCGv fp0 = tcg_temp_new(TCG_TYPE_I32);
7611 TCGv fp1 = tcg_temp_new(TCG_TYPE_I32);
7612 TCGv fp2 = tcg_temp_new(TCG_TYPE_I32);
7613
7614 gen_load_fpr32(fp0, fs);
7615 gen_load_fpr32(fp1, ft);
7616 gen_load_fpr32(fp2, fr);
7617 tcg_gen_helper_1_3(do_float_nmulsub_s, fp2, fp0, fp1, fp2);
7618 tcg_temp_free(fp0);
7619 tcg_temp_free(fp1);
7620 gen_store_fpr32(fp2, fd);
7621 tcg_temp_free(fp2);
7622 }
5a5012ec
TS
7623 opn = "nmsub.s";
7624 break;
7625 case OPC_NMSUB_D:
b8aa4598
TS
7626 check_cop1x(ctx);
7627 check_cp1_registers(ctx, fd | fs | ft | fr);
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_nmulsub_d, 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 = "nmsub.d";
7643 break;
7644 case OPC_NMSUB_PS:
b8aa4598 7645 check_cp1_64bitmode(ctx);
b6d96bed
TS
7646 {
7647 TCGv fp0 = tcg_temp_new(TCG_TYPE_I64);
7648 TCGv fp1 = tcg_temp_new(TCG_TYPE_I64);
7649 TCGv fp2 = tcg_temp_new(TCG_TYPE_I64);
7650
7651 gen_load_fpr64(ctx, fp0, fs);
7652 gen_load_fpr64(ctx, fp1, ft);
7653 gen_load_fpr64(ctx, fp2, fr);
7654 tcg_gen_helper_1_3(do_float_nmulsub_ps, fp2, fp0, fp1, fp2);
7655 tcg_temp_free(fp0);
7656 tcg_temp_free(fp1);
7657 gen_store_fpr64(ctx, fp2, fd);
7658 tcg_temp_free(fp2);
7659 }
5a5012ec
TS
7660 opn = "nmsub.ps";
7661 break;
923617a3
TS
7662 default:
7663 MIPS_INVAL(opn);
5a5012ec
TS
7664 generate_exception (ctx, EXCP_RI);
7665 return;
7666 }
7667 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
7668 fregnames[fs], fregnames[ft]);
7a387fff
TS
7669}
7670
7671/* ISA extensions (ASEs) */
6af0bf9c
FB
7672/* MIPS16 extension to MIPS32 */
7673/* SmartMIPS extension to MIPS32 */
7674
d26bc211 7675#if defined(TARGET_MIPS64)
6af0bf9c
FB
7676
7677/* MDMX extension to MIPS64 */
6af0bf9c
FB
7678
7679#endif
7680
36d23958 7681static void decode_opc (CPUState *env, DisasContext *ctx)
6af0bf9c
FB
7682{
7683 int32_t offset;
7684 int rs, rt, rd, sa;
7a387fff 7685 uint32_t op, op1, op2;
6af0bf9c
FB
7686 int16_t imm;
7687
d796321b
FB
7688 /* make sure instructions are on a word boundary */
7689 if (ctx->pc & 0x3) {
cbeb0857 7690 env->CP0_BadVAddr = ctx->pc;
d796321b
FB
7691 generate_exception(ctx, EXCP_AdEL);
7692 return;
7693 }
7694
8e9ade68 7695 /* Handle blikely not taken case */
4ad40f36 7696 if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
8e9ade68
TS
7697 int l1 = gen_new_label();
7698
3594c774 7699 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
d077b6f7 7700 tcg_gen_brcondi_i32(TCG_COND_NE, bcond, 0, l1);
08ba7963 7701 {
d077b6f7 7702 TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
08ba7963 7703
d077b6f7
TS
7704 tcg_gen_movi_i32(r_tmp, ctx->hflags & ~MIPS_HFLAG_BMASK);
7705 tcg_gen_st_i32(r_tmp, cpu_env, offsetof(CPUState, hflags));
7706 tcg_temp_free(r_tmp);
08ba7963 7707 }
5a5012ec
TS
7708 gen_goto_tb(ctx, 1, ctx->pc + 4);
7709 gen_set_label(l1);
6af0bf9c 7710 }
7a387fff
TS
7711 op = MASK_OP_MAJOR(ctx->opcode);
7712 rs = (ctx->opcode >> 21) & 0x1f;
7713 rt = (ctx->opcode >> 16) & 0x1f;
7714 rd = (ctx->opcode >> 11) & 0x1f;
7715 sa = (ctx->opcode >> 6) & 0x1f;
6af0bf9c
FB
7716 imm = (int16_t)ctx->opcode;
7717 switch (op) {
7a387fff
TS
7718 case OPC_SPECIAL:
7719 op1 = MASK_SPECIAL(ctx->opcode);
6af0bf9c 7720 switch (op1) {
7a387fff
TS
7721 case OPC_SLL: /* Arithmetic with immediate */
7722 case OPC_SRL ... OPC_SRA:
e189e748 7723 gen_arith_imm(env, ctx, op1, rd, rt, sa);
7a387fff 7724 break;
e189e748
TS
7725 case OPC_MOVZ ... OPC_MOVN:
7726 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7a387fff
TS
7727 case OPC_SLLV: /* Arithmetic */
7728 case OPC_SRLV ... OPC_SRAV:
7a387fff
TS
7729 case OPC_ADD ... OPC_NOR:
7730 case OPC_SLT ... OPC_SLTU:
e189e748 7731 gen_arith(env, ctx, op1, rd, rs, rt);
7a387fff
TS
7732 break;
7733 case OPC_MULT ... OPC_DIVU:
e9c71dd1
TS
7734 if (sa) {
7735 check_insn(env, ctx, INSN_VR54XX);
7736 op1 = MASK_MUL_VR54XX(ctx->opcode);
7737 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
7738 } else
7739 gen_muldiv(ctx, op1, rs, rt);
7a387fff
TS
7740 break;
7741 case OPC_JR ... OPC_JALR:
7742 gen_compute_branch(ctx, op1, rs, rd, sa);
6af0bf9c 7743 return;
7a387fff
TS
7744 case OPC_TGE ... OPC_TEQ: /* Traps */
7745 case OPC_TNE:
7746 gen_trap(ctx, op1, rs, rt, -1);
6af0bf9c 7747 break;
7a387fff
TS
7748 case OPC_MFHI: /* Move from HI/LO */
7749 case OPC_MFLO:
7750 gen_HILO(ctx, op1, rd);
6af0bf9c 7751 break;
7a387fff
TS
7752 case OPC_MTHI:
7753 case OPC_MTLO: /* Move to HI/LO */
7754 gen_HILO(ctx, op1, rs);
6af0bf9c 7755 break;
b48cfdff
TS
7756 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
7757#ifdef MIPS_STRICT_STANDARD
7758 MIPS_INVAL("PMON / selsl");
7759 generate_exception(ctx, EXCP_RI);
7760#else
be24bb4f 7761 tcg_gen_helper_0_i(do_pmon, sa);
b48cfdff 7762#endif
7a387fff
TS
7763 break;
7764 case OPC_SYSCALL:
6af0bf9c
FB
7765 generate_exception(ctx, EXCP_SYSCALL);
7766 break;
7a387fff 7767 case OPC_BREAK:
6af0bf9c
FB
7768 generate_exception(ctx, EXCP_BREAK);
7769 break;
b48cfdff
TS
7770 case OPC_SPIM:
7771#ifdef MIPS_STRICT_STANDARD
7772 MIPS_INVAL("SPIM");
7773 generate_exception(ctx, EXCP_RI);
7774#else
7a387fff
TS
7775 /* Implemented as RI exception for now. */
7776 MIPS_INVAL("spim (unofficial)");
7777 generate_exception(ctx, EXCP_RI);
b48cfdff 7778#endif
6af0bf9c 7779 break;
7a387fff 7780 case OPC_SYNC:
ead9360e 7781 /* Treat as NOP. */
6af0bf9c 7782 break;
4ad40f36 7783
7a387fff 7784 case OPC_MOVCI:
e189e748 7785 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
36d23958 7786 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
e397ee33 7787 save_cpu_state(ctx, 1);
5e755519 7788 check_cp1_enabled(ctx);
36d23958
TS
7789 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
7790 (ctx->opcode >> 16) & 1);
7791 } else {
e397ee33 7792 generate_exception_err(ctx, EXCP_CpU, 1);
36d23958 7793 }
4ad40f36
FB
7794 break;
7795
d26bc211 7796#if defined(TARGET_MIPS64)
7a387fff
TS
7797 /* MIPS64 specific opcodes */
7798 case OPC_DSLL:
7799 case OPC_DSRL ... OPC_DSRA:
7800 case OPC_DSLL32:
7801 case OPC_DSRL32 ... OPC_DSRA32:
e189e748
TS
7802 check_insn(env, ctx, ISA_MIPS3);
7803 check_mips_64(ctx);
7804 gen_arith_imm(env, ctx, op1, rd, rt, sa);
7a387fff
TS
7805 break;
7806 case OPC_DSLLV:
7807 case OPC_DSRLV ... OPC_DSRAV:
7808 case OPC_DADD ... OPC_DSUBU:
e189e748
TS
7809 check_insn(env, ctx, ISA_MIPS3);
7810 check_mips_64(ctx);
7811 gen_arith(env, ctx, op1, rd, rs, rt);
7a387fff
TS
7812 break;
7813 case OPC_DMULT ... OPC_DDIVU:
e189e748
TS
7814 check_insn(env, ctx, ISA_MIPS3);
7815 check_mips_64(ctx);
7a387fff
TS
7816 gen_muldiv(ctx, op1, rs, rt);
7817 break;
6af0bf9c
FB
7818#endif
7819 default: /* Invalid */
7820 MIPS_INVAL("special");
7821 generate_exception(ctx, EXCP_RI);
7822 break;
7823 }
7824 break;
7a387fff
TS
7825 case OPC_SPECIAL2:
7826 op1 = MASK_SPECIAL2(ctx->opcode);
6af0bf9c 7827 switch (op1) {
7a387fff
TS
7828 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
7829 case OPC_MSUB ... OPC_MSUBU:
e189e748 7830 check_insn(env, ctx, ISA_MIPS32);
7a387fff 7831 gen_muldiv(ctx, op1, rs, rt);
6af0bf9c 7832 break;
7a387fff 7833 case OPC_MUL:
e189e748 7834 gen_arith(env, ctx, op1, rd, rs, rt);
6af0bf9c 7835 break;
7a387fff 7836 case OPC_CLZ ... OPC_CLO:
e189e748 7837 check_insn(env, ctx, ISA_MIPS32);
7a387fff 7838 gen_cl(ctx, op1, rd, rs);
6af0bf9c 7839 break;
7a387fff 7840 case OPC_SDBBP:
6af0bf9c
FB
7841 /* XXX: not clear which exception should be raised
7842 * when in debug mode...
7843 */
e189e748 7844 check_insn(env, ctx, ISA_MIPS32);
6af0bf9c
FB
7845 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
7846 generate_exception(ctx, EXCP_DBp);
7847 } else {
7848 generate_exception(ctx, EXCP_DBp);
7849 }
ead9360e 7850 /* Treat as NOP. */
6af0bf9c 7851 break;
d26bc211 7852#if defined(TARGET_MIPS64)
7a387fff 7853 case OPC_DCLZ ... OPC_DCLO:
e189e748
TS
7854 check_insn(env, ctx, ISA_MIPS64);
7855 check_mips_64(ctx);
7a387fff
TS
7856 gen_cl(ctx, op1, rd, rs);
7857 break;
7858#endif
6af0bf9c
FB
7859 default: /* Invalid */
7860 MIPS_INVAL("special2");
7861 generate_exception(ctx, EXCP_RI);
7862 break;
7863 }
7864 break;
7a387fff 7865 case OPC_SPECIAL3:
2b0233ab
TS
7866 op1 = MASK_SPECIAL3(ctx->opcode);
7867 switch (op1) {
7868 case OPC_EXT:
7869 case OPC_INS:
7870 check_insn(env, ctx, ISA_MIPS32R2);
7871 gen_bitops(ctx, op1, rt, rs, sa, rd);
7872 break;
7873 case OPC_BSHFL:
7874 check_insn(env, ctx, ISA_MIPS32R2);
7875 op2 = MASK_BSHFL(ctx->opcode);
49bcf33c 7876 gen_bshfl(ctx, op2, rt, rd);
7a387fff 7877 break;
1579a72e 7878 case OPC_RDHWR:
e189e748 7879 check_insn(env, ctx, ISA_MIPS32R2);
6c5c1e20
TS
7880 {
7881 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
7882
7883 switch (rd) {
7884 case 0:
7885 save_cpu_state(ctx, 1);
2796188e 7886 tcg_gen_helper_1_0(do_rdhwr_cpunum, t0);
6c5c1e20
TS
7887 break;
7888 case 1:
7889 save_cpu_state(ctx, 1);
2796188e 7890 tcg_gen_helper_1_0(do_rdhwr_synci_step, t0);
6c5c1e20
TS
7891 break;
7892 case 2:
7893 save_cpu_state(ctx, 1);
2796188e 7894 tcg_gen_helper_1_0(do_rdhwr_cc, t0);
6c5c1e20
TS
7895 break;
7896 case 3:
7897 save_cpu_state(ctx, 1);
2796188e 7898 tcg_gen_helper_1_0(do_rdhwr_ccres, t0);
6c5c1e20
TS
7899 break;
7900 case 29:
0eaef5aa
TS
7901 if (env->user_mode_only) {
7902 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
7903 break;
7904 } else {
7905 /* XXX: Some CPUs implement this in hardware.
7906 Not supported yet. */
7907 }
6c5c1e20
TS
7908 default: /* Invalid */
7909 MIPS_INVAL("rdhwr");
7910 generate_exception(ctx, EXCP_RI);
7911 break;
7912 }
7913 gen_store_gpr(t0, rt);
7914 tcg_temp_free(t0);
1579a72e 7915 }
1579a72e 7916 break;
ead9360e 7917 case OPC_FORK:
7385ac0b 7918 check_insn(env, ctx, ASE_MT);
6c5c1e20
TS
7919 {
7920 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
7921 TCGv t1 = tcg_temp_local_new(TCG_TYPE_TL);
7922
7923 gen_load_gpr(t0, rt);
7924 gen_load_gpr(t1, rs);
7925 tcg_gen_helper_0_2(do_fork, t0, t1);
7926 tcg_temp_free(t0);
7927 tcg_temp_free(t1);
7928 }
ead9360e
TS
7929 break;
7930 case OPC_YIELD:
7385ac0b 7931 check_insn(env, ctx, ASE_MT);
6c5c1e20
TS
7932 {
7933 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
7934
7935 gen_load_gpr(t0, rs);
7936 tcg_gen_helper_1_1(do_yield, t0, t0);
7937 gen_store_gpr(t0, rd);
7938 tcg_temp_free(t0);
7939 }
ead9360e 7940 break;
d26bc211 7941#if defined(TARGET_MIPS64)
1579a72e
TS
7942 case OPC_DEXTM ... OPC_DEXT:
7943 case OPC_DINSM ... OPC_DINS:
e189e748
TS
7944 check_insn(env, ctx, ISA_MIPS64R2);
7945 check_mips_64(ctx);
1579a72e 7946 gen_bitops(ctx, op1, rt, rs, sa, rd);
7a387fff 7947 break;
1579a72e 7948 case OPC_DBSHFL:
e189e748
TS
7949 check_insn(env, ctx, ISA_MIPS64R2);
7950 check_mips_64(ctx);
1579a72e 7951 op2 = MASK_DBSHFL(ctx->opcode);
49bcf33c 7952 gen_bshfl(ctx, op2, rt, rd);
c6d6dd7c 7953 break;
7a387fff
TS
7954#endif
7955 default: /* Invalid */
7956 MIPS_INVAL("special3");
7957 generate_exception(ctx, EXCP_RI);
7958 break;
7959 }
7960 break;
7961 case OPC_REGIMM:
7962 op1 = MASK_REGIMM(ctx->opcode);
7963 switch (op1) {
7964 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
7965 case OPC_BLTZAL ... OPC_BGEZALL:
7966 gen_compute_branch(ctx, op1, rs, -1, imm << 2);
6af0bf9c 7967 return;
7a387fff
TS
7968 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
7969 case OPC_TNEI:
7970 gen_trap(ctx, op1, rs, -1, imm);
7971 break;
7972 case OPC_SYNCI:
e189e748 7973 check_insn(env, ctx, ISA_MIPS32R2);
ead9360e 7974 /* Treat as NOP. */
6af0bf9c
FB
7975 break;
7976 default: /* Invalid */
923617a3 7977 MIPS_INVAL("regimm");
6af0bf9c
FB
7978 generate_exception(ctx, EXCP_RI);
7979 break;
7980 }
7981 break;
7a387fff 7982 case OPC_CP0:
387a8fe5 7983 check_cp0_enabled(ctx);
7a387fff 7984 op1 = MASK_CP0(ctx->opcode);
6af0bf9c 7985 switch (op1) {
7a387fff
TS
7986 case OPC_MFC0:
7987 case OPC_MTC0:
ead9360e
TS
7988 case OPC_MFTR:
7989 case OPC_MTTR:
d26bc211 7990#if defined(TARGET_MIPS64)
7a387fff
TS
7991 case OPC_DMFC0:
7992 case OPC_DMTC0:
7993#endif
f1aa6320 7994#ifndef CONFIG_USER_ONLY
0eaef5aa
TS
7995 if (!env->user_mode_only)
7996 gen_cp0(env, ctx, op1, rt, rd);
7997#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
7998 break;
7999 case OPC_C0_FIRST ... OPC_C0_LAST:
f1aa6320 8000#ifndef CONFIG_USER_ONLY
0eaef5aa
TS
8001 if (!env->user_mode_only)
8002 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
8003#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
8004 break;
8005 case OPC_MFMC0:
8706c382 8006#ifndef CONFIG_USER_ONLY
0eaef5aa 8007 if (!env->user_mode_only) {
6c5c1e20
TS
8008 TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL);
8009
0eaef5aa 8010 op2 = MASK_MFMC0(ctx->opcode);
6c5c1e20
TS
8011 switch (op2) {
8012 case OPC_DMT:
8013 check_insn(env, ctx, ASE_MT);
8014 tcg_gen_helper_1_1(do_dmt, t0, t0);
8015 break;
8016 case OPC_EMT:
8017 check_insn(env, ctx, ASE_MT);
8018 tcg_gen_helper_1_1(do_emt, t0, t0);
da80682b 8019 break;
6c5c1e20
TS
8020 case OPC_DVPE:
8021 check_insn(env, ctx, ASE_MT);
8022 tcg_gen_helper_1_1(do_dvpe, t0, t0);
8023 break;
8024 case OPC_EVPE:
8025 check_insn(env, ctx, ASE_MT);
8026 tcg_gen_helper_1_1(do_evpe, t0, t0);
8027 break;
8028 case OPC_DI:
8029 check_insn(env, ctx, ISA_MIPS32R2);
8030 save_cpu_state(ctx, 1);
2796188e 8031 tcg_gen_helper_1_0(do_di, t0);
6c5c1e20
TS
8032 /* Stop translation as we may have switched the execution mode */
8033 ctx->bstate = BS_STOP;
8034 break;
8035 case OPC_EI:
8036 check_insn(env, ctx, ISA_MIPS32R2);
8037 save_cpu_state(ctx, 1);
2796188e 8038 tcg_gen_helper_1_0(do_ei, t0);
6c5c1e20
TS
8039 /* Stop translation as we may have switched the execution mode */
8040 ctx->bstate = BS_STOP;
8041 break;
8042 default: /* Invalid */
8043 MIPS_INVAL("mfmc0");
8044 generate_exception(ctx, EXCP_RI);
8045 break;
8046 }
8047 gen_store_gpr(t0, rt);
8048 tcg_temp_free(t0);
7a387fff 8049 }
0eaef5aa 8050#endif /* !CONFIG_USER_ONLY */
6af0bf9c 8051 break;
7a387fff 8052 case OPC_RDPGPR:
e189e748 8053 check_insn(env, ctx, ISA_MIPS32R2);
be24bb4f 8054 gen_load_srsgpr(rt, rd);
ead9360e 8055 break;
7a387fff 8056 case OPC_WRPGPR:
e189e748 8057 check_insn(env, ctx, ISA_MIPS32R2);
be24bb4f 8058 gen_store_srsgpr(rt, rd);
38121543 8059 break;
6af0bf9c 8060 default:
923617a3 8061 MIPS_INVAL("cp0");
7a387fff 8062 generate_exception(ctx, EXCP_RI);
6af0bf9c
FB
8063 break;
8064 }
8065 break;
7a387fff 8066 case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
e189e748 8067 gen_arith_imm(env, ctx, op, rt, rs, imm);
7a387fff
TS
8068 break;
8069 case OPC_J ... OPC_JAL: /* Jump */
8070 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
8071 gen_compute_branch(ctx, op, rs, rt, offset);
8072 return;
8073 case OPC_BEQ ... OPC_BGTZ: /* Branch */
8074 case OPC_BEQL ... OPC_BGTZL:
8075 gen_compute_branch(ctx, op, rs, rt, imm << 2);
8076 return;
8077 case OPC_LB ... OPC_LWR: /* Load and stores */
8078 case OPC_SB ... OPC_SW:
8079 case OPC_SWR:
8080 case OPC_LL:
8081 case OPC_SC:
8082 gen_ldst(ctx, op, rt, rs, imm);
8083 break;
8084 case OPC_CACHE:
e189e748 8085 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
ead9360e 8086 /* Treat as NOP. */
34ae7b51 8087 break;
7a387fff 8088 case OPC_PREF:
e189e748 8089 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
ead9360e 8090 /* Treat as NOP. */
6af0bf9c 8091 break;
4ad40f36 8092
923617a3 8093 /* Floating point (COP1). */
7a387fff
TS
8094 case OPC_LWC1:
8095 case OPC_LDC1:
8096 case OPC_SWC1:
8097 case OPC_SDC1:
36d23958
TS
8098 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8099 save_cpu_state(ctx, 1);
5e755519 8100 check_cp1_enabled(ctx);
36d23958
TS
8101 gen_flt_ldst(ctx, op, rt, rs, imm);
8102 } else {
8103 generate_exception_err(ctx, EXCP_CpU, 1);
8104 }
6ea83fed
FB
8105 break;
8106
7a387fff 8107 case OPC_CP1:
36d23958
TS
8108 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
8109 save_cpu_state(ctx, 1);
5e755519 8110 check_cp1_enabled(ctx);
36d23958
TS
8111 op1 = MASK_CP1(ctx->opcode);
8112 switch (op1) {
3a95e3a7
TS
8113 case OPC_MFHC1:
8114 case OPC_MTHC1:
e189e748 8115 check_insn(env, ctx, ISA_MIPS32R2);
36d23958
TS
8116 case OPC_MFC1:
8117 case OPC_CFC1:
8118 case OPC_MTC1:
8119 case OPC_CTC1:
e189e748
TS
8120 gen_cp1(ctx, op1, rt, rd);
8121 break;
d26bc211 8122#if defined(TARGET_MIPS64)
36d23958
TS
8123 case OPC_DMFC1:
8124 case OPC_DMTC1:
e189e748 8125 check_insn(env, ctx, ISA_MIPS3);
36d23958
TS
8126 gen_cp1(ctx, op1, rt, rd);
8127 break;
e189e748 8128#endif
fbcc6828
TS
8129 case OPC_BC1ANY2:
8130 case OPC_BC1ANY4:
b8aa4598 8131 check_cop1x(ctx);
7385ac0b 8132 check_insn(env, ctx, ASE_MIPS3D);
d8a5950a
TS
8133 /* fall through */
8134 case OPC_BC1:
e189e748 8135 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
5a5012ec 8136 (rt >> 2) & 0x7, imm << 2);
36d23958
TS
8137 return;
8138 case OPC_S_FMT:
8139 case OPC_D_FMT:
8140 case OPC_W_FMT:
8141 case OPC_L_FMT:
5a5012ec
TS
8142 case OPC_PS_FMT:
8143 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
8144 (imm >> 8) & 0x7);
36d23958
TS
8145 break;
8146 default:
923617a3 8147 MIPS_INVAL("cp1");
e397ee33 8148 generate_exception (ctx, EXCP_RI);
36d23958
TS
8149 break;
8150 }
8151 } else {
8152 generate_exception_err(ctx, EXCP_CpU, 1);
6ea83fed 8153 }
4ad40f36
FB
8154 break;
8155
8156 /* COP2. */
7a387fff
TS
8157 case OPC_LWC2:
8158 case OPC_LDC2:
8159 case OPC_SWC2:
8160 case OPC_SDC2:
8161 case OPC_CP2:
8162 /* COP2: Not implemented. */
4ad40f36
FB
8163 generate_exception_err(ctx, EXCP_CpU, 2);
8164 break;
8165
7a387fff 8166 case OPC_CP3:
36d23958 8167 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
e397ee33 8168 save_cpu_state(ctx, 1);
5e755519 8169 check_cp1_enabled(ctx);
36d23958
TS
8170 op1 = MASK_CP3(ctx->opcode);
8171 switch (op1) {
5a5012ec
TS
8172 case OPC_LWXC1:
8173 case OPC_LDXC1:
8174 case OPC_LUXC1:
8175 case OPC_SWXC1:
8176 case OPC_SDXC1:
8177 case OPC_SUXC1:
93b12ccc 8178 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
5a5012ec 8179 break;
e0c84da7 8180 case OPC_PREFX:
ead9360e 8181 /* Treat as NOP. */
e0c84da7 8182 break;
5a5012ec
TS
8183 case OPC_ALNV_PS:
8184 case OPC_MADD_S:
8185 case OPC_MADD_D:
8186 case OPC_MADD_PS:
8187 case OPC_MSUB_S:
8188 case OPC_MSUB_D:
8189 case OPC_MSUB_PS:
8190 case OPC_NMADD_S:
8191 case OPC_NMADD_D:
8192 case OPC_NMADD_PS:
8193 case OPC_NMSUB_S:
8194 case OPC_NMSUB_D:
8195 case OPC_NMSUB_PS:
8196 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
8197 break;
36d23958 8198 default:
923617a3 8199 MIPS_INVAL("cp3");
e397ee33 8200 generate_exception (ctx, EXCP_RI);
36d23958
TS
8201 break;
8202 }
8203 } else {
e397ee33 8204 generate_exception_err(ctx, EXCP_CpU, 1);
7a387fff 8205 }
4ad40f36
FB
8206 break;
8207
d26bc211 8208#if defined(TARGET_MIPS64)
7a387fff
TS
8209 /* MIPS64 opcodes */
8210 case OPC_LWU:
8211 case OPC_LDL ... OPC_LDR:
8212 case OPC_SDL ... OPC_SDR:
8213 case OPC_LLD:
8214 case OPC_LD:
8215 case OPC_SCD:
8216 case OPC_SD:
e189e748
TS
8217 check_insn(env, ctx, ISA_MIPS3);
8218 check_mips_64(ctx);
7a387fff
TS
8219 gen_ldst(ctx, op, rt, rs, imm);
8220 break;
8221 case OPC_DADDI ... OPC_DADDIU:
e189e748
TS
8222 check_insn(env, ctx, ISA_MIPS3);
8223 check_mips_64(ctx);
8224 gen_arith_imm(env, ctx, op, rt, rs, imm);
7a387fff 8225 break;
6af0bf9c 8226#endif
7a387fff 8227 case OPC_JALX:
e189e748 8228 check_insn(env, ctx, ASE_MIPS16);
7a387fff 8229 /* MIPS16: Not implemented. */
7a387fff 8230 case OPC_MDMX:
e189e748 8231 check_insn(env, ctx, ASE_MDMX);
7a387fff 8232 /* MDMX: Not implemented. */
6af0bf9c 8233 default: /* Invalid */
923617a3 8234 MIPS_INVAL("major opcode");
6af0bf9c
FB
8235 generate_exception(ctx, EXCP_RI);
8236 break;
8237 }
4ad40f36 8238 if (ctx->hflags & MIPS_HFLAG_BMASK) {
c53f4a62 8239 int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
6af0bf9c 8240 /* Branches completion */
4ad40f36 8241 ctx->hflags &= ~MIPS_HFLAG_BMASK;
6af0bf9c
FB
8242 ctx->bstate = BS_BRANCH;
8243 save_cpu_state(ctx, 0);
2e70f6ef 8244 /* FIXME: Need to clear can_do_io. */
5a5012ec 8245 switch (hflags) {
6af0bf9c
FB
8246 case MIPS_HFLAG_B:
8247 /* unconditional branch */
8248 MIPS_DEBUG("unconditional branch");
6e256c93 8249 gen_goto_tb(ctx, 0, ctx->btarget);
6af0bf9c
FB
8250 break;
8251 case MIPS_HFLAG_BL:
8252 /* blikely taken case */
8253 MIPS_DEBUG("blikely branch taken");
6e256c93 8254 gen_goto_tb(ctx, 0, ctx->btarget);
6af0bf9c
FB
8255 break;
8256 case MIPS_HFLAG_BC:
8257 /* Conditional branch */
8258 MIPS_DEBUG("conditional branch");
c53be334 8259 {
8e9ade68
TS
8260 int l1 = gen_new_label();
8261
d077b6f7 8262 tcg_gen_brcondi_i32(TCG_COND_NE, bcond, 0, l1);
8e9ade68
TS
8263 gen_goto_tb(ctx, 1, ctx->pc + 4);
8264 gen_set_label(l1);
8265 gen_goto_tb(ctx, 0, ctx->btarget);
c53be334 8266 }
6af0bf9c
FB
8267 break;
8268 case MIPS_HFLAG_BR:
8269 /* unconditional branch to register */
8270 MIPS_DEBUG("branch to register");
4b2eb8d2 8271 tcg_gen_mov_tl(cpu_PC, btarget);
57fec1fe 8272 tcg_gen_exit_tb(0);
6af0bf9c
FB
8273 break;
8274 default:
8275 MIPS_DEBUG("unknown branch");
8276 break;
8277 }
8278 }
8279}
8280
2cfc5f17 8281static inline void
820e00f2
TS
8282gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
8283 int search_pc)
6af0bf9c 8284{
278d0702 8285 DisasContext ctx;
6af0bf9c
FB
8286 target_ulong pc_start;
8287 uint16_t *gen_opc_end;
8288 int j, lj = -1;
2e70f6ef
PB
8289 int num_insns;
8290 int max_insns;
6af0bf9c 8291
4ad40f36 8292 if (search_pc && loglevel)
6ea83fed 8293 fprintf (logfile, "search pc %d\n", search_pc);
4ad40f36 8294
6af0bf9c 8295 pc_start = tb->pc;
faf7aaa9
TS
8296 /* Leave some spare opc slots for branch handling. */
8297 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE - 16;
6af0bf9c 8298 ctx.pc = pc_start;
4ad40f36 8299 ctx.saved_pc = -1;
6af0bf9c
FB
8300 ctx.tb = tb;
8301 ctx.bstate = BS_NONE;
4ad40f36 8302 /* Restore delay slot state from the tb context. */
c068688b 8303 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
fd4a04eb 8304 restore_cpu_state(env, &ctx);
0eaef5aa
TS
8305 if (env->user_mode_only)
8306 ctx.mem_idx = MIPS_HFLAG_UM;
8307 else
8308 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
2e70f6ef
PB
8309 num_insns = 0;
8310 max_insns = tb->cflags & CF_COUNT_MASK;
8311 if (max_insns == 0)
8312 max_insns = CF_COUNT_MASK;
6af0bf9c
FB
8313#ifdef DEBUG_DISAS
8314 if (loglevel & CPU_LOG_TB_CPU) {
8315 fprintf(logfile, "------------------------------------------------\n");
4ad40f36 8316 /* FIXME: This may print out stale hflags from env... */
6af0bf9c
FB
8317 cpu_dump_state(env, logfile, fprintf, 0);
8318 }
8319#endif
923617a3 8320#ifdef MIPS_DEBUG_DISAS
6af0bf9c 8321 if (loglevel & CPU_LOG_TB_IN_ASM)
623a930e 8322 fprintf(logfile, "\ntb %p idx %d hflags %04x\n",
4ad40f36 8323 tb, ctx.mem_idx, ctx.hflags);
6af0bf9c 8324#endif
2e70f6ef 8325 gen_icount_start();
faf7aaa9 8326 while (ctx.bstate == BS_NONE) {
4ad40f36
FB
8327 if (env->nb_breakpoints > 0) {
8328 for(j = 0; j < env->nb_breakpoints; j++) {
8329 if (env->breakpoints[j] == ctx.pc) {
278d0702 8330 save_cpu_state(&ctx, 1);
4ad40f36 8331 ctx.bstate = BS_BRANCH;
be24bb4f 8332 tcg_gen_helper_0_i(do_raise_exception, EXCP_DEBUG);
ce62e5ba
TS
8333 /* Include the breakpoint location or the tb won't
8334 * be flushed when it must be. */
8335 ctx.pc += 4;
4ad40f36
FB
8336 goto done_generating;
8337 }
8338 }
8339 }
8340
6af0bf9c
FB
8341 if (search_pc) {
8342 j = gen_opc_ptr - gen_opc_buf;
6af0bf9c
FB
8343 if (lj < j) {
8344 lj++;
8345 while (lj < j)
8346 gen_opc_instr_start[lj++] = 0;
6af0bf9c 8347 }
4ad40f36
FB
8348 gen_opc_pc[lj] = ctx.pc;
8349 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
8350 gen_opc_instr_start[lj] = 1;
2e70f6ef 8351 gen_opc_icount[lj] = num_insns;
6af0bf9c 8352 }
2e70f6ef
PB
8353 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8354 gen_io_start();
6af0bf9c 8355 ctx.opcode = ldl_code(ctx.pc);
36d23958 8356 decode_opc(env, &ctx);
6af0bf9c 8357 ctx.pc += 4;
2e70f6ef 8358 num_insns++;
4ad40f36
FB
8359
8360 if (env->singlestep_enabled)
8361 break;
8362
6af0bf9c
FB
8363 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
8364 break;
4ad40f36 8365
faf7aaa9
TS
8366 if (gen_opc_ptr >= gen_opc_end)
8367 break;
8368
2e70f6ef
PB
8369 if (num_insns >= max_insns)
8370 break;
6af0bf9c
FB
8371#if defined (MIPS_SINGLE_STEP)
8372 break;
8373#endif
8374 }
2e70f6ef
PB
8375 if (tb->cflags & CF_LAST_IO)
8376 gen_io_end();
4ad40f36 8377 if (env->singlestep_enabled) {
278d0702 8378 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
be24bb4f 8379 tcg_gen_helper_0_i(do_raise_exception, EXCP_DEBUG);
16c00cb2
TS
8380 } else {
8381 switch (ctx.bstate) {
16c00cb2 8382 case BS_STOP:
48d38ca5 8383 tcg_gen_helper_0_0(do_interrupt_restart);
df1561e2
TS
8384 gen_goto_tb(&ctx, 0, ctx.pc);
8385 break;
16c00cb2 8386 case BS_NONE:
278d0702 8387 save_cpu_state(&ctx, 0);
16c00cb2
TS
8388 gen_goto_tb(&ctx, 0, ctx.pc);
8389 break;
5a5012ec 8390 case BS_EXCP:
48d38ca5 8391 tcg_gen_helper_0_0(do_interrupt_restart);
57fec1fe 8392 tcg_gen_exit_tb(0);
16c00cb2 8393 break;
5a5012ec
TS
8394 case BS_BRANCH:
8395 default:
8396 break;
16c00cb2 8397 }
6af0bf9c 8398 }
4ad40f36 8399done_generating:
2e70f6ef 8400 gen_icount_end(tb, num_insns);
6af0bf9c
FB
8401 *gen_opc_ptr = INDEX_op_end;
8402 if (search_pc) {
8403 j = gen_opc_ptr - gen_opc_buf;
8404 lj++;
8405 while (lj <= j)
8406 gen_opc_instr_start[lj++] = 0;
6af0bf9c
FB
8407 } else {
8408 tb->size = ctx.pc - pc_start;
2e70f6ef 8409 tb->icount = num_insns;
6af0bf9c
FB
8410 }
8411#ifdef DEBUG_DISAS
8412#if defined MIPS_DEBUG_DISAS
8413 if (loglevel & CPU_LOG_TB_IN_ASM)
8414 fprintf(logfile, "\n");
8415#endif
8416 if (loglevel & CPU_LOG_TB_IN_ASM) {
8417 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
9898128f 8418 target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
6af0bf9c
FB
8419 fprintf(logfile, "\n");
8420 }
6af0bf9c
FB
8421 if (loglevel & CPU_LOG_TB_CPU) {
8422 fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
8423 }
8424#endif
6af0bf9c
FB
8425}
8426
2cfc5f17 8427void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
6af0bf9c 8428{
2cfc5f17 8429 gen_intermediate_code_internal(env, tb, 0);
6af0bf9c
FB
8430}
8431
2cfc5f17 8432void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
6af0bf9c 8433{
2cfc5f17 8434 gen_intermediate_code_internal(env, tb, 1);
6af0bf9c
FB
8435}
8436
8706c382
TS
8437static void fpu_dump_state(CPUState *env, FILE *f,
8438 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
8439 int flags)
6ea83fed
FB
8440{
8441 int i;
5e755519 8442 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
5a5012ec
TS
8443
8444#define printfpr(fp) \
8445 do { \
8446 if (is_fpu64) \
8447 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n", \
8448 (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd, \
8449 (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
8450 else { \
8451 fpr_t tmp; \
8452 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
8453 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
8454 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n", \
8455 tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd, \
8456 tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]); \
8457 } \
6ea83fed
FB
8458 } while(0)
8459
5a5012ec
TS
8460
8461 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
f01be154
TS
8462 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
8463 get_float_exception_flags(&env->active_fpu.fp_status));
5a5012ec
TS
8464 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
8465 fpu_fprintf(f, "%3s: ", fregnames[i]);
f01be154 8466 printfpr(&env->active_fpu.fpr[i]);
6ea83fed
FB
8467 }
8468
8469#undef printfpr
8470}
8471
d26bc211 8472#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16 8473/* Debug help: The architecture requires 32bit code to maintain proper
c7e8a937 8474 sign-extended values on 64bit machines. */
c570fd16
TS
8475
8476#define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
8477
8706c382
TS
8478static void
8479cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
8480 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8481 int flags)
c570fd16
TS
8482{
8483 int i;
8484
b5dc7732
TS
8485 if (!SIGN_EXT_P(env->active_tc.PC))
8486 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
8487 if (!SIGN_EXT_P(env->active_tc.HI[0]))
8488 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
8489 if (!SIGN_EXT_P(env->active_tc.LO[0]))
8490 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
c570fd16 8491 if (!SIGN_EXT_P(env->btarget))
3594c774 8492 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
c570fd16
TS
8493
8494 for (i = 0; i < 32; i++) {
b5dc7732
TS
8495 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
8496 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
c570fd16
TS
8497 }
8498
8499 if (!SIGN_EXT_P(env->CP0_EPC))
3594c774 8500 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
c570fd16 8501 if (!SIGN_EXT_P(env->CP0_LLAddr))
3594c774 8502 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
c570fd16
TS
8503}
8504#endif
8505
5fafdf24 8506void cpu_dump_state (CPUState *env, FILE *f,
6af0bf9c
FB
8507 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8508 int flags)
8509{
8510 int i;
3b46e624 8511
3594c774 8512 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
8513 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
8514 env->hflags, env->btarget, env->bcond);
6af0bf9c
FB
8515 for (i = 0; i < 32; i++) {
8516 if ((i & 3) == 0)
8517 cpu_fprintf(f, "GPR%02d:", i);
b5dc7732 8518 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
6af0bf9c
FB
8519 if ((i & 3) == 3)
8520 cpu_fprintf(f, "\n");
8521 }
568b600d 8522
3594c774 8523 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
5e755519 8524 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
3594c774 8525 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
6af0bf9c 8526 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
5e755519 8527 if (env->hflags & MIPS_HFLAG_FPU)
7a387fff 8528 fpu_dump_state(env, f, cpu_fprintf, flags);
d26bc211 8529#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16
TS
8530 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
8531#endif
6af0bf9c
FB
8532}
8533
39454628
TS
8534static void mips_tcg_init(void)
8535{
f01be154 8536 int i;
39454628
TS
8537 static int inited;
8538
8539 /* Initialize various static tables. */
8540 if (inited)
8541 return;
8542
8543 cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
4b2eb8d2
TS
8544 for (i = 0; i < 32; i++)
8545 cpu_gpr[i] = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
8546 offsetof(CPUState, active_tc.gpr[i]),
8547 regnames[i]);
8548 cpu_PC = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
8549 offsetof(CPUState, active_tc.PC), "PC");
8550 for (i = 0; i < MIPS_DSP_ACC; i++) {
8551 cpu_HI[i] = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
8552 offsetof(CPUState, active_tc.HI[i]),
8553 regnames_HI[i]);
8554 cpu_LO[i] = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
8555 offsetof(CPUState, active_tc.LO[i]),
8556 regnames_LO[i]);
8557 cpu_ACX[i] = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
8558 offsetof(CPUState, active_tc.ACX[i]),
8559 regnames_ACX[i]);
8560 }
8561 cpu_dspctrl = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
8562 offsetof(CPUState, active_tc.DSPControl),
8563 "DSPControl");
d077b6f7
TS
8564 bcond = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
8565 offsetof(CPUState, bcond), "bcond");
8566 btarget = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
8567 offsetof(CPUState, btarget), "btarget");
f01be154
TS
8568 for (i = 0; i < 32; i++)
8569 fpu_fpr32[i] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
8570 offsetof(CPUState, active_fpu.fpr[i].w[FP_ENDIAN_IDX]),
8571 fregnames[i]);
8572 for (i = 0; i < 32; i++)
8573 fpu_fpr64[i] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
8574 offsetof(CPUState, active_fpu.fpr[i]),
8575 fregnames_64[i]);
8576 for (i = 0; i < 32; i++)
8577 fpu_fpr32h[i] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
8578 offsetof(CPUState, active_fpu.fpr[i].w[!FP_ENDIAN_IDX]),
8579 fregnames_h[i]);
8580 fpu_fcr0 = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
8581 offsetof(CPUState, active_fpu.fcr0),
8582 "fcr0");
8583 fpu_fcr31 = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
8584 offsetof(CPUState, active_fpu.fcr31),
8585 "fcr31");
39454628 8586
7dd9e556
TS
8587 /* register helpers */
8588#undef DEF_HELPER
8589#define DEF_HELPER(ret, name, params) tcg_register_helper(name, #name);
8590#include "helper.h"
8591
39454628
TS
8592 inited = 1;
8593}
8594
aaed909a
FB
8595#include "translate_init.c"
8596
8597CPUMIPSState *cpu_mips_init (const char *cpu_model)
6af0bf9c
FB
8598{
8599 CPUMIPSState *env;
aaed909a 8600 const mips_def_t *def;
6af0bf9c 8601
aaed909a
FB
8602 def = cpu_mips_find_by_name(cpu_model);
8603 if (!def)
8604 return NULL;
6af0bf9c
FB
8605 env = qemu_mallocz(sizeof(CPUMIPSState));
8606 if (!env)
8607 return NULL;
aaed909a
FB
8608 env->cpu_model = def;
8609
173d6cfe 8610 cpu_exec_init(env);
01ba9816 8611 env->cpu_model_str = cpu_model;
39454628 8612 mips_tcg_init();
6ae81775
TS
8613 cpu_reset(env);
8614 return env;
8615}
8616
8617void cpu_reset (CPUMIPSState *env)
8618{
8619 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
8620
6af0bf9c 8621 tlb_flush(env, 1);
6ae81775 8622
6af0bf9c 8623 /* Minimal init */
0eaef5aa
TS
8624#if defined(CONFIG_USER_ONLY)
8625 env->user_mode_only = 1;
8626#endif
8627 if (env->user_mode_only) {
8628 env->hflags = MIPS_HFLAG_UM;
aa328add 8629 } else {
0eaef5aa
TS
8630 if (env->hflags & MIPS_HFLAG_BMASK) {
8631 /* If the exception was raised from a delay slot,
8632 come back to the jump. */
8633 env->CP0_ErrorEPC = env->active_tc.PC - 4;
8634 } else {
8635 env->CP0_ErrorEPC = env->active_tc.PC;
8636 }
8637 env->active_tc.PC = (int32_t)0xBFC00000;
8638 env->CP0_Wired = 0;
8639 /* SMP not implemented */
8640 env->CP0_EBase = 0x80000000;
8641 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
8642 /* vectored interrupts not implemented, timer on int 7,
8643 no performance counters. */
8644 env->CP0_IntCtl = 0xe0000000;
8645 {
8646 int i;
8647
8648 for (i = 0; i < 7; i++) {
8649 env->CP0_WatchLo[i] = 0;
8650 env->CP0_WatchHi[i] = 0x80000000;
8651 }
8652 env->CP0_WatchLo[7] = 0;
8653 env->CP0_WatchHi[7] = 0;
fd88b6ab 8654 }
0eaef5aa
TS
8655 /* Count register increments in debug mode, EJTAG version 1 */
8656 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
8657 env->hflags = MIPS_HFLAG_CP0;
fd88b6ab 8658 }
6af0bf9c 8659 env->exception_index = EXCP_NONE;
aaed909a 8660 cpu_mips_register(env, env->cpu_model);
6af0bf9c 8661}
d2856f1a
AJ
8662
8663void gen_pc_load(CPUState *env, TranslationBlock *tb,
8664 unsigned long searched_pc, int pc_pos, void *puc)
8665{
b5dc7732 8666 env->active_tc.PC = gen_opc_pc[pc_pos];
d2856f1a
AJ
8667 env->hflags &= ~MIPS_HFLAG_BMASK;
8668 env->hflags |= gen_opc_hflags[pc_pos];
8669}