]> git.proxmox.com Git - mirror_qemu.git/blame - target-mips/translate.c
target-mips: optimize gen_compute_branch1()
[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{
e214b9bb 5696 int l1 = gen_new_label();
5a5012ec 5697 uint32_t ccbit;
e214b9bb 5698 TCGCond cond;
a7812ae4
PB
5699 TCGv t0 = tcg_temp_local_new();
5700 TCGv_i32 r_tmp = tcg_temp_new_i32();
6ea83fed 5701
e214b9bb 5702 if (cc)
5a5012ec 5703 ccbit = 1 << (24 + cc);
e214b9bb 5704 else
5a5012ec 5705 ccbit = 1 << 23;
e214b9bb 5706 if (tf)
e214b9bb 5707 cond = TCG_COND_EQ;
27848470
TS
5708 else
5709 cond = TCG_COND_NE;
5710
6c5c1e20 5711 gen_load_gpr(t0, rd);
f01be154 5712 tcg_gen_andi_i32(r_tmp, fpu_fcr31, ccbit);
920c608e 5713 tcg_gen_brcondi_i32(cond, r_tmp, 0, l1);
a7812ae4 5714 tcg_temp_free_i32(r_tmp);
9bf3eb2c 5715 gen_load_gpr(t0, rs);
e214b9bb 5716 gen_set_label(l1);
6c5c1e20
TS
5717 gen_store_gpr(t0, rd);
5718 tcg_temp_free(t0);
5a5012ec
TS
5719}
5720
b6d96bed 5721static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
a16336e4
TS
5722{
5723 uint32_t ccbit;
5724 int cond;
a7812ae4
PB
5725 TCGv_i32 r_tmp1 = tcg_temp_new_i32();
5726 TCGv_i32 fp0 = tcg_temp_local_new_i32();
a16336e4
TS
5727 int l1 = gen_new_label();
5728
5729 if (cc)
5730 ccbit = 1 << (24 + cc);
5731 else
5732 ccbit = 1 << 23;
5733
5734 if (tf)
5735 cond = TCG_COND_EQ;
5736 else
5737 cond = TCG_COND_NE;
5738
9bf3eb2c 5739 gen_load_fpr32(fp0, fd);
f01be154 5740 tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit);
a16336e4 5741 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
a7812ae4 5742 tcg_temp_free_i32(r_tmp1);
9bf3eb2c 5743 gen_load_fpr32(fp0, fs);
a16336e4 5744 gen_set_label(l1);
9bf3eb2c 5745 gen_store_fpr32(fp0, fd);
a7812ae4 5746 tcg_temp_free_i32(fp0);
5a5012ec 5747}
a16336e4 5748
b6d96bed 5749static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
a16336e4
TS
5750{
5751 uint32_t ccbit;
5752 int cond;
a7812ae4
PB
5753 TCGv_i32 r_tmp1 = tcg_temp_new_i32();
5754 TCGv_i64 fp0 = tcg_temp_local_new_i64();
a16336e4
TS
5755 int l1 = gen_new_label();
5756
5757 if (cc)
5758 ccbit = 1 << (24 + cc);
5759 else
5760 ccbit = 1 << 23;
5761
5762 if (tf)
5763 cond = TCG_COND_EQ;
5764 else
5765 cond = TCG_COND_NE;
5766
9bf3eb2c 5767 gen_load_fpr64(ctx, fp0, fd);
f01be154 5768 tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit);
a16336e4 5769 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
a7812ae4 5770 tcg_temp_free_i32(r_tmp1);
9bf3eb2c 5771 gen_load_fpr64(ctx, fp0, fs);
a16336e4 5772 gen_set_label(l1);
9bf3eb2c 5773 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 5774 tcg_temp_free_i64(fp0);
a16336e4
TS
5775}
5776
b6d96bed 5777static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
a16336e4 5778{
9bf3eb2c 5779 uint32_t ccbit1, ccbit2;
a16336e4 5780 int cond;
a7812ae4
PB
5781 TCGv_i32 r_tmp1 = tcg_temp_new_i32();
5782 TCGv_i32 fp0 = tcg_temp_local_new_i32();
a16336e4
TS
5783 int l1 = gen_new_label();
5784 int l2 = gen_new_label();
5785
9bf3eb2c
AJ
5786 if (cc) {
5787 ccbit1 = 1 << (24 + cc);
5788 ccbit2 = 1 << (25 + cc);
5789 } else {
5790 ccbit1 = 1 << 23;
5791 ccbit2 = 1 << 25;
5792 }
5793
a16336e4
TS
5794 if (tf)
5795 cond = TCG_COND_EQ;
5796 else
5797 cond = TCG_COND_NE;
5798
9bf3eb2c
AJ
5799 gen_load_fpr32(fp0, fd);
5800 tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit1);
5801 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
b6d96bed 5802 gen_load_fpr32(fp0, fs);
a16336e4 5803 gen_set_label(l1);
9bf3eb2c
AJ
5804 gen_store_fpr32(fp0, fd);
5805
5806 gen_load_fpr32h(fp0, fd);
5807 tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit2);
5808 tcg_gen_brcondi_i32(cond, r_tmp1, 0, l2);
5809 gen_load_fpr32h(fp0, fs);
a16336e4 5810 gen_set_label(l2);
9bf3eb2c
AJ
5811 gen_store_fpr32h(fp0, fd);
5812
a7812ae4
PB
5813 tcg_temp_free_i32(r_tmp1);
5814 tcg_temp_free_i32(fp0);
a16336e4
TS
5815}
5816
6ea83fed 5817
5e755519
TS
5818static void gen_farith (DisasContext *ctx, uint32_t op1,
5819 int ft, int fs, int fd, int cc)
6ea83fed 5820{
923617a3 5821 const char *opn = "farith";
6ea83fed
FB
5822 const char *condnames[] = {
5823 "c.f",
5824 "c.un",
5825 "c.eq",
5826 "c.ueq",
5827 "c.olt",
5828 "c.ult",
5829 "c.ole",
5830 "c.ule",
5831 "c.sf",
5832 "c.ngle",
5833 "c.seq",
5834 "c.ngl",
5835 "c.lt",
5836 "c.nge",
5837 "c.le",
5838 "c.ngt",
5839 };
5a1e8ffb
TS
5840 const char *condnames_abs[] = {
5841 "cabs.f",
5842 "cabs.un",
5843 "cabs.eq",
5844 "cabs.ueq",
5845 "cabs.olt",
5846 "cabs.ult",
5847 "cabs.ole",
5848 "cabs.ule",
5849 "cabs.sf",
5850 "cabs.ngle",
5851 "cabs.seq",
5852 "cabs.ngl",
5853 "cabs.lt",
5854 "cabs.nge",
5855 "cabs.le",
5856 "cabs.ngt",
5857 };
5858 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
7a387fff
TS
5859 uint32_t func = ctx->opcode & 0x3f;
5860
6ea83fed 5861 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
5a5012ec 5862 case FOP(0, 16):
b6d96bed 5863 {
a7812ae4
PB
5864 TCGv_i32 fp0 = tcg_temp_new_i32();
5865 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
5866
5867 gen_load_fpr32(fp0, fs);
5868 gen_load_fpr32(fp1, ft);
a7812ae4
PB
5869 gen_helper_float_add_s(fp0, fp0, fp1);
5870 tcg_temp_free_i32(fp1);
b6d96bed 5871 gen_store_fpr32(fp0, fd);
a7812ae4 5872 tcg_temp_free_i32(fp0);
b6d96bed 5873 }
5a5012ec 5874 opn = "add.s";
5a1e8ffb 5875 optype = BINOP;
5a5012ec
TS
5876 break;
5877 case FOP(1, 16):
b6d96bed 5878 {
a7812ae4
PB
5879 TCGv_i32 fp0 = tcg_temp_new_i32();
5880 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
5881
5882 gen_load_fpr32(fp0, fs);
5883 gen_load_fpr32(fp1, ft);
a7812ae4
PB
5884 gen_helper_float_sub_s(fp0, fp0, fp1);
5885 tcg_temp_free_i32(fp1);
b6d96bed 5886 gen_store_fpr32(fp0, fd);
a7812ae4 5887 tcg_temp_free_i32(fp0);
b6d96bed 5888 }
5a5012ec 5889 opn = "sub.s";
5a1e8ffb 5890 optype = BINOP;
5a5012ec
TS
5891 break;
5892 case FOP(2, 16):
b6d96bed 5893 {
a7812ae4
PB
5894 TCGv_i32 fp0 = tcg_temp_new_i32();
5895 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
5896
5897 gen_load_fpr32(fp0, fs);
5898 gen_load_fpr32(fp1, ft);
a7812ae4
PB
5899 gen_helper_float_mul_s(fp0, fp0, fp1);
5900 tcg_temp_free_i32(fp1);
b6d96bed 5901 gen_store_fpr32(fp0, fd);
a7812ae4 5902 tcg_temp_free_i32(fp0);
b6d96bed 5903 }
5a5012ec 5904 opn = "mul.s";
5a1e8ffb 5905 optype = BINOP;
5a5012ec
TS
5906 break;
5907 case FOP(3, 16):
b6d96bed 5908 {
a7812ae4
PB
5909 TCGv_i32 fp0 = tcg_temp_new_i32();
5910 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
5911
5912 gen_load_fpr32(fp0, fs);
5913 gen_load_fpr32(fp1, ft);
a7812ae4
PB
5914 gen_helper_float_div_s(fp0, fp0, fp1);
5915 tcg_temp_free_i32(fp1);
b6d96bed 5916 gen_store_fpr32(fp0, fd);
a7812ae4 5917 tcg_temp_free_i32(fp0);
b6d96bed 5918 }
5a5012ec 5919 opn = "div.s";
5a1e8ffb 5920 optype = BINOP;
5a5012ec
TS
5921 break;
5922 case FOP(4, 16):
b6d96bed 5923 {
a7812ae4 5924 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5925
5926 gen_load_fpr32(fp0, fs);
a7812ae4 5927 gen_helper_float_sqrt_s(fp0, fp0);
b6d96bed 5928 gen_store_fpr32(fp0, fd);
a7812ae4 5929 tcg_temp_free_i32(fp0);
b6d96bed 5930 }
5a5012ec
TS
5931 opn = "sqrt.s";
5932 break;
5933 case FOP(5, 16):
b6d96bed 5934 {
a7812ae4 5935 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5936
5937 gen_load_fpr32(fp0, fs);
a7812ae4 5938 gen_helper_float_abs_s(fp0, fp0);
b6d96bed 5939 gen_store_fpr32(fp0, fd);
a7812ae4 5940 tcg_temp_free_i32(fp0);
b6d96bed 5941 }
5a5012ec
TS
5942 opn = "abs.s";
5943 break;
5944 case FOP(6, 16):
b6d96bed 5945 {
a7812ae4 5946 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5947
5948 gen_load_fpr32(fp0, fs);
5949 gen_store_fpr32(fp0, fd);
a7812ae4 5950 tcg_temp_free_i32(fp0);
b6d96bed 5951 }
5a5012ec
TS
5952 opn = "mov.s";
5953 break;
5954 case FOP(7, 16):
b6d96bed 5955 {
a7812ae4 5956 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5957
5958 gen_load_fpr32(fp0, fs);
a7812ae4 5959 gen_helper_float_chs_s(fp0, fp0);
b6d96bed 5960 gen_store_fpr32(fp0, fd);
a7812ae4 5961 tcg_temp_free_i32(fp0);
b6d96bed 5962 }
5a5012ec
TS
5963 opn = "neg.s";
5964 break;
5965 case FOP(8, 16):
5e755519 5966 check_cp1_64bitmode(ctx);
b6d96bed 5967 {
a7812ae4
PB
5968 TCGv_i32 fp32 = tcg_temp_new_i32();
5969 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
5970
5971 gen_load_fpr32(fp32, fs);
a7812ae4
PB
5972 gen_helper_float_roundl_s(fp64, fp32);
5973 tcg_temp_free_i32(fp32);
b6d96bed 5974 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 5975 tcg_temp_free_i64(fp64);
b6d96bed 5976 }
5a5012ec
TS
5977 opn = "round.l.s";
5978 break;
5979 case FOP(9, 16):
5e755519 5980 check_cp1_64bitmode(ctx);
b6d96bed 5981 {
a7812ae4
PB
5982 TCGv_i32 fp32 = tcg_temp_new_i32();
5983 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
5984
5985 gen_load_fpr32(fp32, fs);
a7812ae4
PB
5986 gen_helper_float_truncl_s(fp64, fp32);
5987 tcg_temp_free_i32(fp32);
b6d96bed 5988 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 5989 tcg_temp_free_i64(fp64);
b6d96bed 5990 }
5a5012ec
TS
5991 opn = "trunc.l.s";
5992 break;
5993 case FOP(10, 16):
5e755519 5994 check_cp1_64bitmode(ctx);
b6d96bed 5995 {
a7812ae4
PB
5996 TCGv_i32 fp32 = tcg_temp_new_i32();
5997 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
5998
5999 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6000 gen_helper_float_ceill_s(fp64, fp32);
6001 tcg_temp_free_i32(fp32);
b6d96bed 6002 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6003 tcg_temp_free_i64(fp64);
b6d96bed 6004 }
5a5012ec
TS
6005 opn = "ceil.l.s";
6006 break;
6007 case FOP(11, 16):
5e755519 6008 check_cp1_64bitmode(ctx);
b6d96bed 6009 {
a7812ae4
PB
6010 TCGv_i32 fp32 = tcg_temp_new_i32();
6011 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6012
6013 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6014 gen_helper_float_floorl_s(fp64, fp32);
6015 tcg_temp_free_i32(fp32);
b6d96bed 6016 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6017 tcg_temp_free_i64(fp64);
b6d96bed 6018 }
5a5012ec
TS
6019 opn = "floor.l.s";
6020 break;
6021 case FOP(12, 16):
b6d96bed 6022 {
a7812ae4 6023 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6024
6025 gen_load_fpr32(fp0, fs);
a7812ae4 6026 gen_helper_float_roundw_s(fp0, fp0);
b6d96bed 6027 gen_store_fpr32(fp0, fd);
a7812ae4 6028 tcg_temp_free_i32(fp0);
b6d96bed 6029 }
5a5012ec
TS
6030 opn = "round.w.s";
6031 break;
6032 case FOP(13, 16):
b6d96bed 6033 {
a7812ae4 6034 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6035
6036 gen_load_fpr32(fp0, fs);
a7812ae4 6037 gen_helper_float_truncw_s(fp0, fp0);
b6d96bed 6038 gen_store_fpr32(fp0, fd);
a7812ae4 6039 tcg_temp_free_i32(fp0);
b6d96bed 6040 }
5a5012ec
TS
6041 opn = "trunc.w.s";
6042 break;
6043 case FOP(14, 16):
b6d96bed 6044 {
a7812ae4 6045 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6046
6047 gen_load_fpr32(fp0, fs);
a7812ae4 6048 gen_helper_float_ceilw_s(fp0, fp0);
b6d96bed 6049 gen_store_fpr32(fp0, fd);
a7812ae4 6050 tcg_temp_free_i32(fp0);
b6d96bed 6051 }
5a5012ec
TS
6052 opn = "ceil.w.s";
6053 break;
6054 case FOP(15, 16):
b6d96bed 6055 {
a7812ae4 6056 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6057
6058 gen_load_fpr32(fp0, fs);
a7812ae4 6059 gen_helper_float_floorw_s(fp0, fp0);
b6d96bed 6060 gen_store_fpr32(fp0, fd);
a7812ae4 6061 tcg_temp_free_i32(fp0);
b6d96bed 6062 }
5a5012ec
TS
6063 opn = "floor.w.s";
6064 break;
6065 case FOP(17, 16):
b6d96bed 6066 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec
TS
6067 opn = "movcf.s";
6068 break;
6069 case FOP(18, 16):
a16336e4
TS
6070 {
6071 int l1 = gen_new_label();
a7812ae4
PB
6072 TCGv t0 = tcg_temp_new();
6073 TCGv_i32 fp0 = tcg_temp_local_new_i32();
a16336e4 6074
6c5c1e20
TS
6075 gen_load_gpr(t0, ft);
6076 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
b6d96bed
TS
6077 gen_load_fpr32(fp0, fs);
6078 gen_store_fpr32(fp0, fd);
a7812ae4 6079 tcg_temp_free_i32(fp0);
a16336e4 6080 gen_set_label(l1);
2a0ab998 6081 tcg_temp_free(t0);
a16336e4 6082 }
5a5012ec
TS
6083 opn = "movz.s";
6084 break;
6085 case FOP(19, 16):
a16336e4
TS
6086 {
6087 int l1 = gen_new_label();
a7812ae4
PB
6088 TCGv t0 = tcg_temp_new();
6089 TCGv_i32 fp0 = tcg_temp_local_new_i32();
a16336e4 6090
6c5c1e20
TS
6091 gen_load_gpr(t0, ft);
6092 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
b6d96bed
TS
6093 gen_load_fpr32(fp0, fs);
6094 gen_store_fpr32(fp0, fd);
a7812ae4 6095 tcg_temp_free_i32(fp0);
a16336e4 6096 gen_set_label(l1);
2a0ab998 6097 tcg_temp_free(t0);
a16336e4 6098 }
5a5012ec
TS
6099 opn = "movn.s";
6100 break;
57fa1fb3 6101 case FOP(21, 16):
b8aa4598 6102 check_cop1x(ctx);
b6d96bed 6103 {
a7812ae4 6104 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6105
6106 gen_load_fpr32(fp0, fs);
a7812ae4 6107 gen_helper_float_recip_s(fp0, fp0);
b6d96bed 6108 gen_store_fpr32(fp0, fd);
a7812ae4 6109 tcg_temp_free_i32(fp0);
b6d96bed 6110 }
57fa1fb3
TS
6111 opn = "recip.s";
6112 break;
6113 case FOP(22, 16):
b8aa4598 6114 check_cop1x(ctx);
b6d96bed 6115 {
a7812ae4 6116 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6117
6118 gen_load_fpr32(fp0, fs);
a7812ae4 6119 gen_helper_float_rsqrt_s(fp0, fp0);
b6d96bed 6120 gen_store_fpr32(fp0, fd);
a7812ae4 6121 tcg_temp_free_i32(fp0);
b6d96bed 6122 }
57fa1fb3
TS
6123 opn = "rsqrt.s";
6124 break;
6125 case FOP(28, 16):
5e755519 6126 check_cp1_64bitmode(ctx);
b6d96bed 6127 {
a7812ae4
PB
6128 TCGv_i32 fp0 = tcg_temp_new_i32();
6129 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6130
6131 gen_load_fpr32(fp0, fs);
6132 gen_load_fpr32(fp1, fd);
a7812ae4
PB
6133 gen_helper_float_recip2_s(fp0, fp0, fp1);
6134 tcg_temp_free_i32(fp1);
b6d96bed 6135 gen_store_fpr32(fp0, fd);
a7812ae4 6136 tcg_temp_free_i32(fp0);
b6d96bed 6137 }
57fa1fb3
TS
6138 opn = "recip2.s";
6139 break;
6140 case FOP(29, 16):
5e755519 6141 check_cp1_64bitmode(ctx);
b6d96bed 6142 {
a7812ae4 6143 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6144
6145 gen_load_fpr32(fp0, fs);
a7812ae4 6146 gen_helper_float_recip1_s(fp0, fp0);
b6d96bed 6147 gen_store_fpr32(fp0, fd);
a7812ae4 6148 tcg_temp_free_i32(fp0);
b6d96bed 6149 }
57fa1fb3
TS
6150 opn = "recip1.s";
6151 break;
6152 case FOP(30, 16):
5e755519 6153 check_cp1_64bitmode(ctx);
b6d96bed 6154 {
a7812ae4 6155 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6156
6157 gen_load_fpr32(fp0, fs);
a7812ae4 6158 gen_helper_float_rsqrt1_s(fp0, fp0);
b6d96bed 6159 gen_store_fpr32(fp0, fd);
a7812ae4 6160 tcg_temp_free_i32(fp0);
b6d96bed 6161 }
57fa1fb3
TS
6162 opn = "rsqrt1.s";
6163 break;
6164 case FOP(31, 16):
5e755519 6165 check_cp1_64bitmode(ctx);
b6d96bed 6166 {
a7812ae4
PB
6167 TCGv_i32 fp0 = tcg_temp_new_i32();
6168 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6169
6170 gen_load_fpr32(fp0, fs);
6171 gen_load_fpr32(fp1, ft);
a7812ae4
PB
6172 gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
6173 tcg_temp_free_i32(fp1);
b6d96bed 6174 gen_store_fpr32(fp0, fd);
a7812ae4 6175 tcg_temp_free_i32(fp0);
b6d96bed 6176 }
57fa1fb3
TS
6177 opn = "rsqrt2.s";
6178 break;
5a5012ec 6179 case FOP(33, 16):
5e755519 6180 check_cp1_registers(ctx, fd);
b6d96bed 6181 {
a7812ae4
PB
6182 TCGv_i32 fp32 = tcg_temp_new_i32();
6183 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6184
6185 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6186 gen_helper_float_cvtd_s(fp64, fp32);
6187 tcg_temp_free_i32(fp32);
b6d96bed 6188 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6189 tcg_temp_free_i64(fp64);
b6d96bed 6190 }
5a5012ec
TS
6191 opn = "cvt.d.s";
6192 break;
6193 case FOP(36, 16):
b6d96bed 6194 {
a7812ae4 6195 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6196
6197 gen_load_fpr32(fp0, fs);
a7812ae4 6198 gen_helper_float_cvtw_s(fp0, fp0);
b6d96bed 6199 gen_store_fpr32(fp0, fd);
a7812ae4 6200 tcg_temp_free_i32(fp0);
b6d96bed 6201 }
5a5012ec
TS
6202 opn = "cvt.w.s";
6203 break;
6204 case FOP(37, 16):
5e755519 6205 check_cp1_64bitmode(ctx);
b6d96bed 6206 {
a7812ae4
PB
6207 TCGv_i32 fp32 = tcg_temp_new_i32();
6208 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6209
6210 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6211 gen_helper_float_cvtl_s(fp64, fp32);
6212 tcg_temp_free_i32(fp32);
b6d96bed 6213 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6214 tcg_temp_free_i64(fp64);
b6d96bed 6215 }
5a5012ec
TS
6216 opn = "cvt.l.s";
6217 break;
6218 case FOP(38, 16):
5e755519 6219 check_cp1_64bitmode(ctx);
b6d96bed 6220 {
a7812ae4
PB
6221 TCGv_i64 fp64 = tcg_temp_new_i64();
6222 TCGv_i32 fp32_0 = tcg_temp_new_i32();
6223 TCGv_i32 fp32_1 = tcg_temp_new_i32();
b6d96bed
TS
6224
6225 gen_load_fpr32(fp32_0, fs);
6226 gen_load_fpr32(fp32_1, ft);
36aa55dc 6227 tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
a7812ae4
PB
6228 tcg_temp_free_i32(fp32_1);
6229 tcg_temp_free_i32(fp32_0);
36aa55dc 6230 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6231 tcg_temp_free_i64(fp64);
b6d96bed 6232 }
5a5012ec
TS
6233 opn = "cvt.ps.s";
6234 break;
6235 case FOP(48, 16):
6236 case FOP(49, 16):
6237 case FOP(50, 16):
6238 case FOP(51, 16):
6239 case FOP(52, 16):
6240 case FOP(53, 16):
6241 case FOP(54, 16):
6242 case FOP(55, 16):
6243 case FOP(56, 16):
6244 case FOP(57, 16):
6245 case FOP(58, 16):
6246 case FOP(59, 16):
6247 case FOP(60, 16):
6248 case FOP(61, 16):
6249 case FOP(62, 16):
6250 case FOP(63, 16):
b6d96bed 6251 {
a7812ae4
PB
6252 TCGv_i32 fp0 = tcg_temp_new_i32();
6253 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6254
6255 gen_load_fpr32(fp0, fs);
6256 gen_load_fpr32(fp1, ft);
6257 if (ctx->opcode & (1 << 6)) {
6258 check_cop1x(ctx);
6259 gen_cmpabs_s(func-48, fp0, fp1, cc);
6260 opn = condnames_abs[func-48];
6261 } else {
6262 gen_cmp_s(func-48, fp0, fp1, cc);
6263 opn = condnames[func-48];
6264 }
a7812ae4
PB
6265 tcg_temp_free_i32(fp0);
6266 tcg_temp_free_i32(fp1);
5a1e8ffb 6267 }
5a5012ec 6268 break;
6ea83fed 6269 case FOP(0, 17):
5e755519 6270 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6271 {
a7812ae4
PB
6272 TCGv_i64 fp0 = tcg_temp_new_i64();
6273 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6274
6275 gen_load_fpr64(ctx, fp0, fs);
6276 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6277 gen_helper_float_add_d(fp0, fp0, fp1);
6278 tcg_temp_free_i64(fp1);
b6d96bed 6279 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6280 tcg_temp_free_i64(fp0);
b6d96bed 6281 }
6ea83fed 6282 opn = "add.d";
5a1e8ffb 6283 optype = BINOP;
6ea83fed
FB
6284 break;
6285 case FOP(1, 17):
5e755519 6286 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6287 {
a7812ae4
PB
6288 TCGv_i64 fp0 = tcg_temp_new_i64();
6289 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6290
6291 gen_load_fpr64(ctx, fp0, fs);
6292 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6293 gen_helper_float_sub_d(fp0, fp0, fp1);
6294 tcg_temp_free_i64(fp1);
b6d96bed 6295 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6296 tcg_temp_free_i64(fp0);
b6d96bed 6297 }
6ea83fed 6298 opn = "sub.d";
5a1e8ffb 6299 optype = BINOP;
6ea83fed
FB
6300 break;
6301 case FOP(2, 17):
5e755519 6302 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6303 {
a7812ae4
PB
6304 TCGv_i64 fp0 = tcg_temp_new_i64();
6305 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6306
6307 gen_load_fpr64(ctx, fp0, fs);
6308 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6309 gen_helper_float_mul_d(fp0, fp0, fp1);
6310 tcg_temp_free_i64(fp1);
b6d96bed 6311 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6312 tcg_temp_free_i64(fp0);
b6d96bed 6313 }
6ea83fed 6314 opn = "mul.d";
5a1e8ffb 6315 optype = BINOP;
6ea83fed
FB
6316 break;
6317 case FOP(3, 17):
5e755519 6318 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6319 {
a7812ae4
PB
6320 TCGv_i64 fp0 = tcg_temp_new_i64();
6321 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6322
6323 gen_load_fpr64(ctx, fp0, fs);
6324 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6325 gen_helper_float_div_d(fp0, fp0, fp1);
6326 tcg_temp_free_i64(fp1);
b6d96bed 6327 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6328 tcg_temp_free_i64(fp0);
b6d96bed 6329 }
6ea83fed 6330 opn = "div.d";
5a1e8ffb 6331 optype = BINOP;
6ea83fed
FB
6332 break;
6333 case FOP(4, 17):
5e755519 6334 check_cp1_registers(ctx, fs | fd);
b6d96bed 6335 {
a7812ae4 6336 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6337
6338 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6339 gen_helper_float_sqrt_d(fp0, fp0);
b6d96bed 6340 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6341 tcg_temp_free_i64(fp0);
b6d96bed 6342 }
6ea83fed
FB
6343 opn = "sqrt.d";
6344 break;
6345 case FOP(5, 17):
5e755519 6346 check_cp1_registers(ctx, fs | fd);
b6d96bed 6347 {
a7812ae4 6348 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6349
6350 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6351 gen_helper_float_abs_d(fp0, fp0);
b6d96bed 6352 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6353 tcg_temp_free_i64(fp0);
b6d96bed 6354 }
6ea83fed
FB
6355 opn = "abs.d";
6356 break;
6357 case FOP(6, 17):
5e755519 6358 check_cp1_registers(ctx, fs | fd);
b6d96bed 6359 {
a7812ae4 6360 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6361
6362 gen_load_fpr64(ctx, fp0, fs);
6363 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6364 tcg_temp_free_i64(fp0);
b6d96bed 6365 }
6ea83fed
FB
6366 opn = "mov.d";
6367 break;
6368 case FOP(7, 17):
5e755519 6369 check_cp1_registers(ctx, fs | fd);
b6d96bed 6370 {
a7812ae4 6371 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6372
6373 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6374 gen_helper_float_chs_d(fp0, fp0);
b6d96bed 6375 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6376 tcg_temp_free_i64(fp0);
b6d96bed 6377 }
6ea83fed
FB
6378 opn = "neg.d";
6379 break;
5a5012ec 6380 case FOP(8, 17):
5e755519 6381 check_cp1_64bitmode(ctx);
b6d96bed 6382 {
a7812ae4 6383 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6384
6385 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6386 gen_helper_float_roundl_d(fp0, fp0);
b6d96bed 6387 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6388 tcg_temp_free_i64(fp0);
b6d96bed 6389 }
5a5012ec
TS
6390 opn = "round.l.d";
6391 break;
6392 case FOP(9, 17):
5e755519 6393 check_cp1_64bitmode(ctx);
b6d96bed 6394 {
a7812ae4 6395 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6396
6397 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6398 gen_helper_float_truncl_d(fp0, fp0);
b6d96bed 6399 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6400 tcg_temp_free_i64(fp0);
b6d96bed 6401 }
5a5012ec
TS
6402 opn = "trunc.l.d";
6403 break;
6404 case FOP(10, 17):
5e755519 6405 check_cp1_64bitmode(ctx);
b6d96bed 6406 {
a7812ae4 6407 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6408
6409 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6410 gen_helper_float_ceill_d(fp0, fp0);
b6d96bed 6411 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6412 tcg_temp_free_i64(fp0);
b6d96bed 6413 }
5a5012ec
TS
6414 opn = "ceil.l.d";
6415 break;
6416 case FOP(11, 17):
5e755519 6417 check_cp1_64bitmode(ctx);
b6d96bed 6418 {
a7812ae4 6419 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6420
6421 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6422 gen_helper_float_floorl_d(fp0, fp0);
b6d96bed 6423 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6424 tcg_temp_free_i64(fp0);
b6d96bed 6425 }
5a5012ec
TS
6426 opn = "floor.l.d";
6427 break;
6ea83fed 6428 case FOP(12, 17):
5e755519 6429 check_cp1_registers(ctx, fs);
b6d96bed 6430 {
a7812ae4
PB
6431 TCGv_i32 fp32 = tcg_temp_new_i32();
6432 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6433
6434 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6435 gen_helper_float_roundw_d(fp32, fp64);
6436 tcg_temp_free_i64(fp64);
b6d96bed 6437 gen_store_fpr32(fp32, fd);
a7812ae4 6438 tcg_temp_free_i32(fp32);
b6d96bed 6439 }
6ea83fed
FB
6440 opn = "round.w.d";
6441 break;
6442 case FOP(13, 17):
5e755519 6443 check_cp1_registers(ctx, fs);
b6d96bed 6444 {
a7812ae4
PB
6445 TCGv_i32 fp32 = tcg_temp_new_i32();
6446 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6447
6448 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6449 gen_helper_float_truncw_d(fp32, fp64);
6450 tcg_temp_free_i64(fp64);
b6d96bed 6451 gen_store_fpr32(fp32, fd);
a7812ae4 6452 tcg_temp_free_i32(fp32);
b6d96bed 6453 }
6ea83fed
FB
6454 opn = "trunc.w.d";
6455 break;
6456 case FOP(14, 17):
5e755519 6457 check_cp1_registers(ctx, fs);
b6d96bed 6458 {
a7812ae4
PB
6459 TCGv_i32 fp32 = tcg_temp_new_i32();
6460 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6461
6462 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6463 gen_helper_float_ceilw_d(fp32, fp64);
6464 tcg_temp_free_i64(fp64);
b6d96bed 6465 gen_store_fpr32(fp32, fd);
a7812ae4 6466 tcg_temp_free_i32(fp32);
b6d96bed 6467 }
6ea83fed
FB
6468 opn = "ceil.w.d";
6469 break;
6470 case FOP(15, 17):
5e755519 6471 check_cp1_registers(ctx, fs);
b6d96bed 6472 {
a7812ae4
PB
6473 TCGv_i32 fp32 = tcg_temp_new_i32();
6474 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6475
6476 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6477 gen_helper_float_floorw_d(fp32, fp64);
6478 tcg_temp_free_i64(fp64);
b6d96bed 6479 gen_store_fpr32(fp32, fd);
a7812ae4 6480 tcg_temp_free_i32(fp32);
b6d96bed 6481 }
7a387fff 6482 opn = "floor.w.d";
6ea83fed 6483 break;
5a5012ec 6484 case FOP(17, 17):
b6d96bed 6485 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 6486 opn = "movcf.d";
dd016883 6487 break;
5a5012ec 6488 case FOP(18, 17):
a16336e4
TS
6489 {
6490 int l1 = gen_new_label();
a7812ae4
PB
6491 TCGv t0 = tcg_temp_new();
6492 TCGv_i64 fp0 = tcg_temp_local_new_i64();
a16336e4 6493
6c5c1e20
TS
6494 gen_load_gpr(t0, ft);
6495 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
b6d96bed
TS
6496 gen_load_fpr64(ctx, fp0, fs);
6497 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6498 tcg_temp_free_i64(fp0);
a16336e4 6499 gen_set_label(l1);
2a0ab998 6500 tcg_temp_free(t0);
a16336e4 6501 }
5a5012ec
TS
6502 opn = "movz.d";
6503 break;
6504 case FOP(19, 17):
a16336e4
TS
6505 {
6506 int l1 = gen_new_label();
a7812ae4
PB
6507 TCGv t0 = tcg_temp_new();
6508 TCGv_i64 fp0 = tcg_temp_local_new_i64();
a16336e4 6509
6c5c1e20
TS
6510 gen_load_gpr(t0, ft);
6511 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
b6d96bed
TS
6512 gen_load_fpr64(ctx, fp0, fs);
6513 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6514 tcg_temp_free_i64(fp0);
a16336e4 6515 gen_set_label(l1);
2a0ab998 6516 tcg_temp_free(t0);
a16336e4 6517 }
5a5012ec 6518 opn = "movn.d";
6ea83fed 6519 break;
57fa1fb3 6520 case FOP(21, 17):
b8aa4598 6521 check_cp1_64bitmode(ctx);
b6d96bed 6522 {
a7812ae4 6523 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6524
6525 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6526 gen_helper_float_recip_d(fp0, fp0);
b6d96bed 6527 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6528 tcg_temp_free_i64(fp0);
b6d96bed 6529 }
57fa1fb3
TS
6530 opn = "recip.d";
6531 break;
6532 case FOP(22, 17):
b8aa4598 6533 check_cp1_64bitmode(ctx);
b6d96bed 6534 {
a7812ae4 6535 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6536
6537 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6538 gen_helper_float_rsqrt_d(fp0, fp0);
b6d96bed 6539 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6540 tcg_temp_free_i64(fp0);
b6d96bed 6541 }
57fa1fb3
TS
6542 opn = "rsqrt.d";
6543 break;
6544 case FOP(28, 17):
5e755519 6545 check_cp1_64bitmode(ctx);
b6d96bed 6546 {
a7812ae4
PB
6547 TCGv_i64 fp0 = tcg_temp_new_i64();
6548 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6549
6550 gen_load_fpr64(ctx, fp0, fs);
6551 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6552 gen_helper_float_recip2_d(fp0, fp0, fp1);
6553 tcg_temp_free_i64(fp1);
b6d96bed 6554 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6555 tcg_temp_free_i64(fp0);
b6d96bed 6556 }
57fa1fb3
TS
6557 opn = "recip2.d";
6558 break;
6559 case FOP(29, 17):
5e755519 6560 check_cp1_64bitmode(ctx);
b6d96bed 6561 {
a7812ae4 6562 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6563
6564 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6565 gen_helper_float_recip1_d(fp0, fp0);
b6d96bed 6566 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6567 tcg_temp_free_i64(fp0);
b6d96bed 6568 }
57fa1fb3
TS
6569 opn = "recip1.d";
6570 break;
6571 case FOP(30, 17):
5e755519 6572 check_cp1_64bitmode(ctx);
b6d96bed 6573 {
a7812ae4 6574 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6575
6576 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6577 gen_helper_float_rsqrt1_d(fp0, fp0);
b6d96bed 6578 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6579 tcg_temp_free_i64(fp0);
b6d96bed 6580 }
57fa1fb3
TS
6581 opn = "rsqrt1.d";
6582 break;
6583 case FOP(31, 17):
5e755519 6584 check_cp1_64bitmode(ctx);
b6d96bed 6585 {
a7812ae4
PB
6586 TCGv_i64 fp0 = tcg_temp_new_i64();
6587 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6588
6589 gen_load_fpr64(ctx, fp0, fs);
6590 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6591 gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
6592 tcg_temp_free_i64(fp1);
b6d96bed 6593 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6594 tcg_temp_free_i64(fp0);
b6d96bed 6595 }
57fa1fb3
TS
6596 opn = "rsqrt2.d";
6597 break;
6ea83fed
FB
6598 case FOP(48, 17):
6599 case FOP(49, 17):
6600 case FOP(50, 17):
6601 case FOP(51, 17):
6602 case FOP(52, 17):
6603 case FOP(53, 17):
6604 case FOP(54, 17):
6605 case FOP(55, 17):
6606 case FOP(56, 17):
6607 case FOP(57, 17):
6608 case FOP(58, 17):
6609 case FOP(59, 17):
6610 case FOP(60, 17):
6611 case FOP(61, 17):
6612 case FOP(62, 17):
6613 case FOP(63, 17):
b6d96bed 6614 {
a7812ae4
PB
6615 TCGv_i64 fp0 = tcg_temp_new_i64();
6616 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6617
6618 gen_load_fpr64(ctx, fp0, fs);
6619 gen_load_fpr64(ctx, fp1, ft);
6620 if (ctx->opcode & (1 << 6)) {
6621 check_cop1x(ctx);
6622 check_cp1_registers(ctx, fs | ft);
6623 gen_cmpabs_d(func-48, fp0, fp1, cc);
6624 opn = condnames_abs[func-48];
6625 } else {
6626 check_cp1_registers(ctx, fs | ft);
6627 gen_cmp_d(func-48, fp0, fp1, cc);
6628 opn = condnames[func-48];
6629 }
a7812ae4
PB
6630 tcg_temp_free_i64(fp0);
6631 tcg_temp_free_i64(fp1);
5a1e8ffb 6632 }
6ea83fed 6633 break;
5a5012ec 6634 case FOP(32, 17):
5e755519 6635 check_cp1_registers(ctx, fs);
b6d96bed 6636 {
a7812ae4
PB
6637 TCGv_i32 fp32 = tcg_temp_new_i32();
6638 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6639
6640 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6641 gen_helper_float_cvts_d(fp32, fp64);
6642 tcg_temp_free_i64(fp64);
b6d96bed 6643 gen_store_fpr32(fp32, fd);
a7812ae4 6644 tcg_temp_free_i32(fp32);
b6d96bed 6645 }
5a5012ec
TS
6646 opn = "cvt.s.d";
6647 break;
6648 case FOP(36, 17):
5e755519 6649 check_cp1_registers(ctx, fs);
b6d96bed 6650 {
a7812ae4
PB
6651 TCGv_i32 fp32 = tcg_temp_new_i32();
6652 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6653
6654 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6655 gen_helper_float_cvtw_d(fp32, fp64);
6656 tcg_temp_free_i64(fp64);
b6d96bed 6657 gen_store_fpr32(fp32, fd);
a7812ae4 6658 tcg_temp_free_i32(fp32);
b6d96bed 6659 }
5a5012ec
TS
6660 opn = "cvt.w.d";
6661 break;
6662 case FOP(37, 17):
5e755519 6663 check_cp1_64bitmode(ctx);
b6d96bed 6664 {
a7812ae4 6665 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6666
6667 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6668 gen_helper_float_cvtl_d(fp0, fp0);
b6d96bed 6669 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6670 tcg_temp_free_i64(fp0);
b6d96bed 6671 }
5a5012ec
TS
6672 opn = "cvt.l.d";
6673 break;
6674 case FOP(32, 20):
b6d96bed 6675 {
a7812ae4 6676 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6677
6678 gen_load_fpr32(fp0, fs);
a7812ae4 6679 gen_helper_float_cvts_w(fp0, fp0);
b6d96bed 6680 gen_store_fpr32(fp0, fd);
a7812ae4 6681 tcg_temp_free_i32(fp0);
b6d96bed 6682 }
5a5012ec 6683 opn = "cvt.s.w";
6ea83fed 6684 break;
5a5012ec 6685 case FOP(33, 20):
5e755519 6686 check_cp1_registers(ctx, fd);
b6d96bed 6687 {
a7812ae4
PB
6688 TCGv_i32 fp32 = tcg_temp_new_i32();
6689 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6690
6691 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6692 gen_helper_float_cvtd_w(fp64, fp32);
6693 tcg_temp_free_i32(fp32);
b6d96bed 6694 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6695 tcg_temp_free_i64(fp64);
b6d96bed 6696 }
5a5012ec
TS
6697 opn = "cvt.d.w";
6698 break;
6699 case FOP(32, 21):
5e755519 6700 check_cp1_64bitmode(ctx);
b6d96bed 6701 {
a7812ae4
PB
6702 TCGv_i32 fp32 = tcg_temp_new_i32();
6703 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6704
6705 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6706 gen_helper_float_cvts_l(fp32, fp64);
6707 tcg_temp_free_i64(fp64);
b6d96bed 6708 gen_store_fpr32(fp32, fd);
a7812ae4 6709 tcg_temp_free_i32(fp32);
b6d96bed 6710 }
5a5012ec
TS
6711 opn = "cvt.s.l";
6712 break;
6713 case FOP(33, 21):
5e755519 6714 check_cp1_64bitmode(ctx);
b6d96bed 6715 {
a7812ae4 6716 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6717
6718 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6719 gen_helper_float_cvtd_l(fp0, fp0);
b6d96bed 6720 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6721 tcg_temp_free_i64(fp0);
b6d96bed 6722 }
5a5012ec
TS
6723 opn = "cvt.d.l";
6724 break;
6725 case FOP(38, 20):
5e755519 6726 check_cp1_64bitmode(ctx);
b6d96bed 6727 {
a7812ae4 6728 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6729
6730 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6731 gen_helper_float_cvtps_pw(fp0, fp0);
b6d96bed 6732 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6733 tcg_temp_free_i64(fp0);
b6d96bed 6734 }
5a5012ec
TS
6735 opn = "cvt.ps.pw";
6736 break;
6737 case FOP(0, 22):
5e755519 6738 check_cp1_64bitmode(ctx);
b6d96bed 6739 {
a7812ae4
PB
6740 TCGv_i64 fp0 = tcg_temp_new_i64();
6741 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6742
6743 gen_load_fpr64(ctx, fp0, fs);
6744 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6745 gen_helper_float_add_ps(fp0, fp0, fp1);
6746 tcg_temp_free_i64(fp1);
b6d96bed 6747 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6748 tcg_temp_free_i64(fp0);
b6d96bed 6749 }
5a5012ec 6750 opn = "add.ps";
6ea83fed 6751 break;
5a5012ec 6752 case FOP(1, 22):
5e755519 6753 check_cp1_64bitmode(ctx);
b6d96bed 6754 {
a7812ae4
PB
6755 TCGv_i64 fp0 = tcg_temp_new_i64();
6756 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6757
6758 gen_load_fpr64(ctx, fp0, fs);
6759 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6760 gen_helper_float_sub_ps(fp0, fp0, fp1);
6761 tcg_temp_free_i64(fp1);
b6d96bed 6762 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6763 tcg_temp_free_i64(fp0);
b6d96bed 6764 }
5a5012ec 6765 opn = "sub.ps";
6ea83fed 6766 break;
5a5012ec 6767 case FOP(2, 22):
5e755519 6768 check_cp1_64bitmode(ctx);
b6d96bed 6769 {
a7812ae4
PB
6770 TCGv_i64 fp0 = tcg_temp_new_i64();
6771 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6772
6773 gen_load_fpr64(ctx, fp0, fs);
6774 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6775 gen_helper_float_mul_ps(fp0, fp0, fp1);
6776 tcg_temp_free_i64(fp1);
b6d96bed 6777 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6778 tcg_temp_free_i64(fp0);
b6d96bed 6779 }
5a5012ec 6780 opn = "mul.ps";
6ea83fed 6781 break;
5a5012ec 6782 case FOP(5, 22):
5e755519 6783 check_cp1_64bitmode(ctx);
b6d96bed 6784 {
a7812ae4 6785 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6786
6787 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6788 gen_helper_float_abs_ps(fp0, fp0);
b6d96bed 6789 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6790 tcg_temp_free_i64(fp0);
b6d96bed 6791 }
5a5012ec 6792 opn = "abs.ps";
6ea83fed 6793 break;
5a5012ec 6794 case FOP(6, 22):
5e755519 6795 check_cp1_64bitmode(ctx);
b6d96bed 6796 {
a7812ae4 6797 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6798
6799 gen_load_fpr64(ctx, fp0, fs);
6800 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6801 tcg_temp_free_i64(fp0);
b6d96bed 6802 }
5a5012ec 6803 opn = "mov.ps";
6ea83fed 6804 break;
5a5012ec 6805 case FOP(7, 22):
5e755519 6806 check_cp1_64bitmode(ctx);
b6d96bed 6807 {
a7812ae4 6808 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6809
6810 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6811 gen_helper_float_chs_ps(fp0, fp0);
b6d96bed 6812 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6813 tcg_temp_free_i64(fp0);
b6d96bed 6814 }
5a5012ec 6815 opn = "neg.ps";
6ea83fed 6816 break;
5a5012ec 6817 case FOP(17, 22):
5e755519 6818 check_cp1_64bitmode(ctx);
b6d96bed 6819 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 6820 opn = "movcf.ps";
6ea83fed 6821 break;
5a5012ec 6822 case FOP(18, 22):
5e755519 6823 check_cp1_64bitmode(ctx);
a16336e4
TS
6824 {
6825 int l1 = gen_new_label();
a7812ae4
PB
6826 TCGv t0 = tcg_temp_new();
6827 TCGv_i32 fp0 = tcg_temp_local_new_i32();
6828 TCGv_i32 fph0 = tcg_temp_local_new_i32();
a16336e4 6829
6c5c1e20
TS
6830 gen_load_gpr(t0, ft);
6831 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
b6d96bed
TS
6832 gen_load_fpr32(fp0, fs);
6833 gen_load_fpr32h(fph0, fs);
6834 gen_store_fpr32(fp0, fd);
6835 gen_store_fpr32h(fph0, fd);
a7812ae4
PB
6836 tcg_temp_free_i32(fp0);
6837 tcg_temp_free_i32(fph0);
a16336e4 6838 gen_set_label(l1);
2a0ab998 6839 tcg_temp_free(t0);
a16336e4 6840 }
5a5012ec 6841 opn = "movz.ps";
6ea83fed 6842 break;
5a5012ec 6843 case FOP(19, 22):
5e755519 6844 check_cp1_64bitmode(ctx);
a16336e4
TS
6845 {
6846 int l1 = gen_new_label();
a7812ae4
PB
6847 TCGv t0 = tcg_temp_new();
6848 TCGv_i32 fp0 = tcg_temp_local_new_i32();
6849 TCGv_i32 fph0 = tcg_temp_local_new_i32();
a16336e4 6850
6c5c1e20
TS
6851 gen_load_gpr(t0, ft);
6852 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
b6d96bed
TS
6853 gen_load_fpr32(fp0, fs);
6854 gen_load_fpr32h(fph0, fs);
6855 gen_store_fpr32(fp0, fd);
6856 gen_store_fpr32h(fph0, fd);
a7812ae4
PB
6857 tcg_temp_free_i32(fp0);
6858 tcg_temp_free_i32(fph0);
a16336e4 6859 gen_set_label(l1);
2a0ab998 6860 tcg_temp_free(t0);
a16336e4 6861 }
5a5012ec 6862 opn = "movn.ps";
6ea83fed 6863 break;
fbcc6828 6864 case FOP(24, 22):
5e755519 6865 check_cp1_64bitmode(ctx);
b6d96bed 6866 {
a7812ae4
PB
6867 TCGv_i64 fp0 = tcg_temp_new_i64();
6868 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6869
6870 gen_load_fpr64(ctx, fp0, ft);
6871 gen_load_fpr64(ctx, fp1, fs);
a7812ae4
PB
6872 gen_helper_float_addr_ps(fp0, fp0, fp1);
6873 tcg_temp_free_i64(fp1);
b6d96bed 6874 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6875 tcg_temp_free_i64(fp0);
b6d96bed 6876 }
fbcc6828
TS
6877 opn = "addr.ps";
6878 break;
57fa1fb3 6879 case FOP(26, 22):
5e755519 6880 check_cp1_64bitmode(ctx);
b6d96bed 6881 {
a7812ae4
PB
6882 TCGv_i64 fp0 = tcg_temp_new_i64();
6883 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6884
6885 gen_load_fpr64(ctx, fp0, ft);
6886 gen_load_fpr64(ctx, fp1, fs);
a7812ae4
PB
6887 gen_helper_float_mulr_ps(fp0, fp0, fp1);
6888 tcg_temp_free_i64(fp1);
b6d96bed 6889 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6890 tcg_temp_free_i64(fp0);
b6d96bed 6891 }
57fa1fb3
TS
6892 opn = "mulr.ps";
6893 break;
6894 case FOP(28, 22):
5e755519 6895 check_cp1_64bitmode(ctx);
b6d96bed 6896 {
a7812ae4
PB
6897 TCGv_i64 fp0 = tcg_temp_new_i64();
6898 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6899
6900 gen_load_fpr64(ctx, fp0, fs);
6901 gen_load_fpr64(ctx, fp1, fd);
a7812ae4
PB
6902 gen_helper_float_recip2_ps(fp0, fp0, fp1);
6903 tcg_temp_free_i64(fp1);
b6d96bed 6904 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6905 tcg_temp_free_i64(fp0);
b6d96bed 6906 }
57fa1fb3
TS
6907 opn = "recip2.ps";
6908 break;
6909 case FOP(29, 22):
5e755519 6910 check_cp1_64bitmode(ctx);
b6d96bed 6911 {
a7812ae4 6912 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6913
6914 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6915 gen_helper_float_recip1_ps(fp0, fp0);
b6d96bed 6916 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6917 tcg_temp_free_i64(fp0);
b6d96bed 6918 }
57fa1fb3
TS
6919 opn = "recip1.ps";
6920 break;
6921 case FOP(30, 22):
5e755519 6922 check_cp1_64bitmode(ctx);
b6d96bed 6923 {
a7812ae4 6924 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6925
6926 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6927 gen_helper_float_rsqrt1_ps(fp0, fp0);
b6d96bed 6928 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6929 tcg_temp_free_i64(fp0);
b6d96bed 6930 }
57fa1fb3
TS
6931 opn = "rsqrt1.ps";
6932 break;
6933 case FOP(31, 22):
5e755519 6934 check_cp1_64bitmode(ctx);
b6d96bed 6935 {
a7812ae4
PB
6936 TCGv_i64 fp0 = tcg_temp_new_i64();
6937 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6938
6939 gen_load_fpr64(ctx, fp0, fs);
6940 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6941 gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
6942 tcg_temp_free_i64(fp1);
b6d96bed 6943 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6944 tcg_temp_free_i64(fp0);
b6d96bed 6945 }
57fa1fb3
TS
6946 opn = "rsqrt2.ps";
6947 break;
5a5012ec 6948 case FOP(32, 22):
5e755519 6949 check_cp1_64bitmode(ctx);
b6d96bed 6950 {
a7812ae4 6951 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6952
6953 gen_load_fpr32h(fp0, fs);
a7812ae4 6954 gen_helper_float_cvts_pu(fp0, fp0);
b6d96bed 6955 gen_store_fpr32(fp0, fd);
a7812ae4 6956 tcg_temp_free_i32(fp0);
b6d96bed 6957 }
5a5012ec 6958 opn = "cvt.s.pu";
dd016883 6959 break;
5a5012ec 6960 case FOP(36, 22):
5e755519 6961 check_cp1_64bitmode(ctx);
b6d96bed 6962 {
a7812ae4 6963 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6964
6965 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6966 gen_helper_float_cvtpw_ps(fp0, fp0);
b6d96bed 6967 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6968 tcg_temp_free_i64(fp0);
b6d96bed 6969 }
5a5012ec 6970 opn = "cvt.pw.ps";
6ea83fed 6971 break;
5a5012ec 6972 case FOP(40, 22):
5e755519 6973 check_cp1_64bitmode(ctx);
b6d96bed 6974 {
a7812ae4 6975 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6976
6977 gen_load_fpr32(fp0, fs);
a7812ae4 6978 gen_helper_float_cvts_pl(fp0, fp0);
b6d96bed 6979 gen_store_fpr32(fp0, fd);
a7812ae4 6980 tcg_temp_free_i32(fp0);
b6d96bed 6981 }
5a5012ec 6982 opn = "cvt.s.pl";
6ea83fed 6983 break;
5a5012ec 6984 case FOP(44, 22):
5e755519 6985 check_cp1_64bitmode(ctx);
b6d96bed 6986 {
a7812ae4
PB
6987 TCGv_i32 fp0 = tcg_temp_new_i32();
6988 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6989
6990 gen_load_fpr32(fp0, fs);
6991 gen_load_fpr32(fp1, ft);
6992 gen_store_fpr32h(fp0, fd);
6993 gen_store_fpr32(fp1, fd);
a7812ae4
PB
6994 tcg_temp_free_i32(fp0);
6995 tcg_temp_free_i32(fp1);
b6d96bed 6996 }
5a5012ec 6997 opn = "pll.ps";
6ea83fed 6998 break;
5a5012ec 6999 case FOP(45, 22):
5e755519 7000 check_cp1_64bitmode(ctx);
b6d96bed 7001 {
a7812ae4
PB
7002 TCGv_i32 fp0 = tcg_temp_new_i32();
7003 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7004
7005 gen_load_fpr32(fp0, fs);
7006 gen_load_fpr32h(fp1, ft);
7007 gen_store_fpr32(fp1, fd);
7008 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
7009 tcg_temp_free_i32(fp0);
7010 tcg_temp_free_i32(fp1);
b6d96bed 7011 }
5a5012ec
TS
7012 opn = "plu.ps";
7013 break;
7014 case FOP(46, 22):
5e755519 7015 check_cp1_64bitmode(ctx);
b6d96bed 7016 {
a7812ae4
PB
7017 TCGv_i32 fp0 = tcg_temp_new_i32();
7018 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7019
7020 gen_load_fpr32h(fp0, fs);
7021 gen_load_fpr32(fp1, ft);
7022 gen_store_fpr32(fp1, fd);
7023 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
7024 tcg_temp_free_i32(fp0);
7025 tcg_temp_free_i32(fp1);
b6d96bed 7026 }
5a5012ec
TS
7027 opn = "pul.ps";
7028 break;
7029 case FOP(47, 22):
5e755519 7030 check_cp1_64bitmode(ctx);
b6d96bed 7031 {
a7812ae4
PB
7032 TCGv_i32 fp0 = tcg_temp_new_i32();
7033 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7034
7035 gen_load_fpr32h(fp0, fs);
7036 gen_load_fpr32h(fp1, ft);
7037 gen_store_fpr32(fp1, fd);
7038 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
7039 tcg_temp_free_i32(fp0);
7040 tcg_temp_free_i32(fp1);
b6d96bed 7041 }
5a5012ec
TS
7042 opn = "puu.ps";
7043 break;
7044 case FOP(48, 22):
7045 case FOP(49, 22):
7046 case FOP(50, 22):
7047 case FOP(51, 22):
7048 case FOP(52, 22):
7049 case FOP(53, 22):
7050 case FOP(54, 22):
7051 case FOP(55, 22):
7052 case FOP(56, 22):
7053 case FOP(57, 22):
7054 case FOP(58, 22):
7055 case FOP(59, 22):
7056 case FOP(60, 22):
7057 case FOP(61, 22):
7058 case FOP(62, 22):
7059 case FOP(63, 22):
5e755519 7060 check_cp1_64bitmode(ctx);
b6d96bed 7061 {
a7812ae4
PB
7062 TCGv_i64 fp0 = tcg_temp_new_i64();
7063 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7064
7065 gen_load_fpr64(ctx, fp0, fs);
7066 gen_load_fpr64(ctx, fp1, ft);
7067 if (ctx->opcode & (1 << 6)) {
7068 gen_cmpabs_ps(func-48, fp0, fp1, cc);
7069 opn = condnames_abs[func-48];
7070 } else {
7071 gen_cmp_ps(func-48, fp0, fp1, cc);
7072 opn = condnames[func-48];
7073 }
a7812ae4
PB
7074 tcg_temp_free_i64(fp0);
7075 tcg_temp_free_i64(fp1);
5a1e8ffb 7076 }
6ea83fed 7077 break;
5a5012ec 7078 default:
923617a3 7079 MIPS_INVAL(opn);
e397ee33 7080 generate_exception (ctx, EXCP_RI);
6ea83fed
FB
7081 return;
7082 }
5a1e8ffb
TS
7083 switch (optype) {
7084 case BINOP:
6ea83fed 7085 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
5a1e8ffb
TS
7086 break;
7087 case CMPOP:
7088 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7089 break;
7090 default:
6ea83fed 7091 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
5a1e8ffb
TS
7092 break;
7093 }
6ea83fed 7094}
6af0bf9c 7095
5a5012ec 7096/* Coprocessor 3 (FPU) */
5e755519
TS
7097static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7098 int fd, int fs, int base, int index)
7a387fff 7099{
923617a3 7100 const char *opn = "extended float load/store";
93b12ccc 7101 int store = 0;
a7812ae4
PB
7102 TCGv t0 = tcg_temp_local_new();
7103 TCGv t1 = tcg_temp_local_new();
7a387fff 7104
93b12ccc 7105 if (base == 0) {
6c5c1e20 7106 gen_load_gpr(t0, index);
93b12ccc 7107 } else if (index == 0) {
6c5c1e20 7108 gen_load_gpr(t0, base);
93b12ccc 7109 } else {
e9203484
AJ
7110 gen_load_gpr(t0, index);
7111 gen_op_addr_add(ctx, t0, cpu_gpr[base]);
93b12ccc 7112 }
5a5012ec 7113 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 7114 memory access. */
5a5012ec
TS
7115 switch (opc) {
7116 case OPC_LWXC1:
b8aa4598 7117 check_cop1x(ctx);
b6d96bed 7118 {
a7812ae4 7119 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 7120
a7812ae4
PB
7121 tcg_gen_qemu_ld32s(t1, t0, ctx->mem_idx);
7122 tcg_gen_trunc_tl_i32(fp0, t1);
b6d96bed 7123 gen_store_fpr32(fp0, fd);
a7812ae4 7124 tcg_temp_free_i32(fp0);
b6d96bed 7125 }
5a5012ec
TS
7126 opn = "lwxc1";
7127 break;
7128 case OPC_LDXC1:
b8aa4598
TS
7129 check_cop1x(ctx);
7130 check_cp1_registers(ctx, fd);
b6d96bed 7131 {
a7812ae4 7132 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7133
7134 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7135 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7136 tcg_temp_free_i64(fp0);
b6d96bed 7137 }
5a5012ec
TS
7138 opn = "ldxc1";
7139 break;
7140 case OPC_LUXC1:
b8aa4598 7141 check_cp1_64bitmode(ctx);
6c5c1e20 7142 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 7143 {
a7812ae4 7144 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7145
7146 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7147 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7148 tcg_temp_free_i64(fp0);
b6d96bed 7149 }
5a5012ec
TS
7150 opn = "luxc1";
7151 break;
7152 case OPC_SWXC1:
b8aa4598 7153 check_cop1x(ctx);
b6d96bed 7154 {
a7812ae4 7155 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7156
7157 gen_load_fpr32(fp0, fs);
a7812ae4
PB
7158 tcg_gen_extu_i32_tl(t1, fp0);
7159 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7160 tcg_temp_free_i32(fp0);
b6d96bed 7161 }
5a5012ec 7162 opn = "swxc1";
93b12ccc 7163 store = 1;
5a5012ec
TS
7164 break;
7165 case OPC_SDXC1:
b8aa4598
TS
7166 check_cop1x(ctx);
7167 check_cp1_registers(ctx, fs);
b6d96bed 7168 {
a7812ae4 7169 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7170
7171 gen_load_fpr64(ctx, fp0, fs);
7172 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 7173 tcg_temp_free_i64(fp0);
b6d96bed 7174 }
5a5012ec 7175 opn = "sdxc1";
93b12ccc 7176 store = 1;
5a5012ec
TS
7177 break;
7178 case OPC_SUXC1:
b8aa4598 7179 check_cp1_64bitmode(ctx);
6c5c1e20 7180 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 7181 {
a7812ae4 7182 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7183
7184 gen_load_fpr64(ctx, fp0, fs);
7185 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 7186 tcg_temp_free_i64(fp0);
b6d96bed 7187 }
5a5012ec 7188 opn = "suxc1";
93b12ccc 7189 store = 1;
5a5012ec
TS
7190 break;
7191 default:
923617a3 7192 MIPS_INVAL(opn);
5a5012ec 7193 generate_exception(ctx, EXCP_RI);
6c5c1e20
TS
7194 tcg_temp_free(t0);
7195 tcg_temp_free(t1);
5a5012ec
TS
7196 return;
7197 }
6c5c1e20
TS
7198 tcg_temp_free(t0);
7199 tcg_temp_free(t1);
93b12ccc
TS
7200 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7201 regnames[index], regnames[base]);
5a5012ec
TS
7202}
7203
5e755519
TS
7204static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7205 int fd, int fr, int fs, int ft)
5a5012ec 7206{
923617a3 7207 const char *opn = "flt3_arith";
5a5012ec 7208
5a5012ec
TS
7209 switch (opc) {
7210 case OPC_ALNV_PS:
b8aa4598 7211 check_cp1_64bitmode(ctx);
a16336e4 7212 {
a7812ae4
PB
7213 TCGv t0 = tcg_temp_local_new();
7214 TCGv_i32 fp0 = tcg_temp_local_new_i32();
7215 TCGv_i32 fph0 = tcg_temp_local_new_i32();
7216 TCGv_i32 fp1 = tcg_temp_local_new_i32();
7217 TCGv_i32 fph1 = tcg_temp_local_new_i32();
a16336e4
TS
7218 int l1 = gen_new_label();
7219 int l2 = gen_new_label();
7220
6c5c1e20
TS
7221 gen_load_gpr(t0, fr);
7222 tcg_gen_andi_tl(t0, t0, 0x7);
b6d96bed
TS
7223 gen_load_fpr32(fp0, fs);
7224 gen_load_fpr32h(fph0, fs);
7225 gen_load_fpr32(fp1, ft);
7226 gen_load_fpr32h(fph1, ft);
6c5c1e20
TS
7227
7228 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
b6d96bed
TS
7229 gen_store_fpr32(fp0, fd);
7230 gen_store_fpr32h(fph0, fd);
a16336e4
TS
7231 tcg_gen_br(l2);
7232 gen_set_label(l1);
6c5c1e20
TS
7233 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7234 tcg_temp_free(t0);
a16336e4 7235#ifdef TARGET_WORDS_BIGENDIAN
b6d96bed
TS
7236 gen_store_fpr32(fph1, fd);
7237 gen_store_fpr32h(fp0, fd);
a16336e4 7238#else
b6d96bed
TS
7239 gen_store_fpr32(fph0, fd);
7240 gen_store_fpr32h(fp1, fd);
a16336e4
TS
7241#endif
7242 gen_set_label(l2);
a7812ae4
PB
7243 tcg_temp_free_i32(fp0);
7244 tcg_temp_free_i32(fph0);
7245 tcg_temp_free_i32(fp1);
7246 tcg_temp_free_i32(fph1);
a16336e4 7247 }
5a5012ec
TS
7248 opn = "alnv.ps";
7249 break;
7250 case OPC_MADD_S:
b8aa4598 7251 check_cop1x(ctx);
b6d96bed 7252 {
a7812ae4
PB
7253 TCGv_i32 fp0 = tcg_temp_new_i32();
7254 TCGv_i32 fp1 = tcg_temp_new_i32();
7255 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7256
7257 gen_load_fpr32(fp0, fs);
7258 gen_load_fpr32(fp1, ft);
7259 gen_load_fpr32(fp2, fr);
a7812ae4
PB
7260 gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
7261 tcg_temp_free_i32(fp0);
7262 tcg_temp_free_i32(fp1);
b6d96bed 7263 gen_store_fpr32(fp2, fd);
a7812ae4 7264 tcg_temp_free_i32(fp2);
b6d96bed 7265 }
5a5012ec
TS
7266 opn = "madd.s";
7267 break;
7268 case OPC_MADD_D:
b8aa4598
TS
7269 check_cop1x(ctx);
7270 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 7271 {
a7812ae4
PB
7272 TCGv_i64 fp0 = tcg_temp_new_i64();
7273 TCGv_i64 fp1 = tcg_temp_new_i64();
7274 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7275
7276 gen_load_fpr64(ctx, fp0, fs);
7277 gen_load_fpr64(ctx, fp1, ft);
7278 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7279 gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
7280 tcg_temp_free_i64(fp0);
7281 tcg_temp_free_i64(fp1);
b6d96bed 7282 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7283 tcg_temp_free_i64(fp2);
b6d96bed 7284 }
5a5012ec
TS
7285 opn = "madd.d";
7286 break;
7287 case OPC_MADD_PS:
b8aa4598 7288 check_cp1_64bitmode(ctx);
b6d96bed 7289 {
a7812ae4
PB
7290 TCGv_i64 fp0 = tcg_temp_new_i64();
7291 TCGv_i64 fp1 = tcg_temp_new_i64();
7292 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7293
7294 gen_load_fpr64(ctx, fp0, fs);
7295 gen_load_fpr64(ctx, fp1, ft);
7296 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7297 gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
7298 tcg_temp_free_i64(fp0);
7299 tcg_temp_free_i64(fp1);
b6d96bed 7300 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7301 tcg_temp_free_i64(fp2);
b6d96bed 7302 }
5a5012ec
TS
7303 opn = "madd.ps";
7304 break;
7305 case OPC_MSUB_S:
b8aa4598 7306 check_cop1x(ctx);
b6d96bed 7307 {
a7812ae4
PB
7308 TCGv_i32 fp0 = tcg_temp_new_i32();
7309 TCGv_i32 fp1 = tcg_temp_new_i32();
7310 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7311
7312 gen_load_fpr32(fp0, fs);
7313 gen_load_fpr32(fp1, ft);
7314 gen_load_fpr32(fp2, fr);
a7812ae4
PB
7315 gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
7316 tcg_temp_free_i32(fp0);
7317 tcg_temp_free_i32(fp1);
b6d96bed 7318 gen_store_fpr32(fp2, fd);
a7812ae4 7319 tcg_temp_free_i32(fp2);
b6d96bed 7320 }
5a5012ec
TS
7321 opn = "msub.s";
7322 break;
7323 case OPC_MSUB_D:
b8aa4598
TS
7324 check_cop1x(ctx);
7325 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 7326 {
a7812ae4
PB
7327 TCGv_i64 fp0 = tcg_temp_new_i64();
7328 TCGv_i64 fp1 = tcg_temp_new_i64();
7329 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7330
7331 gen_load_fpr64(ctx, fp0, fs);
7332 gen_load_fpr64(ctx, fp1, ft);
7333 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7334 gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
7335 tcg_temp_free_i64(fp0);
7336 tcg_temp_free_i64(fp1);
b6d96bed 7337 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7338 tcg_temp_free_i64(fp2);
b6d96bed 7339 }
5a5012ec
TS
7340 opn = "msub.d";
7341 break;
7342 case OPC_MSUB_PS:
b8aa4598 7343 check_cp1_64bitmode(ctx);
b6d96bed 7344 {
a7812ae4
PB
7345 TCGv_i64 fp0 = tcg_temp_new_i64();
7346 TCGv_i64 fp1 = tcg_temp_new_i64();
7347 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7348
7349 gen_load_fpr64(ctx, fp0, fs);
7350 gen_load_fpr64(ctx, fp1, ft);
7351 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7352 gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
7353 tcg_temp_free_i64(fp0);
7354 tcg_temp_free_i64(fp1);
b6d96bed 7355 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7356 tcg_temp_free_i64(fp2);
b6d96bed 7357 }
5a5012ec
TS
7358 opn = "msub.ps";
7359 break;
7360 case OPC_NMADD_S:
b8aa4598 7361 check_cop1x(ctx);
b6d96bed 7362 {
a7812ae4
PB
7363 TCGv_i32 fp0 = tcg_temp_new_i32();
7364 TCGv_i32 fp1 = tcg_temp_new_i32();
7365 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7366
7367 gen_load_fpr32(fp0, fs);
7368 gen_load_fpr32(fp1, ft);
7369 gen_load_fpr32(fp2, fr);
a7812ae4
PB
7370 gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
7371 tcg_temp_free_i32(fp0);
7372 tcg_temp_free_i32(fp1);
b6d96bed 7373 gen_store_fpr32(fp2, fd);
a7812ae4 7374 tcg_temp_free_i32(fp2);
b6d96bed 7375 }
5a5012ec
TS
7376 opn = "nmadd.s";
7377 break;
7378 case OPC_NMADD_D:
b8aa4598
TS
7379 check_cop1x(ctx);
7380 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 7381 {
a7812ae4
PB
7382 TCGv_i64 fp0 = tcg_temp_new_i64();
7383 TCGv_i64 fp1 = tcg_temp_new_i64();
7384 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7385
7386 gen_load_fpr64(ctx, fp0, fs);
7387 gen_load_fpr64(ctx, fp1, ft);
7388 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7389 gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
7390 tcg_temp_free_i64(fp0);
7391 tcg_temp_free_i64(fp1);
b6d96bed 7392 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7393 tcg_temp_free_i64(fp2);
b6d96bed 7394 }
5a5012ec
TS
7395 opn = "nmadd.d";
7396 break;
7397 case OPC_NMADD_PS:
b8aa4598 7398 check_cp1_64bitmode(ctx);
b6d96bed 7399 {
a7812ae4
PB
7400 TCGv_i64 fp0 = tcg_temp_new_i64();
7401 TCGv_i64 fp1 = tcg_temp_new_i64();
7402 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7403
7404 gen_load_fpr64(ctx, fp0, fs);
7405 gen_load_fpr64(ctx, fp1, ft);
7406 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7407 gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
7408 tcg_temp_free_i64(fp0);
7409 tcg_temp_free_i64(fp1);
b6d96bed 7410 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7411 tcg_temp_free_i64(fp2);
b6d96bed 7412 }
5a5012ec
TS
7413 opn = "nmadd.ps";
7414 break;
7415 case OPC_NMSUB_S:
b8aa4598 7416 check_cop1x(ctx);
b6d96bed 7417 {
a7812ae4
PB
7418 TCGv_i32 fp0 = tcg_temp_new_i32();
7419 TCGv_i32 fp1 = tcg_temp_new_i32();
7420 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7421
7422 gen_load_fpr32(fp0, fs);
7423 gen_load_fpr32(fp1, ft);
7424 gen_load_fpr32(fp2, fr);
a7812ae4
PB
7425 gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
7426 tcg_temp_free_i32(fp0);
7427 tcg_temp_free_i32(fp1);
b6d96bed 7428 gen_store_fpr32(fp2, fd);
a7812ae4 7429 tcg_temp_free_i32(fp2);
b6d96bed 7430 }
5a5012ec
TS
7431 opn = "nmsub.s";
7432 break;
7433 case OPC_NMSUB_D:
b8aa4598
TS
7434 check_cop1x(ctx);
7435 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 7436 {
a7812ae4
PB
7437 TCGv_i64 fp0 = tcg_temp_new_i64();
7438 TCGv_i64 fp1 = tcg_temp_new_i64();
7439 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7440
7441 gen_load_fpr64(ctx, fp0, fs);
7442 gen_load_fpr64(ctx, fp1, ft);
7443 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7444 gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
7445 tcg_temp_free_i64(fp0);
7446 tcg_temp_free_i64(fp1);
b6d96bed 7447 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7448 tcg_temp_free_i64(fp2);
b6d96bed 7449 }
5a5012ec
TS
7450 opn = "nmsub.d";
7451 break;
7452 case OPC_NMSUB_PS:
b8aa4598 7453 check_cp1_64bitmode(ctx);
b6d96bed 7454 {
a7812ae4
PB
7455 TCGv_i64 fp0 = tcg_temp_new_i64();
7456 TCGv_i64 fp1 = tcg_temp_new_i64();
7457 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7458
7459 gen_load_fpr64(ctx, fp0, fs);
7460 gen_load_fpr64(ctx, fp1, ft);
7461 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7462 gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
7463 tcg_temp_free_i64(fp0);
7464 tcg_temp_free_i64(fp1);
b6d96bed 7465 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7466 tcg_temp_free_i64(fp2);
b6d96bed 7467 }
5a5012ec
TS
7468 opn = "nmsub.ps";
7469 break;
923617a3
TS
7470 default:
7471 MIPS_INVAL(opn);
5a5012ec
TS
7472 generate_exception (ctx, EXCP_RI);
7473 return;
7474 }
7475 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
7476 fregnames[fs], fregnames[ft]);
7a387fff
TS
7477}
7478
7479/* ISA extensions (ASEs) */
6af0bf9c
FB
7480/* MIPS16 extension to MIPS32 */
7481/* SmartMIPS extension to MIPS32 */
7482
d26bc211 7483#if defined(TARGET_MIPS64)
6af0bf9c
FB
7484
7485/* MDMX extension to MIPS64 */
6af0bf9c
FB
7486
7487#endif
7488
36d23958 7489static void decode_opc (CPUState *env, DisasContext *ctx)
6af0bf9c
FB
7490{
7491 int32_t offset;
7492 int rs, rt, rd, sa;
7a387fff 7493 uint32_t op, op1, op2;
6af0bf9c
FB
7494 int16_t imm;
7495
d796321b
FB
7496 /* make sure instructions are on a word boundary */
7497 if (ctx->pc & 0x3) {
cbeb0857 7498 env->CP0_BadVAddr = ctx->pc;
d796321b
FB
7499 generate_exception(ctx, EXCP_AdEL);
7500 return;
7501 }
7502
8e9ade68 7503 /* Handle blikely not taken case */
4ad40f36 7504 if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
8e9ade68
TS
7505 int l1 = gen_new_label();
7506
3594c774 7507 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
1ba74fb8 7508 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
41db4607 7509 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
5a5012ec
TS
7510 gen_goto_tb(ctx, 1, ctx->pc + 4);
7511 gen_set_label(l1);
6af0bf9c 7512 }
7a387fff
TS
7513 op = MASK_OP_MAJOR(ctx->opcode);
7514 rs = (ctx->opcode >> 21) & 0x1f;
7515 rt = (ctx->opcode >> 16) & 0x1f;
7516 rd = (ctx->opcode >> 11) & 0x1f;
7517 sa = (ctx->opcode >> 6) & 0x1f;
6af0bf9c
FB
7518 imm = (int16_t)ctx->opcode;
7519 switch (op) {
7a387fff
TS
7520 case OPC_SPECIAL:
7521 op1 = MASK_SPECIAL(ctx->opcode);
6af0bf9c 7522 switch (op1) {
7a387fff
TS
7523 case OPC_SLL: /* Arithmetic with immediate */
7524 case OPC_SRL ... OPC_SRA:
e189e748 7525 gen_arith_imm(env, ctx, op1, rd, rt, sa);
7a387fff 7526 break;
e189e748
TS
7527 case OPC_MOVZ ... OPC_MOVN:
7528 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
7a387fff
TS
7529 case OPC_SLLV: /* Arithmetic */
7530 case OPC_SRLV ... OPC_SRAV:
7a387fff
TS
7531 case OPC_ADD ... OPC_NOR:
7532 case OPC_SLT ... OPC_SLTU:
e189e748 7533 gen_arith(env, ctx, op1, rd, rs, rt);
7a387fff
TS
7534 break;
7535 case OPC_MULT ... OPC_DIVU:
e9c71dd1
TS
7536 if (sa) {
7537 check_insn(env, ctx, INSN_VR54XX);
7538 op1 = MASK_MUL_VR54XX(ctx->opcode);
7539 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
7540 } else
7541 gen_muldiv(ctx, op1, rs, rt);
7a387fff
TS
7542 break;
7543 case OPC_JR ... OPC_JALR:
7544 gen_compute_branch(ctx, op1, rs, rd, sa);
6af0bf9c 7545 return;
7a387fff
TS
7546 case OPC_TGE ... OPC_TEQ: /* Traps */
7547 case OPC_TNE:
7548 gen_trap(ctx, op1, rs, rt, -1);
6af0bf9c 7549 break;
7a387fff
TS
7550 case OPC_MFHI: /* Move from HI/LO */
7551 case OPC_MFLO:
7552 gen_HILO(ctx, op1, rd);
6af0bf9c 7553 break;
7a387fff
TS
7554 case OPC_MTHI:
7555 case OPC_MTLO: /* Move to HI/LO */
7556 gen_HILO(ctx, op1, rs);
6af0bf9c 7557 break;
b48cfdff
TS
7558 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
7559#ifdef MIPS_STRICT_STANDARD
7560 MIPS_INVAL("PMON / selsl");
7561 generate_exception(ctx, EXCP_RI);
7562#else
a7812ae4 7563 gen_helper_0i(pmon, sa);
b48cfdff 7564#endif
7a387fff
TS
7565 break;
7566 case OPC_SYSCALL:
6af0bf9c
FB
7567 generate_exception(ctx, EXCP_SYSCALL);
7568 break;
7a387fff 7569 case OPC_BREAK:
6af0bf9c
FB
7570 generate_exception(ctx, EXCP_BREAK);
7571 break;
b48cfdff
TS
7572 case OPC_SPIM:
7573#ifdef MIPS_STRICT_STANDARD
7574 MIPS_INVAL("SPIM");
7575 generate_exception(ctx, EXCP_RI);
7576#else
7a387fff
TS
7577 /* Implemented as RI exception for now. */
7578 MIPS_INVAL("spim (unofficial)");
7579 generate_exception(ctx, EXCP_RI);
b48cfdff 7580#endif
6af0bf9c 7581 break;
7a387fff 7582 case OPC_SYNC:
ead9360e 7583 /* Treat as NOP. */
6af0bf9c 7584 break;
4ad40f36 7585
7a387fff 7586 case OPC_MOVCI:
e189e748 7587 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
36d23958 7588 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
e397ee33 7589 save_cpu_state(ctx, 1);
5e755519 7590 check_cp1_enabled(ctx);
36d23958
TS
7591 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
7592 (ctx->opcode >> 16) & 1);
7593 } else {
e397ee33 7594 generate_exception_err(ctx, EXCP_CpU, 1);
36d23958 7595 }
4ad40f36
FB
7596 break;
7597
d26bc211 7598#if defined(TARGET_MIPS64)
7a387fff
TS
7599 /* MIPS64 specific opcodes */
7600 case OPC_DSLL:
7601 case OPC_DSRL ... OPC_DSRA:
7602 case OPC_DSLL32:
7603 case OPC_DSRL32 ... OPC_DSRA32:
e189e748
TS
7604 check_insn(env, ctx, ISA_MIPS3);
7605 check_mips_64(ctx);
7606 gen_arith_imm(env, ctx, op1, rd, rt, sa);
7a387fff
TS
7607 break;
7608 case OPC_DSLLV:
7609 case OPC_DSRLV ... OPC_DSRAV:
7610 case OPC_DADD ... OPC_DSUBU:
e189e748
TS
7611 check_insn(env, ctx, ISA_MIPS3);
7612 check_mips_64(ctx);
7613 gen_arith(env, ctx, op1, rd, rs, rt);
7a387fff
TS
7614 break;
7615 case OPC_DMULT ... OPC_DDIVU:
e189e748
TS
7616 check_insn(env, ctx, ISA_MIPS3);
7617 check_mips_64(ctx);
7a387fff
TS
7618 gen_muldiv(ctx, op1, rs, rt);
7619 break;
6af0bf9c
FB
7620#endif
7621 default: /* Invalid */
7622 MIPS_INVAL("special");
7623 generate_exception(ctx, EXCP_RI);
7624 break;
7625 }
7626 break;
7a387fff
TS
7627 case OPC_SPECIAL2:
7628 op1 = MASK_SPECIAL2(ctx->opcode);
6af0bf9c 7629 switch (op1) {
7a387fff
TS
7630 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
7631 case OPC_MSUB ... OPC_MSUBU:
e189e748 7632 check_insn(env, ctx, ISA_MIPS32);
7a387fff 7633 gen_muldiv(ctx, op1, rs, rt);
6af0bf9c 7634 break;
7a387fff 7635 case OPC_MUL:
e189e748 7636 gen_arith(env, ctx, op1, rd, rs, rt);
6af0bf9c 7637 break;
20e1fb52
AJ
7638 case OPC_CLO:
7639 case OPC_CLZ:
e189e748 7640 check_insn(env, ctx, ISA_MIPS32);
7a387fff 7641 gen_cl(ctx, op1, rd, rs);
6af0bf9c 7642 break;
7a387fff 7643 case OPC_SDBBP:
6af0bf9c
FB
7644 /* XXX: not clear which exception should be raised
7645 * when in debug mode...
7646 */
e189e748 7647 check_insn(env, ctx, ISA_MIPS32);
6af0bf9c
FB
7648 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
7649 generate_exception(ctx, EXCP_DBp);
7650 } else {
7651 generate_exception(ctx, EXCP_DBp);
7652 }
ead9360e 7653 /* Treat as NOP. */
6af0bf9c 7654 break;
d26bc211 7655#if defined(TARGET_MIPS64)
20e1fb52
AJ
7656 case OPC_DCLO:
7657 case OPC_DCLZ:
e189e748
TS
7658 check_insn(env, ctx, ISA_MIPS64);
7659 check_mips_64(ctx);
7a387fff
TS
7660 gen_cl(ctx, op1, rd, rs);
7661 break;
7662#endif
6af0bf9c
FB
7663 default: /* Invalid */
7664 MIPS_INVAL("special2");
7665 generate_exception(ctx, EXCP_RI);
7666 break;
7667 }
7668 break;
7a387fff 7669 case OPC_SPECIAL3:
2b0233ab
TS
7670 op1 = MASK_SPECIAL3(ctx->opcode);
7671 switch (op1) {
7672 case OPC_EXT:
7673 case OPC_INS:
7674 check_insn(env, ctx, ISA_MIPS32R2);
7675 gen_bitops(ctx, op1, rt, rs, sa, rd);
7676 break;
7677 case OPC_BSHFL:
7678 check_insn(env, ctx, ISA_MIPS32R2);
7679 op2 = MASK_BSHFL(ctx->opcode);
49bcf33c 7680 gen_bshfl(ctx, op2, rt, rd);
7a387fff 7681 break;
1579a72e 7682 case OPC_RDHWR:
e189e748 7683 check_insn(env, ctx, ISA_MIPS32R2);
6c5c1e20 7684 {
a7812ae4 7685 TCGv t0 = tcg_temp_local_new();
6c5c1e20
TS
7686
7687 switch (rd) {
7688 case 0:
7689 save_cpu_state(ctx, 1);
a7812ae4 7690 gen_helper_rdhwr_cpunum(t0);
6c5c1e20
TS
7691 break;
7692 case 1:
7693 save_cpu_state(ctx, 1);
a7812ae4 7694 gen_helper_rdhwr_synci_step(t0);
6c5c1e20
TS
7695 break;
7696 case 2:
7697 save_cpu_state(ctx, 1);
a7812ae4 7698 gen_helper_rdhwr_cc(t0);
6c5c1e20
TS
7699 break;
7700 case 3:
7701 save_cpu_state(ctx, 1);
a7812ae4 7702 gen_helper_rdhwr_ccres(t0);
6c5c1e20
TS
7703 break;
7704 case 29:
932e71cd
AJ
7705#if defined(CONFIG_USER_ONLY)
7706 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
7707 break;
7708#else
7709 /* XXX: Some CPUs implement this in hardware.
7710 Not supported yet. */
7711#endif
6c5c1e20
TS
7712 default: /* Invalid */
7713 MIPS_INVAL("rdhwr");
7714 generate_exception(ctx, EXCP_RI);
7715 break;
7716 }
7717 gen_store_gpr(t0, rt);
7718 tcg_temp_free(t0);
1579a72e 7719 }
1579a72e 7720 break;
ead9360e 7721 case OPC_FORK:
7385ac0b 7722 check_insn(env, ctx, ASE_MT);
6c5c1e20 7723 {
a7812ae4
PB
7724 TCGv t0 = tcg_temp_local_new();
7725 TCGv t1 = tcg_temp_local_new();
6c5c1e20
TS
7726
7727 gen_load_gpr(t0, rt);
7728 gen_load_gpr(t1, rs);
a7812ae4 7729 gen_helper_fork(t0, t1);
6c5c1e20
TS
7730 tcg_temp_free(t0);
7731 tcg_temp_free(t1);
7732 }
ead9360e
TS
7733 break;
7734 case OPC_YIELD:
7385ac0b 7735 check_insn(env, ctx, ASE_MT);
6c5c1e20 7736 {
a7812ae4 7737 TCGv t0 = tcg_temp_local_new();
6c5c1e20
TS
7738
7739 gen_load_gpr(t0, rs);
a7812ae4 7740 gen_helper_yield(t0, t0);
6c5c1e20
TS
7741 gen_store_gpr(t0, rd);
7742 tcg_temp_free(t0);
7743 }
ead9360e 7744 break;
d26bc211 7745#if defined(TARGET_MIPS64)
1579a72e
TS
7746 case OPC_DEXTM ... OPC_DEXT:
7747 case OPC_DINSM ... OPC_DINS:
e189e748
TS
7748 check_insn(env, ctx, ISA_MIPS64R2);
7749 check_mips_64(ctx);
1579a72e 7750 gen_bitops(ctx, op1, rt, rs, sa, rd);
7a387fff 7751 break;
1579a72e 7752 case OPC_DBSHFL:
e189e748
TS
7753 check_insn(env, ctx, ISA_MIPS64R2);
7754 check_mips_64(ctx);
1579a72e 7755 op2 = MASK_DBSHFL(ctx->opcode);
49bcf33c 7756 gen_bshfl(ctx, op2, rt, rd);
c6d6dd7c 7757 break;
7a387fff
TS
7758#endif
7759 default: /* Invalid */
7760 MIPS_INVAL("special3");
7761 generate_exception(ctx, EXCP_RI);
7762 break;
7763 }
7764 break;
7765 case OPC_REGIMM:
7766 op1 = MASK_REGIMM(ctx->opcode);
7767 switch (op1) {
7768 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
7769 case OPC_BLTZAL ... OPC_BGEZALL:
7770 gen_compute_branch(ctx, op1, rs, -1, imm << 2);
6af0bf9c 7771 return;
7a387fff
TS
7772 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
7773 case OPC_TNEI:
7774 gen_trap(ctx, op1, rs, -1, imm);
7775 break;
7776 case OPC_SYNCI:
e189e748 7777 check_insn(env, ctx, ISA_MIPS32R2);
ead9360e 7778 /* Treat as NOP. */
6af0bf9c
FB
7779 break;
7780 default: /* Invalid */
923617a3 7781 MIPS_INVAL("regimm");
6af0bf9c
FB
7782 generate_exception(ctx, EXCP_RI);
7783 break;
7784 }
7785 break;
7a387fff 7786 case OPC_CP0:
387a8fe5 7787 check_cp0_enabled(ctx);
7a387fff 7788 op1 = MASK_CP0(ctx->opcode);
6af0bf9c 7789 switch (op1) {
7a387fff
TS
7790 case OPC_MFC0:
7791 case OPC_MTC0:
ead9360e
TS
7792 case OPC_MFTR:
7793 case OPC_MTTR:
d26bc211 7794#if defined(TARGET_MIPS64)
7a387fff
TS
7795 case OPC_DMFC0:
7796 case OPC_DMTC0:
7797#endif
f1aa6320 7798#ifndef CONFIG_USER_ONLY
932e71cd 7799 gen_cp0(env, ctx, op1, rt, rd);
0eaef5aa 7800#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
7801 break;
7802 case OPC_C0_FIRST ... OPC_C0_LAST:
f1aa6320 7803#ifndef CONFIG_USER_ONLY
932e71cd 7804 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
0eaef5aa 7805#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
7806 break;
7807 case OPC_MFMC0:
8706c382 7808#ifndef CONFIG_USER_ONLY
932e71cd 7809 {
a7812ae4 7810 TCGv t0 = tcg_temp_local_new();
6c5c1e20 7811
0eaef5aa 7812 op2 = MASK_MFMC0(ctx->opcode);
6c5c1e20
TS
7813 switch (op2) {
7814 case OPC_DMT:
7815 check_insn(env, ctx, ASE_MT);
a7812ae4 7816 gen_helper_dmt(t0, t0);
6c5c1e20
TS
7817 break;
7818 case OPC_EMT:
7819 check_insn(env, ctx, ASE_MT);
a7812ae4 7820 gen_helper_emt(t0, t0);
da80682b 7821 break;
6c5c1e20
TS
7822 case OPC_DVPE:
7823 check_insn(env, ctx, ASE_MT);
a7812ae4 7824 gen_helper_dvpe(t0, t0);
6c5c1e20
TS
7825 break;
7826 case OPC_EVPE:
7827 check_insn(env, ctx, ASE_MT);
a7812ae4 7828 gen_helper_evpe(t0, t0);
6c5c1e20
TS
7829 break;
7830 case OPC_DI:
7831 check_insn(env, ctx, ISA_MIPS32R2);
7832 save_cpu_state(ctx, 1);
a7812ae4 7833 gen_helper_di(t0);
6c5c1e20
TS
7834 /* Stop translation as we may have switched the execution mode */
7835 ctx->bstate = BS_STOP;
7836 break;
7837 case OPC_EI:
7838 check_insn(env, ctx, ISA_MIPS32R2);
7839 save_cpu_state(ctx, 1);
a7812ae4 7840 gen_helper_ei(t0);
6c5c1e20
TS
7841 /* Stop translation as we may have switched the execution mode */
7842 ctx->bstate = BS_STOP;
7843 break;
7844 default: /* Invalid */
7845 MIPS_INVAL("mfmc0");
7846 generate_exception(ctx, EXCP_RI);
7847 break;
7848 }
7849 gen_store_gpr(t0, rt);
7850 tcg_temp_free(t0);
7a387fff 7851 }
0eaef5aa 7852#endif /* !CONFIG_USER_ONLY */
6af0bf9c 7853 break;
7a387fff 7854 case OPC_RDPGPR:
e189e748 7855 check_insn(env, ctx, ISA_MIPS32R2);
be24bb4f 7856 gen_load_srsgpr(rt, rd);
ead9360e 7857 break;
7a387fff 7858 case OPC_WRPGPR:
e189e748 7859 check_insn(env, ctx, ISA_MIPS32R2);
be24bb4f 7860 gen_store_srsgpr(rt, rd);
38121543 7861 break;
6af0bf9c 7862 default:
923617a3 7863 MIPS_INVAL("cp0");
7a387fff 7864 generate_exception(ctx, EXCP_RI);
6af0bf9c
FB
7865 break;
7866 }
7867 break;
7a387fff 7868 case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
e189e748 7869 gen_arith_imm(env, ctx, op, rt, rs, imm);
7a387fff
TS
7870 break;
7871 case OPC_J ... OPC_JAL: /* Jump */
7872 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
7873 gen_compute_branch(ctx, op, rs, rt, offset);
7874 return;
7875 case OPC_BEQ ... OPC_BGTZ: /* Branch */
7876 case OPC_BEQL ... OPC_BGTZL:
7877 gen_compute_branch(ctx, op, rs, rt, imm << 2);
7878 return;
7879 case OPC_LB ... OPC_LWR: /* Load and stores */
7880 case OPC_SB ... OPC_SW:
7881 case OPC_SWR:
7882 case OPC_LL:
7883 case OPC_SC:
7884 gen_ldst(ctx, op, rt, rs, imm);
7885 break;
7886 case OPC_CACHE:
e189e748 7887 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
ead9360e 7888 /* Treat as NOP. */
34ae7b51 7889 break;
7a387fff 7890 case OPC_PREF:
e189e748 7891 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
ead9360e 7892 /* Treat as NOP. */
6af0bf9c 7893 break;
4ad40f36 7894
923617a3 7895 /* Floating point (COP1). */
7a387fff
TS
7896 case OPC_LWC1:
7897 case OPC_LDC1:
7898 case OPC_SWC1:
7899 case OPC_SDC1:
36d23958
TS
7900 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7901 save_cpu_state(ctx, 1);
5e755519 7902 check_cp1_enabled(ctx);
36d23958
TS
7903 gen_flt_ldst(ctx, op, rt, rs, imm);
7904 } else {
7905 generate_exception_err(ctx, EXCP_CpU, 1);
7906 }
6ea83fed
FB
7907 break;
7908
7a387fff 7909 case OPC_CP1:
36d23958
TS
7910 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
7911 save_cpu_state(ctx, 1);
5e755519 7912 check_cp1_enabled(ctx);
36d23958
TS
7913 op1 = MASK_CP1(ctx->opcode);
7914 switch (op1) {
3a95e3a7
TS
7915 case OPC_MFHC1:
7916 case OPC_MTHC1:
e189e748 7917 check_insn(env, ctx, ISA_MIPS32R2);
36d23958
TS
7918 case OPC_MFC1:
7919 case OPC_CFC1:
7920 case OPC_MTC1:
7921 case OPC_CTC1:
e189e748
TS
7922 gen_cp1(ctx, op1, rt, rd);
7923 break;
d26bc211 7924#if defined(TARGET_MIPS64)
36d23958
TS
7925 case OPC_DMFC1:
7926 case OPC_DMTC1:
e189e748 7927 check_insn(env, ctx, ISA_MIPS3);
36d23958
TS
7928 gen_cp1(ctx, op1, rt, rd);
7929 break;
e189e748 7930#endif
fbcc6828
TS
7931 case OPC_BC1ANY2:
7932 case OPC_BC1ANY4:
b8aa4598 7933 check_cop1x(ctx);
7385ac0b 7934 check_insn(env, ctx, ASE_MIPS3D);
d8a5950a
TS
7935 /* fall through */
7936 case OPC_BC1:
e189e748 7937 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
5a5012ec 7938 (rt >> 2) & 0x7, imm << 2);
36d23958
TS
7939 return;
7940 case OPC_S_FMT:
7941 case OPC_D_FMT:
7942 case OPC_W_FMT:
7943 case OPC_L_FMT:
5a5012ec
TS
7944 case OPC_PS_FMT:
7945 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
7946 (imm >> 8) & 0x7);
36d23958
TS
7947 break;
7948 default:
923617a3 7949 MIPS_INVAL("cp1");
e397ee33 7950 generate_exception (ctx, EXCP_RI);
36d23958
TS
7951 break;
7952 }
7953 } else {
7954 generate_exception_err(ctx, EXCP_CpU, 1);
6ea83fed 7955 }
4ad40f36
FB
7956 break;
7957
7958 /* COP2. */
7a387fff
TS
7959 case OPC_LWC2:
7960 case OPC_LDC2:
7961 case OPC_SWC2:
7962 case OPC_SDC2:
7963 case OPC_CP2:
7964 /* COP2: Not implemented. */
4ad40f36
FB
7965 generate_exception_err(ctx, EXCP_CpU, 2);
7966 break;
7967
7a387fff 7968 case OPC_CP3:
36d23958 7969 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
e397ee33 7970 save_cpu_state(ctx, 1);
5e755519 7971 check_cp1_enabled(ctx);
36d23958
TS
7972 op1 = MASK_CP3(ctx->opcode);
7973 switch (op1) {
5a5012ec
TS
7974 case OPC_LWXC1:
7975 case OPC_LDXC1:
7976 case OPC_LUXC1:
7977 case OPC_SWXC1:
7978 case OPC_SDXC1:
7979 case OPC_SUXC1:
93b12ccc 7980 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
5a5012ec 7981 break;
e0c84da7 7982 case OPC_PREFX:
ead9360e 7983 /* Treat as NOP. */
e0c84da7 7984 break;
5a5012ec
TS
7985 case OPC_ALNV_PS:
7986 case OPC_MADD_S:
7987 case OPC_MADD_D:
7988 case OPC_MADD_PS:
7989 case OPC_MSUB_S:
7990 case OPC_MSUB_D:
7991 case OPC_MSUB_PS:
7992 case OPC_NMADD_S:
7993 case OPC_NMADD_D:
7994 case OPC_NMADD_PS:
7995 case OPC_NMSUB_S:
7996 case OPC_NMSUB_D:
7997 case OPC_NMSUB_PS:
7998 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
7999 break;
36d23958 8000 default:
923617a3 8001 MIPS_INVAL("cp3");
e397ee33 8002 generate_exception (ctx, EXCP_RI);
36d23958
TS
8003 break;
8004 }
8005 } else {
e397ee33 8006 generate_exception_err(ctx, EXCP_CpU, 1);
7a387fff 8007 }
4ad40f36
FB
8008 break;
8009
d26bc211 8010#if defined(TARGET_MIPS64)
7a387fff
TS
8011 /* MIPS64 opcodes */
8012 case OPC_LWU:
8013 case OPC_LDL ... OPC_LDR:
8014 case OPC_SDL ... OPC_SDR:
8015 case OPC_LLD:
8016 case OPC_LD:
8017 case OPC_SCD:
8018 case OPC_SD:
e189e748
TS
8019 check_insn(env, ctx, ISA_MIPS3);
8020 check_mips_64(ctx);
7a387fff
TS
8021 gen_ldst(ctx, op, rt, rs, imm);
8022 break;
8023 case OPC_DADDI ... OPC_DADDIU:
e189e748
TS
8024 check_insn(env, ctx, ISA_MIPS3);
8025 check_mips_64(ctx);
8026 gen_arith_imm(env, ctx, op, rt, rs, imm);
7a387fff 8027 break;
6af0bf9c 8028#endif
7a387fff 8029 case OPC_JALX:
e189e748 8030 check_insn(env, ctx, ASE_MIPS16);
7a387fff 8031 /* MIPS16: Not implemented. */
7a387fff 8032 case OPC_MDMX:
e189e748 8033 check_insn(env, ctx, ASE_MDMX);
7a387fff 8034 /* MDMX: Not implemented. */
6af0bf9c 8035 default: /* Invalid */
923617a3 8036 MIPS_INVAL("major opcode");
6af0bf9c
FB
8037 generate_exception(ctx, EXCP_RI);
8038 break;
8039 }
4ad40f36 8040 if (ctx->hflags & MIPS_HFLAG_BMASK) {
c53f4a62 8041 int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
6af0bf9c 8042 /* Branches completion */
4ad40f36 8043 ctx->hflags &= ~MIPS_HFLAG_BMASK;
6af0bf9c
FB
8044 ctx->bstate = BS_BRANCH;
8045 save_cpu_state(ctx, 0);
2e70f6ef 8046 /* FIXME: Need to clear can_do_io. */
5a5012ec 8047 switch (hflags) {
6af0bf9c
FB
8048 case MIPS_HFLAG_B:
8049 /* unconditional branch */
8050 MIPS_DEBUG("unconditional branch");
6e256c93 8051 gen_goto_tb(ctx, 0, ctx->btarget);
6af0bf9c
FB
8052 break;
8053 case MIPS_HFLAG_BL:
8054 /* blikely taken case */
8055 MIPS_DEBUG("blikely branch taken");
6e256c93 8056 gen_goto_tb(ctx, 0, ctx->btarget);
6af0bf9c
FB
8057 break;
8058 case MIPS_HFLAG_BC:
8059 /* Conditional branch */
8060 MIPS_DEBUG("conditional branch");
c53be334 8061 {
8e9ade68
TS
8062 int l1 = gen_new_label();
8063
1ba74fb8 8064 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8e9ade68
TS
8065 gen_goto_tb(ctx, 1, ctx->pc + 4);
8066 gen_set_label(l1);
8067 gen_goto_tb(ctx, 0, ctx->btarget);
c53be334 8068 }
6af0bf9c
FB
8069 break;
8070 case MIPS_HFLAG_BR:
8071 /* unconditional branch to register */
8072 MIPS_DEBUG("branch to register");
4b2eb8d2 8073 tcg_gen_mov_tl(cpu_PC, btarget);
57fec1fe 8074 tcg_gen_exit_tb(0);
6af0bf9c
FB
8075 break;
8076 default:
8077 MIPS_DEBUG("unknown branch");
8078 break;
8079 }
8080 }
8081}
8082
2cfc5f17 8083static inline void
820e00f2
TS
8084gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
8085 int search_pc)
6af0bf9c 8086{
278d0702 8087 DisasContext ctx;
6af0bf9c
FB
8088 target_ulong pc_start;
8089 uint16_t *gen_opc_end;
a1d1bb31 8090 CPUBreakpoint *bp;
6af0bf9c 8091 int j, lj = -1;
2e70f6ef
PB
8092 int num_insns;
8093 int max_insns;
6af0bf9c 8094
93fcfe39
AL
8095 if (search_pc)
8096 qemu_log("search pc %d\n", search_pc);
4ad40f36 8097
6af0bf9c 8098 pc_start = tb->pc;
faf7aaa9
TS
8099 /* Leave some spare opc slots for branch handling. */
8100 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE - 16;
6af0bf9c 8101 ctx.pc = pc_start;
4ad40f36 8102 ctx.saved_pc = -1;
6af0bf9c
FB
8103 ctx.tb = tb;
8104 ctx.bstate = BS_NONE;
4ad40f36 8105 /* Restore delay slot state from the tb context. */
c068688b 8106 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
fd4a04eb 8107 restore_cpu_state(env, &ctx);
932e71cd 8108#ifdef CONFIG_USER_ONLY
0eaef5aa 8109 ctx.mem_idx = MIPS_HFLAG_UM;
932e71cd 8110#else
0eaef5aa 8111 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
932e71cd 8112#endif
2e70f6ef
PB
8113 num_insns = 0;
8114 max_insns = tb->cflags & CF_COUNT_MASK;
8115 if (max_insns == 0)
8116 max_insns = CF_COUNT_MASK;
6af0bf9c 8117#ifdef DEBUG_DISAS
93fcfe39
AL
8118 qemu_log_mask(CPU_LOG_TB_CPU, "------------------------------------------------\n");
8119 /* FIXME: This may print out stale hflags from env... */
8120 log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
6af0bf9c 8121#endif
d12d51d5 8122 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
2e70f6ef 8123 gen_icount_start();
faf7aaa9 8124 while (ctx.bstate == BS_NONE) {
c0ce998e
AL
8125 if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
8126 TAILQ_FOREACH(bp, &env->breakpoints, entry) {
a1d1bb31 8127 if (bp->pc == ctx.pc) {
278d0702 8128 save_cpu_state(&ctx, 1);
4ad40f36 8129 ctx.bstate = BS_BRANCH;
a7812ae4 8130 gen_helper_0i(raise_exception, EXCP_DEBUG);
ce62e5ba
TS
8131 /* Include the breakpoint location or the tb won't
8132 * be flushed when it must be. */
8133 ctx.pc += 4;
4ad40f36
FB
8134 goto done_generating;
8135 }
8136 }
8137 }
8138
6af0bf9c
FB
8139 if (search_pc) {
8140 j = gen_opc_ptr - gen_opc_buf;
6af0bf9c
FB
8141 if (lj < j) {
8142 lj++;
8143 while (lj < j)
8144 gen_opc_instr_start[lj++] = 0;
6af0bf9c 8145 }
4ad40f36
FB
8146 gen_opc_pc[lj] = ctx.pc;
8147 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
8148 gen_opc_instr_start[lj] = 1;
2e70f6ef 8149 gen_opc_icount[lj] = num_insns;
6af0bf9c 8150 }
2e70f6ef
PB
8151 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8152 gen_io_start();
6af0bf9c 8153 ctx.opcode = ldl_code(ctx.pc);
36d23958 8154 decode_opc(env, &ctx);
6af0bf9c 8155 ctx.pc += 4;
2e70f6ef 8156 num_insns++;
4ad40f36
FB
8157
8158 if (env->singlestep_enabled)
8159 break;
8160
6af0bf9c
FB
8161 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
8162 break;
4ad40f36 8163
faf7aaa9
TS
8164 if (gen_opc_ptr >= gen_opc_end)
8165 break;
8166
2e70f6ef
PB
8167 if (num_insns >= max_insns)
8168 break;
6af0bf9c
FB
8169#if defined (MIPS_SINGLE_STEP)
8170 break;
8171#endif
8172 }
2e70f6ef
PB
8173 if (tb->cflags & CF_LAST_IO)
8174 gen_io_end();
4ad40f36 8175 if (env->singlestep_enabled) {
278d0702 8176 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
a7812ae4 8177 gen_helper_0i(raise_exception, EXCP_DEBUG);
16c00cb2 8178 } else {
6958549d 8179 switch (ctx.bstate) {
16c00cb2 8180 case BS_STOP:
a7812ae4 8181 gen_helper_interrupt_restart();
df1561e2
TS
8182 gen_goto_tb(&ctx, 0, ctx.pc);
8183 break;
16c00cb2 8184 case BS_NONE:
278d0702 8185 save_cpu_state(&ctx, 0);
16c00cb2
TS
8186 gen_goto_tb(&ctx, 0, ctx.pc);
8187 break;
5a5012ec 8188 case BS_EXCP:
a7812ae4 8189 gen_helper_interrupt_restart();
57fec1fe 8190 tcg_gen_exit_tb(0);
16c00cb2 8191 break;
5a5012ec
TS
8192 case BS_BRANCH:
8193 default:
8194 break;
6958549d 8195 }
6af0bf9c 8196 }
4ad40f36 8197done_generating:
2e70f6ef 8198 gen_icount_end(tb, num_insns);
6af0bf9c
FB
8199 *gen_opc_ptr = INDEX_op_end;
8200 if (search_pc) {
8201 j = gen_opc_ptr - gen_opc_buf;
8202 lj++;
8203 while (lj <= j)
8204 gen_opc_instr_start[lj++] = 0;
6af0bf9c
FB
8205 } else {
8206 tb->size = ctx.pc - pc_start;
2e70f6ef 8207 tb->icount = num_insns;
6af0bf9c
FB
8208 }
8209#ifdef DEBUG_DISAS
d12d51d5 8210 LOG_DISAS("\n");
8fec2b8c 8211 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
93fcfe39
AL
8212 qemu_log("IN: %s\n", lookup_symbol(pc_start));
8213 log_target_disas(pc_start, ctx.pc - pc_start, 0);
8214 qemu_log("\n");
6af0bf9c 8215 }
93fcfe39 8216 qemu_log_mask(CPU_LOG_TB_CPU, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
6af0bf9c 8217#endif
6af0bf9c
FB
8218}
8219
2cfc5f17 8220void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
6af0bf9c 8221{
2cfc5f17 8222 gen_intermediate_code_internal(env, tb, 0);
6af0bf9c
FB
8223}
8224
2cfc5f17 8225void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
6af0bf9c 8226{
2cfc5f17 8227 gen_intermediate_code_internal(env, tb, 1);
6af0bf9c
FB
8228}
8229
8706c382
TS
8230static void fpu_dump_state(CPUState *env, FILE *f,
8231 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
8232 int flags)
6ea83fed
FB
8233{
8234 int i;
5e755519 8235 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
5a5012ec
TS
8236
8237#define printfpr(fp) \
8238 do { \
8239 if (is_fpu64) \
8240 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n", \
8241 (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd, \
8242 (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
8243 else { \
8244 fpr_t tmp; \
8245 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
8246 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
8247 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n", \
8248 tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd, \
8249 tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]); \
8250 } \
6ea83fed
FB
8251 } while(0)
8252
5a5012ec
TS
8253
8254 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
f01be154
TS
8255 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
8256 get_float_exception_flags(&env->active_fpu.fp_status));
5a5012ec
TS
8257 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
8258 fpu_fprintf(f, "%3s: ", fregnames[i]);
f01be154 8259 printfpr(&env->active_fpu.fpr[i]);
6ea83fed
FB
8260 }
8261
8262#undef printfpr
8263}
8264
d26bc211 8265#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16 8266/* Debug help: The architecture requires 32bit code to maintain proper
c7e8a937 8267 sign-extended values on 64bit machines. */
c570fd16
TS
8268
8269#define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
8270
8706c382
TS
8271static void
8272cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
8273 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8274 int flags)
c570fd16
TS
8275{
8276 int i;
8277
b5dc7732
TS
8278 if (!SIGN_EXT_P(env->active_tc.PC))
8279 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
8280 if (!SIGN_EXT_P(env->active_tc.HI[0]))
8281 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
8282 if (!SIGN_EXT_P(env->active_tc.LO[0]))
8283 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
c570fd16 8284 if (!SIGN_EXT_P(env->btarget))
3594c774 8285 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
c570fd16
TS
8286
8287 for (i = 0; i < 32; i++) {
b5dc7732
TS
8288 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
8289 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
c570fd16
TS
8290 }
8291
8292 if (!SIGN_EXT_P(env->CP0_EPC))
3594c774 8293 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
c570fd16 8294 if (!SIGN_EXT_P(env->CP0_LLAddr))
3594c774 8295 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
c570fd16
TS
8296}
8297#endif
8298
5fafdf24 8299void cpu_dump_state (CPUState *env, FILE *f,
6af0bf9c
FB
8300 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
8301 int flags)
8302{
8303 int i;
3b46e624 8304
3594c774 8305 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
8306 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
8307 env->hflags, env->btarget, env->bcond);
6af0bf9c
FB
8308 for (i = 0; i < 32; i++) {
8309 if ((i & 3) == 0)
8310 cpu_fprintf(f, "GPR%02d:", i);
b5dc7732 8311 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
6af0bf9c
FB
8312 if ((i & 3) == 3)
8313 cpu_fprintf(f, "\n");
8314 }
568b600d 8315
3594c774 8316 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
5e755519 8317 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
3594c774 8318 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
6af0bf9c 8319 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
5e755519 8320 if (env->hflags & MIPS_HFLAG_FPU)
7a387fff 8321 fpu_dump_state(env, f, cpu_fprintf, flags);
d26bc211 8322#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16
TS
8323 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
8324#endif
6af0bf9c
FB
8325}
8326
39454628
TS
8327static void mips_tcg_init(void)
8328{
f01be154 8329 int i;
39454628
TS
8330 static int inited;
8331
8332 /* Initialize various static tables. */
8333 if (inited)
6958549d 8334 return;
39454628 8335
a7812ae4 8336 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
4b2eb8d2 8337 for (i = 0; i < 32; i++)
a7812ae4 8338 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
8339 offsetof(CPUState, active_tc.gpr[i]),
8340 regnames[i]);
a7812ae4 8341 cpu_PC = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
8342 offsetof(CPUState, active_tc.PC), "PC");
8343 for (i = 0; i < MIPS_DSP_ACC; i++) {
a7812ae4 8344 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
8345 offsetof(CPUState, active_tc.HI[i]),
8346 regnames_HI[i]);
a7812ae4 8347 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
8348 offsetof(CPUState, active_tc.LO[i]),
8349 regnames_LO[i]);
a7812ae4 8350 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
8351 offsetof(CPUState, active_tc.ACX[i]),
8352 regnames_ACX[i]);
8353 }
a7812ae4 8354 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
8355 offsetof(CPUState, active_tc.DSPControl),
8356 "DSPControl");
1ba74fb8
AJ
8357 bcond = tcg_global_mem_new(TCG_AREG0,
8358 offsetof(CPUState, bcond), "bcond");
a7812ae4 8359 btarget = tcg_global_mem_new(TCG_AREG0,
d077b6f7 8360 offsetof(CPUState, btarget), "btarget");
41db4607
AJ
8361 hflags = tcg_global_mem_new_i32(TCG_AREG0,
8362 offsetof(CPUState, hflags), "hflags");
8363
a7812ae4
PB
8364 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
8365 offsetof(CPUState, active_fpu.fcr0),
8366 "fcr0");
8367 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
8368 offsetof(CPUState, active_fpu.fcr31),
8369 "fcr31");
39454628 8370
7dd9e556 8371 /* register helpers */
a7812ae4 8372#define GEN_HELPER 2
7dd9e556
TS
8373#include "helper.h"
8374
39454628
TS
8375 inited = 1;
8376}
8377
aaed909a
FB
8378#include "translate_init.c"
8379
8380CPUMIPSState *cpu_mips_init (const char *cpu_model)
6af0bf9c
FB
8381{
8382 CPUMIPSState *env;
aaed909a 8383 const mips_def_t *def;
6af0bf9c 8384
aaed909a
FB
8385 def = cpu_mips_find_by_name(cpu_model);
8386 if (!def)
8387 return NULL;
6af0bf9c 8388 env = qemu_mallocz(sizeof(CPUMIPSState));
aaed909a
FB
8389 env->cpu_model = def;
8390
173d6cfe 8391 cpu_exec_init(env);
01ba9816 8392 env->cpu_model_str = cpu_model;
39454628 8393 mips_tcg_init();
6ae81775
TS
8394 cpu_reset(env);
8395 return env;
8396}
8397
8398void cpu_reset (CPUMIPSState *env)
8399{
eca1bdf4
AL
8400 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
8401 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
8402 log_cpu_state(env, 0);
8403 }
8404
6ae81775
TS
8405 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
8406
6af0bf9c 8407 tlb_flush(env, 1);
6ae81775 8408
6af0bf9c 8409 /* Minimal init */
0eaef5aa 8410#if defined(CONFIG_USER_ONLY)
932e71cd
AJ
8411 env->hflags = MIPS_HFLAG_UM;
8412#else
8413 if (env->hflags & MIPS_HFLAG_BMASK) {
8414 /* If the exception was raised from a delay slot,
8415 come back to the jump. */
8416 env->CP0_ErrorEPC = env->active_tc.PC - 4;
aa328add 8417 } else {
932e71cd
AJ
8418 env->CP0_ErrorEPC = env->active_tc.PC;
8419 }
8420 env->active_tc.PC = (int32_t)0xBFC00000;
8421 env->CP0_Wired = 0;
8422 /* SMP not implemented */
8423 env->CP0_EBase = 0x80000000;
8424 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
8425 /* vectored interrupts not implemented, timer on int 7,
8426 no performance counters. */
8427 env->CP0_IntCtl = 0xe0000000;
8428 {
8429 int i;
8430
8431 for (i = 0; i < 7; i++) {
8432 env->CP0_WatchLo[i] = 0;
8433 env->CP0_WatchHi[i] = 0x80000000;
fd88b6ab 8434 }
932e71cd
AJ
8435 env->CP0_WatchLo[7] = 0;
8436 env->CP0_WatchHi[7] = 0;
fd88b6ab 8437 }
932e71cd
AJ
8438 /* Count register increments in debug mode, EJTAG version 1 */
8439 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
8440 env->hflags = MIPS_HFLAG_CP0;
8441#endif
6af0bf9c 8442 env->exception_index = EXCP_NONE;
aaed909a 8443 cpu_mips_register(env, env->cpu_model);
6af0bf9c 8444}
d2856f1a
AJ
8445
8446void gen_pc_load(CPUState *env, TranslationBlock *tb,
8447 unsigned long searched_pc, int pc_pos, void *puc)
8448{
b5dc7732 8449 env->active_tc.PC = gen_opc_pc[pc_pos];
d2856f1a
AJ
8450 env->hflags &= ~MIPS_HFLAG_BMASK;
8451 env->hflags |= gen_opc_hflags[pc_pos];
8452}