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