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