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