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