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