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