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