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