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