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