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