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