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