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