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