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