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