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