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