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