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