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