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