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