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