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