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