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