]> Git Repo - qemu.git/blame - target-mips/translate.c
Fix indexed FP load/store instructions.
[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";
4239 save_cpu_state(ctx, 0);
4240 gen_op_eret();
4241 ctx->bstate = BS_EXCP;
4242 break;
4243 case OPC_DERET:
4244 opn = "deret";
4245 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
923617a3 4246 MIPS_INVAL(opn);
6af0bf9c
FB
4247 generate_exception(ctx, EXCP_RI);
4248 } else {
4249 save_cpu_state(ctx, 0);
4250 gen_op_deret();
4251 ctx->bstate = BS_EXCP;
4252 }
4253 break;
4ad40f36
FB
4254 case OPC_WAIT:
4255 opn = "wait";
4256 /* If we get an exception, we want to restart at next instruction */
4257 ctx->pc += 4;
4258 save_cpu_state(ctx, 1);
4259 ctx->pc -= 4;
4260 gen_op_wait();
4261 ctx->bstate = BS_EXCP;
4262 break;
6af0bf9c 4263 default:
29929e34 4264 die:
923617a3 4265 MIPS_INVAL(opn);
6af0bf9c
FB
4266 generate_exception(ctx, EXCP_RI);
4267 return;
4268 }
4269 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
4270}
4271
6ea83fed 4272/* CP1 Branches (before delay slot) */
7a387fff 4273static void gen_compute_branch1 (DisasContext *ctx, uint32_t op,
5a5012ec 4274 int32_t cc, int32_t offset)
6ea83fed
FB
4275{
4276 target_ulong btarget;
923617a3 4277 const char *opn = "cp1 cond branch";
6ea83fed
FB
4278
4279 btarget = ctx->pc + 4 + offset;
4280
7a387fff
TS
4281 switch (op) {
4282 case OPC_BC1F:
5a5012ec 4283 gen_op_bc1f(cc);
923617a3 4284 opn = "bc1f";
6ea83fed 4285 goto not_likely;
7a387fff 4286 case OPC_BC1FL:
5a5012ec 4287 gen_op_bc1f(cc);
923617a3 4288 opn = "bc1fl";
6ea83fed 4289 goto likely;
7a387fff 4290 case OPC_BC1T:
5a5012ec 4291 gen_op_bc1t(cc);
923617a3 4292 opn = "bc1t";
5a5012ec 4293 goto not_likely;
7a387fff 4294 case OPC_BC1TL:
5a5012ec 4295 gen_op_bc1t(cc);
923617a3 4296 opn = "bc1tl";
6ea83fed
FB
4297 likely:
4298 ctx->hflags |= MIPS_HFLAG_BL;
5a5012ec
TS
4299 gen_op_set_bcond();
4300 gen_op_save_bcond();
6ea83fed 4301 break;
5a5012ec 4302 case OPC_BC1FANY2:
fd4a04eb
TS
4303 gen_op_bc1any2f(cc);
4304 opn = "bc1any2f";
5a5012ec
TS
4305 goto not_likely;
4306 case OPC_BC1TANY2:
fd4a04eb
TS
4307 gen_op_bc1any2t(cc);
4308 opn = "bc1any2t";
5a5012ec
TS
4309 goto not_likely;
4310 case OPC_BC1FANY4:
fd4a04eb
TS
4311 gen_op_bc1any4f(cc);
4312 opn = "bc1any4f";
5a5012ec
TS
4313 goto not_likely;
4314 case OPC_BC1TANY4:
fd4a04eb
TS
4315 gen_op_bc1any4t(cc);
4316 opn = "bc1any4t";
5a5012ec
TS
4317 not_likely:
4318 ctx->hflags |= MIPS_HFLAG_BC;
4319 gen_op_set_bcond();
4320 break;
4321 default:
923617a3 4322 MIPS_INVAL(opn);
e397ee33 4323 generate_exception (ctx, EXCP_RI);
6ea83fed
FB
4324 return;
4325 }
923617a3 4326 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
6ea83fed
FB
4327 ctx->hflags, btarget);
4328 ctx->btarget = btarget;
6ea83fed
FB
4329}
4330
6af0bf9c 4331/* Coprocessor 1 (FPU) */
5a5012ec 4332
5a5012ec
TS
4333#define FOP(func, fmt) (((fmt) << 21) | (func))
4334
7a387fff 4335static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6ea83fed 4336{
923617a3 4337 const char *opn = "cp1 move";
6ea83fed
FB
4338
4339 switch (opc) {
4340 case OPC_MFC1:
4341 GEN_LOAD_FREG_FTN(WT0, fs);
4342 gen_op_mfc1();
4343 GEN_STORE_TN_REG(rt, T0);
4344 opn = "mfc1";
4345 break;
4346 case OPC_MTC1:
4347 GEN_LOAD_REG_TN(T0, rt);
4348 gen_op_mtc1();
4349 GEN_STORE_FTN_FREG(fs, WT0);
4350 opn = "mtc1";
4351 break;
4352 case OPC_CFC1:
6ea83fed
FB
4353 GEN_LOAD_IMM_TN(T1, fs);
4354 gen_op_cfc1();
4355 GEN_STORE_TN_REG(rt, T0);
4356 opn = "cfc1";
4357 break;
4358 case OPC_CTC1:
6ea83fed
FB
4359 GEN_LOAD_IMM_TN(T1, fs);
4360 GEN_LOAD_REG_TN(T0, rt);
4361 gen_op_ctc1();
4362 opn = "ctc1";
4363 break;
9c2149c8 4364 case OPC_DMFC1:
5a5012ec
TS
4365 GEN_LOAD_FREG_FTN(DT0, fs);
4366 gen_op_dmfc1();
4367 GEN_STORE_TN_REG(rt, T0);
4368 opn = "dmfc1";
4369 break;
9c2149c8 4370 case OPC_DMTC1:
5a5012ec
TS
4371 GEN_LOAD_REG_TN(T0, rt);
4372 gen_op_dmtc1();
4373 GEN_STORE_FTN_FREG(fs, DT0);
4374 opn = "dmtc1";
4375 break;
4376 case OPC_MFHC1:
5a5012ec
TS
4377 GEN_LOAD_FREG_FTN(WTH0, fs);
4378 gen_op_mfhc1();
4379 GEN_STORE_TN_REG(rt, T0);
4380 opn = "mfhc1";
4381 break;
4382 case OPC_MTHC1:
5a5012ec
TS
4383 GEN_LOAD_REG_TN(T0, rt);
4384 gen_op_mthc1();
4385 GEN_STORE_FTN_FREG(fs, WTH0);
4386 opn = "mthc1";
4387 break;
6ea83fed 4388 default:
923617a3 4389 MIPS_INVAL(opn);
e397ee33 4390 generate_exception (ctx, EXCP_RI);
6ea83fed
FB
4391 return;
4392 }
4393 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
4394}
4395
5a5012ec
TS
4396static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
4397{
4398 uint32_t ccbit;
6ea83fed 4399
5a5012ec
TS
4400 GEN_LOAD_REG_TN(T0, rd);
4401 GEN_LOAD_REG_TN(T1, rs);
57fa1fb3 4402 if (cc) {
5a5012ec 4403 ccbit = 1 << (24 + cc);
57fa1fb3 4404 } else
5a5012ec
TS
4405 ccbit = 1 << 23;
4406 if (!tf)
4407 gen_op_movf(ccbit);
4408 else
4409 gen_op_movt(ccbit);
4410 GEN_STORE_TN_REG(rd, T0);
4411}
4412
4413#define GEN_MOVCF(fmt) \
4414static void glue(gen_movcf_, fmt) (DisasContext *ctx, int cc, int tf) \
4415{ \
4416 uint32_t ccbit; \
4417 \
57fa1fb3 4418 if (cc) { \
5a5012ec 4419 ccbit = 1 << (24 + cc); \
57fa1fb3 4420 } else \
5a5012ec
TS
4421 ccbit = 1 << 23; \
4422 if (!tf) \
4423 glue(gen_op_float_movf_, fmt)(ccbit); \
4424 else \
4425 glue(gen_op_float_movt_, fmt)(ccbit); \
4426}
4427GEN_MOVCF(d);
4428GEN_MOVCF(s);
4429GEN_MOVCF(ps);
4430#undef GEN_MOVCF
6ea83fed 4431
5a5012ec
TS
4432static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4433 int fs, int fd, int cc)
6ea83fed 4434{
923617a3 4435 const char *opn = "farith";
6ea83fed
FB
4436 const char *condnames[] = {
4437 "c.f",
4438 "c.un",
4439 "c.eq",
4440 "c.ueq",
4441 "c.olt",
4442 "c.ult",
4443 "c.ole",
4444 "c.ule",
4445 "c.sf",
4446 "c.ngle",
4447 "c.seq",
4448 "c.ngl",
4449 "c.lt",
4450 "c.nge",
4451 "c.le",
4452 "c.ngt",
4453 };
5a1e8ffb
TS
4454 const char *condnames_abs[] = {
4455 "cabs.f",
4456 "cabs.un",
4457 "cabs.eq",
4458 "cabs.ueq",
4459 "cabs.olt",
4460 "cabs.ult",
4461 "cabs.ole",
4462 "cabs.ule",
4463 "cabs.sf",
4464 "cabs.ngle",
4465 "cabs.seq",
4466 "cabs.ngl",
4467 "cabs.lt",
4468 "cabs.nge",
4469 "cabs.le",
4470 "cabs.ngt",
4471 };
4472 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
7a387fff
TS
4473 uint32_t func = ctx->opcode & 0x3f;
4474
6ea83fed 4475 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
5a5012ec
TS
4476 case FOP(0, 16):
4477 GEN_LOAD_FREG_FTN(WT0, fs);
4478 GEN_LOAD_FREG_FTN(WT1, ft);
4479 gen_op_float_add_s();
4480 GEN_STORE_FTN_FREG(fd, WT2);
4481 opn = "add.s";
5a1e8ffb 4482 optype = BINOP;
5a5012ec
TS
4483 break;
4484 case FOP(1, 16):
4485 GEN_LOAD_FREG_FTN(WT0, fs);
4486 GEN_LOAD_FREG_FTN(WT1, ft);
4487 gen_op_float_sub_s();
4488 GEN_STORE_FTN_FREG(fd, WT2);
4489 opn = "sub.s";
5a1e8ffb 4490 optype = BINOP;
5a5012ec
TS
4491 break;
4492 case FOP(2, 16):
4493 GEN_LOAD_FREG_FTN(WT0, fs);
4494 GEN_LOAD_FREG_FTN(WT1, ft);
4495 gen_op_float_mul_s();
4496 GEN_STORE_FTN_FREG(fd, WT2);
4497 opn = "mul.s";
5a1e8ffb 4498 optype = BINOP;
5a5012ec
TS
4499 break;
4500 case FOP(3, 16):
4501 GEN_LOAD_FREG_FTN(WT0, fs);
4502 GEN_LOAD_FREG_FTN(WT1, ft);
4503 gen_op_float_div_s();
4504 GEN_STORE_FTN_FREG(fd, WT2);
4505 opn = "div.s";
5a1e8ffb 4506 optype = BINOP;
5a5012ec
TS
4507 break;
4508 case FOP(4, 16):
4509 GEN_LOAD_FREG_FTN(WT0, fs);
4510 gen_op_float_sqrt_s();
4511 GEN_STORE_FTN_FREG(fd, WT2);
4512 opn = "sqrt.s";
4513 break;
4514 case FOP(5, 16):
4515 GEN_LOAD_FREG_FTN(WT0, fs);
4516 gen_op_float_abs_s();
4517 GEN_STORE_FTN_FREG(fd, WT2);
4518 opn = "abs.s";
4519 break;
4520 case FOP(6, 16):
4521 GEN_LOAD_FREG_FTN(WT0, fs);
4522 gen_op_float_mov_s();
4523 GEN_STORE_FTN_FREG(fd, WT2);
4524 opn = "mov.s";
4525 break;
4526 case FOP(7, 16):
4527 GEN_LOAD_FREG_FTN(WT0, fs);
4528 gen_op_float_chs_s();
4529 GEN_STORE_FTN_FREG(fd, WT2);
4530 opn = "neg.s";
4531 break;
4532 case FOP(8, 16):
57fa1fb3 4533 gen_op_cp1_64bitmode();
5a5012ec
TS
4534 GEN_LOAD_FREG_FTN(WT0, fs);
4535 gen_op_float_roundl_s();
4536 GEN_STORE_FTN_FREG(fd, DT2);
4537 opn = "round.l.s";
4538 break;
4539 case FOP(9, 16):
57fa1fb3 4540 gen_op_cp1_64bitmode();
5a5012ec
TS
4541 GEN_LOAD_FREG_FTN(WT0, fs);
4542 gen_op_float_truncl_s();
4543 GEN_STORE_FTN_FREG(fd, DT2);
4544 opn = "trunc.l.s";
4545 break;
4546 case FOP(10, 16):
57fa1fb3 4547 gen_op_cp1_64bitmode();
5a5012ec
TS
4548 GEN_LOAD_FREG_FTN(WT0, fs);
4549 gen_op_float_ceill_s();
4550 GEN_STORE_FTN_FREG(fd, DT2);
4551 opn = "ceil.l.s";
4552 break;
4553 case FOP(11, 16):
57fa1fb3 4554 gen_op_cp1_64bitmode();
5a5012ec
TS
4555 GEN_LOAD_FREG_FTN(WT0, fs);
4556 gen_op_float_floorl_s();
4557 GEN_STORE_FTN_FREG(fd, DT2);
4558 opn = "floor.l.s";
4559 break;
4560 case FOP(12, 16):
4561 GEN_LOAD_FREG_FTN(WT0, fs);
4562 gen_op_float_roundw_s();
4563 GEN_STORE_FTN_FREG(fd, WT2);
4564 opn = "round.w.s";
4565 break;
4566 case FOP(13, 16):
4567 GEN_LOAD_FREG_FTN(WT0, fs);
4568 gen_op_float_truncw_s();
4569 GEN_STORE_FTN_FREG(fd, WT2);
4570 opn = "trunc.w.s";
4571 break;
4572 case FOP(14, 16):
4573 GEN_LOAD_FREG_FTN(WT0, fs);
4574 gen_op_float_ceilw_s();
4575 GEN_STORE_FTN_FREG(fd, WT2);
4576 opn = "ceil.w.s";
4577 break;
4578 case FOP(15, 16):
4579 GEN_LOAD_FREG_FTN(WT0, fs);
4580 gen_op_float_floorw_s();
4581 GEN_STORE_FTN_FREG(fd, WT2);
4582 opn = "floor.w.s";
4583 break;
4584 case FOP(17, 16):
4585 GEN_LOAD_REG_TN(T0, ft);
4586 GEN_LOAD_FREG_FTN(WT0, fs);
4587 GEN_LOAD_FREG_FTN(WT2, fd);
4588 gen_movcf_s(ctx, (ft >> 2) & 0x7, ft & 0x1);
4589 GEN_STORE_FTN_FREG(fd, WT2);
4590 opn = "movcf.s";
4591 break;
4592 case FOP(18, 16):
4593 GEN_LOAD_REG_TN(T0, ft);
4594 GEN_LOAD_FREG_FTN(WT0, fs);
4595 GEN_LOAD_FREG_FTN(WT2, fd);
4596 gen_op_float_movz_s();
4597 GEN_STORE_FTN_FREG(fd, WT2);
4598 opn = "movz.s";
4599 break;
4600 case FOP(19, 16):
4601 GEN_LOAD_REG_TN(T0, ft);
4602 GEN_LOAD_FREG_FTN(WT0, fs);
4603 GEN_LOAD_FREG_FTN(WT2, fd);
4604 gen_op_float_movn_s();
4605 GEN_STORE_FTN_FREG(fd, WT2);
4606 opn = "movn.s";
4607 break;
57fa1fb3
TS
4608 case FOP(21, 16):
4609 GEN_LOAD_FREG_FTN(WT0, fs);
4610 gen_op_float_recip_s();
4611 GEN_STORE_FTN_FREG(fd, WT2);
4612 opn = "recip.s";
4613 break;
4614 case FOP(22, 16):
4615 GEN_LOAD_FREG_FTN(WT0, fs);
4616 gen_op_float_rsqrt_s();
4617 GEN_STORE_FTN_FREG(fd, WT2);
4618 opn = "rsqrt.s";
4619 break;
4620 case FOP(28, 16):
4621 gen_op_cp1_64bitmode();
4622 GEN_LOAD_FREG_FTN(WT0, fs);
4623 GEN_LOAD_FREG_FTN(WT2, fd);
4624 gen_op_float_recip2_s();
4625 GEN_STORE_FTN_FREG(fd, WT2);
4626 opn = "recip2.s";
4627 break;
4628 case FOP(29, 16):
4629 gen_op_cp1_64bitmode();
4630 GEN_LOAD_FREG_FTN(WT0, fs);
4631 gen_op_float_recip1_s();
4632 GEN_STORE_FTN_FREG(fd, WT2);
4633 opn = "recip1.s";
4634 break;
4635 case FOP(30, 16):
4636 gen_op_cp1_64bitmode();
4637 GEN_LOAD_FREG_FTN(WT0, fs);
4638 gen_op_float_rsqrt1_s();
4639 GEN_STORE_FTN_FREG(fd, WT2);
4640 opn = "rsqrt1.s";
4641 break;
4642 case FOP(31, 16):
4643 gen_op_cp1_64bitmode();
4644 GEN_LOAD_FREG_FTN(WT0, fs);
4645 GEN_LOAD_FREG_FTN(WT2, fd);
4646 gen_op_float_rsqrt2_s();
4647 GEN_STORE_FTN_FREG(fd, WT2);
4648 opn = "rsqrt2.s";
4649 break;
5a5012ec 4650 case FOP(33, 16):
fd4a04eb 4651 gen_op_cp1_registers(fd);
5a5012ec
TS
4652 GEN_LOAD_FREG_FTN(WT0, fs);
4653 gen_op_float_cvtd_s();
4654 GEN_STORE_FTN_FREG(fd, DT2);
4655 opn = "cvt.d.s";
4656 break;
4657 case FOP(36, 16):
4658 GEN_LOAD_FREG_FTN(WT0, fs);
4659 gen_op_float_cvtw_s();
4660 GEN_STORE_FTN_FREG(fd, WT2);
4661 opn = "cvt.w.s";
4662 break;
4663 case FOP(37, 16):
57fa1fb3 4664 gen_op_cp1_64bitmode();
5a5012ec
TS
4665 GEN_LOAD_FREG_FTN(WT0, fs);
4666 gen_op_float_cvtl_s();
4667 GEN_STORE_FTN_FREG(fd, DT2);
4668 opn = "cvt.l.s";
4669 break;
4670 case FOP(38, 16):
57fa1fb3 4671 gen_op_cp1_64bitmode();
5a5012ec
TS
4672 GEN_LOAD_FREG_FTN(WT1, fs);
4673 GEN_LOAD_FREG_FTN(WT0, ft);
4674 gen_op_float_cvtps_s();
4675 GEN_STORE_FTN_FREG(fd, DT2);
4676 opn = "cvt.ps.s";
4677 break;
4678 case FOP(48, 16):
4679 case FOP(49, 16):
4680 case FOP(50, 16):
4681 case FOP(51, 16):
4682 case FOP(52, 16):
4683 case FOP(53, 16):
4684 case FOP(54, 16):
4685 case FOP(55, 16):
4686 case FOP(56, 16):
4687 case FOP(57, 16):
4688 case FOP(58, 16):
4689 case FOP(59, 16):
4690 case FOP(60, 16):
4691 case FOP(61, 16):
4692 case FOP(62, 16):
4693 case FOP(63, 16):
4694 GEN_LOAD_FREG_FTN(WT0, fs);
4695 GEN_LOAD_FREG_FTN(WT1, ft);
5a1e8ffb 4696 if (ctx->opcode & (1 << 6)) {
57fa1fb3 4697 gen_op_cp1_64bitmode();
5a1e8ffb
TS
4698 gen_cmpabs_s(func-48, cc);
4699 opn = condnames_abs[func-48];
4700 } else {
4701 gen_cmp_s(func-48, cc);
4702 opn = condnames[func-48];
4703 }
5a5012ec 4704 break;
6ea83fed 4705 case FOP(0, 17):
fd4a04eb 4706 gen_op_cp1_registers(fs | ft | fd);
6ea83fed
FB
4707 GEN_LOAD_FREG_FTN(DT0, fs);
4708 GEN_LOAD_FREG_FTN(DT1, ft);
4709 gen_op_float_add_d();
4710 GEN_STORE_FTN_FREG(fd, DT2);
4711 opn = "add.d";
5a1e8ffb 4712 optype = BINOP;
6ea83fed
FB
4713 break;
4714 case FOP(1, 17):
fd4a04eb 4715 gen_op_cp1_registers(fs | ft | fd);
6ea83fed
FB
4716 GEN_LOAD_FREG_FTN(DT0, fs);
4717 GEN_LOAD_FREG_FTN(DT1, ft);
4718 gen_op_float_sub_d();
4719 GEN_STORE_FTN_FREG(fd, DT2);
4720 opn = "sub.d";
5a1e8ffb 4721 optype = BINOP;
6ea83fed
FB
4722 break;
4723 case FOP(2, 17):
fd4a04eb 4724 gen_op_cp1_registers(fs | ft | fd);
6ea83fed
FB
4725 GEN_LOAD_FREG_FTN(DT0, fs);
4726 GEN_LOAD_FREG_FTN(DT1, ft);
4727 gen_op_float_mul_d();
4728 GEN_STORE_FTN_FREG(fd, DT2);
4729 opn = "mul.d";
5a1e8ffb 4730 optype = BINOP;
6ea83fed
FB
4731 break;
4732 case FOP(3, 17):
fd4a04eb 4733 gen_op_cp1_registers(fs | ft | fd);
6ea83fed
FB
4734 GEN_LOAD_FREG_FTN(DT0, fs);
4735 GEN_LOAD_FREG_FTN(DT1, ft);
4736 gen_op_float_div_d();
4737 GEN_STORE_FTN_FREG(fd, DT2);
4738 opn = "div.d";
5a1e8ffb 4739 optype = BINOP;
6ea83fed
FB
4740 break;
4741 case FOP(4, 17):
fd4a04eb 4742 gen_op_cp1_registers(fs | fd);
6ea83fed
FB
4743 GEN_LOAD_FREG_FTN(DT0, fs);
4744 gen_op_float_sqrt_d();
4745 GEN_STORE_FTN_FREG(fd, DT2);
4746 opn = "sqrt.d";
4747 break;
4748 case FOP(5, 17):
fd4a04eb 4749 gen_op_cp1_registers(fs | fd);
6ea83fed
FB
4750 GEN_LOAD_FREG_FTN(DT0, fs);
4751 gen_op_float_abs_d();
4752 GEN_STORE_FTN_FREG(fd, DT2);
4753 opn = "abs.d";
4754 break;
4755 case FOP(6, 17):
fd4a04eb 4756 gen_op_cp1_registers(fs | fd);
6ea83fed
FB
4757 GEN_LOAD_FREG_FTN(DT0, fs);
4758 gen_op_float_mov_d();
4759 GEN_STORE_FTN_FREG(fd, DT2);
4760 opn = "mov.d";
4761 break;
4762 case FOP(7, 17):
fd4a04eb 4763 gen_op_cp1_registers(fs | fd);
6ea83fed
FB
4764 GEN_LOAD_FREG_FTN(DT0, fs);
4765 gen_op_float_chs_d();
4766 GEN_STORE_FTN_FREG(fd, DT2);
4767 opn = "neg.d";
4768 break;
5a5012ec 4769 case FOP(8, 17):
57fa1fb3 4770 gen_op_cp1_64bitmode();
5a5012ec
TS
4771 GEN_LOAD_FREG_FTN(DT0, fs);
4772 gen_op_float_roundl_d();
4773 GEN_STORE_FTN_FREG(fd, DT2);
4774 opn = "round.l.d";
4775 break;
4776 case FOP(9, 17):
57fa1fb3 4777 gen_op_cp1_64bitmode();
5a5012ec
TS
4778 GEN_LOAD_FREG_FTN(DT0, fs);
4779 gen_op_float_truncl_d();
4780 GEN_STORE_FTN_FREG(fd, DT2);
4781 opn = "trunc.l.d";
4782 break;
4783 case FOP(10, 17):
57fa1fb3 4784 gen_op_cp1_64bitmode();
5a5012ec
TS
4785 GEN_LOAD_FREG_FTN(DT0, fs);
4786 gen_op_float_ceill_d();
4787 GEN_STORE_FTN_FREG(fd, DT2);
4788 opn = "ceil.l.d";
4789 break;
4790 case FOP(11, 17):
57fa1fb3 4791 gen_op_cp1_64bitmode();
5a5012ec
TS
4792 GEN_LOAD_FREG_FTN(DT0, fs);
4793 gen_op_float_floorl_d();
4794 GEN_STORE_FTN_FREG(fd, DT2);
4795 opn = "floor.l.d";
4796 break;
6ea83fed 4797 case FOP(12, 17):
fd4a04eb 4798 gen_op_cp1_registers(fs);
6ea83fed
FB
4799 GEN_LOAD_FREG_FTN(DT0, fs);
4800 gen_op_float_roundw_d();
4801 GEN_STORE_FTN_FREG(fd, WT2);
4802 opn = "round.w.d";
4803 break;
4804 case FOP(13, 17):
fd4a04eb 4805 gen_op_cp1_registers(fs);
6ea83fed
FB
4806 GEN_LOAD_FREG_FTN(DT0, fs);
4807 gen_op_float_truncw_d();
4808 GEN_STORE_FTN_FREG(fd, WT2);
4809 opn = "trunc.w.d";
4810 break;
4811 case FOP(14, 17):
fd4a04eb 4812 gen_op_cp1_registers(fs);
6ea83fed
FB
4813 GEN_LOAD_FREG_FTN(DT0, fs);
4814 gen_op_float_ceilw_d();
4815 GEN_STORE_FTN_FREG(fd, WT2);
4816 opn = "ceil.w.d";
4817 break;
4818 case FOP(15, 17):
fd4a04eb 4819 gen_op_cp1_registers(fs);
6ea83fed
FB
4820 GEN_LOAD_FREG_FTN(DT0, fs);
4821 gen_op_float_floorw_d();
4822 GEN_STORE_FTN_FREG(fd, WT2);
7a387fff 4823 opn = "floor.w.d";
6ea83fed 4824 break;
5a5012ec
TS
4825 case FOP(17, 17):
4826 GEN_LOAD_REG_TN(T0, ft);
4827 GEN_LOAD_FREG_FTN(DT0, fs);
4828 GEN_LOAD_FREG_FTN(DT2, fd);
4829 gen_movcf_d(ctx, (ft >> 2) & 0x7, ft & 0x1);
dd016883 4830 GEN_STORE_FTN_FREG(fd, DT2);
5a5012ec 4831 opn = "movcf.d";
dd016883 4832 break;
5a5012ec
TS
4833 case FOP(18, 17):
4834 GEN_LOAD_REG_TN(T0, ft);
4835 GEN_LOAD_FREG_FTN(DT0, fs);
4836 GEN_LOAD_FREG_FTN(DT2, fd);
4837 gen_op_float_movz_d();
6ea83fed 4838 GEN_STORE_FTN_FREG(fd, DT2);
5a5012ec
TS
4839 opn = "movz.d";
4840 break;
4841 case FOP(19, 17):
4842 GEN_LOAD_REG_TN(T0, ft);
4843 GEN_LOAD_FREG_FTN(DT0, fs);
4844 GEN_LOAD_FREG_FTN(DT2, fd);
4845 gen_op_float_movn_d();
4846 GEN_STORE_FTN_FREG(fd, DT2);
4847 opn = "movn.d";
6ea83fed 4848 break;
57fa1fb3
TS
4849 case FOP(21, 17):
4850 gen_op_cp1_registers(fs | fd);
4851 GEN_LOAD_FREG_FTN(DT0, fs);
4852 gen_op_float_recip_d();
4853 GEN_STORE_FTN_FREG(fd, DT2);
4854 opn = "recip.d";
4855 break;
4856 case FOP(22, 17):
4857 gen_op_cp1_registers(fs | fd);
4858 GEN_LOAD_FREG_FTN(DT0, fs);
4859 gen_op_float_rsqrt_d();
4860 GEN_STORE_FTN_FREG(fd, DT2);
4861 opn = "rsqrt.d";
4862 break;
4863 case FOP(28, 17):
4864 gen_op_cp1_64bitmode();
4865 GEN_LOAD_FREG_FTN(DT0, fs);
4866 GEN_LOAD_FREG_FTN(DT2, ft);
4867 gen_op_float_recip2_d();
4868 GEN_STORE_FTN_FREG(fd, DT2);
4869 opn = "recip2.d";
4870 break;
4871 case FOP(29, 17):
4872 gen_op_cp1_64bitmode();
4873 GEN_LOAD_FREG_FTN(DT0, fs);
4874 gen_op_float_recip1_d();
4875 GEN_STORE_FTN_FREG(fd, DT2);
4876 opn = "recip1.d";
4877 break;
4878 case FOP(30, 17):
4879 gen_op_cp1_64bitmode();
4880 GEN_LOAD_FREG_FTN(DT0, fs);
4881 gen_op_float_rsqrt1_d();
4882 GEN_STORE_FTN_FREG(fd, DT2);
4883 opn = "rsqrt1.d";
4884 break;
4885 case FOP(31, 17):
4886 gen_op_cp1_64bitmode();
4887 GEN_LOAD_FREG_FTN(DT0, fs);
4888 GEN_LOAD_FREG_FTN(DT2, ft);
4889 gen_op_float_rsqrt2_d();
4890 GEN_STORE_FTN_FREG(fd, DT2);
4891 opn = "rsqrt2.d";
4892 break;
6ea83fed
FB
4893 case FOP(48, 17):
4894 case FOP(49, 17):
4895 case FOP(50, 17):
4896 case FOP(51, 17):
4897 case FOP(52, 17):
4898 case FOP(53, 17):
4899 case FOP(54, 17):
4900 case FOP(55, 17):
4901 case FOP(56, 17):
4902 case FOP(57, 17):
4903 case FOP(58, 17):
4904 case FOP(59, 17):
4905 case FOP(60, 17):
4906 case FOP(61, 17):
4907 case FOP(62, 17):
4908 case FOP(63, 17):
6ea83fed
FB
4909 GEN_LOAD_FREG_FTN(DT0, fs);
4910 GEN_LOAD_FREG_FTN(DT1, ft);
5a1e8ffb 4911 if (ctx->opcode & (1 << 6)) {
57fa1fb3 4912 gen_op_cp1_64bitmode();
5a1e8ffb
TS
4913 gen_cmpabs_d(func-48, cc);
4914 opn = condnames_abs[func-48];
4915 } else {
57fa1fb3 4916 gen_op_cp1_registers(fs | ft);
5a1e8ffb
TS
4917 gen_cmp_d(func-48, cc);
4918 opn = condnames[func-48];
4919 }
6ea83fed 4920 break;
5a5012ec 4921 case FOP(32, 17):
fd4a04eb 4922 gen_op_cp1_registers(fs);
5a5012ec
TS
4923 GEN_LOAD_FREG_FTN(DT0, fs);
4924 gen_op_float_cvts_d();
4925 GEN_STORE_FTN_FREG(fd, WT2);
4926 opn = "cvt.s.d";
4927 break;
4928 case FOP(36, 17):
fd4a04eb 4929 gen_op_cp1_registers(fs);
5a5012ec
TS
4930 GEN_LOAD_FREG_FTN(DT0, fs);
4931 gen_op_float_cvtw_d();
4932 GEN_STORE_FTN_FREG(fd, WT2);
4933 opn = "cvt.w.d";
4934 break;
4935 case FOP(37, 17):
57fa1fb3 4936 gen_op_cp1_64bitmode();
5a5012ec
TS
4937 GEN_LOAD_FREG_FTN(DT0, fs);
4938 gen_op_float_cvtl_d();
4939 GEN_STORE_FTN_FREG(fd, DT2);
4940 opn = "cvt.l.d";
4941 break;
4942 case FOP(32, 20):
6ea83fed 4943 GEN_LOAD_FREG_FTN(WT0, fs);
5a5012ec 4944 gen_op_float_cvts_w();
6ea83fed 4945 GEN_STORE_FTN_FREG(fd, WT2);
5a5012ec 4946 opn = "cvt.s.w";
6ea83fed 4947 break;
5a5012ec 4948 case FOP(33, 20):
fd4a04eb 4949 gen_op_cp1_registers(fd);
6ea83fed 4950 GEN_LOAD_FREG_FTN(WT0, fs);
5a5012ec
TS
4951 gen_op_float_cvtd_w();
4952 GEN_STORE_FTN_FREG(fd, DT2);
4953 opn = "cvt.d.w";
4954 break;
4955 case FOP(32, 21):
57fa1fb3 4956 gen_op_cp1_64bitmode();
5a5012ec
TS
4957 GEN_LOAD_FREG_FTN(DT0, fs);
4958 gen_op_float_cvts_l();
4959 GEN_STORE_FTN_FREG(fd, WT2);
4960 opn = "cvt.s.l";
4961 break;
4962 case FOP(33, 21):
57fa1fb3 4963 gen_op_cp1_64bitmode();
5a5012ec
TS
4964 GEN_LOAD_FREG_FTN(DT0, fs);
4965 gen_op_float_cvtd_l();
4966 GEN_STORE_FTN_FREG(fd, DT2);
4967 opn = "cvt.d.l";
4968 break;
4969 case FOP(38, 20):
4970 case FOP(38, 21):
57fa1fb3 4971 gen_op_cp1_64bitmode();
5a5012ec
TS
4972 GEN_LOAD_FREG_FTN(WT0, fs);
4973 GEN_LOAD_FREG_FTN(WTH0, fs);
4974 gen_op_float_cvtps_pw();
4975 GEN_STORE_FTN_FREG(fd, WT2);
4976 GEN_STORE_FTN_FREG(fd, WTH2);
4977 opn = "cvt.ps.pw";
4978 break;
4979 case FOP(0, 22):
57fa1fb3 4980 gen_op_cp1_64bitmode();
5a5012ec
TS
4981 GEN_LOAD_FREG_FTN(WT0, fs);
4982 GEN_LOAD_FREG_FTN(WTH0, fs);
6ea83fed 4983 GEN_LOAD_FREG_FTN(WT1, ft);
5a5012ec
TS
4984 GEN_LOAD_FREG_FTN(WTH1, ft);
4985 gen_op_float_add_ps();
6ea83fed 4986 GEN_STORE_FTN_FREG(fd, WT2);
5a5012ec
TS
4987 GEN_STORE_FTN_FREG(fd, WTH2);
4988 opn = "add.ps";
6ea83fed 4989 break;
5a5012ec 4990 case FOP(1, 22):
57fa1fb3 4991 gen_op_cp1_64bitmode();
6ea83fed 4992 GEN_LOAD_FREG_FTN(WT0, fs);
5a5012ec 4993 GEN_LOAD_FREG_FTN(WTH0, fs);
6ea83fed 4994 GEN_LOAD_FREG_FTN(WT1, ft);
5a5012ec
TS
4995 GEN_LOAD_FREG_FTN(WTH1, ft);
4996 gen_op_float_sub_ps();
6ea83fed 4997 GEN_STORE_FTN_FREG(fd, WT2);
5a5012ec
TS
4998 GEN_STORE_FTN_FREG(fd, WTH2);
4999 opn = "sub.ps";
6ea83fed 5000 break;
5a5012ec 5001 case FOP(2, 22):
57fa1fb3 5002 gen_op_cp1_64bitmode();
6ea83fed 5003 GEN_LOAD_FREG_FTN(WT0, fs);
5a5012ec 5004 GEN_LOAD_FREG_FTN(WTH0, fs);
6ea83fed 5005 GEN_LOAD_FREG_FTN(WT1, ft);
5a5012ec
TS
5006 GEN_LOAD_FREG_FTN(WTH1, ft);
5007 gen_op_float_mul_ps();
6ea83fed 5008 GEN_STORE_FTN_FREG(fd, WT2);
5a5012ec
TS
5009 GEN_STORE_FTN_FREG(fd, WTH2);
5010 opn = "mul.ps";
6ea83fed 5011 break;
5a5012ec 5012 case FOP(5, 22):
57fa1fb3 5013 gen_op_cp1_64bitmode();
6ea83fed 5014 GEN_LOAD_FREG_FTN(WT0, fs);
5a5012ec
TS
5015 GEN_LOAD_FREG_FTN(WTH0, fs);
5016 gen_op_float_abs_ps();
6ea83fed 5017 GEN_STORE_FTN_FREG(fd, WT2);
5a5012ec
TS
5018 GEN_STORE_FTN_FREG(fd, WTH2);
5019 opn = "abs.ps";
6ea83fed 5020 break;
5a5012ec 5021 case FOP(6, 22):
57fa1fb3 5022 gen_op_cp1_64bitmode();
6ea83fed 5023 GEN_LOAD_FREG_FTN(WT0, fs);
5a5012ec
TS
5024 GEN_LOAD_FREG_FTN(WTH0, fs);
5025 gen_op_float_mov_ps();
6ea83fed 5026 GEN_STORE_FTN_FREG(fd, WT2);
5a5012ec
TS
5027 GEN_STORE_FTN_FREG(fd, WTH2);
5028 opn = "mov.ps";
6ea83fed 5029 break;
5a5012ec 5030 case FOP(7, 22):
57fa1fb3 5031 gen_op_cp1_64bitmode();
6ea83fed 5032 GEN_LOAD_FREG_FTN(WT0, fs);
5a5012ec
TS
5033 GEN_LOAD_FREG_FTN(WTH0, fs);
5034 gen_op_float_chs_ps();
6ea83fed 5035 GEN_STORE_FTN_FREG(fd, WT2);
5a5012ec
TS
5036 GEN_STORE_FTN_FREG(fd, WTH2);
5037 opn = "neg.ps";
6ea83fed 5038 break;
5a5012ec 5039 case FOP(17, 22):
57fa1fb3 5040 gen_op_cp1_64bitmode();
5a5012ec 5041 GEN_LOAD_REG_TN(T0, ft);
6ea83fed 5042 GEN_LOAD_FREG_FTN(WT0, fs);
5a5012ec
TS
5043 GEN_LOAD_FREG_FTN(WTH0, fs);
5044 GEN_LOAD_FREG_FTN(WT2, fd);
5045 GEN_LOAD_FREG_FTN(WTH2, fd);
5046 gen_movcf_ps(ctx, (ft >> 2) & 0x7, ft & 0x1);
6ea83fed 5047 GEN_STORE_FTN_FREG(fd, WT2);
5a5012ec
TS
5048 GEN_STORE_FTN_FREG(fd, WTH2);
5049 opn = "movcf.ps";
6ea83fed 5050 break;
5a5012ec 5051 case FOP(18, 22):
57fa1fb3 5052 gen_op_cp1_64bitmode();
5a5012ec 5053 GEN_LOAD_REG_TN(T0, ft);
6ea83fed 5054 GEN_LOAD_FREG_FTN(WT0, fs);
5a5012ec
TS
5055 GEN_LOAD_FREG_FTN(WTH0, fs);
5056 GEN_LOAD_FREG_FTN(WT2, fd);
5057 GEN_LOAD_FREG_FTN(WTH2, fd);
5058 gen_op_float_movz_ps();
6ea83fed 5059 GEN_STORE_FTN_FREG(fd, WT2);
5a5012ec
TS
5060 GEN_STORE_FTN_FREG(fd, WTH2);
5061 opn = "movz.ps";
6ea83fed 5062 break;
5a5012ec 5063 case FOP(19, 22):
57fa1fb3 5064 gen_op_cp1_64bitmode();
5a5012ec 5065 GEN_LOAD_REG_TN(T0, ft);
6ea83fed 5066 GEN_LOAD_FREG_FTN(WT0, fs);
5a5012ec
TS
5067 GEN_LOAD_FREG_FTN(WTH0, fs);
5068 GEN_LOAD_FREG_FTN(WT2, fd);
5069 GEN_LOAD_FREG_FTN(WTH2, fd);
5070 gen_op_float_movn_ps();
6ea83fed 5071 GEN_STORE_FTN_FREG(fd, WT2);
5a5012ec
TS
5072 GEN_STORE_FTN_FREG(fd, WTH2);
5073 opn = "movn.ps";
6ea83fed 5074 break;
fbcc6828 5075 case FOP(24, 22):
57fa1fb3 5076 gen_op_cp1_64bitmode();
fbcc6828
TS
5077 GEN_LOAD_FREG_FTN(WT0, fs);
5078 GEN_LOAD_FREG_FTN(WTH0, fs);
5079 GEN_LOAD_FREG_FTN(WT1, ft);
5080 GEN_LOAD_FREG_FTN(WTH1, ft);
5081 gen_op_float_addr_ps();
5082 GEN_STORE_FTN_FREG(fd, WT2);
5083 GEN_STORE_FTN_FREG(fd, WTH2);
5084 opn = "addr.ps";
5085 break;
57fa1fb3
TS
5086 case FOP(26, 22):
5087 gen_op_cp1_64bitmode();
5088 GEN_LOAD_FREG_FTN(WT0, fs);
5089 GEN_LOAD_FREG_FTN(WTH0, fs);
5090 GEN_LOAD_FREG_FTN(WT1, ft);
5091 GEN_LOAD_FREG_FTN(WTH1, ft);
5092 gen_op_float_mulr_ps();
5093 GEN_STORE_FTN_FREG(fd, WT2);
5094 GEN_STORE_FTN_FREG(fd, WTH2);
5095 opn = "mulr.ps";
5096 break;
5097 case FOP(28, 22):
5098 gen_op_cp1_64bitmode();
5099 GEN_LOAD_FREG_FTN(WT0, fs);
5100 GEN_LOAD_FREG_FTN(WTH0, fs);
5101 GEN_LOAD_FREG_FTN(WT2, fd);
5102 GEN_LOAD_FREG_FTN(WTH2, fd);
5103 gen_op_float_recip2_ps();
5104 GEN_STORE_FTN_FREG(fd, WT2);
5105 GEN_STORE_FTN_FREG(fd, WTH2);
5106 opn = "recip2.ps";
5107 break;
5108 case FOP(29, 22):
5109 gen_op_cp1_64bitmode();
5110 GEN_LOAD_FREG_FTN(WT0, fs);
5111 GEN_LOAD_FREG_FTN(WTH0, fs);
5112 gen_op_float_recip1_ps();
5113 GEN_STORE_FTN_FREG(fd, WT2);
5114 GEN_STORE_FTN_FREG(fd, WTH2);
5115 opn = "recip1.ps";
5116 break;
5117 case FOP(30, 22):
5118 gen_op_cp1_64bitmode();
5119 GEN_LOAD_FREG_FTN(WT0, fs);
5120 GEN_LOAD_FREG_FTN(WTH0, fs);
5121 gen_op_float_rsqrt1_ps();
5122 GEN_STORE_FTN_FREG(fd, WT2);
5123 GEN_STORE_FTN_FREG(fd, WTH2);
5124 opn = "rsqrt1.ps";
5125 break;
5126 case FOP(31, 22):
5127 gen_op_cp1_64bitmode();
5128 GEN_LOAD_FREG_FTN(WT0, fs);
5129 GEN_LOAD_FREG_FTN(WTH0, fs);
5130 GEN_LOAD_FREG_FTN(WT2, fd);
5131 GEN_LOAD_FREG_FTN(WTH2, fd);
5132 gen_op_float_rsqrt2_ps();
5133 GEN_STORE_FTN_FREG(fd, WT2);
5134 GEN_STORE_FTN_FREG(fd, WTH2);
5135 opn = "rsqrt2.ps";
5136 break;
5a5012ec 5137 case FOP(32, 22):
57fa1fb3 5138 gen_op_cp1_64bitmode();
5a5012ec
TS
5139 GEN_LOAD_FREG_FTN(WTH0, fs);
5140 gen_op_float_cvts_pu();
dd016883 5141 GEN_STORE_FTN_FREG(fd, WT2);
5a5012ec 5142 opn = "cvt.s.pu";
dd016883 5143 break;
5a5012ec 5144 case FOP(36, 22):
57fa1fb3 5145 gen_op_cp1_64bitmode();
6ea83fed 5146 GEN_LOAD_FREG_FTN(WT0, fs);
5a5012ec
TS
5147 GEN_LOAD_FREG_FTN(WTH0, fs);
5148 gen_op_float_cvtpw_ps();
6ea83fed 5149 GEN_STORE_FTN_FREG(fd, WT2);
5a5012ec
TS
5150 GEN_STORE_FTN_FREG(fd, WTH2);
5151 opn = "cvt.pw.ps";
6ea83fed 5152 break;
5a5012ec 5153 case FOP(40, 22):
57fa1fb3 5154 gen_op_cp1_64bitmode();
6ea83fed 5155 GEN_LOAD_FREG_FTN(WT0, fs);
5a5012ec 5156 gen_op_float_cvts_pl();
6ea83fed 5157 GEN_STORE_FTN_FREG(fd, WT2);
5a5012ec 5158 opn = "cvt.s.pl";
6ea83fed 5159 break;
5a5012ec 5160 case FOP(44, 22):
57fa1fb3 5161 gen_op_cp1_64bitmode();
5a5012ec
TS
5162 GEN_LOAD_FREG_FTN(WT0, fs);
5163 GEN_LOAD_FREG_FTN(WT1, ft);
5164 gen_op_float_pll_ps();
5165 GEN_STORE_FTN_FREG(fd, DT2);
5166 opn = "pll.ps";
6ea83fed 5167 break;
5a5012ec 5168 case FOP(45, 22):
57fa1fb3 5169 gen_op_cp1_64bitmode();
6ea83fed 5170 GEN_LOAD_FREG_FTN(WT0, fs);
5a5012ec
TS
5171 GEN_LOAD_FREG_FTN(WTH1, ft);
5172 gen_op_float_plu_ps();
5173 GEN_STORE_FTN_FREG(fd, DT2);
5174 opn = "plu.ps";
5175 break;
5176 case FOP(46, 22):
57fa1fb3 5177 gen_op_cp1_64bitmode();
5a5012ec 5178 GEN_LOAD_FREG_FTN(WTH0, fs);
6ea83fed 5179 GEN_LOAD_FREG_FTN(WT1, ft);
5a5012ec
TS
5180 gen_op_float_pul_ps();
5181 GEN_STORE_FTN_FREG(fd, DT2);
5182 opn = "pul.ps";
5183 break;
5184 case FOP(47, 22):
57fa1fb3 5185 gen_op_cp1_64bitmode();
5a5012ec
TS
5186 GEN_LOAD_FREG_FTN(WTH0, fs);
5187 GEN_LOAD_FREG_FTN(WTH1, ft);
5188 gen_op_float_puu_ps();
5189 GEN_STORE_FTN_FREG(fd, DT2);
5190 opn = "puu.ps";
5191 break;
5192 case FOP(48, 22):
5193 case FOP(49, 22):
5194 case FOP(50, 22):
5195 case FOP(51, 22):
5196 case FOP(52, 22):
5197 case FOP(53, 22):
5198 case FOP(54, 22):
5199 case FOP(55, 22):
5200 case FOP(56, 22):
5201 case FOP(57, 22):
5202 case FOP(58, 22):
5203 case FOP(59, 22):
5204 case FOP(60, 22):
5205 case FOP(61, 22):
5206 case FOP(62, 22):
5207 case FOP(63, 22):
57fa1fb3 5208 gen_op_cp1_64bitmode();
5a5012ec
TS
5209 GEN_LOAD_FREG_FTN(WT0, fs);
5210 GEN_LOAD_FREG_FTN(WTH0, fs);
5211 GEN_LOAD_FREG_FTN(WT1, ft);
5212 GEN_LOAD_FREG_FTN(WTH1, ft);
5a1e8ffb
TS
5213 if (ctx->opcode & (1 << 6)) {
5214 gen_cmpabs_ps(func-48, cc);
5215 opn = condnames_abs[func-48];
5216 } else {
5217 gen_cmp_ps(func-48, cc);
5218 opn = condnames[func-48];
5219 }
6ea83fed 5220 break;
5a5012ec 5221 default:
923617a3 5222 MIPS_INVAL(opn);
e397ee33 5223 generate_exception (ctx, EXCP_RI);
6ea83fed
FB
5224 return;
5225 }
5a1e8ffb
TS
5226 switch (optype) {
5227 case BINOP:
6ea83fed 5228 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
5a1e8ffb
TS
5229 break;
5230 case CMPOP:
5231 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
5232 break;
5233 default:
6ea83fed 5234 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
5a1e8ffb
TS
5235 break;
5236 }
6ea83fed 5237}
6af0bf9c 5238
5a5012ec
TS
5239/* Coprocessor 3 (FPU) */
5240static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc, int fd,
93b12ccc 5241 int fs, int base, int index)
7a387fff 5242{
923617a3 5243 const char *opn = "extended float load/store";
93b12ccc 5244 int store = 0;
7a387fff 5245
57fa1fb3
TS
5246 /* All of those work only on 64bit FPUs. */
5247 gen_op_cp1_64bitmode();
93b12ccc
TS
5248 if (base == 0) {
5249 if (index == 0)
5250 gen_op_reset_T0();
5251 else
5252 GEN_LOAD_REG_TN(T0, index);
5253 } else if (index == 0) {
5254 GEN_LOAD_REG_TN(T0, base);
5255 } else {
5256 GEN_LOAD_REG_TN(T0, base);
5257 GEN_LOAD_REG_TN(T1, index);
5258 gen_op_addr_add();
5259 }
5a5012ec
TS
5260 /* Don't do NOP if destination is zero: we must perform the actual
5261 * memory access
5262 */
5263 switch (opc) {
5264 case OPC_LWXC1:
93b12ccc 5265 op_ldst(lwc1);
5a5012ec
TS
5266 GEN_STORE_FTN_FREG(fd, WT0);
5267 opn = "lwxc1";
5268 break;
5269 case OPC_LDXC1:
93b12ccc 5270 op_ldst(ldc1);
5a5012ec
TS
5271 GEN_STORE_FTN_FREG(fd, DT0);
5272 opn = "ldxc1";
5273 break;
5274 case OPC_LUXC1:
5275 op_ldst(luxc1);
5276 GEN_STORE_FTN_FREG(fd, DT0);
5277 opn = "luxc1";
5278 break;
5279 case OPC_SWXC1:
93b12ccc
TS
5280 GEN_LOAD_FREG_FTN(WT0, fs);
5281 op_ldst(swc1);
5a5012ec 5282 opn = "swxc1";
93b12ccc 5283 store = 1;
5a5012ec
TS
5284 break;
5285 case OPC_SDXC1:
93b12ccc
TS
5286 GEN_LOAD_FREG_FTN(DT0, fs);
5287 op_ldst(sdc1);
5a5012ec 5288 opn = "sdxc1";
93b12ccc 5289 store = 1;
5a5012ec
TS
5290 break;
5291 case OPC_SUXC1:
93b12ccc 5292 GEN_LOAD_FREG_FTN(DT0, fs);
5a5012ec
TS
5293 op_ldst(suxc1);
5294 opn = "suxc1";
93b12ccc 5295 store = 1;
5a5012ec
TS
5296 break;
5297 default:
923617a3 5298 MIPS_INVAL(opn);
5a5012ec
TS
5299 generate_exception(ctx, EXCP_RI);
5300 return;
5301 }
93b12ccc
TS
5302 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
5303 regnames[index], regnames[base]);
5a5012ec
TS
5304}
5305
5306static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, int fd,
5307 int fr, int fs, int ft)
5308{
923617a3 5309 const char *opn = "flt3_arith";
5a5012ec
TS
5310
5311 /* All of those work only on 64bit FPUs. */
57fa1fb3 5312 gen_op_cp1_64bitmode();
5a5012ec
TS
5313 switch (opc) {
5314 case OPC_ALNV_PS:
5315 GEN_LOAD_REG_TN(T0, fr);
5316 GEN_LOAD_FREG_FTN(DT0, fs);
5317 GEN_LOAD_FREG_FTN(DT1, ft);
5318 gen_op_float_alnv_ps();
5319 GEN_STORE_FTN_FREG(fd, DT2);
5320 opn = "alnv.ps";
5321 break;
5322 case OPC_MADD_S:
5323 GEN_LOAD_FREG_FTN(WT0, fs);
5324 GEN_LOAD_FREG_FTN(WT1, ft);
5325 GEN_LOAD_FREG_FTN(WT2, fr);
5326 gen_op_float_muladd_s();
5327 GEN_STORE_FTN_FREG(fd, WT2);
5328 opn = "madd.s";
5329 break;
5330 case OPC_MADD_D:
fbcc6828
TS
5331 GEN_LOAD_FREG_FTN(DT0, fs);
5332 GEN_LOAD_FREG_FTN(DT1, ft);
5333 GEN_LOAD_FREG_FTN(DT2, fr);
5334 gen_op_float_muladd_d();
5335 GEN_STORE_FTN_FREG(fd, DT2);
5a5012ec
TS
5336 opn = "madd.d";
5337 break;
5338 case OPC_MADD_PS:
fbcc6828
TS
5339 GEN_LOAD_FREG_FTN(WT0, fs);
5340 GEN_LOAD_FREG_FTN(WTH0, fs);
5341 GEN_LOAD_FREG_FTN(WT1, ft);
5342 GEN_LOAD_FREG_FTN(WTH1, ft);
5343 GEN_LOAD_FREG_FTN(WT2, fr);
5344 GEN_LOAD_FREG_FTN(WTH2, fr);
5345 gen_op_float_muladd_ps();
5346 GEN_STORE_FTN_FREG(fd, WT2);
5347 GEN_STORE_FTN_FREG(fd, WTH2);
5a5012ec
TS
5348 opn = "madd.ps";
5349 break;
5350 case OPC_MSUB_S:
fbcc6828
TS
5351 GEN_LOAD_FREG_FTN(WT0, fs);
5352 GEN_LOAD_FREG_FTN(WT1, ft);
5353 GEN_LOAD_FREG_FTN(WT2, fr);
5354 gen_op_float_mulsub_s();
5355 GEN_STORE_FTN_FREG(fd, WT2);
5a5012ec
TS
5356 opn = "msub.s";
5357 break;
5358 case OPC_MSUB_D:
fbcc6828
TS
5359 GEN_LOAD_FREG_FTN(DT0, fs);
5360 GEN_LOAD_FREG_FTN(DT1, ft);
5361 GEN_LOAD_FREG_FTN(DT2, fr);
5362 gen_op_float_mulsub_d();
5363 GEN_STORE_FTN_FREG(fd, DT2);
5a5012ec
TS
5364 opn = "msub.d";
5365 break;
5366 case OPC_MSUB_PS:
fbcc6828
TS
5367 GEN_LOAD_FREG_FTN(WT0, fs);
5368 GEN_LOAD_FREG_FTN(WTH0, fs);
5369 GEN_LOAD_FREG_FTN(WT1, ft);
5370 GEN_LOAD_FREG_FTN(WTH1, ft);
5371 GEN_LOAD_FREG_FTN(WT2, fr);
5372 GEN_LOAD_FREG_FTN(WTH2, fr);
5373 gen_op_float_mulsub_ps();
5374 GEN_STORE_FTN_FREG(fd, WT2);
5375 GEN_STORE_FTN_FREG(fd, WTH2);
5a5012ec
TS
5376 opn = "msub.ps";
5377 break;
5378 case OPC_NMADD_S:
fbcc6828
TS
5379 GEN_LOAD_FREG_FTN(WT0, fs);
5380 GEN_LOAD_FREG_FTN(WT1, ft);
5381 GEN_LOAD_FREG_FTN(WT2, fr);
5382 gen_op_float_nmuladd_s();
5383 GEN_STORE_FTN_FREG(fd, WT2);
5a5012ec
TS
5384 opn = "nmadd.s";
5385 break;
5386 case OPC_NMADD_D:
fbcc6828
TS
5387 GEN_LOAD_FREG_FTN(DT0, fs);
5388 GEN_LOAD_FREG_FTN(DT1, ft);
5389 GEN_LOAD_FREG_FTN(DT2, fr);
5390 gen_op_float_nmuladd_d();
5391 GEN_STORE_FTN_FREG(fd, DT2);
5a5012ec
TS
5392 opn = "nmadd.d";
5393 break;
5394 case OPC_NMADD_PS:
fbcc6828
TS
5395 GEN_LOAD_FREG_FTN(WT0, fs);
5396 GEN_LOAD_FREG_FTN(WTH0, fs);
5397 GEN_LOAD_FREG_FTN(WT1, ft);
5398 GEN_LOAD_FREG_FTN(WTH1, ft);
5399 GEN_LOAD_FREG_FTN(WT2, fr);
5400 GEN_LOAD_FREG_FTN(WTH2, fr);
5401 gen_op_float_nmuladd_ps();
5402 GEN_STORE_FTN_FREG(fd, WT2);
5403 GEN_STORE_FTN_FREG(fd, WTH2);
5a5012ec
TS
5404 opn = "nmadd.ps";
5405 break;
5406 case OPC_NMSUB_S:
fbcc6828
TS
5407 GEN_LOAD_FREG_FTN(WT0, fs);
5408 GEN_LOAD_FREG_FTN(WT1, ft);
5409 GEN_LOAD_FREG_FTN(WT2, fr);
5410 gen_op_float_nmulsub_s();
5411 GEN_STORE_FTN_FREG(fd, WT2);
5a5012ec
TS
5412 opn = "nmsub.s";
5413 break;
5414 case OPC_NMSUB_D:
fbcc6828
TS
5415 GEN_LOAD_FREG_FTN(DT0, fs);
5416 GEN_LOAD_FREG_FTN(DT1, ft);
5417 GEN_LOAD_FREG_FTN(DT2, fr);
5418 gen_op_float_nmulsub_d();
5419 GEN_STORE_FTN_FREG(fd, DT2);
5a5012ec
TS
5420 opn = "nmsub.d";
5421 break;
5422 case OPC_NMSUB_PS:
fbcc6828
TS
5423 GEN_LOAD_FREG_FTN(WT0, fs);
5424 GEN_LOAD_FREG_FTN(WTH0, fs);
5425 GEN_LOAD_FREG_FTN(WT1, ft);
5426 GEN_LOAD_FREG_FTN(WTH1, ft);
5427 GEN_LOAD_FREG_FTN(WT2, fr);
5428 GEN_LOAD_FREG_FTN(WTH2, fr);
5429 gen_op_float_nmulsub_ps();
5430 GEN_STORE_FTN_FREG(fd, WT2);
5431 GEN_STORE_FTN_FREG(fd, WTH2);
5a5012ec
TS
5432 opn = "nmsub.ps";
5433 break;
923617a3
TS
5434 default:
5435 MIPS_INVAL(opn);
5a5012ec
TS
5436 generate_exception (ctx, EXCP_RI);
5437 return;
5438 }
5439 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
5440 fregnames[fs], fregnames[ft]);
7a387fff
TS
5441}
5442
5443/* ISA extensions (ASEs) */
6af0bf9c
FB
5444/* MIPS16 extension to MIPS32 */
5445/* SmartMIPS extension to MIPS32 */
5446
60aa19ab 5447#ifdef TARGET_MIPS64
6af0bf9c
FB
5448
5449/* MDMX extension to MIPS64 */
5450/* MIPS-3D extension to MIPS64 */
5451
5452#endif
5453
36d23958 5454static void decode_opc (CPUState *env, DisasContext *ctx)
6af0bf9c
FB
5455{
5456 int32_t offset;
5457 int rs, rt, rd, sa;
7a387fff 5458 uint32_t op, op1, op2;
6af0bf9c
FB
5459 int16_t imm;
5460
d796321b
FB
5461 /* make sure instructions are on a word boundary */
5462 if (ctx->pc & 0x3) {
cbeb0857 5463 env->CP0_BadVAddr = ctx->pc;
d796321b
FB
5464 generate_exception(ctx, EXCP_AdEL);
5465 return;
5466 }
5467
4ad40f36 5468 if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
5a5012ec 5469 int l1;
6af0bf9c 5470 /* Handle blikely not taken case */
3594c774 5471 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
5a5012ec
TS
5472 l1 = gen_new_label();
5473 gen_op_jnz_T2(l1);
5474 gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
5475 gen_goto_tb(ctx, 1, ctx->pc + 4);
5476 gen_set_label(l1);
6af0bf9c 5477 }
7a387fff
TS
5478 op = MASK_OP_MAJOR(ctx->opcode);
5479 rs = (ctx->opcode >> 21) & 0x1f;
5480 rt = (ctx->opcode >> 16) & 0x1f;
5481 rd = (ctx->opcode >> 11) & 0x1f;
5482 sa = (ctx->opcode >> 6) & 0x1f;
6af0bf9c
FB
5483 imm = (int16_t)ctx->opcode;
5484 switch (op) {
7a387fff
TS
5485 case OPC_SPECIAL:
5486 op1 = MASK_SPECIAL(ctx->opcode);
6af0bf9c 5487 switch (op1) {
7a387fff
TS
5488 case OPC_SLL: /* Arithmetic with immediate */
5489 case OPC_SRL ... OPC_SRA:
5490 gen_arith_imm(ctx, op1, rd, rt, sa);
5491 break;
5492 case OPC_SLLV: /* Arithmetic */
5493 case OPC_SRLV ... OPC_SRAV:
5494 case OPC_MOVZ ... OPC_MOVN:
5495 case OPC_ADD ... OPC_NOR:
5496 case OPC_SLT ... OPC_SLTU:
5497 gen_arith(ctx, op1, rd, rs, rt);
5498 break;
5499 case OPC_MULT ... OPC_DIVU:
5500 gen_muldiv(ctx, op1, rs, rt);
5501 break;
5502 case OPC_JR ... OPC_JALR:
5503 gen_compute_branch(ctx, op1, rs, rd, sa);
6af0bf9c 5504 return;
7a387fff
TS
5505 case OPC_TGE ... OPC_TEQ: /* Traps */
5506 case OPC_TNE:
5507 gen_trap(ctx, op1, rs, rt, -1);
6af0bf9c 5508 break;
7a387fff
TS
5509 case OPC_MFHI: /* Move from HI/LO */
5510 case OPC_MFLO:
5511 gen_HILO(ctx, op1, rd);
6af0bf9c 5512 break;
7a387fff
TS
5513 case OPC_MTHI:
5514 case OPC_MTLO: /* Move to HI/LO */
5515 gen_HILO(ctx, op1, rs);
6af0bf9c 5516 break;
b48cfdff
TS
5517 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
5518#ifdef MIPS_STRICT_STANDARD
5519 MIPS_INVAL("PMON / selsl");
5520 generate_exception(ctx, EXCP_RI);
5521#else
7a387fff 5522 gen_op_pmon(sa);
b48cfdff 5523#endif
7a387fff
TS
5524 break;
5525 case OPC_SYSCALL:
6af0bf9c
FB
5526 generate_exception(ctx, EXCP_SYSCALL);
5527 break;
7a387fff 5528 case OPC_BREAK:
6af0bf9c
FB
5529 generate_exception(ctx, EXCP_BREAK);
5530 break;
b48cfdff
TS
5531 case OPC_SPIM:
5532#ifdef MIPS_STRICT_STANDARD
5533 MIPS_INVAL("SPIM");
5534 generate_exception(ctx, EXCP_RI);
5535#else
7a387fff
TS
5536 /* Implemented as RI exception for now. */
5537 MIPS_INVAL("spim (unofficial)");
5538 generate_exception(ctx, EXCP_RI);
b48cfdff 5539#endif
6af0bf9c 5540 break;
7a387fff
TS
5541 case OPC_SYNC:
5542 /* Treat as a noop. */
6af0bf9c 5543 break;
4ad40f36 5544
7a387fff 5545 case OPC_MOVCI:
36d23958 5546 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
e397ee33 5547 save_cpu_state(ctx, 1);
36d23958
TS
5548 gen_op_cp1_enabled();
5549 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
5550 (ctx->opcode >> 16) & 1);
5551 } else {
e397ee33 5552 generate_exception_err(ctx, EXCP_CpU, 1);
36d23958 5553 }
4ad40f36
FB
5554 break;
5555
60aa19ab 5556#ifdef TARGET_MIPS64
7a387fff
TS
5557 /* MIPS64 specific opcodes */
5558 case OPC_DSLL:
5559 case OPC_DSRL ... OPC_DSRA:
5560 case OPC_DSLL32:
5561 case OPC_DSRL32 ... OPC_DSRA32:
5562 gen_arith_imm(ctx, op1, rd, rt, sa);
5563 break;
5564 case OPC_DSLLV:
5565 case OPC_DSRLV ... OPC_DSRAV:
5566 case OPC_DADD ... OPC_DSUBU:
5567 gen_arith(ctx, op1, rd, rs, rt);
5568 break;
5569 case OPC_DMULT ... OPC_DDIVU:
5570 gen_muldiv(ctx, op1, rs, rt);
5571 break;
6af0bf9c
FB
5572#endif
5573 default: /* Invalid */
5574 MIPS_INVAL("special");
5575 generate_exception(ctx, EXCP_RI);
5576 break;
5577 }
5578 break;
7a387fff
TS
5579 case OPC_SPECIAL2:
5580 op1 = MASK_SPECIAL2(ctx->opcode);
6af0bf9c 5581 switch (op1) {
7a387fff
TS
5582 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
5583 case OPC_MSUB ... OPC_MSUBU:
5584 gen_muldiv(ctx, op1, rs, rt);
6af0bf9c 5585 break;
7a387fff
TS
5586 case OPC_MUL:
5587 gen_arith(ctx, op1, rd, rs, rt);
6af0bf9c 5588 break;
7a387fff
TS
5589 case OPC_CLZ ... OPC_CLO:
5590 gen_cl(ctx, op1, rd, rs);
6af0bf9c 5591 break;
7a387fff 5592 case OPC_SDBBP:
6af0bf9c
FB
5593 /* XXX: not clear which exception should be raised
5594 * when in debug mode...
5595 */
5596 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
5597 generate_exception(ctx, EXCP_DBp);
5598 } else {
5599 generate_exception(ctx, EXCP_DBp);
5600 }
5601 /* Treat as a noop */
5602 break;
60aa19ab 5603#ifdef TARGET_MIPS64
7a387fff
TS
5604 case OPC_DCLZ ... OPC_DCLO:
5605 gen_cl(ctx, op1, rd, rs);
5606 break;
5607#endif
6af0bf9c
FB
5608 default: /* Invalid */
5609 MIPS_INVAL("special2");
5610 generate_exception(ctx, EXCP_RI);
5611 break;
5612 }
5613 break;
7a387fff 5614 case OPC_SPECIAL3:
1579a72e
TS
5615 op1 = MASK_SPECIAL3(ctx->opcode);
5616 switch (op1) {
5617 case OPC_EXT:
5618 case OPC_INS:
5619 gen_bitops(ctx, op1, rt, rs, sa, rd);
5620 break;
5621 case OPC_BSHFL:
5622 op2 = MASK_BSHFL(ctx->opcode);
5623 switch (op2) {
5624 case OPC_WSBH:
5625 GEN_LOAD_REG_TN(T1, rt);
5626 gen_op_wsbh();
5627 break;
5628 case OPC_SEB:
5629 GEN_LOAD_REG_TN(T1, rt);
5630 gen_op_seb();
5631 break;
5632 case OPC_SEH:
5633 GEN_LOAD_REG_TN(T1, rt);
5634 gen_op_seh();
5635 break;
5636 default: /* Invalid */
5637 MIPS_INVAL("bshfl");
5638 generate_exception(ctx, EXCP_RI);
5639 break;
5640 }
5641 GEN_STORE_TN_REG(rd, T0);
7a387fff 5642 break;
1579a72e
TS
5643 case OPC_RDHWR:
5644 switch (rd) {
5645 case 0:
97428a4d 5646 save_cpu_state(ctx, 1);
1579a72e 5647 gen_op_rdhwr_cpunum();
7a387fff 5648 break;
1579a72e 5649 case 1:
97428a4d 5650 save_cpu_state(ctx, 1);
1579a72e 5651 gen_op_rdhwr_synci_step();
7a387fff 5652 break;
1579a72e 5653 case 2:
97428a4d 5654 save_cpu_state(ctx, 1);
1579a72e 5655 gen_op_rdhwr_cc();
7a387fff 5656 break;
1579a72e 5657 case 3:
97428a4d 5658 save_cpu_state(ctx, 1);
1579a72e 5659 gen_op_rdhwr_ccres();
7a387fff 5660 break;
1579a72e 5661 case 29:
6f5b89a0 5662#if defined (CONFIG_USER_ONLY)
1579a72e 5663 gen_op_tls_value ();
1579a72e 5664 break;
97428a4d 5665#endif
1579a72e
TS
5666 default: /* Invalid */
5667 MIPS_INVAL("rdhwr");
5668 generate_exception(ctx, EXCP_RI);
5669 break;
5670 }
5671 GEN_STORE_TN_REG(rt, T0);
5672 break;
60aa19ab 5673#ifdef TARGET_MIPS64
1579a72e
TS
5674 case OPC_DEXTM ... OPC_DEXT:
5675 case OPC_DINSM ... OPC_DINS:
5676 gen_bitops(ctx, op1, rt, rs, sa, rd);
7a387fff 5677 break;
1579a72e
TS
5678 case OPC_DBSHFL:
5679 op2 = MASK_DBSHFL(ctx->opcode);
5680 switch (op2) {
5681 case OPC_DSBH:
5682 GEN_LOAD_REG_TN(T1, rt);
5683 gen_op_dsbh();
5684 break;
5685 case OPC_DSHD:
5686 GEN_LOAD_REG_TN(T1, rt);
5687 gen_op_dshd();
5688 break;
7a387fff
TS
5689 default: /* Invalid */
5690 MIPS_INVAL("dbshfl");
5691 generate_exception(ctx, EXCP_RI);
5692 break;
1579a72e
TS
5693 }
5694 GEN_STORE_TN_REG(rd, T0);
7a387fff
TS
5695#endif
5696 default: /* Invalid */
5697 MIPS_INVAL("special3");
5698 generate_exception(ctx, EXCP_RI);
5699 break;
5700 }
5701 break;
5702 case OPC_REGIMM:
5703 op1 = MASK_REGIMM(ctx->opcode);
5704 switch (op1) {
5705 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
5706 case OPC_BLTZAL ... OPC_BGEZALL:
5707 gen_compute_branch(ctx, op1, rs, -1, imm << 2);
6af0bf9c 5708 return;
7a387fff
TS
5709 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
5710 case OPC_TNEI:
5711 gen_trap(ctx, op1, rs, -1, imm);
5712 break;
5713 case OPC_SYNCI:
24c7b0e3 5714 /* treat as noop */
6af0bf9c
FB
5715 break;
5716 default: /* Invalid */
923617a3 5717 MIPS_INVAL("regimm");
6af0bf9c
FB
5718 generate_exception(ctx, EXCP_RI);
5719 break;
5720 }
5721 break;
7a387fff 5722 case OPC_CP0:
f41c52f1 5723 save_cpu_state(ctx, 1);
24c7b0e3 5724 gen_op_cp0_enabled();
7a387fff 5725 op1 = MASK_CP0(ctx->opcode);
6af0bf9c 5726 switch (op1) {
7a387fff
TS
5727 case OPC_MFC0:
5728 case OPC_MTC0:
60aa19ab 5729#ifdef TARGET_MIPS64
7a387fff
TS
5730 case OPC_DMFC0:
5731 case OPC_DMTC0:
5732#endif
29929e34 5733 gen_cp0(env, ctx, op1, rt, rd);
7a387fff
TS
5734 break;
5735 case OPC_C0_FIRST ... OPC_C0_LAST:
29929e34 5736 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
7a387fff
TS
5737 break;
5738 case OPC_MFMC0:
5739 op2 = MASK_MFMC0(ctx->opcode);
5740 switch (op2) {
5741 case OPC_DI:
5742 gen_op_di();
5743 /* Stop translation as we may have switched the execution mode */
5744 ctx->bstate = BS_STOP;
5745 break;
5746 case OPC_EI:
5747 gen_op_ei();
5748 /* Stop translation as we may have switched the execution mode */
5749 ctx->bstate = BS_STOP;
5750 break;
5751 default: /* Invalid */
923617a3 5752 MIPS_INVAL("mfmc0");
7a387fff
TS
5753 generate_exception(ctx, EXCP_RI);
5754 break;
5755 }
5756 GEN_STORE_TN_REG(rt, T0);
6af0bf9c 5757 break;
7a387fff
TS
5758 case OPC_RDPGPR:
5759 case OPC_WRPGPR:
38121543
TS
5760 if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR)) {
5761 /* Shadow registers not implemented. */
5762 GEN_LOAD_REG_TN(T0, rt);
5763 GEN_STORE_TN_REG(rd, T0);
923617a3
TS
5764 } else {
5765 MIPS_INVAL("shadow register move");
38121543 5766 generate_exception(ctx, EXCP_RI);
923617a3 5767 }
38121543 5768 break;
6af0bf9c 5769 default:
923617a3 5770 MIPS_INVAL("cp0");
7a387fff 5771 generate_exception(ctx, EXCP_RI);
6af0bf9c
FB
5772 break;
5773 }
5774 break;
7a387fff
TS
5775 case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
5776 gen_arith_imm(ctx, op, rt, rs, imm);
5777 break;
5778 case OPC_J ... OPC_JAL: /* Jump */
5779 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
5780 gen_compute_branch(ctx, op, rs, rt, offset);
5781 return;
5782 case OPC_BEQ ... OPC_BGTZ: /* Branch */
5783 case OPC_BEQL ... OPC_BGTZL:
5784 gen_compute_branch(ctx, op, rs, rt, imm << 2);
5785 return;
5786 case OPC_LB ... OPC_LWR: /* Load and stores */
5787 case OPC_SB ... OPC_SW:
5788 case OPC_SWR:
5789 case OPC_LL:
5790 case OPC_SC:
5791 gen_ldst(ctx, op, rt, rs, imm);
5792 break;
5793 case OPC_CACHE:
34ae7b51
TS
5794 /* FIXME: This works around self-modifying code, but only
5795 if the guest OS handles it properly, and if there's no
5796 such code executed in uncached space. */
5797 if (!(rt & 0x3))
5798 switch ((rt >> 2) & 0x7) {
5799 case 4:
5800 GEN_LOAD_REG_TN(T0, rs);
5801 GEN_LOAD_IMM_TN(T1, imm);
5802 gen_op_flush_icache_range();
5803 break;
5804 case 2:
5805 case 1:
5806 case 0:
5807 /* Can be very inefficient. */
5808 gen_op_flush_icache_all();
5809 break;
5810 default:
5811 break;
5812 }
5813 break;
7a387fff 5814 case OPC_PREF:
6af0bf9c
FB
5815 /* Treat as a noop */
5816 break;
4ad40f36 5817
923617a3 5818 /* Floating point (COP1). */
7a387fff
TS
5819 case OPC_LWC1:
5820 case OPC_LDC1:
5821 case OPC_SWC1:
5822 case OPC_SDC1:
36d23958
TS
5823 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5824 save_cpu_state(ctx, 1);
5825 gen_op_cp1_enabled();
5826 gen_flt_ldst(ctx, op, rt, rs, imm);
5827 } else {
5828 generate_exception_err(ctx, EXCP_CpU, 1);
5829 }
6ea83fed
FB
5830 break;
5831
7a387fff 5832 case OPC_CP1:
36d23958
TS
5833 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5834 save_cpu_state(ctx, 1);
5835 gen_op_cp1_enabled();
5836 op1 = MASK_CP1(ctx->opcode);
5837 switch (op1) {
5838 case OPC_MFC1:
5839 case OPC_CFC1:
5840 case OPC_MTC1:
5841 case OPC_CTC1:
60aa19ab 5842#ifdef TARGET_MIPS64
36d23958
TS
5843 case OPC_DMFC1:
5844 case OPC_DMTC1:
9c2149c8 5845#endif
5a5012ec
TS
5846 case OPC_MFHC1:
5847 case OPC_MTHC1:
36d23958
TS
5848 gen_cp1(ctx, op1, rt, rd);
5849 break;
5850 case OPC_BC1:
fbcc6828
TS
5851 case OPC_BC1ANY2:
5852 case OPC_BC1ANY4:
5a5012ec
TS
5853 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
5854 (rt >> 2) & 0x7, imm << 2);
36d23958
TS
5855 return;
5856 case OPC_S_FMT:
5857 case OPC_D_FMT:
5858 case OPC_W_FMT:
5859 case OPC_L_FMT:
5a5012ec
TS
5860 case OPC_PS_FMT:
5861 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
5862 (imm >> 8) & 0x7);
36d23958
TS
5863 break;
5864 default:
923617a3 5865 MIPS_INVAL("cp1");
e397ee33 5866 generate_exception (ctx, EXCP_RI);
36d23958
TS
5867 break;
5868 }
5869 } else {
5870 generate_exception_err(ctx, EXCP_CpU, 1);
6ea83fed 5871 }
4ad40f36
FB
5872 break;
5873
5874 /* COP2. */
7a387fff
TS
5875 case OPC_LWC2:
5876 case OPC_LDC2:
5877 case OPC_SWC2:
5878 case OPC_SDC2:
5879 case OPC_CP2:
5880 /* COP2: Not implemented. */
4ad40f36
FB
5881 generate_exception_err(ctx, EXCP_CpU, 2);
5882 break;
5883
7a387fff 5884 case OPC_CP3:
36d23958 5885 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
e397ee33 5886 save_cpu_state(ctx, 1);
36d23958
TS
5887 gen_op_cp1_enabled();
5888 op1 = MASK_CP3(ctx->opcode);
5889 switch (op1) {
5a5012ec
TS
5890 case OPC_LWXC1:
5891 case OPC_LDXC1:
5892 case OPC_LUXC1:
5893 case OPC_SWXC1:
5894 case OPC_SDXC1:
5895 case OPC_SUXC1:
93b12ccc 5896 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
5a5012ec 5897 break;
e0c84da7
TS
5898 case OPC_PREFX:
5899 /* treat as noop */
5900 break;
5a5012ec
TS
5901 case OPC_ALNV_PS:
5902 case OPC_MADD_S:
5903 case OPC_MADD_D:
5904 case OPC_MADD_PS:
5905 case OPC_MSUB_S:
5906 case OPC_MSUB_D:
5907 case OPC_MSUB_PS:
5908 case OPC_NMADD_S:
5909 case OPC_NMADD_D:
5910 case OPC_NMADD_PS:
5911 case OPC_NMSUB_S:
5912 case OPC_NMSUB_D:
5913 case OPC_NMSUB_PS:
5914 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
5915 break;
36d23958 5916 default:
923617a3 5917 MIPS_INVAL("cp3");
e397ee33 5918 generate_exception (ctx, EXCP_RI);
36d23958
TS
5919 break;
5920 }
5921 } else {
e397ee33 5922 generate_exception_err(ctx, EXCP_CpU, 1);
7a387fff 5923 }
4ad40f36
FB
5924 break;
5925
60aa19ab 5926#ifdef TARGET_MIPS64
7a387fff
TS
5927 /* MIPS64 opcodes */
5928 case OPC_LWU:
5929 case OPC_LDL ... OPC_LDR:
5930 case OPC_SDL ... OPC_SDR:
5931 case OPC_LLD:
5932 case OPC_LD:
5933 case OPC_SCD:
5934 case OPC_SD:
5935 gen_ldst(ctx, op, rt, rs, imm);
5936 break;
5937 case OPC_DADDI ... OPC_DADDIU:
5938 gen_arith_imm(ctx, op, rt, rs, imm);
5939 break;
6af0bf9c 5940#endif
7a387fff
TS
5941#ifdef MIPS_HAS_MIPS16
5942 case OPC_JALX:
5943 /* MIPS16: Not implemented. */
5944#endif
5945#ifdef MIPS_HAS_MDMX
5946 case OPC_MDMX:
5947 /* MDMX: Not implemented. */
6af0bf9c 5948#endif
6af0bf9c 5949 default: /* Invalid */
923617a3 5950 MIPS_INVAL("major opcode");
6af0bf9c
FB
5951 generate_exception(ctx, EXCP_RI);
5952 break;
5953 }
4ad40f36 5954 if (ctx->hflags & MIPS_HFLAG_BMASK) {
c53f4a62 5955 int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
6af0bf9c 5956 /* Branches completion */
4ad40f36 5957 ctx->hflags &= ~MIPS_HFLAG_BMASK;
6af0bf9c
FB
5958 ctx->bstate = BS_BRANCH;
5959 save_cpu_state(ctx, 0);
5a5012ec 5960 switch (hflags) {
6af0bf9c
FB
5961 case MIPS_HFLAG_B:
5962 /* unconditional branch */
5963 MIPS_DEBUG("unconditional branch");
6e256c93 5964 gen_goto_tb(ctx, 0, ctx->btarget);
6af0bf9c
FB
5965 break;
5966 case MIPS_HFLAG_BL:
5967 /* blikely taken case */
5968 MIPS_DEBUG("blikely branch taken");
6e256c93 5969 gen_goto_tb(ctx, 0, ctx->btarget);
6af0bf9c
FB
5970 break;
5971 case MIPS_HFLAG_BC:
5972 /* Conditional branch */
5973 MIPS_DEBUG("conditional branch");
c53be334
FB
5974 {
5975 int l1;
5976 l1 = gen_new_label();
5977 gen_op_jnz_T2(l1);
6e256c93 5978 gen_goto_tb(ctx, 1, ctx->pc + 4);
eeef26cd
FB
5979 gen_set_label(l1);
5980 gen_goto_tb(ctx, 0, ctx->btarget);
c53be334 5981 }
6af0bf9c
FB
5982 break;
5983 case MIPS_HFLAG_BR:
5984 /* unconditional branch to register */
5985 MIPS_DEBUG("branch to register");
5986 gen_op_breg();
5a5012ec
TS
5987 gen_op_reset_T0();
5988 gen_op_exit_tb();
6af0bf9c
FB
5989 break;
5990 default:
5991 MIPS_DEBUG("unknown branch");
5992 break;
5993 }
5994 }
5995}
5996
820e00f2
TS
5997static inline int
5998gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
5999 int search_pc)
6af0bf9c
FB
6000{
6001 DisasContext ctx, *ctxp = &ctx;
6002 target_ulong pc_start;
6003 uint16_t *gen_opc_end;
6004 int j, lj = -1;
6005
4ad40f36 6006 if (search_pc && loglevel)
6ea83fed 6007 fprintf (logfile, "search pc %d\n", search_pc);
4ad40f36 6008
6af0bf9c
FB
6009 pc_start = tb->pc;
6010 gen_opc_ptr = gen_opc_buf;
6011 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6012 gen_opparam_ptr = gen_opparam_buf;
c53be334 6013 nb_gen_labels = 0;
6af0bf9c 6014 ctx.pc = pc_start;
4ad40f36 6015 ctx.saved_pc = -1;
6af0bf9c
FB
6016 ctx.tb = tb;
6017 ctx.bstate = BS_NONE;
4ad40f36
FB
6018 /* Restore delay slot state from the tb context. */
6019 ctx.hflags = tb->flags;
fd4a04eb 6020 restore_cpu_state(env, &ctx);
6af0bf9c
FB
6021#if defined(CONFIG_USER_ONLY)
6022 ctx.mem_idx = 0;
6023#else
3d9fb9fe 6024 ctx.mem_idx = !((ctx.hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM);
6af0bf9c 6025#endif
6af0bf9c
FB
6026#ifdef DEBUG_DISAS
6027 if (loglevel & CPU_LOG_TB_CPU) {
6028 fprintf(logfile, "------------------------------------------------\n");
4ad40f36 6029 /* FIXME: This may print out stale hflags from env... */
6af0bf9c
FB
6030 cpu_dump_state(env, logfile, fprintf, 0);
6031 }
6032#endif
923617a3 6033#ifdef MIPS_DEBUG_DISAS
6af0bf9c 6034 if (loglevel & CPU_LOG_TB_IN_ASM)
4ad40f36
FB
6035 fprintf(logfile, "\ntb %p super %d cond %04x\n",
6036 tb, ctx.mem_idx, ctx.hflags);
6af0bf9c
FB
6037#endif
6038 while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
4ad40f36
FB
6039 if (env->nb_breakpoints > 0) {
6040 for(j = 0; j < env->nb_breakpoints; j++) {
6041 if (env->breakpoints[j] == ctx.pc) {
6042 save_cpu_state(ctxp, 1);
6043 ctx.bstate = BS_BRANCH;
6044 gen_op_debug();
6045 goto done_generating;
6046 }
6047 }
6048 }
6049
6af0bf9c
FB
6050 if (search_pc) {
6051 j = gen_opc_ptr - gen_opc_buf;
6af0bf9c
FB
6052 if (lj < j) {
6053 lj++;
6054 while (lj < j)
6055 gen_opc_instr_start[lj++] = 0;
6af0bf9c 6056 }
4ad40f36
FB
6057 gen_opc_pc[lj] = ctx.pc;
6058 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
6059 gen_opc_instr_start[lj] = 1;
6af0bf9c
FB
6060 }
6061 ctx.opcode = ldl_code(ctx.pc);
36d23958 6062 decode_opc(env, &ctx);
6af0bf9c 6063 ctx.pc += 4;
4ad40f36
FB
6064
6065 if (env->singlestep_enabled)
6066 break;
6067
6af0bf9c
FB
6068 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
6069 break;
4ad40f36 6070
6af0bf9c
FB
6071#if defined (MIPS_SINGLE_STEP)
6072 break;
6073#endif
6074 }
4ad40f36
FB
6075 if (env->singlestep_enabled) {
6076 save_cpu_state(ctxp, ctx.bstate == BS_NONE);
6077 gen_op_debug();
16c00cb2
TS
6078 } else {
6079 switch (ctx.bstate) {
16c00cb2
TS
6080 case BS_STOP:
6081 gen_op_interrupt_restart();
6082 /* Fall through. */
6083 case BS_NONE:
6084 save_cpu_state(ctxp, 0);
6085 gen_goto_tb(&ctx, 0, ctx.pc);
6086 break;
5a5012ec
TS
6087 case BS_EXCP:
6088 gen_op_interrupt_restart();
a85427b1 6089 gen_op_reset_T0();
a85427b1 6090 gen_op_exit_tb();
16c00cb2 6091 break;
5a5012ec
TS
6092 case BS_BRANCH:
6093 default:
6094 break;
16c00cb2 6095 }
6af0bf9c 6096 }
4ad40f36 6097done_generating:
6af0bf9c
FB
6098 *gen_opc_ptr = INDEX_op_end;
6099 if (search_pc) {
6100 j = gen_opc_ptr - gen_opc_buf;
6101 lj++;
6102 while (lj <= j)
6103 gen_opc_instr_start[lj++] = 0;
6104 tb->size = 0;
6105 } else {
6106 tb->size = ctx.pc - pc_start;
6107 }
6108#ifdef DEBUG_DISAS
6109#if defined MIPS_DEBUG_DISAS
6110 if (loglevel & CPU_LOG_TB_IN_ASM)
6111 fprintf(logfile, "\n");
6112#endif
6113 if (loglevel & CPU_LOG_TB_IN_ASM) {
6114 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
9898128f 6115 target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
6af0bf9c
FB
6116 fprintf(logfile, "\n");
6117 }
6118 if (loglevel & CPU_LOG_TB_OP) {
6119 fprintf(logfile, "OP:\n");
6120 dump_ops(gen_opc_buf, gen_opparam_buf);
6121 fprintf(logfile, "\n");
6122 }
6123 if (loglevel & CPU_LOG_TB_CPU) {
6124 fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
6125 }
6126#endif
6127
6128 return 0;
6129}
6130
6131int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
6132{
6133 return gen_intermediate_code_internal(env, tb, 0);
6134}
6135
6136int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
6137{
6138 return gen_intermediate_code_internal(env, tb, 1);
6139}
6140
6ea83fed
FB
6141void fpu_dump_state(CPUState *env, FILE *f,
6142 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
6143 int flags)
6144{
6145 int i;
5a5012ec
TS
6146 int is_fpu64 = !!(env->CP0_Status & (1 << CP0St_FR));
6147
6148#define printfpr(fp) \
6149 do { \
6150 if (is_fpu64) \
6151 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n", \
6152 (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd, \
6153 (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
6154 else { \
6155 fpr_t tmp; \
6156 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
6157 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
6158 fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n", \
6159 tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd, \
6160 tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]); \
6161 } \
6ea83fed
FB
6162 } while(0)
6163
5a5012ec
TS
6164
6165 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
6166 env->fcr0, env->fcr31, is_fpu64, env->fp_status, get_float_exception_flags(&env->fp_status));
6ea83fed
FB
6167 fpu_fprintf(f, "FT0: "); printfpr(&env->ft0);
6168 fpu_fprintf(f, "FT1: "); printfpr(&env->ft1);
6169 fpu_fprintf(f, "FT2: "); printfpr(&env->ft2);
5a5012ec
TS
6170 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
6171 fpu_fprintf(f, "%3s: ", fregnames[i]);
6172 printfpr(&env->fpr[i]);
6ea83fed
FB
6173 }
6174
6175#undef printfpr
6176}
6177
7a387fff 6178void dump_fpu (CPUState *env)
6ea83fed
FB
6179{
6180 if (loglevel) {
3594c774 6181 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
6182 env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
6183 fpu_dump_state(env, logfile, fprintf, 0);
6184 }
6185}
6ea83fed 6186
60aa19ab 6187#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16
TS
6188/* Debug help: The architecture requires 32bit code to maintain proper
6189 sign-extened values on 64bit machines. */
6190
6191#define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
6192
6193void cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
6194 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
6195 int flags)
6196{
6197 int i;
6198
6199 if (!SIGN_EXT_P(env->PC))
3594c774 6200 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->PC);
c570fd16 6201 if (!SIGN_EXT_P(env->HI))
3594c774 6202 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->HI);
c570fd16 6203 if (!SIGN_EXT_P(env->LO))
3594c774 6204 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->LO);
c570fd16 6205 if (!SIGN_EXT_P(env->btarget))
3594c774 6206 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
c570fd16
TS
6207
6208 for (i = 0; i < 32; i++) {
6209 if (!SIGN_EXT_P(env->gpr[i]))
3594c774 6210 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->gpr[i]);
c570fd16
TS
6211 }
6212
6213 if (!SIGN_EXT_P(env->CP0_EPC))
3594c774 6214 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
c570fd16 6215 if (!SIGN_EXT_P(env->CP0_LLAddr))
3594c774 6216 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
c570fd16
TS
6217}
6218#endif
6219
6af0bf9c
FB
6220void cpu_dump_state (CPUState *env, FILE *f,
6221 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
6222 int flags)
6223{
568b600d 6224 uint32_t c0_status;
6af0bf9c
FB
6225 int i;
6226
3594c774 6227 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
6228 env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
6229 for (i = 0; i < 32; i++) {
6230 if ((i & 3) == 0)
6231 cpu_fprintf(f, "GPR%02d:", i);
3594c774 6232 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->gpr[i]);
6af0bf9c
FB
6233 if ((i & 3) == 3)
6234 cpu_fprintf(f, "\n");
6235 }
568b600d
FB
6236
6237 c0_status = env->CP0_Status;
568b600d 6238
3594c774 6239 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
568b600d 6240 c0_status, env->CP0_Cause, env->CP0_EPC);
3594c774 6241 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
6af0bf9c 6242 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
7a387fff
TS
6243 if (c0_status & (1 << CP0St_CU1))
6244 fpu_dump_state(env, f, cpu_fprintf, flags);
60aa19ab 6245#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16
TS
6246 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
6247#endif
6af0bf9c
FB
6248}
6249
6250CPUMIPSState *cpu_mips_init (void)
6251{
6252 CPUMIPSState *env;
6253
6af0bf9c
FB
6254 env = qemu_mallocz(sizeof(CPUMIPSState));
6255 if (!env)
6256 return NULL;
173d6cfe 6257 cpu_exec_init(env);
6ae81775
TS
6258 cpu_reset(env);
6259 return env;
6260}
6261
6262void cpu_reset (CPUMIPSState *env)
6263{
6264 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
6265
6af0bf9c 6266 tlb_flush(env, 1);
6ae81775 6267
6af0bf9c 6268 /* Minimal init */
ca7c2b1b 6269#if !defined(CONFIG_USER_ONLY)
aa328add
TS
6270 if (env->hflags & MIPS_HFLAG_BMASK) {
6271 /* If the exception was raised from a delay slot,
6272 * come back to the jump. */
6273 env->CP0_ErrorEPC = env->PC - 4;
6274 env->hflags &= ~MIPS_HFLAG_BMASK;
6275 } else {
6276 env->CP0_ErrorEPC = env->PC;
6277 }
24c7b0e3 6278 env->hflags = 0;
5dc4b744 6279 env->PC = (int32_t)0xBFC00000;
6af0bf9c 6280 env->CP0_Wired = 0;
7a387fff 6281 /* SMP not implemented */
b29a0341 6282 env->CP0_EBase = 0x80000000;
aa328add 6283 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
c090a8f4
TS
6284 /* vectored interrupts not implemented, timer on int 7,
6285 no performance counters. */
6286 env->CP0_IntCtl = 0xe0000000;
6af0bf9c 6287 env->CP0_WatchLo = 0;
4e7a4a4e 6288 env->CP0_WatchHi = 0;
6af0bf9c
FB
6289 /* Count register increments in debug mode, EJTAG version 1 */
6290 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
ca7c2b1b 6291#endif
6af0bf9c 6292 env->exception_index = EXCP_NONE;
eeef26cd
FB
6293#if defined(CONFIG_USER_ONLY)
6294 env->hflags |= MIPS_HFLAG_UM;
ca7c2b1b 6295 env->user_mode_only = 1;
6ea83fed 6296#endif
6af0bf9c 6297}
33d68b5f
TS
6298
6299#include "translate_init.c"
This page took 1.031616 seconds and 4 git commands to generate.