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