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