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