Statistics
| Branch: | Revision:

root / target-mips / translate.c @ 70ead434

History | View | Annotate | Download (111.7 kB)

1 6af0bf9c bellard
/*
2 6af0bf9c bellard
 *  MIPS32 emulation for qemu: main translation routines.
3 6af0bf9c bellard
 * 
4 6af0bf9c bellard
 *  Copyright (c) 2004-2005 Jocelyn Mayer
5 6ea83fed bellard
 *  Copyright (c) 2006 Marius Groeger (FPU operations)
6 bb8a53ad ths
 *  Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 6af0bf9c bellard
 *
8 6af0bf9c bellard
 * This library is free software; you can redistribute it and/or
9 6af0bf9c bellard
 * modify it under the terms of the GNU Lesser General Public
10 6af0bf9c bellard
 * License as published by the Free Software Foundation; either
11 6af0bf9c bellard
 * version 2 of the License, or (at your option) any later version.
12 6af0bf9c bellard
 *
13 6af0bf9c bellard
 * This library is distributed in the hope that it will be useful,
14 6af0bf9c bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 6af0bf9c bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 6af0bf9c bellard
 * Lesser General Public License for more details.
17 6af0bf9c bellard
 *
18 6af0bf9c bellard
 * You should have received a copy of the GNU Lesser General Public
19 6af0bf9c bellard
 * License along with this library; if not, write to the Free Software
20 6af0bf9c bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 6af0bf9c bellard
 */
22 6af0bf9c bellard
23 6af0bf9c bellard
#include <stdarg.h>
24 6af0bf9c bellard
#include <stdlib.h>
25 6af0bf9c bellard
#include <stdio.h>
26 6af0bf9c bellard
#include <string.h>
27 6af0bf9c bellard
#include <inttypes.h>
28 6af0bf9c bellard
29 6af0bf9c bellard
#include "cpu.h"
30 6af0bf9c bellard
#include "exec-all.h"
31 6af0bf9c bellard
#include "disas.h"
32 6af0bf9c bellard
33 eeef26cd bellard
//#define MIPS_DEBUG_DISAS
34 c570fd16 ths
//#define MIPS_DEBUG_SIGN_EXTENSIONS
35 6af0bf9c bellard
//#define MIPS_SINGLE_STEP
36 6af0bf9c bellard
37 c53be334 bellard
#ifdef USE_DIRECT_JUMP
38 c53be334 bellard
#define TBPARAM(x)
39 c53be334 bellard
#else
40 c53be334 bellard
#define TBPARAM(x) (long)(x)
41 c53be334 bellard
#endif
42 c53be334 bellard
43 6af0bf9c bellard
enum {
44 6af0bf9c bellard
#define DEF(s, n, copy_size) INDEX_op_ ## s,
45 6af0bf9c bellard
#include "opc.h"
46 6af0bf9c bellard
#undef DEF
47 6af0bf9c bellard
    NB_OPS,
48 6af0bf9c bellard
};
49 6af0bf9c bellard
50 6af0bf9c bellard
static uint16_t *gen_opc_ptr;
51 6af0bf9c bellard
static uint32_t *gen_opparam_ptr;
52 6af0bf9c bellard
53 6af0bf9c bellard
#include "gen-op.h"
54 6af0bf9c bellard
55 7a387fff ths
/* MIPS major opcodes */
56 7a387fff ths
#define MASK_OP_MAJOR(op)  (op & (0x3F << 26))
57 e37e863f bellard
58 e37e863f bellard
enum {
59 e37e863f bellard
    /* indirect opcode tables */
60 7a387fff ths
    OPC_SPECIAL  = (0x00 << 26),
61 7a387fff ths
    OPC_REGIMM   = (0x01 << 26),
62 7a387fff ths
    OPC_CP0      = (0x10 << 26),
63 7a387fff ths
    OPC_CP1      = (0x11 << 26),
64 7a387fff ths
    OPC_CP2      = (0x12 << 26),
65 7a387fff ths
    OPC_CP3      = (0x13 << 26),
66 7a387fff ths
    OPC_SPECIAL2 = (0x1C << 26),
67 7a387fff ths
    OPC_SPECIAL3 = (0x1F << 26),
68 e37e863f bellard
    /* arithmetic with immediate */
69 7a387fff ths
    OPC_ADDI     = (0x08 << 26),
70 7a387fff ths
    OPC_ADDIU    = (0x09 << 26),
71 7a387fff ths
    OPC_SLTI     = (0x0A << 26),
72 7a387fff ths
    OPC_SLTIU    = (0x0B << 26),
73 7a387fff ths
    OPC_ANDI     = (0x0C << 26),
74 7a387fff ths
    OPC_ORI      = (0x0D << 26),
75 7a387fff ths
    OPC_XORI     = (0x0E << 26),
76 7a387fff ths
    OPC_LUI      = (0x0F << 26),
77 7a387fff ths
    OPC_DADDI    = (0x18 << 26),
78 7a387fff ths
    OPC_DADDIU   = (0x19 << 26),
79 e37e863f bellard
    /* Jump and branches */
80 7a387fff ths
    OPC_J        = (0x02 << 26),
81 7a387fff ths
    OPC_JAL      = (0x03 << 26),
82 7a387fff ths
    OPC_BEQ      = (0x04 << 26),  /* Unconditional if rs = rt = 0 (B) */
83 7a387fff ths
    OPC_BEQL     = (0x14 << 26),
84 7a387fff ths
    OPC_BNE      = (0x05 << 26),
85 7a387fff ths
    OPC_BNEL     = (0x15 << 26),
86 7a387fff ths
    OPC_BLEZ     = (0x06 << 26),
87 7a387fff ths
    OPC_BLEZL    = (0x16 << 26),
88 7a387fff ths
    OPC_BGTZ     = (0x07 << 26),
89 7a387fff ths
    OPC_BGTZL    = (0x17 << 26),
90 7a387fff ths
    OPC_JALX     = (0x1D << 26),  /* MIPS 16 only */
91 e37e863f bellard
    /* Load and stores */
92 7a387fff ths
    OPC_LDL      = (0x1A << 26),
93 7a387fff ths
    OPC_LDR      = (0x1B << 26),
94 7a387fff ths
    OPC_LB       = (0x20 << 26),
95 7a387fff ths
    OPC_LH       = (0x21 << 26),
96 7a387fff ths
    OPC_LWL      = (0x22 << 26),
97 7a387fff ths
    OPC_LW       = (0x23 << 26),
98 7a387fff ths
    OPC_LBU      = (0x24 << 26),
99 7a387fff ths
    OPC_LHU      = (0x25 << 26),
100 7a387fff ths
    OPC_LWR      = (0x26 << 26),
101 7a387fff ths
    OPC_LWU      = (0x27 << 26),
102 7a387fff ths
    OPC_SB       = (0x28 << 26),
103 7a387fff ths
    OPC_SH       = (0x29 << 26),
104 7a387fff ths
    OPC_SWL      = (0x2A << 26),
105 7a387fff ths
    OPC_SW       = (0x2B << 26),
106 7a387fff ths
    OPC_SDL      = (0x2C << 26),
107 7a387fff ths
    OPC_SDR      = (0x2D << 26),
108 7a387fff ths
    OPC_SWR      = (0x2E << 26),
109 7a387fff ths
    OPC_LL       = (0x30 << 26),
110 7a387fff ths
    OPC_LLD      = (0x34 << 26),
111 7a387fff ths
    OPC_LD       = (0x37 << 26),
112 7a387fff ths
    OPC_SC       = (0x38 << 26),
113 7a387fff ths
    OPC_SCD      = (0x3C << 26),
114 7a387fff ths
    OPC_SD       = (0x3F << 26),
115 e37e863f bellard
    /* Floating point load/store */
116 7a387fff ths
    OPC_LWC1     = (0x31 << 26),
117 7a387fff ths
    OPC_LWC2     = (0x32 << 26),
118 7a387fff ths
    OPC_LDC1     = (0x35 << 26),
119 7a387fff ths
    OPC_LDC2     = (0x36 << 26),
120 7a387fff ths
    OPC_SWC1     = (0x39 << 26),
121 7a387fff ths
    OPC_SWC2     = (0x3A << 26),
122 7a387fff ths
    OPC_SDC1     = (0x3D << 26),
123 7a387fff ths
    OPC_SDC2     = (0x3E << 26),
124 7a387fff ths
    /* MDMX ASE specific */
125 7a387fff ths
    OPC_MDMX     = (0x1E << 26),
126 e37e863f bellard
    /* Cache and prefetch */
127 7a387fff ths
    OPC_CACHE    = (0x2F << 26),
128 7a387fff ths
    OPC_PREF     = (0x33 << 26),
129 7a387fff ths
    /* Reserved major opcode */
130 7a387fff ths
    OPC_MAJOR3B_RESERVED = (0x3B << 26),
131 e37e863f bellard
};
132 e37e863f bellard
133 e37e863f bellard
/* MIPS special opcodes */
134 7a387fff ths
#define MASK_SPECIAL(op)   MASK_OP_MAJOR(op) | (op & 0x3F)
135 7a387fff ths
136 e37e863f bellard
enum {
137 e37e863f bellard
    /* Shifts */
138 7a387fff ths
    OPC_SLL      = 0x00 | OPC_SPECIAL,
139 e37e863f bellard
    /* NOP is SLL r0, r0, 0   */
140 e37e863f bellard
    /* SSNOP is SLL r0, r0, 1 */
141 7a387fff ths
    /* EHB is SLL r0, r0, 3 */
142 7a387fff ths
    OPC_SRL      = 0x02 | OPC_SPECIAL, /* also ROTR */
143 7a387fff ths
    OPC_SRA      = 0x03 | OPC_SPECIAL,
144 7a387fff ths
    OPC_SLLV     = 0x04 | OPC_SPECIAL,
145 7a387fff ths
    OPC_SRLV     = 0x06 | OPC_SPECIAL,
146 7a387fff ths
    OPC_SRAV     = 0x07 | OPC_SPECIAL,
147 7a387fff ths
    OPC_DSLLV    = 0x14 | OPC_SPECIAL,
148 7a387fff ths
    OPC_DSRLV    = 0x16 | OPC_SPECIAL, /* also DROTRV */
149 7a387fff ths
    OPC_DSRAV    = 0x17 | OPC_SPECIAL,
150 7a387fff ths
    OPC_DSLL     = 0x38 | OPC_SPECIAL,
151 7a387fff ths
    OPC_DSRL     = 0x3A | OPC_SPECIAL, /* also DROTR */
152 7a387fff ths
    OPC_DSRA     = 0x3B | OPC_SPECIAL,
153 7a387fff ths
    OPC_DSLL32   = 0x3C | OPC_SPECIAL,
154 7a387fff ths
    OPC_DSRL32   = 0x3E | OPC_SPECIAL, /* also DROTR32 */
155 7a387fff ths
    OPC_DSRA32   = 0x3F | OPC_SPECIAL,
156 e37e863f bellard
    /* Multiplication / division */
157 7a387fff ths
    OPC_MULT     = 0x18 | OPC_SPECIAL,
158 7a387fff ths
    OPC_MULTU    = 0x19 | OPC_SPECIAL,
159 7a387fff ths
    OPC_DIV      = 0x1A | OPC_SPECIAL,
160 7a387fff ths
    OPC_DIVU     = 0x1B | OPC_SPECIAL,
161 7a387fff ths
    OPC_DMULT    = 0x1C | OPC_SPECIAL,
162 7a387fff ths
    OPC_DMULTU   = 0x1D | OPC_SPECIAL,
163 7a387fff ths
    OPC_DDIV     = 0x1E | OPC_SPECIAL,
164 7a387fff ths
    OPC_DDIVU    = 0x1F | OPC_SPECIAL,
165 e37e863f bellard
    /* 2 registers arithmetic / logic */
166 7a387fff ths
    OPC_ADD      = 0x20 | OPC_SPECIAL,
167 7a387fff ths
    OPC_ADDU     = 0x21 | OPC_SPECIAL,
168 7a387fff ths
    OPC_SUB      = 0x22 | OPC_SPECIAL,
169 7a387fff ths
    OPC_SUBU     = 0x23 | OPC_SPECIAL,
170 7a387fff ths
    OPC_AND      = 0x24 | OPC_SPECIAL,
171 7a387fff ths
    OPC_OR       = 0x25 | OPC_SPECIAL,
172 7a387fff ths
    OPC_XOR      = 0x26 | OPC_SPECIAL,
173 7a387fff ths
    OPC_NOR      = 0x27 | OPC_SPECIAL,
174 7a387fff ths
    OPC_SLT      = 0x2A | OPC_SPECIAL,
175 7a387fff ths
    OPC_SLTU     = 0x2B | OPC_SPECIAL,
176 7a387fff ths
    OPC_DADD     = 0x2C | OPC_SPECIAL,
177 7a387fff ths
    OPC_DADDU    = 0x2D | OPC_SPECIAL,
178 7a387fff ths
    OPC_DSUB     = 0x2E | OPC_SPECIAL,
179 7a387fff ths
    OPC_DSUBU    = 0x2F | OPC_SPECIAL,
180 e37e863f bellard
    /* Jumps */
181 7a387fff ths
    OPC_JR       = 0x08 | OPC_SPECIAL, /* Also JR.HB */
182 7a387fff ths
    OPC_JALR     = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
183 e37e863f bellard
    /* Traps */
184 7a387fff ths
    OPC_TGE      = 0x30 | OPC_SPECIAL,
185 7a387fff ths
    OPC_TGEU     = 0x31 | OPC_SPECIAL,
186 7a387fff ths
    OPC_TLT      = 0x32 | OPC_SPECIAL,
187 7a387fff ths
    OPC_TLTU     = 0x33 | OPC_SPECIAL,
188 7a387fff ths
    OPC_TEQ      = 0x34 | OPC_SPECIAL,
189 7a387fff ths
    OPC_TNE      = 0x36 | OPC_SPECIAL,
190 e37e863f bellard
    /* HI / LO registers load & stores */
191 7a387fff ths
    OPC_MFHI     = 0x10 | OPC_SPECIAL,
192 7a387fff ths
    OPC_MTHI     = 0x11 | OPC_SPECIAL,
193 7a387fff ths
    OPC_MFLO     = 0x12 | OPC_SPECIAL,
194 7a387fff ths
    OPC_MTLO     = 0x13 | OPC_SPECIAL,
195 e37e863f bellard
    /* Conditional moves */
196 7a387fff ths
    OPC_MOVZ     = 0x0A | OPC_SPECIAL,
197 7a387fff ths
    OPC_MOVN     = 0x0B | OPC_SPECIAL,
198 e37e863f bellard
199 7a387fff ths
    OPC_MOVCI    = 0x01 | OPC_SPECIAL,
200 e37e863f bellard
201 e37e863f bellard
    /* Special */
202 7a387fff ths
    OPC_PMON     = 0x05 | OPC_SPECIAL, /* inofficial */
203 7a387fff ths
    OPC_SYSCALL  = 0x0C | OPC_SPECIAL,
204 7a387fff ths
    OPC_BREAK    = 0x0D | OPC_SPECIAL,
205 7a387fff ths
    OPC_SPIM     = 0x0E | OPC_SPECIAL, /* inofficial */
206 7a387fff ths
    OPC_SYNC     = 0x0F | OPC_SPECIAL,
207 7a387fff ths
208 7a387fff ths
    OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
209 7a387fff ths
    OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
210 7a387fff ths
    OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
211 7a387fff ths
    OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
212 7a387fff ths
    OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
213 7a387fff ths
    OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
214 7a387fff ths
    OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
215 7a387fff ths
};
216 7a387fff ths
217 7a387fff ths
/* REGIMM (rt field) opcodes */
218 7a387fff ths
#define MASK_REGIMM(op)    MASK_OP_MAJOR(op) | (op & (0x1F << 16))
219 7a387fff ths
220 7a387fff ths
enum {
221 7a387fff ths
    OPC_BLTZ     = (0x00 << 16) | OPC_REGIMM,
222 7a387fff ths
    OPC_BLTZL    = (0x02 << 16) | OPC_REGIMM,
223 7a387fff ths
    OPC_BGEZ     = (0x01 << 16) | OPC_REGIMM,
224 7a387fff ths
    OPC_BGEZL    = (0x03 << 16) | OPC_REGIMM,
225 7a387fff ths
    OPC_BLTZAL   = (0x10 << 16) | OPC_REGIMM,
226 7a387fff ths
    OPC_BLTZALL  = (0x12 << 16) | OPC_REGIMM,
227 7a387fff ths
    OPC_BGEZAL   = (0x11 << 16) | OPC_REGIMM,
228 7a387fff ths
    OPC_BGEZALL  = (0x13 << 16) | OPC_REGIMM,
229 7a387fff ths
    OPC_TGEI     = (0x08 << 16) | OPC_REGIMM,
230 7a387fff ths
    OPC_TGEIU    = (0x09 << 16) | OPC_REGIMM,
231 7a387fff ths
    OPC_TLTI     = (0x0A << 16) | OPC_REGIMM,
232 7a387fff ths
    OPC_TLTIU    = (0x0B << 16) | OPC_REGIMM,
233 7a387fff ths
    OPC_TEQI     = (0x0C << 16) | OPC_REGIMM,
234 7a387fff ths
    OPC_TNEI     = (0x0E << 16) | OPC_REGIMM,
235 7a387fff ths
    OPC_SYNCI    = (0x1F << 16) | OPC_REGIMM,
236 e37e863f bellard
};
237 e37e863f bellard
238 7a387fff ths
/* Special2 opcodes */
239 7a387fff ths
#define MASK_SPECIAL2(op)  MASK_OP_MAJOR(op) | (op & 0x3F)
240 7a387fff ths
241 e37e863f bellard
enum {
242 7a387fff ths
    /* Multiply & xxx operations */
243 7a387fff ths
    OPC_MADD     = 0x00 | OPC_SPECIAL2,
244 7a387fff ths
    OPC_MADDU    = 0x01 | OPC_SPECIAL2,
245 7a387fff ths
    OPC_MUL      = 0x02 | OPC_SPECIAL2,
246 7a387fff ths
    OPC_MSUB     = 0x04 | OPC_SPECIAL2,
247 7a387fff ths
    OPC_MSUBU    = 0x05 | OPC_SPECIAL2,
248 e37e863f bellard
    /* Misc */
249 7a387fff ths
    OPC_CLZ      = 0x20 | OPC_SPECIAL2,
250 7a387fff ths
    OPC_CLO      = 0x21 | OPC_SPECIAL2,
251 7a387fff ths
    OPC_DCLZ     = 0x24 | OPC_SPECIAL2,
252 7a387fff ths
    OPC_DCLO     = 0x25 | OPC_SPECIAL2,
253 e37e863f bellard
    /* Special */
254 7a387fff ths
    OPC_SDBBP    = 0x3F | OPC_SPECIAL2,
255 7a387fff ths
};
256 7a387fff ths
257 7a387fff ths
/* Special3 opcodes */
258 7a387fff ths
#define MASK_SPECIAL3(op)  MASK_OP_MAJOR(op) | (op & 0x3F)
259 7a387fff ths
260 7a387fff ths
enum {
261 7a387fff ths
    OPC_EXT      = 0x00 | OPC_SPECIAL3,
262 7a387fff ths
    OPC_DEXTM    = 0x01 | OPC_SPECIAL3,
263 7a387fff ths
    OPC_DEXTU    = 0x02 | OPC_SPECIAL3,
264 7a387fff ths
    OPC_DEXT     = 0x03 | OPC_SPECIAL3,
265 7a387fff ths
    OPC_INS      = 0x04 | OPC_SPECIAL3,
266 7a387fff ths
    OPC_DINSM    = 0x05 | OPC_SPECIAL3,
267 7a387fff ths
    OPC_DINSU    = 0x06 | OPC_SPECIAL3,
268 7a387fff ths
    OPC_DINS     = 0x07 | OPC_SPECIAL3,
269 7a387fff ths
    OPC_BSHFL    = 0x20 | OPC_SPECIAL3,
270 7a387fff ths
    OPC_DBSHFL   = 0x24 | OPC_SPECIAL3,
271 7a387fff ths
    OPC_RDHWR    = 0x3B | OPC_SPECIAL3,
272 e37e863f bellard
};
273 e37e863f bellard
274 7a387fff ths
/* BSHFL opcodes */
275 7a387fff ths
#define MASK_BSHFL(op)     MASK_SPECIAL3(op) | (op & (0x1F << 6))
276 7a387fff ths
277 e37e863f bellard
enum {
278 7a387fff ths
    OPC_WSBH     = (0x02 << 6) | OPC_BSHFL,
279 7a387fff ths
    OPC_SEB      = (0x10 << 6) | OPC_BSHFL,
280 7a387fff ths
    OPC_SEH      = (0x18 << 6) | OPC_BSHFL,
281 e37e863f bellard
};
282 e37e863f bellard
283 7a387fff ths
/* DBSHFL opcodes */
284 7a387fff ths
#define MASK_DBSHFL(op)    MASK_SPECIAL3(op) | (op & (0x1F << 6))
285 7a387fff ths
286 e37e863f bellard
enum {
287 7a387fff ths
    OPC_DSBH     = (0x02 << 6) | OPC_DBSHFL,
288 7a387fff ths
    OPC_DSHD     = (0x05 << 6) | OPC_DBSHFL,
289 e37e863f bellard
};
290 e37e863f bellard
291 7a387fff ths
/* Coprocessor 0 (rs field) */
292 7a387fff ths
#define MASK_CP0(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
293 7a387fff ths
294 6ea83fed bellard
enum {
295 7a387fff ths
    OPC_MFC0     = (0x00 << 21) | OPC_CP0,
296 7a387fff ths
    OPC_DMFC0    = (0x01 << 21) | OPC_CP0,
297 7a387fff ths
    OPC_MTC0     = (0x04 << 21) | OPC_CP0,
298 7a387fff ths
    OPC_DMTC0    = (0x05 << 21) | OPC_CP0,
299 7a387fff ths
    OPC_RDPGPR   = (0x0A << 21) | OPC_CP0,
300 7a387fff ths
    OPC_MFMC0    = (0x0B << 21) | OPC_CP0,
301 7a387fff ths
    OPC_WRPGPR   = (0x0E << 21) | OPC_CP0,
302 7a387fff ths
    OPC_C0       = (0x10 << 21) | OPC_CP0,
303 7a387fff ths
    OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
304 7a387fff ths
    OPC_C0_LAST  = (0x1F << 21) | OPC_CP0,
305 6ea83fed bellard
};
306 7a387fff ths
307 7a387fff ths
/* MFMC0 opcodes */
308 7a387fff ths
#define MASK_MFMC0(op)     MASK_CP0(op) | (op & ((0x0C << 11) | (1 << 5)))
309 7a387fff ths
310 7a387fff ths
enum {
311 7a387fff ths
    OPC_DI       = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
312 7a387fff ths
    OPC_EI       = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
313 7a387fff ths
};
314 7a387fff ths
315 7a387fff ths
/* Coprocessor 0 (with rs == C0) */
316 7a387fff ths
#define MASK_C0(op)        MASK_CP0(op) | (op & 0x3F)
317 7a387fff ths
318 7a387fff ths
enum {
319 7a387fff ths
    OPC_TLBR     = 0x01 | OPC_C0,
320 7a387fff ths
    OPC_TLBWI    = 0x02 | OPC_C0,
321 7a387fff ths
    OPC_TLBWR    = 0x06 | OPC_C0,
322 7a387fff ths
    OPC_TLBP     = 0x08 | OPC_C0,
323 7a387fff ths
    OPC_RFE      = 0x10 | OPC_C0,
324 7a387fff ths
    OPC_ERET     = 0x18 | OPC_C0,
325 7a387fff ths
    OPC_DERET    = 0x1F | OPC_C0,
326 7a387fff ths
    OPC_WAIT     = 0x20 | OPC_C0,
327 7a387fff ths
};
328 7a387fff ths
329 7a387fff ths
/* Coprocessor 1 (rs field) */
330 7a387fff ths
#define MASK_CP1(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
331 7a387fff ths
332 7a387fff ths
enum {
333 7a387fff ths
    OPC_MFC1     = (0x00 << 21) | OPC_CP1,
334 7a387fff ths
    OPC_DMFC1    = (0x01 << 21) | OPC_CP1,
335 7a387fff ths
    OPC_CFC1     = (0x02 << 21) | OPC_CP1,
336 7a387fff ths
    OPC_MFHCI    = (0x03 << 21) | OPC_CP1,
337 7a387fff ths
    OPC_MTC1     = (0x04 << 21) | OPC_CP1,
338 7a387fff ths
    OPC_DMTC1    = (0x05 << 21) | OPC_CP1,
339 7a387fff ths
    OPC_CTC1     = (0x06 << 21) | OPC_CP1,
340 7a387fff ths
    OPC_MTHCI    = (0x07 << 21) | OPC_CP1,
341 7a387fff ths
    OPC_BC1      = (0x08 << 21) | OPC_CP1, /* bc */
342 7a387fff ths
    OPC_S_FMT    = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */
343 7a387fff ths
    OPC_D_FMT    = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */
344 7a387fff ths
    OPC_E_FMT    = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */
345 7a387fff ths
    OPC_Q_FMT    = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */
346 7a387fff ths
    OPC_W_FMT    = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
347 7a387fff ths
    OPC_L_FMT    = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
348 7a387fff ths
};
349 7a387fff ths
350 7a387fff ths
enum {
351 7a387fff ths
    OPC_BC1F     = (0x00 << 16) | OPC_BC1,
352 7a387fff ths
    OPC_BC1T     = (0x01 << 16) | OPC_BC1,
353 7a387fff ths
    OPC_BC1FL    = (0x02 << 16) | OPC_BC1,
354 7a387fff ths
    OPC_BC1TL    = (0x03 << 16) | OPC_BC1,
355 7a387fff ths
};
356 7a387fff ths
357 e1449664 ths
#define MASK_CP1_BCOND(op)      MASK_CP1(op) | (op & (0x3 << 16))
358 e1449664 ths
#define MASK_CP1_FUNC(op)       MASK_CP1(op) | (op & 0x3F)
359 7a387fff ths
360 7a387fff ths
#define MASK_CP2(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
361 7a387fff ths
#define MASK_CP3(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
362 6ea83fed bellard
363 6af0bf9c bellard
const unsigned char *regnames[] =
364 6af0bf9c bellard
    { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
365 6af0bf9c bellard
      "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
366 6af0bf9c bellard
      "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
367 6af0bf9c bellard
      "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
368 6af0bf9c bellard
369 6af0bf9c bellard
/* Warning: no function for r0 register (hard wired to zero) */
370 6af0bf9c bellard
#define GEN32(func, NAME) \
371 6af0bf9c bellard
static GenOpFunc *NAME ## _table [32] = {                                     \
372 6af0bf9c bellard
NULL,       NAME ## 1, NAME ## 2, NAME ## 3,                                  \
373 6af0bf9c bellard
NAME ## 4,  NAME ## 5, NAME ## 6, NAME ## 7,                                  \
374 6af0bf9c bellard
NAME ## 8,  NAME ## 9, NAME ## 10, NAME ## 11,                                \
375 6af0bf9c bellard
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
376 6af0bf9c bellard
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
377 6af0bf9c bellard
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
378 6af0bf9c bellard
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
379 6af0bf9c bellard
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
380 6af0bf9c bellard
};                                                                            \
381 6af0bf9c bellard
static inline void func(int n)                                                \
382 6af0bf9c bellard
{                                                                             \
383 6af0bf9c bellard
    NAME ## _table[n]();                                                      \
384 6af0bf9c bellard
}
385 6af0bf9c bellard
386 6af0bf9c bellard
/* General purpose registers moves */
387 6af0bf9c bellard
GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
388 6af0bf9c bellard
GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
389 6af0bf9c bellard
GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr);
390 6af0bf9c bellard
391 6af0bf9c bellard
GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
392 6af0bf9c bellard
GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
393 6af0bf9c bellard
394 71fb7241 ths
#ifdef MIPS_USES_FPU
395 71fb7241 ths
396 7a387fff ths
static const char *fregnames[] =
397 6ea83fed bellard
    { "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
398 6ea83fed bellard
      "f8",  "f9",  "f10", "f11", "f12", "f13", "f14", "f15",
399 6ea83fed bellard
      "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
400 6ea83fed bellard
      "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
401 6ea83fed bellard
402 6ea83fed bellard
# define SFGEN32(func, NAME) \
403 6ea83fed bellard
static GenOpFunc *NAME ## _table [32] = {                                     \
404 6ea83fed bellard
NAME ## 0,  NAME ## 1,  NAME ## 2,  NAME ## 3,                                \
405 6ea83fed bellard
NAME ## 4,  NAME ## 5,  NAME ## 6,  NAME ## 7,                                \
406 6ea83fed bellard
NAME ## 8,  NAME ## 9,  NAME ## 10, NAME ## 11,                               \
407 6ea83fed bellard
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
408 6ea83fed bellard
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
409 6ea83fed bellard
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
410 6ea83fed bellard
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
411 6ea83fed bellard
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
412 6ea83fed bellard
};                                                                            \
413 6ea83fed bellard
static inline void func(int n)                                                \
414 6ea83fed bellard
{                                                                             \
415 6ea83fed bellard
    NAME ## _table[n]();                                                      \
416 6ea83fed bellard
}
417 6ea83fed bellard
418 6ea83fed bellard
# define DFGEN32(func, NAME) \
419 6ea83fed bellard
static GenOpFunc *NAME ## _table [32] = {                                     \
420 6ea83fed bellard
NAME ## 0,  0, NAME ## 2,  0,                                                 \
421 6ea83fed bellard
NAME ## 4,  0, NAME ## 6,  0,                                                 \
422 6ea83fed bellard
NAME ## 8,  0, NAME ## 10, 0,                                                 \
423 6ea83fed bellard
NAME ## 12, 0, NAME ## 14, 0,                                                 \
424 6ea83fed bellard
NAME ## 16, 0, NAME ## 18, 0,                                                 \
425 6ea83fed bellard
NAME ## 20, 0, NAME ## 22, 0,                                                 \
426 6ea83fed bellard
NAME ## 24, 0, NAME ## 26, 0,                                                 \
427 6ea83fed bellard
NAME ## 28, 0, NAME ## 30, 0,                                                 \
428 6ea83fed bellard
};                                                                            \
429 6ea83fed bellard
static inline void func(int n)                                                \
430 6ea83fed bellard
{                                                                             \
431 6ea83fed bellard
    NAME ## _table[n]();                                                      \
432 6ea83fed bellard
}
433 6ea83fed bellard
434 6ea83fed bellard
SFGEN32(gen_op_load_fpr_WT0,  gen_op_load_fpr_WT0_fpr);
435 6ea83fed bellard
SFGEN32(gen_op_store_fpr_WT0, gen_op_store_fpr_WT0_fpr);
436 6ea83fed bellard
437 6ea83fed bellard
SFGEN32(gen_op_load_fpr_WT1,  gen_op_load_fpr_WT1_fpr);
438 6ea83fed bellard
SFGEN32(gen_op_store_fpr_WT1, gen_op_store_fpr_WT1_fpr);
439 6ea83fed bellard
440 6ea83fed bellard
SFGEN32(gen_op_load_fpr_WT2,  gen_op_load_fpr_WT2_fpr);
441 6ea83fed bellard
SFGEN32(gen_op_store_fpr_WT2, gen_op_store_fpr_WT2_fpr);
442 6ea83fed bellard
443 6ea83fed bellard
DFGEN32(gen_op_load_fpr_DT0,  gen_op_load_fpr_DT0_fpr);
444 6ea83fed bellard
DFGEN32(gen_op_store_fpr_DT0, gen_op_store_fpr_DT0_fpr);
445 6ea83fed bellard
446 6ea83fed bellard
DFGEN32(gen_op_load_fpr_DT1,  gen_op_load_fpr_DT1_fpr);
447 6ea83fed bellard
DFGEN32(gen_op_store_fpr_DT1, gen_op_store_fpr_DT1_fpr);
448 6ea83fed bellard
449 6ea83fed bellard
DFGEN32(gen_op_load_fpr_DT2,  gen_op_load_fpr_DT2_fpr);
450 6ea83fed bellard
DFGEN32(gen_op_store_fpr_DT2, gen_op_store_fpr_DT2_fpr);
451 6ea83fed bellard
452 6ea83fed bellard
#define FOP_CONDS(fmt) \
453 6ea83fed bellard
static GenOpFunc * cond_ ## fmt ## _table[16] = {                       \
454 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _f,                                           \
455 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _un,                                          \
456 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _eq,                                          \
457 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _ueq,                                         \
458 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _olt,                                         \
459 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _ult,                                         \
460 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _ole,                                         \
461 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _ule,                                         \
462 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _sf,                                          \
463 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _ngle,                                        \
464 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _seq,                                         \
465 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _ngl,                                         \
466 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _lt,                                          \
467 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _nge,                                         \
468 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _le,                                          \
469 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _ngt,                                         \
470 6ea83fed bellard
};                                                                      \
471 6ea83fed bellard
static inline void gen_cmp_ ## fmt(int n)                               \
472 6ea83fed bellard
{                                                                       \
473 6ea83fed bellard
    cond_ ## fmt ## _table[n]();                                        \
474 6ea83fed bellard
}
475 6ea83fed bellard
476 6ea83fed bellard
FOP_CONDS(d)
477 6ea83fed bellard
FOP_CONDS(s)
478 6ea83fed bellard
479 71fb7241 ths
#endif /* MIPS_USES_FPU */
480 71fb7241 ths
481 6af0bf9c bellard
typedef struct DisasContext {
482 6af0bf9c bellard
    struct TranslationBlock *tb;
483 6af0bf9c bellard
    target_ulong pc, saved_pc;
484 6af0bf9c bellard
    uint32_t opcode;
485 6af0bf9c bellard
    /* Routine used to access memory */
486 6af0bf9c bellard
    int mem_idx;
487 6af0bf9c bellard
    uint32_t hflags, saved_hflags;
488 6af0bf9c bellard
    uint32_t CP0_Status;
489 6af0bf9c bellard
    int bstate;
490 6af0bf9c bellard
    target_ulong btarget;
491 6af0bf9c bellard
} DisasContext;
492 6af0bf9c bellard
493 6af0bf9c bellard
enum {
494 6af0bf9c bellard
    BS_NONE     = 0, /* We go out of the TB without reaching a branch or an
495 6af0bf9c bellard
                      * exception condition
496 6af0bf9c bellard
                      */
497 6af0bf9c bellard
    BS_STOP     = 1, /* We want to stop translation for any reason */
498 6af0bf9c bellard
    BS_BRANCH   = 2, /* We reached a branch condition     */
499 6af0bf9c bellard
    BS_EXCP     = 3, /* We reached an exception condition */
500 6af0bf9c bellard
};
501 6af0bf9c bellard
502 6af0bf9c bellard
#if defined MIPS_DEBUG_DISAS
503 6af0bf9c bellard
#define MIPS_DEBUG(fmt, args...)                                              \
504 6af0bf9c bellard
do {                                                                          \
505 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_IN_ASM) {                                       \
506 c570fd16 ths
        fprintf(logfile, TLSZ ": %08x " fmt "\n",                             \
507 6af0bf9c bellard
                ctx->pc, ctx->opcode , ##args);                               \
508 6af0bf9c bellard
    }                                                                         \
509 6af0bf9c bellard
} while (0)
510 6af0bf9c bellard
#else
511 6af0bf9c bellard
#define MIPS_DEBUG(fmt, args...) do { } while(0)
512 6af0bf9c bellard
#endif
513 6af0bf9c bellard
514 6af0bf9c bellard
#define MIPS_INVAL(op)                                                        \
515 6af0bf9c bellard
do {                                                                          \
516 6af0bf9c bellard
    MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26,            \
517 6af0bf9c bellard
               ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F));             \
518 6af0bf9c bellard
} while (0)
519 6af0bf9c bellard
520 6af0bf9c bellard
#define GEN_LOAD_REG_TN(Tn, Rn)                                               \
521 6af0bf9c bellard
do {                                                                          \
522 6af0bf9c bellard
    if (Rn == 0) {                                                            \
523 6af0bf9c bellard
        glue(gen_op_reset_, Tn)();                                            \
524 6af0bf9c bellard
    } else {                                                                  \
525 6af0bf9c bellard
        glue(gen_op_load_gpr_, Tn)(Rn);                                       \
526 6af0bf9c bellard
    }                                                                         \
527 6af0bf9c bellard
} while (0)
528 6af0bf9c bellard
529 6af0bf9c bellard
#define GEN_LOAD_IMM_TN(Tn, Imm)                                              \
530 6af0bf9c bellard
do {                                                                          \
531 6af0bf9c bellard
    if (Imm == 0) {                                                           \
532 6af0bf9c bellard
        glue(gen_op_reset_, Tn)();                                            \
533 6af0bf9c bellard
    } else {                                                                  \
534 6af0bf9c bellard
        glue(gen_op_set_, Tn)(Imm);                                           \
535 6af0bf9c bellard
    }                                                                         \
536 6af0bf9c bellard
} while (0)
537 6af0bf9c bellard
538 6af0bf9c bellard
#define GEN_STORE_TN_REG(Rn, Tn)                                              \
539 6af0bf9c bellard
do {                                                                          \
540 6af0bf9c bellard
    if (Rn != 0) {                                                            \
541 6af0bf9c bellard
        glue(glue(gen_op_store_, Tn),_gpr)(Rn);                               \
542 6af0bf9c bellard
    }                                                                         \
543 6af0bf9c bellard
} while (0)
544 6af0bf9c bellard
545 7a387fff ths
#define GEN_LOAD_FREG_FTN(FTn, Fn)                                            \
546 6ea83fed bellard
do {                                                                          \
547 6ea83fed bellard
    glue(gen_op_load_fpr_, FTn)(Fn);                                          \
548 6ea83fed bellard
} while (0)
549 6ea83fed bellard
550 6ea83fed bellard
#define GEN_STORE_FTN_FREG(Fn, FTn)                                           \
551 6ea83fed bellard
do {                                                                          \
552 6ea83fed bellard
    glue(gen_op_store_fpr_, FTn)(Fn);                                         \
553 6ea83fed bellard
} while (0)
554 6ea83fed bellard
555 6af0bf9c bellard
static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
556 6af0bf9c bellard
{
557 6af0bf9c bellard
#if defined MIPS_DEBUG_DISAS
558 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_IN_ASM) {
559 6af0bf9c bellard
            fprintf(logfile, "hflags %08x saved %08x\n",
560 6af0bf9c bellard
                    ctx->hflags, ctx->saved_hflags);
561 6af0bf9c bellard
    }
562 6af0bf9c bellard
#endif
563 6af0bf9c bellard
    if (do_save_pc && ctx->pc != ctx->saved_pc) {
564 6af0bf9c bellard
        gen_op_save_pc(ctx->pc);
565 6af0bf9c bellard
        ctx->saved_pc = ctx->pc;
566 6af0bf9c bellard
    }
567 6af0bf9c bellard
    if (ctx->hflags != ctx->saved_hflags) {
568 6af0bf9c bellard
        gen_op_save_state(ctx->hflags);
569 6af0bf9c bellard
        ctx->saved_hflags = ctx->hflags;
570 6af0bf9c bellard
        if (ctx->hflags & MIPS_HFLAG_BR) {
571 6af0bf9c bellard
            gen_op_save_breg_target();
572 6af0bf9c bellard
        } else if (ctx->hflags & MIPS_HFLAG_B) {
573 6af0bf9c bellard
            gen_op_save_btarget(ctx->btarget);
574 6af0bf9c bellard
        } else if (ctx->hflags & MIPS_HFLAG_BMASK) {
575 6af0bf9c bellard
            gen_op_save_bcond();
576 6af0bf9c bellard
            gen_op_save_btarget(ctx->btarget);
577 6af0bf9c bellard
        }
578 6af0bf9c bellard
    }
579 6af0bf9c bellard
}
580 6af0bf9c bellard
581 4ad40f36 bellard
static inline void generate_exception_err (DisasContext *ctx, int excp, int err)
582 6af0bf9c bellard
{
583 6af0bf9c bellard
#if defined MIPS_DEBUG_DISAS
584 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_IN_ASM)
585 6af0bf9c bellard
            fprintf(logfile, "%s: raise exception %d\n", __func__, excp);
586 6af0bf9c bellard
#endif
587 6af0bf9c bellard
    save_cpu_state(ctx, 1);
588 4ad40f36 bellard
    if (err == 0)
589 4ad40f36 bellard
        gen_op_raise_exception(excp);
590 4ad40f36 bellard
    else
591 4ad40f36 bellard
        gen_op_raise_exception_err(excp, err);
592 6af0bf9c bellard
    ctx->bstate = BS_EXCP;
593 6af0bf9c bellard
}
594 6af0bf9c bellard
595 4ad40f36 bellard
static inline void generate_exception (DisasContext *ctx, int excp)
596 4ad40f36 bellard
{
597 4ad40f36 bellard
    generate_exception_err (ctx, excp, 0);
598 4ad40f36 bellard
}
599 4ad40f36 bellard
600 6af0bf9c bellard
#if defined(CONFIG_USER_ONLY)
601 6af0bf9c bellard
#define op_ldst(name)        gen_op_##name##_raw()
602 6af0bf9c bellard
#define OP_LD_TABLE(width)
603 6af0bf9c bellard
#define OP_ST_TABLE(width)
604 6af0bf9c bellard
#else
605 6af0bf9c bellard
#define op_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
606 6af0bf9c bellard
#define OP_LD_TABLE(width)                                                    \
607 6af0bf9c bellard
static GenOpFunc *gen_op_l##width[] = {                                       \
608 6af0bf9c bellard
    &gen_op_l##width##_user,                                                  \
609 6af0bf9c bellard
    &gen_op_l##width##_kernel,                                                \
610 6af0bf9c bellard
}
611 6af0bf9c bellard
#define OP_ST_TABLE(width)                                                    \
612 6af0bf9c bellard
static GenOpFunc *gen_op_s##width[] = {                                       \
613 6af0bf9c bellard
    &gen_op_s##width##_user,                                                  \
614 6af0bf9c bellard
    &gen_op_s##width##_kernel,                                                \
615 6af0bf9c bellard
}
616 6af0bf9c bellard
#endif
617 6af0bf9c bellard
618 7a387fff ths
#ifdef MIPS_HAS_MIPS64
619 6af0bf9c bellard
OP_LD_TABLE(d);
620 6af0bf9c bellard
OP_LD_TABLE(dl);
621 6af0bf9c bellard
OP_LD_TABLE(dr);
622 6af0bf9c bellard
OP_ST_TABLE(d);
623 6af0bf9c bellard
OP_ST_TABLE(dl);
624 6af0bf9c bellard
OP_ST_TABLE(dr);
625 c570fd16 ths
OP_LD_TABLE(ld);
626 c570fd16 ths
OP_ST_TABLE(cd);
627 6af0bf9c bellard
#endif
628 6af0bf9c bellard
OP_LD_TABLE(w);
629 d796321b bellard
OP_LD_TABLE(wu);
630 6af0bf9c bellard
OP_LD_TABLE(wl);
631 6af0bf9c bellard
OP_LD_TABLE(wr);
632 6af0bf9c bellard
OP_ST_TABLE(w);
633 6af0bf9c bellard
OP_ST_TABLE(wl);
634 6af0bf9c bellard
OP_ST_TABLE(wr);
635 6af0bf9c bellard
OP_LD_TABLE(h);
636 6af0bf9c bellard
OP_LD_TABLE(hu);
637 6af0bf9c bellard
OP_ST_TABLE(h);
638 6af0bf9c bellard
OP_LD_TABLE(b);
639 6af0bf9c bellard
OP_LD_TABLE(bu);
640 6af0bf9c bellard
OP_ST_TABLE(b);
641 6af0bf9c bellard
OP_LD_TABLE(l);
642 6af0bf9c bellard
OP_ST_TABLE(c);
643 71fb7241 ths
#ifdef MIPS_USES_FPU
644 6ea83fed bellard
OP_LD_TABLE(wc1);
645 6ea83fed bellard
OP_ST_TABLE(wc1);
646 6ea83fed bellard
OP_LD_TABLE(dc1);
647 6ea83fed bellard
OP_ST_TABLE(dc1);
648 71fb7241 ths
#endif
649 6af0bf9c bellard
650 6af0bf9c bellard
/* Load and store */
651 7a387fff ths
static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
652 6af0bf9c bellard
                      int base, int16_t offset)
653 6af0bf9c bellard
{
654 7a387fff ths
    const char *opn = "unk";
655 6af0bf9c bellard
656 6af0bf9c bellard
    if (base == 0) {
657 6af0bf9c bellard
        GEN_LOAD_IMM_TN(T0, offset);
658 6af0bf9c bellard
    } else if (offset == 0) {
659 6af0bf9c bellard
        gen_op_load_gpr_T0(base);
660 6af0bf9c bellard
    } else {
661 6af0bf9c bellard
        gen_op_load_gpr_T0(base);
662 6af0bf9c bellard
        gen_op_set_T1(offset);
663 6af0bf9c bellard
        gen_op_add();
664 6af0bf9c bellard
    }
665 6af0bf9c bellard
    /* Don't do NOP if destination is zero: we must perform the actual
666 6af0bf9c bellard
     * memory access
667 6af0bf9c bellard
     */
668 6af0bf9c bellard
    switch (opc) {
669 7a387fff ths
#ifdef MIPS_HAS_MIPS64
670 6af0bf9c bellard
    case OPC_LD:
671 6af0bf9c bellard
        op_ldst(ld);
672 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
673 6af0bf9c bellard
        opn = "ld";
674 6af0bf9c bellard
        break;
675 7a387fff ths
    case OPC_LLD:
676 7a387fff ths
        op_ldst(lld);
677 7a387fff ths
        GEN_STORE_TN_REG(rt, T0);
678 7a387fff ths
        opn = "lld";
679 7a387fff ths
        break;
680 6af0bf9c bellard
    case OPC_SD:
681 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
682 6af0bf9c bellard
        op_ldst(sd);
683 6af0bf9c bellard
        opn = "sd";
684 6af0bf9c bellard
        break;
685 7a387fff ths
    case OPC_SCD:
686 7a387fff ths
        GEN_LOAD_REG_TN(T1, rt);
687 7a387fff ths
        op_ldst(scd);
688 7a387fff ths
        opn = "scd";
689 7a387fff ths
        break;
690 6af0bf9c bellard
    case OPC_LDL:
691 6af0bf9c bellard
        op_ldst(ldl);
692 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
693 6af0bf9c bellard
        opn = "ldl";
694 6af0bf9c bellard
        break;
695 6af0bf9c bellard
    case OPC_SDL:
696 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
697 6af0bf9c bellard
        op_ldst(sdl);
698 6af0bf9c bellard
        opn = "sdl";
699 6af0bf9c bellard
        break;
700 6af0bf9c bellard
    case OPC_LDR:
701 6af0bf9c bellard
        op_ldst(ldr);
702 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
703 6af0bf9c bellard
        opn = "ldr";
704 6af0bf9c bellard
        break;
705 6af0bf9c bellard
    case OPC_SDR:
706 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
707 6af0bf9c bellard
        op_ldst(sdr);
708 6af0bf9c bellard
        opn = "sdr";
709 6af0bf9c bellard
        break;
710 6af0bf9c bellard
#endif
711 6af0bf9c bellard
    case OPC_LW:
712 6af0bf9c bellard
        op_ldst(lw);
713 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
714 6af0bf9c bellard
        opn = "lw";
715 6af0bf9c bellard
        break;
716 d796321b bellard
    case OPC_LWU:
717 d796321b bellard
        op_ldst(lwu);
718 d796321b bellard
        GEN_STORE_TN_REG(rt, T0);
719 d796321b bellard
        opn = "lwu";
720 d796321b bellard
        break;
721 6af0bf9c bellard
    case OPC_SW:
722 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
723 6af0bf9c bellard
        op_ldst(sw);
724 6af0bf9c bellard
        opn = "sw";
725 6af0bf9c bellard
        break;
726 6af0bf9c bellard
    case OPC_LH:
727 6af0bf9c bellard
        op_ldst(lh);
728 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
729 6af0bf9c bellard
        opn = "lh";
730 6af0bf9c bellard
        break;
731 6af0bf9c bellard
    case OPC_SH:
732 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
733 6af0bf9c bellard
        op_ldst(sh);
734 6af0bf9c bellard
        opn = "sh";
735 6af0bf9c bellard
        break;
736 6af0bf9c bellard
    case OPC_LHU:
737 6af0bf9c bellard
        op_ldst(lhu);
738 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
739 6af0bf9c bellard
        opn = "lhu";
740 6af0bf9c bellard
        break;
741 6af0bf9c bellard
    case OPC_LB:
742 6af0bf9c bellard
        op_ldst(lb);
743 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
744 6af0bf9c bellard
        opn = "lb";
745 6af0bf9c bellard
        break;
746 6af0bf9c bellard
    case OPC_SB:
747 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
748 6af0bf9c bellard
        op_ldst(sb);
749 6af0bf9c bellard
        opn = "sb";
750 6af0bf9c bellard
        break;
751 6af0bf9c bellard
    case OPC_LBU:
752 6af0bf9c bellard
        op_ldst(lbu);
753 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
754 6af0bf9c bellard
        opn = "lbu";
755 6af0bf9c bellard
        break;
756 6af0bf9c bellard
    case OPC_LWL:
757 9d1d106a bellard
        GEN_LOAD_REG_TN(T1, rt);
758 6af0bf9c bellard
        op_ldst(lwl);
759 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
760 6af0bf9c bellard
        opn = "lwl";
761 6af0bf9c bellard
        break;
762 6af0bf9c bellard
    case OPC_SWL:
763 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
764 6af0bf9c bellard
        op_ldst(swl);
765 6af0bf9c bellard
        opn = "swr";
766 6af0bf9c bellard
        break;
767 6af0bf9c bellard
    case OPC_LWR:
768 9d1d106a bellard
        GEN_LOAD_REG_TN(T1, rt);
769 6af0bf9c bellard
        op_ldst(lwr);
770 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
771 6af0bf9c bellard
        opn = "lwr";
772 6af0bf9c bellard
        break;
773 6af0bf9c bellard
    case OPC_SWR:
774 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
775 6af0bf9c bellard
        op_ldst(swr);
776 6af0bf9c bellard
        opn = "swr";
777 6af0bf9c bellard
        break;
778 6af0bf9c bellard
    case OPC_LL:
779 6af0bf9c bellard
        op_ldst(ll);
780 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
781 6af0bf9c bellard
        opn = "ll";
782 6af0bf9c bellard
        break;
783 6af0bf9c bellard
    case OPC_SC:
784 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
785 6af0bf9c bellard
        op_ldst(sc);
786 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
787 6af0bf9c bellard
        opn = "sc";
788 6af0bf9c bellard
        break;
789 6af0bf9c bellard
    default:
790 6af0bf9c bellard
        MIPS_INVAL("load/store");
791 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
792 6af0bf9c bellard
        return;
793 6af0bf9c bellard
    }
794 6af0bf9c bellard
    MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
795 6af0bf9c bellard
}
796 6af0bf9c bellard
797 71fb7241 ths
#ifdef MIPS_USES_FPU
798 71fb7241 ths
799 6ea83fed bellard
/* Load and store */
800 7a387fff ths
static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
801 6ea83fed bellard
                      int base, int16_t offset)
802 6ea83fed bellard
{
803 7a387fff ths
    const char *opn = "unk";
804 6ea83fed bellard
805 6ea83fed bellard
    if (base == 0) {
806 6ea83fed bellard
        GEN_LOAD_IMM_TN(T0, offset);
807 6ea83fed bellard
    } else if (offset == 0) {
808 6ea83fed bellard
        gen_op_load_gpr_T0(base);
809 6ea83fed bellard
    } else {
810 6ea83fed bellard
        gen_op_load_gpr_T0(base);
811 6ea83fed bellard
        gen_op_set_T1(offset);
812 6ea83fed bellard
        gen_op_add();
813 6ea83fed bellard
    }
814 6ea83fed bellard
    /* Don't do NOP if destination is zero: we must perform the actual
815 6ea83fed bellard
     * memory access
816 6ea83fed bellard
     */
817 6ea83fed bellard
    switch (opc) {
818 6ea83fed bellard
    case OPC_LWC1:
819 6ea83fed bellard
        op_ldst(lwc1);
820 6ea83fed bellard
        GEN_STORE_FTN_FREG(ft, WT0);
821 6ea83fed bellard
        opn = "lwc1";
822 6ea83fed bellard
        break;
823 6ea83fed bellard
    case OPC_SWC1:
824 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, ft);
825 6ea83fed bellard
        op_ldst(swc1);
826 6ea83fed bellard
        opn = "swc1";
827 6ea83fed bellard
        break;
828 6ea83fed bellard
    case OPC_LDC1:
829 6ea83fed bellard
        op_ldst(ldc1);
830 6ea83fed bellard
        GEN_STORE_FTN_FREG(ft, DT0);
831 6ea83fed bellard
        opn = "ldc1";
832 6ea83fed bellard
        break;
833 6ea83fed bellard
    case OPC_SDC1:
834 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, ft);
835 6ea83fed bellard
        op_ldst(sdc1);
836 6ea83fed bellard
        opn = "sdc1";
837 6ea83fed bellard
        break;
838 6ea83fed bellard
    default:
839 6ea83fed bellard
        MIPS_INVAL("float load/store");
840 7a387fff ths
        generate_exception_err(ctx, EXCP_CpU, 1);
841 6ea83fed bellard
        return;
842 6ea83fed bellard
    }
843 6ea83fed bellard
    MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
844 6ea83fed bellard
}
845 6ea83fed bellard
846 71fb7241 ths
#endif /* MIPS_USES_FPU */
847 71fb7241 ths
848 6af0bf9c bellard
/* Arithmetic with immediate operand */
849 7a387fff ths
static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt,
850 6af0bf9c bellard
                           int rs, int16_t imm)
851 6af0bf9c bellard
{
852 6af0bf9c bellard
    uint32_t uimm;
853 7a387fff ths
    const char *opn = "unk";
854 6af0bf9c bellard
855 7a387fff ths
    if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
856 6af0bf9c bellard
        /* if no destination, treat it as a NOP 
857 6af0bf9c bellard
         * For addi, we must generate the overflow exception when needed.
858 6af0bf9c bellard
         */
859 6af0bf9c bellard
        MIPS_DEBUG("NOP");
860 6af0bf9c bellard
        return;
861 6af0bf9c bellard
    }
862 6af0bf9c bellard
    if (opc == OPC_ADDI || opc == OPC_ADDIU ||
863 7a387fff ths
        opc == OPC_DADDI || opc == OPC_DADDIU ||
864 6af0bf9c bellard
        opc == OPC_SLTI || opc == OPC_SLTIU)
865 7a387fff ths
        uimm = (int32_t)imm; /* Sign extend to 32 bits */
866 6af0bf9c bellard
    else
867 6af0bf9c bellard
        uimm = (uint16_t)imm;
868 6af0bf9c bellard
    if (opc != OPC_LUI) {
869 6af0bf9c bellard
        GEN_LOAD_REG_TN(T0, rs);
870 6af0bf9c bellard
        GEN_LOAD_IMM_TN(T1, uimm);
871 6af0bf9c bellard
    } else {
872 6af0bf9c bellard
        uimm = uimm << 16;
873 6af0bf9c bellard
        GEN_LOAD_IMM_TN(T0, uimm);
874 6af0bf9c bellard
    }
875 6af0bf9c bellard
    switch (opc) {
876 6af0bf9c bellard
    case OPC_ADDI:
877 6af0bf9c bellard
        save_cpu_state(ctx, 1);
878 6af0bf9c bellard
        gen_op_addo();
879 6af0bf9c bellard
        opn = "addi";
880 6af0bf9c bellard
        break;
881 6af0bf9c bellard
    case OPC_ADDIU:
882 6af0bf9c bellard
        gen_op_add();
883 6af0bf9c bellard
        opn = "addiu";
884 6af0bf9c bellard
        break;
885 7a387fff ths
#ifdef MIPS_HAS_MIPS64
886 7a387fff ths
    case OPC_DADDI:
887 7a387fff ths
        save_cpu_state(ctx, 1);
888 7a387fff ths
        gen_op_daddo();
889 7a387fff ths
        opn = "daddi";
890 7a387fff ths
        break;
891 7a387fff ths
    case OPC_DADDIU:
892 7a387fff ths
        gen_op_dadd();
893 7a387fff ths
        opn = "daddiu";
894 7a387fff ths
        break;
895 7a387fff ths
#endif
896 6af0bf9c bellard
    case OPC_SLTI:
897 6af0bf9c bellard
        gen_op_lt();
898 6af0bf9c bellard
        opn = "slti";
899 6af0bf9c bellard
        break;
900 6af0bf9c bellard
    case OPC_SLTIU:
901 6af0bf9c bellard
        gen_op_ltu();
902 6af0bf9c bellard
        opn = "sltiu";
903 6af0bf9c bellard
        break;
904 6af0bf9c bellard
    case OPC_ANDI:
905 6af0bf9c bellard
        gen_op_and();
906 6af0bf9c bellard
        opn = "andi";
907 6af0bf9c bellard
        break;
908 6af0bf9c bellard
    case OPC_ORI:
909 6af0bf9c bellard
        gen_op_or();
910 6af0bf9c bellard
        opn = "ori";
911 6af0bf9c bellard
        break;
912 6af0bf9c bellard
    case OPC_XORI:
913 6af0bf9c bellard
        gen_op_xor();
914 6af0bf9c bellard
        opn = "xori";
915 6af0bf9c bellard
        break;
916 6af0bf9c bellard
    case OPC_LUI:
917 6af0bf9c bellard
        opn = "lui";
918 6af0bf9c bellard
        break;
919 6af0bf9c bellard
    case OPC_SLL:
920 6af0bf9c bellard
        gen_op_sll();
921 6af0bf9c bellard
        opn = "sll";
922 6af0bf9c bellard
        break;
923 6af0bf9c bellard
    case OPC_SRA:
924 6af0bf9c bellard
        gen_op_sra();
925 6af0bf9c bellard
        opn = "sra";
926 6af0bf9c bellard
        break;
927 6af0bf9c bellard
    case OPC_SRL:
928 7a387fff ths
       if ((ctx->opcode >> 21) & 1) {
929 7a387fff ths
            gen_op_rotr();
930 7a387fff ths
            opn = "rotr";
931 7a387fff ths
       } else {
932 7a387fff ths
            gen_op_srl();
933 7a387fff ths
            opn = "srl";
934 7a387fff ths
       }
935 7a387fff ths
        break;
936 7a387fff ths
#ifdef MIPS_HAS_MIPS64
937 7a387fff ths
    case OPC_DSLL:
938 7a387fff ths
        gen_op_dsll();
939 7a387fff ths
        opn = "dsll";
940 7a387fff ths
        break;
941 7a387fff ths
    case OPC_DSRA:
942 7a387fff ths
        gen_op_dsra();
943 7a387fff ths
        opn = "dsra";
944 7a387fff ths
        break;
945 7a387fff ths
    case OPC_DSRL:
946 7a387fff ths
       if ((ctx->opcode >> 21) & 1) {
947 7a387fff ths
            gen_op_drotr();
948 7a387fff ths
            opn = "drotr";
949 7a387fff ths
       } else {
950 7a387fff ths
            gen_op_dsrl();
951 7a387fff ths
            opn = "dsrl";
952 7a387fff ths
       }
953 7a387fff ths
        break;
954 7a387fff ths
    case OPC_DSLL32:
955 7a387fff ths
        gen_op_dsll32();
956 7a387fff ths
        opn = "dsll32";
957 7a387fff ths
        break;
958 7a387fff ths
    case OPC_DSRA32:
959 7a387fff ths
        gen_op_dsra32();
960 7a387fff ths
        opn = "dsra32";
961 7a387fff ths
        break;
962 7a387fff ths
    case OPC_DSRL32:
963 7a387fff ths
       if ((ctx->opcode >> 21) & 1) {
964 7a387fff ths
            gen_op_drotr32();
965 7a387fff ths
            opn = "drotr32";
966 7a387fff ths
       } else {
967 7a387fff ths
            gen_op_dsrl32();
968 7a387fff ths
            opn = "dsrl32";
969 7a387fff ths
       }
970 6af0bf9c bellard
        break;
971 7a387fff ths
#endif
972 6af0bf9c bellard
    default:
973 6af0bf9c bellard
        MIPS_INVAL("imm arith");
974 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
975 6af0bf9c bellard
        return;
976 6af0bf9c bellard
    }
977 6af0bf9c bellard
    GEN_STORE_TN_REG(rt, T0);
978 6af0bf9c bellard
    MIPS_DEBUG("%s %s, %s, %x", opn, regnames[rt], regnames[rs], uimm);
979 6af0bf9c bellard
}
980 6af0bf9c bellard
981 6af0bf9c bellard
/* Arithmetic */
982 7a387fff ths
static void gen_arith (DisasContext *ctx, uint32_t opc,
983 6af0bf9c bellard
                       int rd, int rs, int rt)
984 6af0bf9c bellard
{
985 7a387fff ths
    const char *opn = "unk";
986 6af0bf9c bellard
987 7a387fff ths
    if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
988 7a387fff ths
       && opc != OPC_DADD && opc != OPC_DSUB) {
989 6af0bf9c bellard
        /* if no destination, treat it as a NOP 
990 6af0bf9c bellard
         * For add & sub, we must generate the overflow exception when needed.
991 6af0bf9c bellard
         */
992 6af0bf9c bellard
        MIPS_DEBUG("NOP");
993 6af0bf9c bellard
        return;
994 6af0bf9c bellard
    }
995 6af0bf9c bellard
    GEN_LOAD_REG_TN(T0, rs);
996 6af0bf9c bellard
    GEN_LOAD_REG_TN(T1, rt);
997 6af0bf9c bellard
    switch (opc) {
998 6af0bf9c bellard
    case OPC_ADD:
999 6af0bf9c bellard
        save_cpu_state(ctx, 1);
1000 6af0bf9c bellard
        gen_op_addo();
1001 6af0bf9c bellard
        opn = "add";
1002 6af0bf9c bellard
        break;
1003 6af0bf9c bellard
    case OPC_ADDU:
1004 6af0bf9c bellard
        gen_op_add();
1005 6af0bf9c bellard
        opn = "addu";
1006 6af0bf9c bellard
        break;
1007 6af0bf9c bellard
    case OPC_SUB:
1008 6af0bf9c bellard
        save_cpu_state(ctx, 1);
1009 6af0bf9c bellard
        gen_op_subo();
1010 6af0bf9c bellard
        opn = "sub";
1011 6af0bf9c bellard
        break;
1012 6af0bf9c bellard
    case OPC_SUBU:
1013 6af0bf9c bellard
        gen_op_sub();
1014 6af0bf9c bellard
        opn = "subu";
1015 6af0bf9c bellard
        break;
1016 7a387fff ths
#ifdef MIPS_HAS_MIPS64
1017 7a387fff ths
    case OPC_DADD:
1018 7a387fff ths
        save_cpu_state(ctx, 1);
1019 7a387fff ths
        gen_op_daddo();
1020 7a387fff ths
        opn = "dadd";
1021 7a387fff ths
        break;
1022 7a387fff ths
    case OPC_DADDU:
1023 7a387fff ths
        gen_op_dadd();
1024 7a387fff ths
        opn = "daddu";
1025 7a387fff ths
        break;
1026 7a387fff ths
    case OPC_DSUB:
1027 7a387fff ths
        save_cpu_state(ctx, 1);
1028 7a387fff ths
        gen_op_dsubo();
1029 7a387fff ths
        opn = "dsub";
1030 7a387fff ths
        break;
1031 7a387fff ths
    case OPC_DSUBU:
1032 7a387fff ths
        gen_op_dsub();
1033 7a387fff ths
        opn = "dsubu";
1034 7a387fff ths
        break;
1035 7a387fff ths
#endif
1036 6af0bf9c bellard
    case OPC_SLT:
1037 6af0bf9c bellard
        gen_op_lt();
1038 6af0bf9c bellard
        opn = "slt";
1039 6af0bf9c bellard
        break;
1040 6af0bf9c bellard
    case OPC_SLTU:
1041 6af0bf9c bellard
        gen_op_ltu();
1042 6af0bf9c bellard
        opn = "sltu";
1043 6af0bf9c bellard
        break;
1044 6af0bf9c bellard
    case OPC_AND:
1045 6af0bf9c bellard
        gen_op_and();
1046 6af0bf9c bellard
        opn = "and";
1047 6af0bf9c bellard
        break;
1048 6af0bf9c bellard
    case OPC_NOR:
1049 6af0bf9c bellard
        gen_op_nor();
1050 6af0bf9c bellard
        opn = "nor";
1051 6af0bf9c bellard
        break;
1052 6af0bf9c bellard
    case OPC_OR:
1053 6af0bf9c bellard
        gen_op_or();
1054 6af0bf9c bellard
        opn = "or";
1055 6af0bf9c bellard
        break;
1056 6af0bf9c bellard
    case OPC_XOR:
1057 6af0bf9c bellard
        gen_op_xor();
1058 6af0bf9c bellard
        opn = "xor";
1059 6af0bf9c bellard
        break;
1060 6af0bf9c bellard
    case OPC_MUL:
1061 6af0bf9c bellard
        gen_op_mul();
1062 6af0bf9c bellard
        opn = "mul";
1063 6af0bf9c bellard
        break;
1064 6af0bf9c bellard
    case OPC_MOVN:
1065 6af0bf9c bellard
        gen_op_movn(rd);
1066 6af0bf9c bellard
        opn = "movn";
1067 6af0bf9c bellard
        goto print;
1068 6af0bf9c bellard
    case OPC_MOVZ:
1069 6af0bf9c bellard
        gen_op_movz(rd);
1070 6af0bf9c bellard
        opn = "movz";
1071 6af0bf9c bellard
        goto print;
1072 6af0bf9c bellard
    case OPC_SLLV:
1073 6af0bf9c bellard
        gen_op_sllv();
1074 6af0bf9c bellard
        opn = "sllv";
1075 6af0bf9c bellard
        break;
1076 6af0bf9c bellard
    case OPC_SRAV:
1077 6af0bf9c bellard
        gen_op_srav();
1078 6af0bf9c bellard
        opn = "srav";
1079 6af0bf9c bellard
        break;
1080 6af0bf9c bellard
    case OPC_SRLV:
1081 7a387fff ths
       if ((ctx->opcode >> 6) & 1) {
1082 7a387fff ths
            gen_op_rotrv();
1083 7a387fff ths
            opn = "rotrv";
1084 7a387fff ths
       } else {
1085 7a387fff ths
            gen_op_srlv();
1086 7a387fff ths
            opn = "srlv";
1087 7a387fff ths
       }
1088 7a387fff ths
        break;
1089 7a387fff ths
#ifdef MIPS_HAS_MIPS64
1090 7a387fff ths
    case OPC_DSLLV:
1091 7a387fff ths
        gen_op_dsllv();
1092 7a387fff ths
        opn = "dsllv";
1093 7a387fff ths
        break;
1094 7a387fff ths
    case OPC_DSRAV:
1095 7a387fff ths
        gen_op_dsrav();
1096 7a387fff ths
        opn = "dsrav";
1097 7a387fff ths
        break;
1098 7a387fff ths
    case OPC_DSRLV:
1099 7a387fff ths
       if ((ctx->opcode >> 6) & 1) {
1100 7a387fff ths
            gen_op_drotrv();
1101 7a387fff ths
            opn = "drotrv";
1102 7a387fff ths
       } else {
1103 7a387fff ths
            gen_op_dsrlv();
1104 7a387fff ths
            opn = "dsrlv";
1105 7a387fff ths
       }
1106 6af0bf9c bellard
        break;
1107 7a387fff ths
#endif
1108 6af0bf9c bellard
    default:
1109 6af0bf9c bellard
        MIPS_INVAL("arith");
1110 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
1111 6af0bf9c bellard
        return;
1112 6af0bf9c bellard
    }
1113 6af0bf9c bellard
    GEN_STORE_TN_REG(rd, T0);
1114 6af0bf9c bellard
 print:
1115 6af0bf9c bellard
    MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1116 6af0bf9c bellard
}
1117 6af0bf9c bellard
1118 6af0bf9c bellard
/* Arithmetic on HI/LO registers */
1119 7a387fff ths
static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1120 6af0bf9c bellard
{
1121 7a387fff ths
    const char *opn = "unk";
1122 6af0bf9c bellard
1123 6af0bf9c bellard
    if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1124 6af0bf9c bellard
        /* Treat as a NOP */
1125 6af0bf9c bellard
        MIPS_DEBUG("NOP");
1126 6af0bf9c bellard
        return;
1127 6af0bf9c bellard
    }
1128 6af0bf9c bellard
    switch (opc) {
1129 6af0bf9c bellard
    case OPC_MFHI:
1130 6af0bf9c bellard
        gen_op_load_HI();
1131 6af0bf9c bellard
        GEN_STORE_TN_REG(reg, T0);
1132 6af0bf9c bellard
        opn = "mfhi";
1133 6af0bf9c bellard
        break;
1134 6af0bf9c bellard
    case OPC_MFLO:
1135 6af0bf9c bellard
        gen_op_load_LO();
1136 6af0bf9c bellard
        GEN_STORE_TN_REG(reg, T0);
1137 6af0bf9c bellard
        opn = "mflo";
1138 6af0bf9c bellard
        break;
1139 6af0bf9c bellard
    case OPC_MTHI:
1140 6af0bf9c bellard
        GEN_LOAD_REG_TN(T0, reg);
1141 6af0bf9c bellard
        gen_op_store_HI();
1142 6af0bf9c bellard
        opn = "mthi";
1143 6af0bf9c bellard
        break;
1144 6af0bf9c bellard
    case OPC_MTLO:
1145 6af0bf9c bellard
        GEN_LOAD_REG_TN(T0, reg);
1146 6af0bf9c bellard
        gen_op_store_LO();
1147 6af0bf9c bellard
        opn = "mtlo";
1148 6af0bf9c bellard
        break;
1149 6af0bf9c bellard
    default:
1150 6af0bf9c bellard
        MIPS_INVAL("HILO");
1151 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
1152 6af0bf9c bellard
        return;
1153 6af0bf9c bellard
    }
1154 6af0bf9c bellard
    MIPS_DEBUG("%s %s", opn, regnames[reg]);
1155 6af0bf9c bellard
}
1156 6af0bf9c bellard
1157 7a387fff ths
static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1158 6af0bf9c bellard
                        int rs, int rt)
1159 6af0bf9c bellard
{
1160 7a387fff ths
    const char *opn = "unk";
1161 6af0bf9c bellard
1162 6af0bf9c bellard
    GEN_LOAD_REG_TN(T0, rs);
1163 6af0bf9c bellard
    GEN_LOAD_REG_TN(T1, rt);
1164 6af0bf9c bellard
    switch (opc) {
1165 6af0bf9c bellard
    case OPC_DIV:
1166 6af0bf9c bellard
        gen_op_div();
1167 6af0bf9c bellard
        opn = "div";
1168 6af0bf9c bellard
        break;
1169 6af0bf9c bellard
    case OPC_DIVU:
1170 6af0bf9c bellard
        gen_op_divu();
1171 6af0bf9c bellard
        opn = "divu";
1172 6af0bf9c bellard
        break;
1173 6af0bf9c bellard
    case OPC_MULT:
1174 6af0bf9c bellard
        gen_op_mult();
1175 6af0bf9c bellard
        opn = "mult";
1176 6af0bf9c bellard
        break;
1177 6af0bf9c bellard
    case OPC_MULTU:
1178 6af0bf9c bellard
        gen_op_multu();
1179 6af0bf9c bellard
        opn = "multu";
1180 6af0bf9c bellard
        break;
1181 7a387fff ths
#ifdef MIPS_HAS_MIPS64
1182 7a387fff ths
    case OPC_DDIV:
1183 7a387fff ths
        gen_op_ddiv();
1184 7a387fff ths
        opn = "ddiv";
1185 7a387fff ths
        break;
1186 7a387fff ths
    case OPC_DDIVU:
1187 7a387fff ths
        gen_op_ddivu();
1188 7a387fff ths
        opn = "ddivu";
1189 7a387fff ths
        break;
1190 7a387fff ths
    case OPC_DMULT:
1191 7a387fff ths
        gen_op_dmult();
1192 7a387fff ths
        opn = "dmult";
1193 7a387fff ths
        break;
1194 7a387fff ths
    case OPC_DMULTU:
1195 7a387fff ths
        gen_op_dmultu();
1196 7a387fff ths
        opn = "dmultu";
1197 7a387fff ths
        break;
1198 7a387fff ths
#endif
1199 6af0bf9c bellard
    case OPC_MADD:
1200 6af0bf9c bellard
        gen_op_madd();
1201 6af0bf9c bellard
        opn = "madd";
1202 6af0bf9c bellard
        break;
1203 6af0bf9c bellard
    case OPC_MADDU:
1204 6af0bf9c bellard
        gen_op_maddu();
1205 6af0bf9c bellard
        opn = "maddu";
1206 6af0bf9c bellard
        break;
1207 6af0bf9c bellard
    case OPC_MSUB:
1208 6af0bf9c bellard
        gen_op_msub();
1209 6af0bf9c bellard
        opn = "msub";
1210 6af0bf9c bellard
        break;
1211 6af0bf9c bellard
    case OPC_MSUBU:
1212 6af0bf9c bellard
        gen_op_msubu();
1213 6af0bf9c bellard
        opn = "msubu";
1214 6af0bf9c bellard
        break;
1215 6af0bf9c bellard
    default:
1216 6af0bf9c bellard
        MIPS_INVAL("mul/div");
1217 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
1218 6af0bf9c bellard
        return;
1219 6af0bf9c bellard
    }
1220 6af0bf9c bellard
    MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
1221 6af0bf9c bellard
}
1222 6af0bf9c bellard
1223 7a387fff ths
static void gen_cl (DisasContext *ctx, uint32_t opc,
1224 6af0bf9c bellard
                    int rd, int rs)
1225 6af0bf9c bellard
{
1226 7a387fff ths
    const char *opn = "unk";
1227 6af0bf9c bellard
    if (rd == 0) {
1228 6af0bf9c bellard
        /* Treat as a NOP */
1229 6af0bf9c bellard
        MIPS_DEBUG("NOP");
1230 6af0bf9c bellard
        return;
1231 6af0bf9c bellard
    }
1232 6af0bf9c bellard
    GEN_LOAD_REG_TN(T0, rs);
1233 6af0bf9c bellard
    switch (opc) {
1234 6af0bf9c bellard
    case OPC_CLO:
1235 6af0bf9c bellard
        gen_op_clo();
1236 6af0bf9c bellard
        opn = "clo";
1237 6af0bf9c bellard
        break;
1238 6af0bf9c bellard
    case OPC_CLZ:
1239 6af0bf9c bellard
        gen_op_clz();
1240 6af0bf9c bellard
        opn = "clz";
1241 6af0bf9c bellard
        break;
1242 7a387fff ths
#ifdef MIPS_HAS_MIPS64
1243 7a387fff ths
    case OPC_DCLO:
1244 7a387fff ths
        gen_op_dclo();
1245 7a387fff ths
        opn = "dclo";
1246 7a387fff ths
        break;
1247 7a387fff ths
    case OPC_DCLZ:
1248 7a387fff ths
        gen_op_dclz();
1249 7a387fff ths
        opn = "dclz";
1250 7a387fff ths
        break;
1251 7a387fff ths
#endif
1252 6af0bf9c bellard
    default:
1253 6af0bf9c bellard
        MIPS_INVAL("CLx");
1254 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
1255 6af0bf9c bellard
        return;
1256 6af0bf9c bellard
    }
1257 6af0bf9c bellard
    gen_op_store_T0_gpr(rd);
1258 6af0bf9c bellard
    MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
1259 6af0bf9c bellard
}
1260 6af0bf9c bellard
1261 6af0bf9c bellard
/* Traps */
1262 7a387fff ths
static void gen_trap (DisasContext *ctx, uint32_t opc,
1263 6af0bf9c bellard
                      int rs, int rt, int16_t imm)
1264 6af0bf9c bellard
{
1265 6af0bf9c bellard
    int cond;
1266 6af0bf9c bellard
1267 6af0bf9c bellard
    cond = 0;
1268 6af0bf9c bellard
    /* Load needed operands */
1269 6af0bf9c bellard
    switch (opc) {
1270 6af0bf9c bellard
    case OPC_TEQ:
1271 6af0bf9c bellard
    case OPC_TGE:
1272 6af0bf9c bellard
    case OPC_TGEU:
1273 6af0bf9c bellard
    case OPC_TLT:
1274 6af0bf9c bellard
    case OPC_TLTU:
1275 6af0bf9c bellard
    case OPC_TNE:
1276 6af0bf9c bellard
        /* Compare two registers */
1277 6af0bf9c bellard
        if (rs != rt) {
1278 6af0bf9c bellard
            GEN_LOAD_REG_TN(T0, rs);
1279 6af0bf9c bellard
            GEN_LOAD_REG_TN(T1, rt);
1280 6af0bf9c bellard
            cond = 1;
1281 6af0bf9c bellard
        }
1282 179e32bb ths
        break;
1283 6af0bf9c bellard
    case OPC_TEQI:
1284 6af0bf9c bellard
    case OPC_TGEI:
1285 6af0bf9c bellard
    case OPC_TGEIU:
1286 6af0bf9c bellard
    case OPC_TLTI:
1287 6af0bf9c bellard
    case OPC_TLTIU:
1288 6af0bf9c bellard
    case OPC_TNEI:
1289 6af0bf9c bellard
        /* Compare register to immediate */
1290 6af0bf9c bellard
        if (rs != 0 || imm != 0) {
1291 6af0bf9c bellard
            GEN_LOAD_REG_TN(T0, rs);
1292 6af0bf9c bellard
            GEN_LOAD_IMM_TN(T1, (int32_t)imm);
1293 6af0bf9c bellard
            cond = 1;
1294 6af0bf9c bellard
        }
1295 6af0bf9c bellard
        break;
1296 6af0bf9c bellard
    }
1297 6af0bf9c bellard
    if (cond == 0) {
1298 6af0bf9c bellard
        switch (opc) {
1299 6af0bf9c bellard
        case OPC_TEQ:   /* rs == rs */
1300 6af0bf9c bellard
        case OPC_TEQI:  /* r0 == 0  */
1301 6af0bf9c bellard
        case OPC_TGE:   /* rs >= rs */
1302 6af0bf9c bellard
        case OPC_TGEI:  /* r0 >= 0  */
1303 6af0bf9c bellard
        case OPC_TGEU:  /* rs >= rs unsigned */
1304 6af0bf9c bellard
        case OPC_TGEIU: /* r0 >= 0  unsigned */
1305 6af0bf9c bellard
            /* Always trap */
1306 6af0bf9c bellard
            gen_op_set_T0(1);
1307 6af0bf9c bellard
            break;
1308 6af0bf9c bellard
        case OPC_TLT:   /* rs < rs           */
1309 6af0bf9c bellard
        case OPC_TLTI:  /* r0 < 0            */
1310 6af0bf9c bellard
        case OPC_TLTU:  /* rs < rs unsigned  */
1311 6af0bf9c bellard
        case OPC_TLTIU: /* r0 < 0  unsigned  */
1312 6af0bf9c bellard
        case OPC_TNE:   /* rs != rs          */
1313 6af0bf9c bellard
        case OPC_TNEI:  /* r0 != 0           */
1314 6af0bf9c bellard
            /* Never trap: treat as NOP */
1315 6af0bf9c bellard
            return;
1316 6af0bf9c bellard
        default:
1317 6af0bf9c bellard
            MIPS_INVAL("TRAP");
1318 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
1319 6af0bf9c bellard
            return;
1320 6af0bf9c bellard
        }
1321 6af0bf9c bellard
    } else {
1322 6af0bf9c bellard
        switch (opc) {
1323 6af0bf9c bellard
        case OPC_TEQ:
1324 6af0bf9c bellard
        case OPC_TEQI:
1325 6af0bf9c bellard
            gen_op_eq();
1326 6af0bf9c bellard
            break;
1327 6af0bf9c bellard
        case OPC_TGE:
1328 6af0bf9c bellard
        case OPC_TGEI:
1329 6af0bf9c bellard
            gen_op_ge();
1330 6af0bf9c bellard
            break;
1331 6af0bf9c bellard
        case OPC_TGEU:
1332 6af0bf9c bellard
        case OPC_TGEIU:
1333 6af0bf9c bellard
            gen_op_geu();
1334 6af0bf9c bellard
            break;
1335 6af0bf9c bellard
        case OPC_TLT:
1336 6af0bf9c bellard
        case OPC_TLTI:
1337 6af0bf9c bellard
            gen_op_lt();
1338 6af0bf9c bellard
            break;
1339 6af0bf9c bellard
        case OPC_TLTU:
1340 6af0bf9c bellard
        case OPC_TLTIU:
1341 6af0bf9c bellard
            gen_op_ltu();
1342 6af0bf9c bellard
            break;
1343 6af0bf9c bellard
        case OPC_TNE:
1344 6af0bf9c bellard
        case OPC_TNEI:
1345 6af0bf9c bellard
            gen_op_ne();
1346 6af0bf9c bellard
            break;
1347 6af0bf9c bellard
        default:
1348 6af0bf9c bellard
            MIPS_INVAL("TRAP");
1349 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
1350 6af0bf9c bellard
            return;
1351 6af0bf9c bellard
        }
1352 6af0bf9c bellard
    }
1353 6af0bf9c bellard
    save_cpu_state(ctx, 1);
1354 6af0bf9c bellard
    gen_op_trap();
1355 6af0bf9c bellard
    ctx->bstate = BS_STOP;
1356 6af0bf9c bellard
}
1357 6af0bf9c bellard
1358 6e256c93 bellard
static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
1359 c53be334 bellard
{
1360 6e256c93 bellard
    TranslationBlock *tb;
1361 6e256c93 bellard
    tb = ctx->tb;
1362 6e256c93 bellard
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
1363 6e256c93 bellard
        if (n == 0)
1364 6e256c93 bellard
            gen_op_goto_tb0(TBPARAM(tb));
1365 6e256c93 bellard
        else
1366 6e256c93 bellard
            gen_op_goto_tb1(TBPARAM(tb));
1367 6e256c93 bellard
        gen_op_save_pc(dest);
1368 6e256c93 bellard
        gen_op_set_T0((long)tb + n);
1369 6e256c93 bellard
        gen_op_exit_tb();
1370 6e256c93 bellard
    } else {
1371 6e256c93 bellard
        gen_op_save_pc(dest);
1372 6e256c93 bellard
        gen_op_set_T0(0);
1373 6e256c93 bellard
        gen_op_exit_tb();
1374 6e256c93 bellard
    }
1375 c53be334 bellard
}
1376 c53be334 bellard
1377 6af0bf9c bellard
/* Branches (before delay slot) */
1378 7a387fff ths
static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
1379 6af0bf9c bellard
                                int rs, int rt, int32_t offset)
1380 6af0bf9c bellard
{
1381 6af0bf9c bellard
    target_ulong btarget;
1382 6af0bf9c bellard
    int blink, bcond;
1383 6af0bf9c bellard
1384 6af0bf9c bellard
    btarget = -1;
1385 6af0bf9c bellard
    blink = 0;
1386 6af0bf9c bellard
    bcond = 0;
1387 6af0bf9c bellard
    /* Load needed operands */
1388 6af0bf9c bellard
    switch (opc) {
1389 6af0bf9c bellard
    case OPC_BEQ:
1390 6af0bf9c bellard
    case OPC_BEQL:
1391 6af0bf9c bellard
    case OPC_BNE:
1392 6af0bf9c bellard
    case OPC_BNEL:
1393 6af0bf9c bellard
        /* Compare two registers */
1394 6af0bf9c bellard
        if (rs != rt) {
1395 6af0bf9c bellard
            GEN_LOAD_REG_TN(T0, rs);
1396 6af0bf9c bellard
            GEN_LOAD_REG_TN(T1, rt);
1397 6af0bf9c bellard
            bcond = 1;
1398 6af0bf9c bellard
        }
1399 6af0bf9c bellard
        btarget = ctx->pc + 4 + offset;
1400 6af0bf9c bellard
        break;
1401 6af0bf9c bellard
    case OPC_BGEZ:
1402 6af0bf9c bellard
    case OPC_BGEZAL:
1403 6af0bf9c bellard
    case OPC_BGEZALL:
1404 6af0bf9c bellard
    case OPC_BGEZL:
1405 6af0bf9c bellard
    case OPC_BGTZ:
1406 6af0bf9c bellard
    case OPC_BGTZL:
1407 6af0bf9c bellard
    case OPC_BLEZ:
1408 6af0bf9c bellard
    case OPC_BLEZL:
1409 6af0bf9c bellard
    case OPC_BLTZ:
1410 6af0bf9c bellard
    case OPC_BLTZAL:
1411 6af0bf9c bellard
    case OPC_BLTZALL:
1412 6af0bf9c bellard
    case OPC_BLTZL:
1413 6af0bf9c bellard
        /* Compare to zero */
1414 6af0bf9c bellard
        if (rs != 0) {
1415 6af0bf9c bellard
            gen_op_load_gpr_T0(rs);
1416 6af0bf9c bellard
            bcond = 1;
1417 6af0bf9c bellard
        }
1418 6af0bf9c bellard
        btarget = ctx->pc + 4 + offset;
1419 6af0bf9c bellard
        break;
1420 6af0bf9c bellard
    case OPC_J:
1421 6af0bf9c bellard
    case OPC_JAL:
1422 6af0bf9c bellard
        /* Jump to immediate */
1423 5dc4b744 ths
        btarget = ((ctx->pc + 4) & (int32_t)0xF0000000) | offset;
1424 6af0bf9c bellard
        break;
1425 6af0bf9c bellard
    case OPC_JR:
1426 6af0bf9c bellard
    case OPC_JALR:
1427 6af0bf9c bellard
        /* Jump to register */
1428 7a387fff ths
        if (offset != 0 && offset != 16) {
1429 7a387fff ths
            /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
1430 7a387fff ths
              others are reserved. */
1431 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
1432 6af0bf9c bellard
            return;
1433 6af0bf9c bellard
        }
1434 6af0bf9c bellard
        GEN_LOAD_REG_TN(T2, rs);
1435 6af0bf9c bellard
        break;
1436 6af0bf9c bellard
    default:
1437 6af0bf9c bellard
        MIPS_INVAL("branch/jump");
1438 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
1439 6af0bf9c bellard
        return;
1440 6af0bf9c bellard
    }
1441 6af0bf9c bellard
    if (bcond == 0) {
1442 6af0bf9c bellard
        /* No condition to be computed */
1443 6af0bf9c bellard
        switch (opc) {
1444 6af0bf9c bellard
        case OPC_BEQ:     /* rx == rx        */
1445 6af0bf9c bellard
        case OPC_BEQL:    /* rx == rx likely */
1446 6af0bf9c bellard
        case OPC_BGEZ:    /* 0 >= 0          */
1447 6af0bf9c bellard
        case OPC_BGEZL:   /* 0 >= 0 likely   */
1448 6af0bf9c bellard
        case OPC_BLEZ:    /* 0 <= 0          */
1449 6af0bf9c bellard
        case OPC_BLEZL:   /* 0 <= 0 likely   */
1450 6af0bf9c bellard
            /* Always take */
1451 4ad40f36 bellard
            ctx->hflags |= MIPS_HFLAG_B;
1452 6af0bf9c bellard
            MIPS_DEBUG("balways");
1453 6af0bf9c bellard
            break;
1454 6af0bf9c bellard
        case OPC_BGEZAL:  /* 0 >= 0          */
1455 6af0bf9c bellard
        case OPC_BGEZALL: /* 0 >= 0 likely   */
1456 6af0bf9c bellard
            /* Always take and link */
1457 6af0bf9c bellard
            blink = 31;
1458 4ad40f36 bellard
            ctx->hflags |= MIPS_HFLAG_B;
1459 6af0bf9c bellard
            MIPS_DEBUG("balways and link");
1460 6af0bf9c bellard
            break;
1461 6af0bf9c bellard
        case OPC_BNE:     /* rx != rx        */
1462 6af0bf9c bellard
        case OPC_BGTZ:    /* 0 > 0           */
1463 6af0bf9c bellard
        case OPC_BLTZ:    /* 0 < 0           */
1464 6af0bf9c bellard
            /* Treated as NOP */
1465 6af0bf9c bellard
            MIPS_DEBUG("bnever (NOP)");
1466 6af0bf9c bellard
            return;
1467 eeef26cd bellard
        case OPC_BLTZAL:  /* 0 < 0           */
1468 eeef26cd bellard
            gen_op_set_T0(ctx->pc + 8);
1469 eeef26cd bellard
            gen_op_store_T0_gpr(31);
1470 eeef26cd bellard
            return;
1471 eeef26cd bellard
        case OPC_BLTZALL: /* 0 < 0 likely */
1472 eeef26cd bellard
            gen_op_set_T0(ctx->pc + 8);
1473 eeef26cd bellard
            gen_op_store_T0_gpr(31);
1474 eeef26cd bellard
            gen_goto_tb(ctx, 0, ctx->pc + 4);
1475 eeef26cd bellard
            return;
1476 6af0bf9c bellard
        case OPC_BNEL:    /* rx != rx likely */
1477 6af0bf9c bellard
        case OPC_BGTZL:   /* 0 > 0 likely */
1478 6af0bf9c bellard
        case OPC_BLTZL:   /* 0 < 0 likely */
1479 6af0bf9c bellard
            /* Skip the instruction in the delay slot */
1480 6af0bf9c bellard
            MIPS_DEBUG("bnever and skip");
1481 6e256c93 bellard
            gen_goto_tb(ctx, 0, ctx->pc + 4);
1482 6af0bf9c bellard
            return;
1483 6af0bf9c bellard
        case OPC_J:
1484 4ad40f36 bellard
            ctx->hflags |= MIPS_HFLAG_B;
1485 6af0bf9c bellard
            MIPS_DEBUG("j %08x", btarget);
1486 6af0bf9c bellard
            break;
1487 6af0bf9c bellard
        case OPC_JAL:
1488 6af0bf9c bellard
            blink = 31;
1489 4ad40f36 bellard
            ctx->hflags |= MIPS_HFLAG_B;
1490 6af0bf9c bellard
            MIPS_DEBUG("jal %08x", btarget);
1491 6af0bf9c bellard
            break;
1492 6af0bf9c bellard
        case OPC_JR:
1493 4ad40f36 bellard
            ctx->hflags |= MIPS_HFLAG_BR;
1494 6af0bf9c bellard
            MIPS_DEBUG("jr %s", regnames[rs]);
1495 6af0bf9c bellard
            break;
1496 6af0bf9c bellard
        case OPC_JALR:
1497 6af0bf9c bellard
            blink = rt;
1498 4ad40f36 bellard
            ctx->hflags |= MIPS_HFLAG_BR;
1499 6af0bf9c bellard
            MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
1500 6af0bf9c bellard
            break;
1501 6af0bf9c bellard
        default:
1502 6af0bf9c bellard
            MIPS_INVAL("branch/jump");
1503 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
1504 6af0bf9c bellard
            return;
1505 6af0bf9c bellard
        }
1506 6af0bf9c bellard
    } else {
1507 6af0bf9c bellard
        switch (opc) {
1508 6af0bf9c bellard
        case OPC_BEQ:
1509 6af0bf9c bellard
            gen_op_eq();
1510 6af0bf9c bellard
            MIPS_DEBUG("beq %s, %s, %08x",
1511 6af0bf9c bellard
                       regnames[rs], regnames[rt], btarget);
1512 6af0bf9c bellard
            goto not_likely;
1513 6af0bf9c bellard
        case OPC_BEQL:
1514 6af0bf9c bellard
            gen_op_eq();
1515 6af0bf9c bellard
            MIPS_DEBUG("beql %s, %s, %08x",
1516 6af0bf9c bellard
                       regnames[rs], regnames[rt], btarget);
1517 6af0bf9c bellard
            goto likely;
1518 6af0bf9c bellard
        case OPC_BNE:
1519 6af0bf9c bellard
            gen_op_ne();
1520 6af0bf9c bellard
            MIPS_DEBUG("bne %s, %s, %08x",
1521 6af0bf9c bellard
                       regnames[rs], regnames[rt], btarget);
1522 6af0bf9c bellard
            goto not_likely;
1523 6af0bf9c bellard
        case OPC_BNEL:
1524 6af0bf9c bellard
            gen_op_ne();
1525 6af0bf9c bellard
            MIPS_DEBUG("bnel %s, %s, %08x",
1526 6af0bf9c bellard
                       regnames[rs], regnames[rt], btarget);
1527 6af0bf9c bellard
            goto likely;
1528 6af0bf9c bellard
        case OPC_BGEZ:
1529 6af0bf9c bellard
            gen_op_gez();
1530 6af0bf9c bellard
            MIPS_DEBUG("bgez %s, %08x", regnames[rs], btarget);
1531 6af0bf9c bellard
            goto not_likely;
1532 6af0bf9c bellard
        case OPC_BGEZL:
1533 6af0bf9c bellard
            gen_op_gez();
1534 6af0bf9c bellard
            MIPS_DEBUG("bgezl %s, %08x", regnames[rs], btarget);
1535 6af0bf9c bellard
            goto likely;
1536 6af0bf9c bellard
        case OPC_BGEZAL:
1537 6af0bf9c bellard
            gen_op_gez();
1538 6af0bf9c bellard
            MIPS_DEBUG("bgezal %s, %08x", regnames[rs], btarget);
1539 6af0bf9c bellard
            blink = 31;
1540 6af0bf9c bellard
            goto not_likely;
1541 6af0bf9c bellard
        case OPC_BGEZALL:
1542 6af0bf9c bellard
            gen_op_gez();
1543 6af0bf9c bellard
            blink = 31;
1544 6af0bf9c bellard
            MIPS_DEBUG("bgezall %s, %08x", regnames[rs], btarget);
1545 6af0bf9c bellard
            goto likely;
1546 6af0bf9c bellard
        case OPC_BGTZ:
1547 6af0bf9c bellard
            gen_op_gtz();
1548 6af0bf9c bellard
            MIPS_DEBUG("bgtz %s, %08x", regnames[rs], btarget);
1549 6af0bf9c bellard
            goto not_likely;
1550 6af0bf9c bellard
        case OPC_BGTZL:
1551 6af0bf9c bellard
            gen_op_gtz();
1552 6af0bf9c bellard
            MIPS_DEBUG("bgtzl %s, %08x", regnames[rs], btarget);
1553 6af0bf9c bellard
            goto likely;
1554 6af0bf9c bellard
        case OPC_BLEZ:
1555 6af0bf9c bellard
            gen_op_lez();
1556 6af0bf9c bellard
            MIPS_DEBUG("blez %s, %08x", regnames[rs], btarget);
1557 6af0bf9c bellard
            goto not_likely;
1558 6af0bf9c bellard
        case OPC_BLEZL:
1559 6af0bf9c bellard
            gen_op_lez();
1560 6af0bf9c bellard
            MIPS_DEBUG("blezl %s, %08x", regnames[rs], btarget);
1561 6af0bf9c bellard
            goto likely;
1562 6af0bf9c bellard
        case OPC_BLTZ:
1563 6af0bf9c bellard
            gen_op_ltz();
1564 6af0bf9c bellard
            MIPS_DEBUG("bltz %s, %08x", regnames[rs], btarget);
1565 6af0bf9c bellard
            goto not_likely;
1566 6af0bf9c bellard
        case OPC_BLTZL:
1567 6af0bf9c bellard
            gen_op_ltz();
1568 6af0bf9c bellard
            MIPS_DEBUG("bltzl %s, %08x", regnames[rs], btarget);
1569 6af0bf9c bellard
            goto likely;
1570 6af0bf9c bellard
        case OPC_BLTZAL:
1571 6af0bf9c bellard
            gen_op_ltz();
1572 6af0bf9c bellard
            blink = 31;
1573 6af0bf9c bellard
            MIPS_DEBUG("bltzal %s, %08x", regnames[rs], btarget);
1574 6af0bf9c bellard
        not_likely:
1575 4ad40f36 bellard
            ctx->hflags |= MIPS_HFLAG_BC;
1576 6af0bf9c bellard
            break;
1577 6af0bf9c bellard
        case OPC_BLTZALL:
1578 6af0bf9c bellard
            gen_op_ltz();
1579 6af0bf9c bellard
            blink = 31;
1580 6af0bf9c bellard
            MIPS_DEBUG("bltzall %s, %08x", regnames[rs], btarget);
1581 6af0bf9c bellard
        likely:
1582 4ad40f36 bellard
            ctx->hflags |= MIPS_HFLAG_BL;
1583 6af0bf9c bellard
            break;
1584 6af0bf9c bellard
        }
1585 6af0bf9c bellard
        gen_op_set_bcond();
1586 6af0bf9c bellard
    }
1587 6af0bf9c bellard
    MIPS_DEBUG("enter ds: link %d cond %02x target %08x",
1588 6af0bf9c bellard
               blink, ctx->hflags, btarget);
1589 6af0bf9c bellard
    ctx->btarget = btarget;
1590 6af0bf9c bellard
    if (blink > 0) {
1591 6af0bf9c bellard
        gen_op_set_T0(ctx->pc + 8);
1592 6af0bf9c bellard
        gen_op_store_T0_gpr(blink);
1593 6af0bf9c bellard
    }
1594 6af0bf9c bellard
    return;
1595 6af0bf9c bellard
}
1596 6af0bf9c bellard
1597 7a387fff ths
/* special3 bitfield operations */
1598 7a387fff ths
static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
1599 7a387fff ths
                       int rs, int lsb, int msb)
1600 7a387fff ths
{
1601 7a387fff ths
    GEN_LOAD_REG_TN(T1, rs);
1602 7a387fff ths
    switch (opc) {
1603 7a387fff ths
    case OPC_EXT:
1604 7a387fff ths
        if (lsb + msb > 31)
1605 7a387fff ths
            goto fail;
1606 7a387fff ths
        gen_op_ext(lsb, msb + 1);
1607 7a387fff ths
        break;
1608 7a387fff ths
    case OPC_DEXTM:
1609 7a387fff ths
        if (lsb + msb > 63)
1610 7a387fff ths
            goto fail;
1611 7a387fff ths
        gen_op_ext(lsb, msb + 1 + 32);
1612 7a387fff ths
        break;
1613 7a387fff ths
    case OPC_DEXTU:
1614 7a387fff ths
        if (lsb + msb > 63)
1615 7a387fff ths
            goto fail;
1616 7a387fff ths
        gen_op_ext(lsb + 32, msb + 1);
1617 7a387fff ths
        break;
1618 7a387fff ths
    case OPC_DEXT:
1619 7a387fff ths
        gen_op_ext(lsb, msb + 1);
1620 7a387fff ths
        break;
1621 7a387fff ths
    case OPC_INS:
1622 7a387fff ths
        if (lsb > msb)
1623 7a387fff ths
            goto fail;
1624 7a387fff ths
        GEN_LOAD_REG_TN(T2, rt);
1625 7a387fff ths
        gen_op_ins(lsb, msb - lsb + 1);
1626 7a387fff ths
        break;
1627 7a387fff ths
    case OPC_DINSM:
1628 7a387fff ths
        if (lsb > msb)
1629 7a387fff ths
            goto fail;
1630 7a387fff ths
        GEN_LOAD_REG_TN(T2, rt);
1631 7a387fff ths
        gen_op_ins(lsb, msb - lsb + 1 + 32);
1632 7a387fff ths
        break;
1633 7a387fff ths
    case OPC_DINSU:
1634 7a387fff ths
        if (lsb > msb)
1635 7a387fff ths
            goto fail;
1636 7a387fff ths
        GEN_LOAD_REG_TN(T2, rt);
1637 7a387fff ths
        gen_op_ins(lsb + 32, msb - lsb + 1);
1638 7a387fff ths
        break;
1639 7a387fff ths
    case OPC_DINS:
1640 7a387fff ths
        if (lsb > msb)
1641 7a387fff ths
            goto fail;
1642 7a387fff ths
        GEN_LOAD_REG_TN(T2, rt);
1643 7a387fff ths
        gen_op_ins(lsb, msb - lsb + 1);
1644 7a387fff ths
        break;
1645 7a387fff ths
    default:
1646 7a387fff ths
fail:
1647 7a387fff ths
        MIPS_INVAL("bitops");
1648 7a387fff ths
        generate_exception(ctx, EXCP_RI);
1649 7a387fff ths
        return;
1650 7a387fff ths
    }
1651 7a387fff ths
    GEN_STORE_TN_REG(rt, T0);
1652 7a387fff ths
}
1653 7a387fff ths
1654 6af0bf9c bellard
/* CP0 (MMU and control) */
1655 873eb012 ths
static void gen_mfc0 (DisasContext *ctx, int reg, int sel)
1656 873eb012 ths
{
1657 7a387fff ths
    const char *rn = "invalid";
1658 873eb012 ths
1659 873eb012 ths
    switch (reg) {
1660 873eb012 ths
    case 0:
1661 7a387fff ths
        switch (sel) {
1662 7a387fff ths
        case 0:
1663 7a387fff ths
           gen_op_mfc0_index();
1664 7a387fff ths
            rn = "Index";
1665 7a387fff ths
            break;
1666 7a387fff ths
        case 1:
1667 7a387fff ths
//         gen_op_mfc0_mvpcontrol(); /* MT ASE */
1668 7a387fff ths
            rn = "MVPControl";
1669 7a387fff ths
//         break;
1670 7a387fff ths
        case 2:
1671 7a387fff ths
//         gen_op_mfc0_mvpconf0(); /* MT ASE */
1672 7a387fff ths
            rn = "MVPConf0";
1673 7a387fff ths
//         break;
1674 7a387fff ths
        case 3:
1675 7a387fff ths
//         gen_op_mfc0_mvpconf1(); /* MT ASE */
1676 7a387fff ths
            rn = "MVPConf1";
1677 7a387fff ths
//         break;
1678 7a387fff ths
        default:
1679 7a387fff ths
            goto die;
1680 7a387fff ths
        }
1681 873eb012 ths
        break;
1682 873eb012 ths
    case 1:
1683 7a387fff ths
        switch (sel) {
1684 7a387fff ths
        case 0:
1685 7a387fff ths
            gen_op_mfc0_random();
1686 7a387fff ths
            rn = "Random";
1687 7a387fff ths
           break;
1688 7a387fff ths
        case 1:
1689 7a387fff ths
//         gen_op_mfc0_vpecontrol(); /* MT ASE */
1690 7a387fff ths
            rn = "VPEControl";
1691 7a387fff ths
//         break;
1692 7a387fff ths
        case 2:
1693 7a387fff ths
//         gen_op_mfc0_vpeconf0(); /* MT ASE */
1694 7a387fff ths
            rn = "VPEConf0";
1695 7a387fff ths
//         break;
1696 7a387fff ths
        case 3:
1697 7a387fff ths
//         gen_op_mfc0_vpeconf1(); /* MT ASE */
1698 7a387fff ths
            rn = "VPEConf1";
1699 7a387fff ths
//         break;
1700 7a387fff ths
        case 4:
1701 7a387fff ths
//         gen_op_mfc0_YQMask(); /* MT ASE */
1702 7a387fff ths
            rn = "YQMask";
1703 7a387fff ths
//         break;
1704 7a387fff ths
        case 5:
1705 7a387fff ths
//         gen_op_mfc0_vpeschedule(); /* MT ASE */
1706 7a387fff ths
            rn = "VPESchedule";
1707 7a387fff ths
//         break;
1708 7a387fff ths
        case 6:
1709 7a387fff ths
//         gen_op_mfc0_vpeschefback(); /* MT ASE */
1710 7a387fff ths
            rn = "VPEScheFBack";
1711 7a387fff ths
//         break;
1712 7a387fff ths
        case 7:
1713 7a387fff ths
//         gen_op_mfc0_vpeopt(); /* MT ASE */
1714 7a387fff ths
            rn = "VPEOpt";
1715 7a387fff ths
//         break;
1716 7a387fff ths
        default:
1717 7a387fff ths
            goto die;
1718 7a387fff ths
        }
1719 873eb012 ths
        break;
1720 873eb012 ths
    case 2:
1721 7a387fff ths
        switch (sel) {
1722 7a387fff ths
        case 0:
1723 7a387fff ths
           gen_op_mfc0_entrylo0();
1724 7a387fff ths
           rn = "EntryLo0";
1725 7a387fff ths
           break;
1726 7a387fff ths
        case 1:
1727 7a387fff ths
//         gen_op_mfc0_tcstatus(); /* MT ASE */
1728 7a387fff ths
           rn = "TCStatus";
1729 7a387fff ths
//         break;
1730 7a387fff ths
        case 2:
1731 7a387fff ths
//         gen_op_mfc0_tcbind(); /* MT ASE */
1732 7a387fff ths
           rn = "TCBind";
1733 7a387fff ths
//         break;
1734 7a387fff ths
        case 3:
1735 7a387fff ths
//         gen_op_mfc0_tcrestart(); /* MT ASE */
1736 7a387fff ths
           rn = "TCRestart";
1737 7a387fff ths
//         break;
1738 7a387fff ths
        case 4:
1739 7a387fff ths
//         gen_op_mfc0_tchalt(); /* MT ASE */
1740 7a387fff ths
           rn = "TCHalt";
1741 7a387fff ths
//         break;
1742 7a387fff ths
        case 5:
1743 7a387fff ths
//         gen_op_mfc0_tccontext(); /* MT ASE */
1744 7a387fff ths
           rn = "TCContext";
1745 7a387fff ths
//         break;
1746 7a387fff ths
        case 6:
1747 7a387fff ths
//         gen_op_mfc0_tcschedule(); /* MT ASE */
1748 7a387fff ths
           rn = "TCSchedule";
1749 7a387fff ths
//         break;
1750 7a387fff ths
        case 7:
1751 7a387fff ths
//         gen_op_mfc0_tcschefback(); /* MT ASE */
1752 7a387fff ths
           rn = "TCScheFBack";
1753 7a387fff ths
//         break;
1754 7a387fff ths
        default:
1755 7a387fff ths
            goto die;
1756 7a387fff ths
        }
1757 873eb012 ths
        break;
1758 873eb012 ths
    case 3:
1759 7a387fff ths
        switch (sel) {
1760 7a387fff ths
        case 0:
1761 7a387fff ths
           gen_op_mfc0_entrylo1();
1762 7a387fff ths
           rn = "EntryLo1";
1763 7a387fff ths
           break;
1764 7a387fff ths
        default:
1765 7a387fff ths
            goto die;
1766 7a387fff ths
       }
1767 873eb012 ths
        break;
1768 873eb012 ths
    case 4:
1769 7a387fff ths
        switch (sel) {
1770 7a387fff ths
        case 0:
1771 7a387fff ths
           gen_op_mfc0_context();
1772 7a387fff ths
           rn = "Context";
1773 7a387fff ths
           break;
1774 7a387fff ths
        case 1:
1775 7a387fff ths
//         gen_op_mfc0_contextconfig(); /* SmartMIPS ASE */
1776 7a387fff ths
           rn = "ContextConfig";
1777 7a387fff ths
//         break;
1778 7a387fff ths
        default:
1779 7a387fff ths
            goto die;
1780 7a387fff ths
       }
1781 873eb012 ths
        break;
1782 873eb012 ths
    case 5:
1783 7a387fff ths
        switch (sel) {
1784 7a387fff ths
        case 0:
1785 7a387fff ths
           gen_op_mfc0_pagemask();
1786 7a387fff ths
           rn = "PageMask";
1787 7a387fff ths
           break;
1788 7a387fff ths
        case 1:
1789 7a387fff ths
           gen_op_mfc0_pagegrain();
1790 7a387fff ths
           rn = "PageGrain";
1791 7a387fff ths
           break;
1792 7a387fff ths
        default:
1793 7a387fff ths
            goto die;
1794 7a387fff ths
       }
1795 873eb012 ths
        break;
1796 873eb012 ths
    case 6:
1797 7a387fff ths
        switch (sel) {
1798 7a387fff ths
        case 0:
1799 7a387fff ths
           gen_op_mfc0_wired();
1800 7a387fff ths
           rn = "Wired";
1801 7a387fff ths
           break;
1802 7a387fff ths
        case 1:
1803 7a387fff ths
//         gen_op_mfc0_srsconf0(); /* shadow registers */
1804 7a387fff ths
           rn = "SRSConf0";
1805 7a387fff ths
//         break;
1806 7a387fff ths
        case 2:
1807 7a387fff ths
//         gen_op_mfc0_srsconf1(); /* shadow registers */
1808 7a387fff ths
           rn = "SRSConf1";
1809 7a387fff ths
//         break;
1810 7a387fff ths
        case 3:
1811 7a387fff ths
//         gen_op_mfc0_srsconf2(); /* shadow registers */
1812 7a387fff ths
           rn = "SRSConf2";
1813 7a387fff ths
//         break;
1814 7a387fff ths
        case 4:
1815 7a387fff ths
//         gen_op_mfc0_srsconf3(); /* shadow registers */
1816 7a387fff ths
           rn = "SRSConf3";
1817 7a387fff ths
//         break;
1818 7a387fff ths
        case 5:
1819 7a387fff ths
//         gen_op_mfc0_srsconf4(); /* shadow registers */
1820 7a387fff ths
           rn = "SRSConf4";
1821 7a387fff ths
//         break;
1822 7a387fff ths
        default:
1823 7a387fff ths
            goto die;
1824 7a387fff ths
       }
1825 873eb012 ths
        break;
1826 8c0fdd85 ths
    case 7:
1827 7a387fff ths
        switch (sel) {
1828 7a387fff ths
        case 0:
1829 7a387fff ths
           gen_op_mfc0_hwrena();
1830 7a387fff ths
           rn = "HWREna";
1831 7a387fff ths
           break;
1832 7a387fff ths
        default:
1833 7a387fff ths
            goto die;
1834 7a387fff ths
       }
1835 8c0fdd85 ths
        break;
1836 873eb012 ths
    case 8:
1837 7a387fff ths
        switch (sel) {
1838 7a387fff ths
        case 0:
1839 7a387fff ths
           gen_op_mfc0_badvaddr();
1840 7a387fff ths
           rn = "BadVaddr";
1841 7a387fff ths
           break;
1842 7a387fff ths
        default:
1843 7a387fff ths
            goto die;
1844 7a387fff ths
       }
1845 873eb012 ths
        break;
1846 873eb012 ths
    case 9:
1847 7a387fff ths
        switch (sel) {
1848 7a387fff ths
        case 0:
1849 7a387fff ths
           gen_op_mfc0_count();
1850 7a387fff ths
           rn = "Count";
1851 7a387fff ths
           break;
1852 7a387fff ths
       /* 6,7 are implementation dependent */
1853 7a387fff ths
        default:
1854 7a387fff ths
            goto die;
1855 7a387fff ths
       }
1856 873eb012 ths
        break;
1857 873eb012 ths
    case 10:
1858 7a387fff ths
        switch (sel) {
1859 7a387fff ths
        case 0:
1860 7a387fff ths
           gen_op_mfc0_entryhi();
1861 7a387fff ths
           rn = "EntryHi";
1862 7a387fff ths
           break;
1863 7a387fff ths
        default:
1864 7a387fff ths
            goto die;
1865 7a387fff ths
       }
1866 873eb012 ths
        break;
1867 873eb012 ths
    case 11:
1868 7a387fff ths
        switch (sel) {
1869 7a387fff ths
        case 0:
1870 7a387fff ths
           gen_op_mfc0_compare();
1871 7a387fff ths
           rn = "Compare";
1872 7a387fff ths
           break;
1873 7a387fff ths
       /* 6,7 are implementation dependent */
1874 7a387fff ths
        default:
1875 7a387fff ths
            goto die;
1876 7a387fff ths
       }
1877 873eb012 ths
        break;
1878 873eb012 ths
    case 12:
1879 7a387fff ths
        switch (sel) {
1880 7a387fff ths
        case 0:
1881 7a387fff ths
           gen_op_mfc0_status();
1882 7a387fff ths
           rn = "Status";
1883 7a387fff ths
           break;
1884 7a387fff ths
        case 1:
1885 7a387fff ths
           gen_op_mfc0_intctl();
1886 7a387fff ths
           rn = "IntCtl";
1887 7a387fff ths
           break;
1888 7a387fff ths
        case 2:
1889 7a387fff ths
           gen_op_mfc0_srsctl();
1890 7a387fff ths
           rn = "SRSCtl";
1891 7a387fff ths
           break;
1892 7a387fff ths
        case 3:
1893 7a387fff ths
//         gen_op_mfc0_srsmap(); /* shadow registers */
1894 7a387fff ths
           rn = "SRSMap";
1895 7a387fff ths
//         break;
1896 7a387fff ths
        default:
1897 7a387fff ths
            goto die;
1898 7a387fff ths
       }
1899 873eb012 ths
        break;
1900 873eb012 ths
    case 13:
1901 7a387fff ths
        switch (sel) {
1902 7a387fff ths
        case 0:
1903 7a387fff ths
           gen_op_mfc0_cause();
1904 7a387fff ths
           rn = "Cause";
1905 7a387fff ths
           break;
1906 7a387fff ths
        default:
1907 7a387fff ths
            goto die;
1908 7a387fff ths
       }
1909 873eb012 ths
        break;
1910 873eb012 ths
    case 14:
1911 7a387fff ths
        switch (sel) {
1912 7a387fff ths
        case 0:
1913 7a387fff ths
           gen_op_mfc0_epc();
1914 7a387fff ths
           rn = "EPC";
1915 7a387fff ths
           break;
1916 7a387fff ths
        default:
1917 7a387fff ths
            goto die;
1918 7a387fff ths
       }
1919 873eb012 ths
        break;
1920 873eb012 ths
    case 15:
1921 7a387fff ths
        switch (sel) {
1922 7a387fff ths
        case 0:
1923 7a387fff ths
           gen_op_mfc0_prid();
1924 7a387fff ths
           rn = "PRid";
1925 7a387fff ths
           break;
1926 7a387fff ths
        case 1:
1927 7a387fff ths
           gen_op_mfc0_ebase();
1928 7a387fff ths
           rn = "EBase";
1929 7a387fff ths
           break;
1930 7a387fff ths
        default:
1931 7a387fff ths
            goto die;
1932 7a387fff ths
       }
1933 873eb012 ths
        break;
1934 873eb012 ths
    case 16:
1935 873eb012 ths
        switch (sel) {
1936 873eb012 ths
        case 0:
1937 873eb012 ths
           gen_op_mfc0_config0();
1938 873eb012 ths
            rn = "Config";
1939 873eb012 ths
            break;
1940 873eb012 ths
        case 1:
1941 873eb012 ths
           gen_op_mfc0_config1();
1942 873eb012 ths
            rn = "Config1";
1943 873eb012 ths
            break;
1944 7a387fff ths
        case 2:
1945 7a387fff ths
           gen_op_mfc0_config2();
1946 7a387fff ths
            rn = "Config2";
1947 7a387fff ths
            break;
1948 7a387fff ths
        case 3:
1949 7a387fff ths
           gen_op_mfc0_config3();
1950 7a387fff ths
            rn = "Config3";
1951 7a387fff ths
            break;
1952 7a387fff ths
       /* 6,7 are implementation dependent */
1953 873eb012 ths
        default:
1954 873eb012 ths
            goto die;
1955 873eb012 ths
        }
1956 873eb012 ths
        break;
1957 873eb012 ths
    case 17:
1958 7a387fff ths
        switch (sel) {
1959 7a387fff ths
        case 0:
1960 7a387fff ths
           gen_op_mfc0_lladdr();
1961 7a387fff ths
           rn = "LLAddr";
1962 7a387fff ths
           break;
1963 7a387fff ths
        default:
1964 7a387fff ths
            goto die;
1965 7a387fff ths
        }
1966 873eb012 ths
        break;
1967 873eb012 ths
    case 18:
1968 7a387fff ths
        switch (sel) {
1969 7a387fff ths
        case 0:
1970 7a387fff ths
           gen_op_mfc0_watchlo0();
1971 7a387fff ths
           rn = "WatchLo";
1972 7a387fff ths
           break;
1973 7a387fff ths
        case 1:
1974 7a387fff ths
//         gen_op_mfc0_watchlo1();
1975 7a387fff ths
           rn = "WatchLo1";
1976 7a387fff ths
//         break;
1977 7a387fff ths
        case 2:
1978 7a387fff ths
//         gen_op_mfc0_watchlo2();
1979 7a387fff ths
           rn = "WatchLo2";
1980 7a387fff ths
//         break;
1981 7a387fff ths
        case 3:
1982 7a387fff ths
//         gen_op_mfc0_watchlo3();
1983 7a387fff ths
           rn = "WatchLo3";
1984 7a387fff ths
//         break;
1985 7a387fff ths
        case 4:
1986 7a387fff ths
//         gen_op_mfc0_watchlo4();
1987 7a387fff ths
           rn = "WatchLo4";
1988 7a387fff ths
//         break;
1989 7a387fff ths
        case 5:
1990 7a387fff ths
//         gen_op_mfc0_watchlo5();
1991 7a387fff ths
           rn = "WatchLo5";
1992 7a387fff ths
//         break;
1993 7a387fff ths
        case 6:
1994 7a387fff ths
//         gen_op_mfc0_watchlo6();
1995 7a387fff ths
           rn = "WatchLo6";
1996 7a387fff ths
//         break;
1997 7a387fff ths
        case 7:
1998 7a387fff ths
//         gen_op_mfc0_watchlo7();
1999 7a387fff ths
           rn = "WatchLo7";
2000 7a387fff ths
//         break;
2001 7a387fff ths
        default:
2002 7a387fff ths
            goto die;
2003 7a387fff ths
        }
2004 873eb012 ths
        break;
2005 873eb012 ths
    case 19:
2006 7a387fff ths
        switch (sel) {
2007 7a387fff ths
        case 0:
2008 7a387fff ths
           gen_op_mfc0_watchhi0();
2009 7a387fff ths
           rn = "WatchHi";
2010 7a387fff ths
           break;
2011 7a387fff ths
        case 1:
2012 7a387fff ths
//         gen_op_mfc0_watchhi1();
2013 7a387fff ths
           rn = "WatchHi1";
2014 7a387fff ths
//         break;
2015 7a387fff ths
        case 2:
2016 7a387fff ths
//         gen_op_mfc0_watchhi2();
2017 7a387fff ths
           rn = "WatchHi2";
2018 7a387fff ths
//         break;
2019 7a387fff ths
        case 3:
2020 7a387fff ths
//         gen_op_mfc0_watchhi3();
2021 7a387fff ths
           rn = "WatchHi3";
2022 7a387fff ths
//         break;
2023 7a387fff ths
        case 4:
2024 7a387fff ths
//         gen_op_mfc0_watchhi4();
2025 7a387fff ths
           rn = "WatchHi4";
2026 7a387fff ths
//         break;
2027 7a387fff ths
        case 5:
2028 7a387fff ths
//         gen_op_mfc0_watchhi5();
2029 7a387fff ths
           rn = "WatchHi5";
2030 7a387fff ths
//         break;
2031 7a387fff ths
        case 6:
2032 7a387fff ths
//         gen_op_mfc0_watchhi6();
2033 7a387fff ths
           rn = "WatchHi6";
2034 7a387fff ths
//         break;
2035 7a387fff ths
        case 7:
2036 7a387fff ths
//         gen_op_mfc0_watchhi7();
2037 7a387fff ths
           rn = "WatchHi7";
2038 7a387fff ths
//         break;
2039 7a387fff ths
        default:
2040 7a387fff ths
            goto die;
2041 7a387fff ths
        }
2042 873eb012 ths
        break;
2043 8c0fdd85 ths
    case 20:
2044 7a387fff ths
        switch (sel) {
2045 7a387fff ths
        case 0:
2046 7a387fff ths
           /* 64 bit MMU only */
2047 7a387fff ths
           gen_op_mfc0_xcontext();
2048 7a387fff ths
           rn = "XContext";
2049 7a387fff ths
           break;
2050 7a387fff ths
        default:
2051 7a387fff ths
            goto die;
2052 7a387fff ths
        }
2053 8c0fdd85 ths
        break;
2054 8c0fdd85 ths
    case 21:
2055 7a387fff ths
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
2056 7a387fff ths
        switch (sel) {
2057 7a387fff ths
        case 0:
2058 7a387fff ths
           gen_op_mfc0_framemask();
2059 7a387fff ths
           rn = "Framemask";
2060 7a387fff ths
           break;
2061 7a387fff ths
        default:
2062 7a387fff ths
            goto die;
2063 7a387fff ths
        }
2064 8c0fdd85 ths
        break;
2065 8c0fdd85 ths
    case 22:
2066 7a387fff ths
       /* ignored */
2067 7a387fff ths
       rn = "'Diagnostic"; /* implementation dependent */
2068 7a387fff ths
       break;
2069 873eb012 ths
    case 23:
2070 7a387fff ths
        switch (sel) {
2071 7a387fff ths
        case 0:
2072 7a387fff ths
           gen_op_mfc0_debug(); /* EJTAG support */
2073 7a387fff ths
           rn = "Debug";
2074 7a387fff ths
           break;
2075 7a387fff ths
        case 1:
2076 7a387fff ths
//         gen_op_mfc0_tracecontrol(); /* PDtrace support */
2077 7a387fff ths
           rn = "TraceControl";
2078 7a387fff ths
//         break;
2079 7a387fff ths
        case 2:
2080 7a387fff ths
//         gen_op_mfc0_tracecontrol2(); /* PDtrace support */
2081 7a387fff ths
           rn = "TraceControl2";
2082 7a387fff ths
//         break;
2083 7a387fff ths
        case 3:
2084 7a387fff ths
//         gen_op_mfc0_usertracedata(); /* PDtrace support */
2085 7a387fff ths
           rn = "UserTraceData";
2086 7a387fff ths
//         break;
2087 7a387fff ths
        case 4:
2088 7a387fff ths
//         gen_op_mfc0_debug(); /* PDtrace support */
2089 7a387fff ths
           rn = "TraceBPC";
2090 7a387fff ths
//         break;
2091 7a387fff ths
        default:
2092 7a387fff ths
            goto die;
2093 7a387fff ths
        }
2094 873eb012 ths
        break;
2095 873eb012 ths
    case 24:
2096 7a387fff ths
        switch (sel) {
2097 7a387fff ths
        case 0:
2098 7a387fff ths
           gen_op_mfc0_depc(); /* EJTAG support */
2099 7a387fff ths
           rn = "DEPC";
2100 7a387fff ths
           break;
2101 7a387fff ths
        default:
2102 7a387fff ths
            goto die;
2103 7a387fff ths
        }
2104 873eb012 ths
        break;
2105 8c0fdd85 ths
    case 25:
2106 7a387fff ths
        switch (sel) {
2107 7a387fff ths
        case 0:
2108 7a387fff ths
           gen_op_mfc0_performance0();
2109 7a387fff ths
           rn = "Performance0";
2110 7a387fff ths
            break;
2111 7a387fff ths
        case 1:
2112 7a387fff ths
//         gen_op_mfc0_performance1();
2113 7a387fff ths
           rn = "Performance1";
2114 7a387fff ths
//         break;
2115 7a387fff ths
        case 2:
2116 7a387fff ths
//         gen_op_mfc0_performance2();
2117 7a387fff ths
           rn = "Performance2";
2118 7a387fff ths
//         break;
2119 7a387fff ths
        case 3:
2120 7a387fff ths
//         gen_op_mfc0_performance3();
2121 7a387fff ths
           rn = "Performance3";
2122 7a387fff ths
//         break;
2123 7a387fff ths
        case 4:
2124 7a387fff ths
//         gen_op_mfc0_performance4();
2125 7a387fff ths
           rn = "Performance4";
2126 7a387fff ths
//         break;
2127 7a387fff ths
        case 5:
2128 7a387fff ths
//         gen_op_mfc0_performance5();
2129 7a387fff ths
           rn = "Performance5";
2130 7a387fff ths
//         break;
2131 7a387fff ths
        case 6:
2132 7a387fff ths
//         gen_op_mfc0_performance6();
2133 7a387fff ths
           rn = "Performance6";
2134 7a387fff ths
//         break;
2135 7a387fff ths
        case 7:
2136 7a387fff ths
//         gen_op_mfc0_performance7();
2137 7a387fff ths
           rn = "Performance7";
2138 7a387fff ths
//         break;
2139 7a387fff ths
        default:
2140 7a387fff ths
            goto die;
2141 7a387fff ths
        }
2142 8c0fdd85 ths
        break;
2143 8c0fdd85 ths
    case 26:
2144 7a387fff ths
       rn = "ECC";
2145 7a387fff ths
       break;
2146 8c0fdd85 ths
    case 27:
2147 7a387fff ths
        switch (sel) {
2148 7a387fff ths
        /* ignored */
2149 7a387fff ths
        case 0 ... 3:
2150 7a387fff ths
           rn = "CacheErr";
2151 7a387fff ths
           break;
2152 7a387fff ths
        default:
2153 7a387fff ths
            goto die;
2154 7a387fff ths
        }
2155 8c0fdd85 ths
        break;
2156 873eb012 ths
    case 28:
2157 873eb012 ths
        switch (sel) {
2158 873eb012 ths
        case 0:
2159 7a387fff ths
        case 2:
2160 7a387fff ths
        case 4:
2161 7a387fff ths
        case 6:
2162 873eb012 ths
            gen_op_mfc0_taglo();
2163 873eb012 ths
            rn = "TagLo";
2164 873eb012 ths
            break;
2165 873eb012 ths
        case 1:
2166 7a387fff ths
        case 3:
2167 7a387fff ths
        case 5:
2168 7a387fff ths
        case 7:
2169 873eb012 ths
            gen_op_mfc0_datalo();
2170 873eb012 ths
            rn = "DataLo";
2171 873eb012 ths
            break;
2172 873eb012 ths
        default:
2173 873eb012 ths
            goto die;
2174 873eb012 ths
        }
2175 873eb012 ths
        break;
2176 8c0fdd85 ths
    case 29:
2177 7a387fff ths
        switch (sel) {
2178 7a387fff ths
        case 0:
2179 7a387fff ths
        case 2:
2180 7a387fff ths
        case 4:
2181 7a387fff ths
        case 6:
2182 7a387fff ths
            gen_op_mfc0_taghi();
2183 7a387fff ths
            rn = "TagHi";
2184 7a387fff ths
            break;
2185 7a387fff ths
        case 1:
2186 7a387fff ths
        case 3:
2187 7a387fff ths
        case 5:
2188 7a387fff ths
        case 7:
2189 7a387fff ths
            gen_op_mfc0_datahi();
2190 7a387fff ths
            rn = "DataHi";
2191 7a387fff ths
            break;
2192 7a387fff ths
        default:
2193 7a387fff ths
            goto die;
2194 7a387fff ths
        }
2195 8c0fdd85 ths
        break;
2196 873eb012 ths
    case 30:
2197 7a387fff ths
        switch (sel) {
2198 7a387fff ths
        case 0:
2199 7a387fff ths
           gen_op_mfc0_errorepc();
2200 7a387fff ths
           rn = "ErrorEPC";
2201 7a387fff ths
           break;
2202 7a387fff ths
        default:
2203 7a387fff ths
            goto die;
2204 7a387fff ths
        }
2205 873eb012 ths
        break;
2206 873eb012 ths
    case 31:
2207 7a387fff ths
        switch (sel) {
2208 7a387fff ths
        case 0:
2209 7a387fff ths
           gen_op_mfc0_desave(); /* EJTAG support */
2210 7a387fff ths
           rn = "DESAVE";
2211 7a387fff ths
           break;
2212 7a387fff ths
        default:
2213 7a387fff ths
            goto die;
2214 7a387fff ths
        }
2215 873eb012 ths
        break;
2216 873eb012 ths
    default:
2217 873eb012 ths
       goto die;
2218 873eb012 ths
    }
2219 873eb012 ths
#if defined MIPS_DEBUG_DISAS
2220 873eb012 ths
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2221 7a387fff ths
        fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
2222 7a387fff ths
                rn, reg, sel);
2223 873eb012 ths
    }
2224 873eb012 ths
#endif
2225 873eb012 ths
    return;
2226 873eb012 ths
2227 873eb012 ths
die:
2228 873eb012 ths
#if defined MIPS_DEBUG_DISAS
2229 873eb012 ths
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2230 7a387fff ths
        fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
2231 7a387fff ths
                rn, reg, sel);
2232 873eb012 ths
    }
2233 873eb012 ths
#endif
2234 873eb012 ths
    generate_exception(ctx, EXCP_RI);
2235 873eb012 ths
}
2236 873eb012 ths
2237 8c0fdd85 ths
static void gen_mtc0 (DisasContext *ctx, int reg, int sel)
2238 8c0fdd85 ths
{
2239 7a387fff ths
    const char *rn = "invalid";
2240 7a387fff ths
2241 8c0fdd85 ths
    switch (reg) {
2242 8c0fdd85 ths
    case 0:
2243 7a387fff ths
        switch (sel) {
2244 7a387fff ths
        case 0:
2245 7a387fff ths
           gen_op_mtc0_index();
2246 7a387fff ths
            rn = "Index";
2247 7a387fff ths
            break;
2248 7a387fff ths
        case 1:
2249 7a387fff ths
//         gen_op_mtc0_mvpcontrol(); /* MT ASE */
2250 7a387fff ths
            rn = "MVPControl";
2251 7a387fff ths
//         break;
2252 7a387fff ths
        case 2:
2253 7a387fff ths
//         gen_op_mtc0_mvpconf0(); /* MT ASE */
2254 7a387fff ths
            rn = "MVPConf0";
2255 7a387fff ths
//         break;
2256 7a387fff ths
        case 3:
2257 7a387fff ths
//         gen_op_mtc0_mvpconf1(); /* MT ASE */
2258 7a387fff ths
            rn = "MVPConf1";
2259 7a387fff ths
//         break;
2260 7a387fff ths
        default:
2261 7a387fff ths
            goto die;
2262 7a387fff ths
        }
2263 8c0fdd85 ths
        break;
2264 8c0fdd85 ths
    case 1:
2265 7a387fff ths
        switch (sel) {
2266 7a387fff ths
        case 0:
2267 7a387fff ths
           /* ignored */
2268 7a387fff ths
            rn = "Random";
2269 7a387fff ths
           break;
2270 7a387fff ths
        case 1:
2271 7a387fff ths
//         gen_op_mtc0_vpecontrol(); /* MT ASE */
2272 7a387fff ths
            rn = "VPEControl";
2273 7a387fff ths
//         break;
2274 7a387fff ths
        case 2:
2275 7a387fff ths
//         gen_op_mtc0_vpeconf0(); /* MT ASE */
2276 7a387fff ths
            rn = "VPEConf0";
2277 7a387fff ths
//         break;
2278 7a387fff ths
        case 3:
2279 7a387fff ths
//         gen_op_mtc0_vpeconf1(); /* MT ASE */
2280 7a387fff ths
            rn = "VPEConf1";
2281 7a387fff ths
//         break;
2282 7a387fff ths
        case 4:
2283 7a387fff ths
//         gen_op_mtc0_YQMask(); /* MT ASE */
2284 7a387fff ths
            rn = "YQMask";
2285 7a387fff ths
//         break;
2286 7a387fff ths
        case 5:
2287 7a387fff ths
//         gen_op_mtc0_vpeschedule(); /* MT ASE */
2288 7a387fff ths
            rn = "VPESchedule";
2289 7a387fff ths
//         break;
2290 7a387fff ths
        case 6:
2291 7a387fff ths
//         gen_op_mtc0_vpeschefback(); /* MT ASE */
2292 7a387fff ths
            rn = "VPEScheFBack";
2293 7a387fff ths
//         break;
2294 7a387fff ths
        case 7:
2295 7a387fff ths
//         gen_op_mtc0_vpeopt(); /* MT ASE */
2296 7a387fff ths
            rn = "VPEOpt";
2297 7a387fff ths
//         break;
2298 7a387fff ths
        default:
2299 7a387fff ths
            goto die;
2300 7a387fff ths
        }
2301 8c0fdd85 ths
        break;
2302 8c0fdd85 ths
    case 2:
2303 7a387fff ths
        switch (sel) {
2304 7a387fff ths
        case 0:
2305 7a387fff ths
           gen_op_mtc0_entrylo0();
2306 7a387fff ths
           rn = "EntryLo0";
2307 7a387fff ths
           break;
2308 7a387fff ths
        case 1:
2309 7a387fff ths
//         gen_op_mtc0_tcstatus(); /* MT ASE */
2310 7a387fff ths
           rn = "TCStatus";
2311 7a387fff ths
//         break;
2312 7a387fff ths
        case 2:
2313 7a387fff ths
//         gen_op_mtc0_tcbind(); /* MT ASE */
2314 7a387fff ths
           rn = "TCBind";
2315 7a387fff ths
//         break;
2316 7a387fff ths
        case 3:
2317 7a387fff ths
//         gen_op_mtc0_tcrestart(); /* MT ASE */
2318 7a387fff ths
           rn = "TCRestart";
2319 7a387fff ths
//         break;
2320 7a387fff ths
        case 4:
2321 7a387fff ths
//         gen_op_mtc0_tchalt(); /* MT ASE */
2322 7a387fff ths
           rn = "TCHalt";
2323 7a387fff ths
//         break;
2324 7a387fff ths
        case 5:
2325 7a387fff ths
//         gen_op_mtc0_tccontext(); /* MT ASE */
2326 7a387fff ths
           rn = "TCContext";
2327 7a387fff ths
//         break;
2328 7a387fff ths
        case 6:
2329 7a387fff ths
//         gen_op_mtc0_tcschedule(); /* MT ASE */
2330 7a387fff ths
           rn = "TCSchedule";
2331 7a387fff ths
//         break;
2332 7a387fff ths
        case 7:
2333 7a387fff ths
//         gen_op_mtc0_tcschefback(); /* MT ASE */
2334 7a387fff ths
           rn = "TCScheFBack";
2335 7a387fff ths
//         break;
2336 7a387fff ths
        default:
2337 7a387fff ths
            goto die;
2338 7a387fff ths
        }
2339 8c0fdd85 ths
        break;
2340 8c0fdd85 ths
    case 3:
2341 7a387fff ths
        switch (sel) {
2342 7a387fff ths
        case 0:
2343 7a387fff ths
           gen_op_mtc0_entrylo1();
2344 7a387fff ths
           rn = "EntryLo1";
2345 7a387fff ths
           break;
2346 7a387fff ths
        default:
2347 7a387fff ths
            goto die;
2348 7a387fff ths
       }
2349 8c0fdd85 ths
        break;
2350 8c0fdd85 ths
    case 4:
2351 7a387fff ths
        switch (sel) {
2352 7a387fff ths
        case 0:
2353 7a387fff ths
           gen_op_mtc0_context();
2354 7a387fff ths
           rn = "Context";
2355 7a387fff ths
           break;
2356 7a387fff ths
        case 1:
2357 7a387fff ths
//         gen_op_mtc0_contextconfig(); /* SmartMIPS ASE */
2358 7a387fff ths
           rn = "ContextConfig";
2359 7a387fff ths
//         break;
2360 7a387fff ths
        default:
2361 7a387fff ths
            goto die;
2362 7a387fff ths
       }
2363 8c0fdd85 ths
        break;
2364 8c0fdd85 ths
    case 5:
2365 7a387fff ths
        switch (sel) {
2366 7a387fff ths
        case 0:
2367 7a387fff ths
           gen_op_mtc0_pagemask();
2368 7a387fff ths
           rn = "PageMask";
2369 7a387fff ths
           break;
2370 7a387fff ths
        case 1:
2371 7a387fff ths
           gen_op_mtc0_pagegrain();
2372 7a387fff ths
           rn = "PageGrain";
2373 7a387fff ths
           break;
2374 7a387fff ths
        default:
2375 7a387fff ths
            goto die;
2376 7a387fff ths
       }
2377 8c0fdd85 ths
        break;
2378 8c0fdd85 ths
    case 6:
2379 7a387fff ths
        switch (sel) {
2380 7a387fff ths
        case 0:
2381 7a387fff ths
           gen_op_mtc0_wired();
2382 7a387fff ths
           rn = "Wired";
2383 7a387fff ths
           break;
2384 7a387fff ths
        case 1:
2385 7a387fff ths
//         gen_op_mtc0_srsconf0(); /* shadow registers */
2386 7a387fff ths
           rn = "SRSConf0";
2387 7a387fff ths
//         break;
2388 7a387fff ths
        case 2:
2389 7a387fff ths
//         gen_op_mtc0_srsconf1(); /* shadow registers */
2390 7a387fff ths
           rn = "SRSConf1";
2391 7a387fff ths
//         break;
2392 7a387fff ths
        case 3:
2393 7a387fff ths
//         gen_op_mtc0_srsconf2(); /* shadow registers */
2394 7a387fff ths
           rn = "SRSConf2";
2395 7a387fff ths
//         break;
2396 7a387fff ths
        case 4:
2397 7a387fff ths
//         gen_op_mtc0_srsconf3(); /* shadow registers */
2398 7a387fff ths
           rn = "SRSConf3";
2399 7a387fff ths
//         break;
2400 7a387fff ths
        case 5:
2401 7a387fff ths
//         gen_op_mtc0_srsconf4(); /* shadow registers */
2402 7a387fff ths
           rn = "SRSConf4";
2403 7a387fff ths
//         break;
2404 7a387fff ths
        default:
2405 7a387fff ths
            goto die;
2406 7a387fff ths
       }
2407 8c0fdd85 ths
        break;
2408 8c0fdd85 ths
    case 7:
2409 7a387fff ths
        switch (sel) {
2410 7a387fff ths
        case 0:
2411 7a387fff ths
           gen_op_mtc0_hwrena();
2412 7a387fff ths
           rn = "HWREna";
2413 7a387fff ths
           break;
2414 7a387fff ths
        default:
2415 7a387fff ths
            goto die;
2416 7a387fff ths
       }
2417 8c0fdd85 ths
        break;
2418 8c0fdd85 ths
    case 8:
2419 7a387fff ths
        /* ignored */
2420 8c0fdd85 ths
        rn = "BadVaddr";
2421 8c0fdd85 ths
        break;
2422 8c0fdd85 ths
    case 9:
2423 7a387fff ths
        switch (sel) {
2424 7a387fff ths
        case 0:
2425 7a387fff ths
           gen_op_mtc0_count();
2426 7a387fff ths
           rn = "Count";
2427 7a387fff ths
           break;
2428 7a387fff ths
       /* 6,7 are implementation dependent */
2429 7a387fff ths
        default:
2430 7a387fff ths
            goto die;
2431 7a387fff ths
       }
2432 7a387fff ths
       /* Stop translation as we may have switched the execution mode */
2433 7a387fff ths
       ctx->bstate = BS_STOP;
2434 8c0fdd85 ths
        break;
2435 8c0fdd85 ths
    case 10:
2436 7a387fff ths
        switch (sel) {
2437 7a387fff ths
        case 0:
2438 7a387fff ths
           gen_op_mtc0_entryhi();
2439 7a387fff ths
           rn = "EntryHi";
2440 7a387fff ths
           break;
2441 7a387fff ths
        default:
2442 7a387fff ths
            goto die;
2443 7a387fff ths
       }
2444 8c0fdd85 ths
        break;
2445 8c0fdd85 ths
    case 11:
2446 7a387fff ths
        switch (sel) {
2447 7a387fff ths
        case 0:
2448 7a387fff ths
           gen_op_mtc0_compare();
2449 7a387fff ths
           rn = "Compare";
2450 7a387fff ths
           break;
2451 7a387fff ths
       /* 6,7 are implementation dependent */
2452 7a387fff ths
        default:
2453 7a387fff ths
            goto die;
2454 7a387fff ths
       }
2455 7a387fff ths
       /* Stop translation as we may have switched the execution mode */
2456 7a387fff ths
       ctx->bstate = BS_STOP;
2457 8c0fdd85 ths
        break;
2458 8c0fdd85 ths
    case 12:
2459 7a387fff ths
        switch (sel) {
2460 7a387fff ths
        case 0:
2461 7a387fff ths
           gen_op_mtc0_status();
2462 7a387fff ths
           rn = "Status";
2463 7a387fff ths
           break;
2464 7a387fff ths
        case 1:
2465 7a387fff ths
           gen_op_mtc0_intctl();
2466 7a387fff ths
           rn = "IntCtl";
2467 7a387fff ths
           break;
2468 7a387fff ths
        case 2:
2469 7a387fff ths
           gen_op_mtc0_srsctl();
2470 7a387fff ths
           rn = "SRSCtl";
2471 7a387fff ths
           break;
2472 7a387fff ths
        case 3:
2473 7a387fff ths
//         gen_op_mtc0_srsmap(); /* shadow registers */
2474 7a387fff ths
           rn = "SRSMap";
2475 7a387fff ths
//         break;
2476 7a387fff ths
        default:
2477 7a387fff ths
            goto die;
2478 7a387fff ths
       }
2479 7a387fff ths
       /* Stop translation as we may have switched the execution mode */
2480 7a387fff ths
       ctx->bstate = BS_STOP;
2481 8c0fdd85 ths
        break;
2482 8c0fdd85 ths
    case 13:
2483 7a387fff ths
        switch (sel) {
2484 7a387fff ths
        case 0:
2485 7a387fff ths
           gen_op_mtc0_cause();
2486 7a387fff ths
           rn = "Cause";
2487 7a387fff ths
           break;
2488 7a387fff ths
        default:
2489 7a387fff ths
            goto die;
2490 7a387fff ths
       }
2491 7a387fff ths
       /* Stop translation as we may have switched the execution mode */
2492 7a387fff ths
       ctx->bstate = BS_STOP;
2493 8c0fdd85 ths
        break;
2494 8c0fdd85 ths
    case 14:
2495 7a387fff ths
        switch (sel) {
2496 7a387fff ths
        case 0:
2497 7a387fff ths
           gen_op_mtc0_epc();
2498 7a387fff ths
           rn = "EPC";
2499 7a387fff ths
           break;
2500 7a387fff ths
        default:
2501 7a387fff ths
            goto die;
2502 7a387fff ths
       }
2503 8c0fdd85 ths
        break;
2504 8c0fdd85 ths
    case 15:
2505 7a387fff ths
        switch (sel) {
2506 7a387fff ths
        case 0:
2507 7a387fff ths
           /* ignored */
2508 7a387fff ths
           rn = "PRid";
2509 7a387fff ths
           break;
2510 7a387fff ths
        case 1:
2511 7a387fff ths
           gen_op_mtc0_ebase();
2512 7a387fff ths
           rn = "EBase";
2513 7a387fff ths
           break;
2514 7a387fff ths
        default:
2515 7a387fff ths
            goto die;
2516 7a387fff ths
       }
2517 8c0fdd85 ths
        break;
2518 8c0fdd85 ths
    case 16:
2519 8c0fdd85 ths
        switch (sel) {
2520 8c0fdd85 ths
        case 0:
2521 8c0fdd85 ths
           gen_op_mtc0_config0();
2522 7a387fff ths
            rn = "Config";
2523 7a387fff ths
            break;
2524 7a387fff ths
        case 1:
2525 7a387fff ths
           /* ignored */
2526 7a387fff ths
            rn = "Config1";
2527 7a387fff ths
            break;
2528 7a387fff ths
        case 2:
2529 7a387fff ths
           gen_op_mtc0_config2();
2530 7a387fff ths
            rn = "Config2";
2531 8c0fdd85 ths
            break;
2532 7a387fff ths
        case 3:
2533 7a387fff ths
           /* ignored */
2534 7a387fff ths
            rn = "Config3";
2535 7a387fff ths
            break;
2536 7a387fff ths
       /* 6,7 are implementation dependent */
2537 8c0fdd85 ths
        default:
2538 8c0fdd85 ths
            rn = "Invalid config selector";
2539 8c0fdd85 ths
            goto die;
2540 8c0fdd85 ths
        }
2541 7a387fff ths
       /* Stop translation as we may have switched the execution mode */
2542 7a387fff ths
       ctx->bstate = BS_STOP;
2543 8c0fdd85 ths
        break;
2544 8c0fdd85 ths
    case 17:
2545 7a387fff ths
        switch (sel) {
2546 7a387fff ths
        case 0:
2547 7a387fff ths
           /* ignored */
2548 7a387fff ths
           rn = "LLAddr";
2549 7a387fff ths
           break;
2550 7a387fff ths
        default:
2551 7a387fff ths
            goto die;
2552 7a387fff ths
        }
2553 8c0fdd85 ths
        break;
2554 8c0fdd85 ths
    case 18:
2555 7a387fff ths
        switch (sel) {
2556 7a387fff ths
        case 0:
2557 7a387fff ths
           gen_op_mtc0_watchlo0();
2558 7a387fff ths
           rn = "WatchLo";
2559 7a387fff ths
           break;
2560 7a387fff ths
        case 1:
2561 7a387fff ths
//         gen_op_mtc0_watchlo1();
2562 7a387fff ths
           rn = "WatchLo1";
2563 7a387fff ths
//         break;
2564 7a387fff ths
        case 2:
2565 7a387fff ths
//         gen_op_mtc0_watchlo2();
2566 7a387fff ths
           rn = "WatchLo2";
2567 7a387fff ths
//         break;
2568 7a387fff ths
        case 3:
2569 7a387fff ths
//         gen_op_mtc0_watchlo3();
2570 7a387fff ths
           rn = "WatchLo3";
2571 7a387fff ths
//         break;
2572 7a387fff ths
        case 4:
2573 7a387fff ths
//         gen_op_mtc0_watchlo4();
2574 7a387fff ths
           rn = "WatchLo4";
2575 7a387fff ths
//         break;
2576 7a387fff ths
        case 5:
2577 7a387fff ths
//         gen_op_mtc0_watchlo5();
2578 7a387fff ths
           rn = "WatchLo5";
2579 7a387fff ths
//         break;
2580 7a387fff ths
        case 6:
2581 7a387fff ths
//         gen_op_mtc0_watchlo6();
2582 7a387fff ths
           rn = "WatchLo6";
2583 7a387fff ths
//         break;
2584 7a387fff ths
        case 7:
2585 7a387fff ths
//         gen_op_mtc0_watchlo7();
2586 7a387fff ths
           rn = "WatchLo7";
2587 7a387fff ths
//         break;
2588 7a387fff ths
        default:
2589 7a387fff ths
            goto die;
2590 7a387fff ths
        }
2591 8c0fdd85 ths
        break;
2592 8c0fdd85 ths
    case 19:
2593 7a387fff ths
        switch (sel) {
2594 7a387fff ths
        case 0:
2595 7a387fff ths
           gen_op_mtc0_watchhi0();
2596 7a387fff ths
           rn = "WatchHi";
2597 7a387fff ths
           break;
2598 7a387fff ths
        case 1:
2599 7a387fff ths
//         gen_op_mtc0_watchhi1();
2600 7a387fff ths
           rn = "WatchHi1";
2601 7a387fff ths
//         break;
2602 7a387fff ths
        case 2:
2603 7a387fff ths
//         gen_op_mtc0_watchhi2();
2604 7a387fff ths
           rn = "WatchHi2";
2605 7a387fff ths
//         break;
2606 7a387fff ths
        case 3:
2607 7a387fff ths
//         gen_op_mtc0_watchhi3();
2608 7a387fff ths
           rn = "WatchHi3";
2609 7a387fff ths
//         break;
2610 7a387fff ths
        case 4:
2611 7a387fff ths
//         gen_op_mtc0_watchhi4();
2612 7a387fff ths
           rn = "WatchHi4";
2613 7a387fff ths
//         break;
2614 7a387fff ths
        case 5:
2615 7a387fff ths
//         gen_op_mtc0_watchhi5();
2616 7a387fff ths
           rn = "WatchHi5";
2617 7a387fff ths
//         break;
2618 7a387fff ths
        case 6:
2619 7a387fff ths
//         gen_op_mtc0_watchhi6();
2620 7a387fff ths
           rn = "WatchHi6";
2621 7a387fff ths
//         break;
2622 7a387fff ths
        case 7:
2623 7a387fff ths
//         gen_op_mtc0_watchhi7();
2624 7a387fff ths
           rn = "WatchHi7";
2625 7a387fff ths
//         break;
2626 7a387fff ths
        default:
2627 7a387fff ths
            goto die;
2628 7a387fff ths
        }
2629 8c0fdd85 ths
        break;
2630 8c0fdd85 ths
    case 20:
2631 7a387fff ths
        switch (sel) {
2632 7a387fff ths
        case 0:
2633 7a387fff ths
           /* 64 bit MMU only */
2634 7a387fff ths
           gen_op_mtc0_xcontext();
2635 7a387fff ths
           rn = "XContext";
2636 7a387fff ths
           break;
2637 7a387fff ths
        default:
2638 7a387fff ths
            goto die;
2639 7a387fff ths
        }
2640 8c0fdd85 ths
        break;
2641 8c0fdd85 ths
    case 21:
2642 7a387fff ths
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
2643 7a387fff ths
        switch (sel) {
2644 7a387fff ths
        case 0:
2645 7a387fff ths
           gen_op_mtc0_framemask();
2646 7a387fff ths
           rn = "Framemask";
2647 7a387fff ths
           break;
2648 7a387fff ths
        default:
2649 7a387fff ths
            goto die;
2650 7a387fff ths
        }
2651 7a387fff ths
        break;
2652 8c0fdd85 ths
    case 22:
2653 7a387fff ths
        /* ignored */
2654 7a387fff ths
        rn = "Diagnostic"; /* implementation dependent */
2655 8c0fdd85 ths
       break;
2656 8c0fdd85 ths
    case 23:
2657 7a387fff ths
        switch (sel) {
2658 7a387fff ths
        case 0:
2659 7a387fff ths
           gen_op_mtc0_debug(); /* EJTAG support */
2660 7a387fff ths
           rn = "Debug";
2661 7a387fff ths
           break;
2662 7a387fff ths
        case 1:
2663 7a387fff ths
//         gen_op_mtc0_tracecontrol(); /* PDtrace support */
2664 7a387fff ths
           rn = "TraceControl";
2665 7a387fff ths
//         break;
2666 7a387fff ths
        case 2:
2667 7a387fff ths
//         gen_op_mtc0_tracecontrol2(); /* PDtrace support */
2668 7a387fff ths
           rn = "TraceControl2";
2669 7a387fff ths
//         break;
2670 7a387fff ths
        case 3:
2671 7a387fff ths
//         gen_op_mtc0_usertracedata(); /* PDtrace support */
2672 7a387fff ths
           rn = "UserTraceData";
2673 7a387fff ths
//         break;
2674 7a387fff ths
        case 4:
2675 7a387fff ths
//         gen_op_mtc0_debug(); /* PDtrace support */
2676 7a387fff ths
           rn = "TraceBPC";
2677 7a387fff ths
//         break;
2678 7a387fff ths
        default:
2679 7a387fff ths
            goto die;
2680 7a387fff ths
        }
2681 7a387fff ths
       /* Stop translation as we may have switched the execution mode */
2682 7a387fff ths
       ctx->bstate = BS_STOP;
2683 8c0fdd85 ths
        break;
2684 8c0fdd85 ths
    case 24:
2685 7a387fff ths
        switch (sel) {
2686 7a387fff ths
        case 0:
2687 7a387fff ths
           gen_op_mtc0_depc(); /* EJTAG support */
2688 7a387fff ths
           rn = "DEPC";
2689 7a387fff ths
           break;
2690 7a387fff ths
        default:
2691 7a387fff ths
            goto die;
2692 7a387fff ths
        }
2693 8c0fdd85 ths
        break;
2694 8c0fdd85 ths
    case 25:
2695 7a387fff ths
        switch (sel) {
2696 7a387fff ths
        case 0:
2697 7a387fff ths
           gen_op_mtc0_performance0();
2698 7a387fff ths
           rn = "Performance0";
2699 7a387fff ths
           break;
2700 7a387fff ths
        case 1:
2701 7a387fff ths
//         gen_op_mtc0_performance1();
2702 7a387fff ths
           rn = "Performance1";
2703 7a387fff ths
//         break;
2704 7a387fff ths
        case 2:
2705 7a387fff ths
//         gen_op_mtc0_performance2();
2706 7a387fff ths
           rn = "Performance2";
2707 7a387fff ths
//         break;
2708 7a387fff ths
        case 3:
2709 7a387fff ths
//         gen_op_mtc0_performance3();
2710 7a387fff ths
           rn = "Performance3";
2711 7a387fff ths
//         break;
2712 7a387fff ths
        case 4:
2713 7a387fff ths
//         gen_op_mtc0_performance4();
2714 7a387fff ths
           rn = "Performance4";
2715 7a387fff ths
//         break;
2716 7a387fff ths
        case 5:
2717 7a387fff ths
//         gen_op_mtc0_performance5();
2718 7a387fff ths
           rn = "Performance5";
2719 7a387fff ths
//         break;
2720 7a387fff ths
        case 6:
2721 7a387fff ths
//         gen_op_mtc0_performance6();
2722 7a387fff ths
           rn = "Performance6";
2723 7a387fff ths
//         break;
2724 7a387fff ths
        case 7:
2725 7a387fff ths
//         gen_op_mtc0_performance7();
2726 7a387fff ths
           rn = "Performance7";
2727 7a387fff ths
//         break;
2728 7a387fff ths
        default:
2729 7a387fff ths
            goto die;
2730 7a387fff ths
        }
2731 8c0fdd85 ths
       break;
2732 8c0fdd85 ths
    case 26:
2733 7a387fff ths
       /* ignored */
2734 8c0fdd85 ths
        rn = "ECC";
2735 8c0fdd85 ths
       break;
2736 8c0fdd85 ths
    case 27:
2737 7a387fff ths
        switch (sel) {
2738 7a387fff ths
        case 0 ... 3:
2739 7a387fff ths
           /* ignored */
2740 7a387fff ths
           rn = "CacheErr";
2741 7a387fff ths
           break;
2742 7a387fff ths
        default:
2743 7a387fff ths
            goto die;
2744 7a387fff ths
        }
2745 8c0fdd85 ths
       break;
2746 8c0fdd85 ths
    case 28:
2747 8c0fdd85 ths
        switch (sel) {
2748 8c0fdd85 ths
        case 0:
2749 7a387fff ths
        case 2:
2750 7a387fff ths
        case 4:
2751 7a387fff ths
        case 6:
2752 8c0fdd85 ths
            gen_op_mtc0_taglo();
2753 8c0fdd85 ths
            rn = "TagLo";
2754 8c0fdd85 ths
            break;
2755 7a387fff ths
        case 1:
2756 7a387fff ths
        case 3:
2757 7a387fff ths
        case 5:
2758 7a387fff ths
        case 7:
2759 7a387fff ths
           gen_op_mtc0_datalo();
2760 7a387fff ths
            rn = "DataLo";
2761 7a387fff ths
            break;
2762 8c0fdd85 ths
        default:
2763 8c0fdd85 ths
            goto die;
2764 8c0fdd85 ths
        }
2765 8c0fdd85 ths
        break;
2766 8c0fdd85 ths
    case 29:
2767 7a387fff ths
        switch (sel) {
2768 7a387fff ths
        case 0:
2769 7a387fff ths
        case 2:
2770 7a387fff ths
        case 4:
2771 7a387fff ths
        case 6:
2772 7a387fff ths
            gen_op_mtc0_taghi();
2773 7a387fff ths
            rn = "TagHi";
2774 7a387fff ths
            break;
2775 7a387fff ths
        case 1:
2776 7a387fff ths
        case 3:
2777 7a387fff ths
        case 5:
2778 7a387fff ths
        case 7:
2779 7a387fff ths
           gen_op_mtc0_datahi();
2780 7a387fff ths
            rn = "DataHi";
2781 7a387fff ths
            break;
2782 7a387fff ths
        default:
2783 7a387fff ths
            rn = "invalid sel";
2784 7a387fff ths
            goto die;
2785 7a387fff ths
        }
2786 8c0fdd85 ths
       break;
2787 8c0fdd85 ths
    case 30:
2788 7a387fff ths
        switch (sel) {
2789 7a387fff ths
        case 0:
2790 7a387fff ths
           gen_op_mtc0_errorepc();
2791 7a387fff ths
           rn = "ErrorEPC";
2792 7a387fff ths
           break;
2793 7a387fff ths
        default:
2794 7a387fff ths
            goto die;
2795 7a387fff ths
        }
2796 8c0fdd85 ths
        break;
2797 8c0fdd85 ths
    case 31:
2798 7a387fff ths
        switch (sel) {
2799 7a387fff ths
        case 0:
2800 7a387fff ths
           gen_op_mtc0_desave(); /* EJTAG support */
2801 7a387fff ths
           rn = "DESAVE";
2802 7a387fff ths
           break;
2803 7a387fff ths
        default:
2804 7a387fff ths
            goto die;
2805 7a387fff ths
        }
2806 7a387fff ths
       /* Stop translation as we may have switched the execution mode */
2807 7a387fff ths
       ctx->bstate = BS_STOP;
2808 8c0fdd85 ths
        break;
2809 8c0fdd85 ths
    default:
2810 8c0fdd85 ths
       goto die;
2811 8c0fdd85 ths
    }
2812 8c0fdd85 ths
#if defined MIPS_DEBUG_DISAS
2813 8c0fdd85 ths
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2814 7a387fff ths
        fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
2815 7a387fff ths
                rn, reg, sel);
2816 8c0fdd85 ths
    }
2817 8c0fdd85 ths
#endif
2818 8c0fdd85 ths
    return;
2819 8c0fdd85 ths
2820 8c0fdd85 ths
die:
2821 8c0fdd85 ths
#if defined MIPS_DEBUG_DISAS
2822 8c0fdd85 ths
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2823 7a387fff ths
        fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
2824 7a387fff ths
                rn, reg, sel);
2825 8c0fdd85 ths
    }
2826 8c0fdd85 ths
#endif
2827 8c0fdd85 ths
    generate_exception(ctx, EXCP_RI);
2828 8c0fdd85 ths
}
2829 8c0fdd85 ths
2830 7a387fff ths
static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd)
2831 6af0bf9c bellard
{
2832 7a387fff ths
    const char *opn = "unk";
2833 6af0bf9c bellard
2834 aa328add ths
    if ((!ctx->CP0_Status & (1 << CP0St_CU0) &&
2835 aa328add ths
          (ctx->hflags & MIPS_HFLAG_UM)) &&
2836 bc2c3909 bellard
        !(ctx->hflags & MIPS_HFLAG_ERL) &&
2837 bc2c3909 bellard
        !(ctx->hflags & MIPS_HFLAG_EXL)) {
2838 6af0bf9c bellard
        if (loglevel & CPU_LOG_TB_IN_ASM) {
2839 6af0bf9c bellard
            fprintf(logfile, "CP0 is not usable\n");
2840 6af0bf9c bellard
        }
2841 7a387fff ths
        generate_exception (ctx, EXCP_CpU);
2842 6af0bf9c bellard
        return;
2843 6af0bf9c bellard
    }
2844 d796321b bellard
2845 6af0bf9c bellard
    switch (opc) {
2846 6af0bf9c bellard
    case OPC_MFC0:
2847 6af0bf9c bellard
        if (rt == 0) {
2848 6af0bf9c bellard
            /* Treat as NOP */
2849 6af0bf9c bellard
            return;
2850 6af0bf9c bellard
        }
2851 873eb012 ths
        gen_mfc0(ctx, rd, ctx->opcode & 0x7);
2852 6af0bf9c bellard
        gen_op_store_T0_gpr(rt);
2853 6af0bf9c bellard
        opn = "mfc0";
2854 6af0bf9c bellard
        break;
2855 6af0bf9c bellard
    case OPC_MTC0:
2856 6af0bf9c bellard
        /* If we get an exception, we want to restart at next instruction */
2857 7a387fff ths
       /* XXX: breaks for mtc in delay slot */
2858 6af0bf9c bellard
        ctx->pc += 4;
2859 6af0bf9c bellard
        save_cpu_state(ctx, 1);
2860 6af0bf9c bellard
        ctx->pc -= 4;
2861 6af0bf9c bellard
        GEN_LOAD_REG_TN(T0, rt);
2862 8c0fdd85 ths
        gen_mtc0(ctx, rd, ctx->opcode & 0x7);
2863 6af0bf9c bellard
        opn = "mtc0";
2864 6af0bf9c bellard
        break;
2865 6af0bf9c bellard
#if defined(MIPS_USES_R4K_TLB)
2866 6af0bf9c bellard
    case OPC_TLBWI:
2867 6af0bf9c bellard
        gen_op_tlbwi();
2868 6af0bf9c bellard
        opn = "tlbwi";
2869 6af0bf9c bellard
        break;
2870 6af0bf9c bellard
    case OPC_TLBWR:
2871 6af0bf9c bellard
        gen_op_tlbwr();
2872 6af0bf9c bellard
        opn = "tlbwr";
2873 6af0bf9c bellard
        break;
2874 6af0bf9c bellard
    case OPC_TLBP:
2875 6af0bf9c bellard
        gen_op_tlbp();
2876 6af0bf9c bellard
        opn = "tlbp";
2877 6af0bf9c bellard
        break;
2878 6af0bf9c bellard
    case OPC_TLBR:
2879 6af0bf9c bellard
        gen_op_tlbr();
2880 6af0bf9c bellard
        opn = "tlbr";
2881 6af0bf9c bellard
        break;
2882 6af0bf9c bellard
#endif
2883 6af0bf9c bellard
    case OPC_ERET:
2884 6af0bf9c bellard
        opn = "eret";
2885 6af0bf9c bellard
        save_cpu_state(ctx, 0);
2886 6af0bf9c bellard
        gen_op_eret();
2887 6af0bf9c bellard
        ctx->bstate = BS_EXCP;
2888 6af0bf9c bellard
        break;
2889 6af0bf9c bellard
    case OPC_DERET:
2890 6af0bf9c bellard
        opn = "deret";
2891 6af0bf9c bellard
        if (!(ctx->hflags & MIPS_HFLAG_DM)) {
2892 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
2893 6af0bf9c bellard
        } else {
2894 6af0bf9c bellard
            save_cpu_state(ctx, 0);
2895 6af0bf9c bellard
            gen_op_deret();
2896 6af0bf9c bellard
            ctx->bstate = BS_EXCP;
2897 6af0bf9c bellard
        }
2898 6af0bf9c bellard
        break;
2899 4ad40f36 bellard
    case OPC_WAIT:
2900 4ad40f36 bellard
        opn = "wait";
2901 4ad40f36 bellard
        /* If we get an exception, we want to restart at next instruction */
2902 4ad40f36 bellard
        ctx->pc += 4;
2903 4ad40f36 bellard
        save_cpu_state(ctx, 1);
2904 4ad40f36 bellard
        ctx->pc -= 4;
2905 4ad40f36 bellard
        gen_op_wait();
2906 4ad40f36 bellard
        ctx->bstate = BS_EXCP;
2907 4ad40f36 bellard
        break;
2908 6af0bf9c bellard
    default:
2909 6af0bf9c bellard
        if (loglevel & CPU_LOG_TB_IN_ASM) {
2910 6af0bf9c bellard
            fprintf(logfile, "Invalid CP0 opcode: %08x %03x %03x %03x\n",
2911 6af0bf9c bellard
                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
2912 6af0bf9c bellard
                    ((ctx->opcode >> 16) & 0x1F));
2913 6af0bf9c bellard
        }
2914 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
2915 6af0bf9c bellard
        return;
2916 6af0bf9c bellard
    }
2917 6af0bf9c bellard
    MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
2918 6af0bf9c bellard
}
2919 6af0bf9c bellard
2920 71fb7241 ths
#ifdef MIPS_USES_FPU
2921 71fb7241 ths
2922 6ea83fed bellard
/* CP1 Branches (before delay slot) */
2923 7a387fff ths
static void gen_compute_branch1 (DisasContext *ctx, uint32_t op,
2924 6ea83fed bellard
                                 int32_t offset)
2925 6ea83fed bellard
{
2926 6ea83fed bellard
    target_ulong btarget;
2927 6ea83fed bellard
2928 6ea83fed bellard
    btarget = ctx->pc + 4 + offset;
2929 6ea83fed bellard
2930 7a387fff ths
    switch (op) {
2931 7a387fff ths
    case OPC_BC1F:
2932 6ea83fed bellard
        gen_op_bc1f();
2933 c570fd16 ths
        MIPS_DEBUG("bc1f " TLSZ, btarget);
2934 6ea83fed bellard
        goto not_likely;
2935 7a387fff ths
    case OPC_BC1FL:
2936 6ea83fed bellard
        gen_op_bc1f();
2937 c570fd16 ths
        MIPS_DEBUG("bc1fl " TLSZ, btarget);
2938 6ea83fed bellard
        goto likely;
2939 7a387fff ths
    case OPC_BC1T:
2940 6ea83fed bellard
        gen_op_bc1t();
2941 c570fd16 ths
        MIPS_DEBUG("bc1t " TLSZ, btarget);
2942 6ea83fed bellard
    not_likely:
2943 6ea83fed bellard
        ctx->hflags |= MIPS_HFLAG_BC;
2944 6ea83fed bellard
        break;
2945 7a387fff ths
    case OPC_BC1TL:
2946 6ea83fed bellard
        gen_op_bc1t();
2947 c570fd16 ths
        MIPS_DEBUG("bc1tl " TLSZ, btarget);
2948 6ea83fed bellard
    likely:
2949 6ea83fed bellard
        ctx->hflags |= MIPS_HFLAG_BL;
2950 6ea83fed bellard
        break;
2951 6ea83fed bellard
    default:    
2952 6ea83fed bellard
        MIPS_INVAL("cp1 branch/jump");
2953 7a387fff ths
        generate_exception_err (ctx, EXCP_RI, 1);
2954 6ea83fed bellard
        return;
2955 6ea83fed bellard
    }
2956 6ea83fed bellard
    gen_op_set_bcond();
2957 6ea83fed bellard
2958 c570fd16 ths
    MIPS_DEBUG("enter ds: cond %02x target " TLSZ,
2959 6ea83fed bellard
               ctx->hflags, btarget);
2960 6ea83fed bellard
    ctx->btarget = btarget;
2961 6ea83fed bellard
2962 6ea83fed bellard
    return;
2963 6ea83fed bellard
}
2964 6ea83fed bellard
2965 6af0bf9c bellard
/* Coprocessor 1 (FPU) */
2966 7a387fff ths
static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
2967 6ea83fed bellard
{
2968 7a387fff ths
    const char *opn = "unk";
2969 6ea83fed bellard
2970 6ea83fed bellard
    switch (opc) {
2971 6ea83fed bellard
    case OPC_MFC1:
2972 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
2973 6ea83fed bellard
        gen_op_mfc1();
2974 6ea83fed bellard
        GEN_STORE_TN_REG(rt, T0);
2975 6ea83fed bellard
        opn = "mfc1";
2976 6ea83fed bellard
        break;
2977 6ea83fed bellard
    case OPC_MTC1:
2978 6ea83fed bellard
        GEN_LOAD_REG_TN(T0, rt);
2979 6ea83fed bellard
        gen_op_mtc1();
2980 6ea83fed bellard
        GEN_STORE_FTN_FREG(fs, WT0);
2981 6ea83fed bellard
        opn = "mtc1";
2982 6ea83fed bellard
        break;
2983 6ea83fed bellard
    case OPC_CFC1:
2984 6ea83fed bellard
        if (fs != 0 && fs != 31) {
2985 6ea83fed bellard
            MIPS_INVAL("cfc1 freg");
2986 7a387fff ths
            generate_exception_err (ctx, EXCP_RI, 1);
2987 6ea83fed bellard
            return;
2988 6ea83fed bellard
        }
2989 6ea83fed bellard
        GEN_LOAD_IMM_TN(T1, fs);
2990 6ea83fed bellard
        gen_op_cfc1();
2991 6ea83fed bellard
        GEN_STORE_TN_REG(rt, T0);
2992 6ea83fed bellard
        opn = "cfc1";
2993 6ea83fed bellard
        break;
2994 6ea83fed bellard
    case OPC_CTC1:
2995 7a387fff ths
         if (fs != 0 && fs != 31) {
2996 6ea83fed bellard
            MIPS_INVAL("ctc1 freg");
2997 7a387fff ths
            generate_exception_err (ctx, EXCP_RI, 1);
2998 6ea83fed bellard
            return;
2999 6ea83fed bellard
        }
3000 6ea83fed bellard
        GEN_LOAD_IMM_TN(T1, fs);
3001 6ea83fed bellard
        GEN_LOAD_REG_TN(T0, rt);
3002 6ea83fed bellard
        gen_op_ctc1();
3003 6ea83fed bellard
        opn = "ctc1";
3004 6ea83fed bellard
        break;
3005 6ea83fed bellard
    default:
3006 6ea83fed bellard
        if (loglevel & CPU_LOG_TB_IN_ASM) {
3007 6ea83fed bellard
            fprintf(logfile, "Invalid CP1 opcode: %08x %03x %03x %03x\n",
3008 6ea83fed bellard
                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
3009 6ea83fed bellard
                    ((ctx->opcode >> 16) & 0x1F));
3010 6ea83fed bellard
        }
3011 7a387fff ths
        generate_exception_err (ctx, EXCP_RI, 1);
3012 6ea83fed bellard
        return;
3013 6ea83fed bellard
    }
3014 6ea83fed bellard
    MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
3015 6ea83fed bellard
}
3016 6ea83fed bellard
3017 6ea83fed bellard
/* verify if floating point register is valid; an operation is not defined
3018 6ea83fed bellard
 * if bit 0 of any register specification is set and the FR bit in the
3019 6ea83fed bellard
 * Status register equals zero, since the register numbers specify an
3020 6ea83fed bellard
 * even-odd pair of adjacent coprocessor general registers. When the FR bit
3021 6ea83fed bellard
 * in the Status register equals one, both even and odd register numbers
3022 6ea83fed bellard
 * are valid.
3023 6ea83fed bellard
 * 
3024 6ea83fed bellard
 * Multiple float registers can be checked by calling
3025 6ea83fed bellard
 * CHECK_FR(ctx, freg1 | freg2 | ... | fregN);
3026 6ea83fed bellard
 */
3027 6ea83fed bellard
#define CHECK_FR(ctx, freg) do { \
3028 6ea83fed bellard
        if (!((ctx)->CP0_Status & (1<<CP0St_FR)) && ((freg) & 1)) { \
3029 7a387fff ths
            generate_exception_err (ctx, EXCP_RI, 1); \
3030 6ea83fed bellard
            return; \
3031 6ea83fed bellard
        } \
3032 6ea83fed bellard
    } while(0)
3033 6ea83fed bellard
3034 6ea83fed bellard
#define FOP(func, fmt) (((fmt) << 21) | (func))
3035 6ea83fed bellard
3036 7a387fff ths
static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, int fs, int fd)
3037 6ea83fed bellard
{
3038 7a387fff ths
    const char *opn = "unk";
3039 6ea83fed bellard
    const char *condnames[] = {
3040 6ea83fed bellard
            "c.f",
3041 6ea83fed bellard
            "c.un",
3042 6ea83fed bellard
            "c.eq",
3043 6ea83fed bellard
            "c.ueq",
3044 6ea83fed bellard
            "c.olt",
3045 6ea83fed bellard
            "c.ult",
3046 6ea83fed bellard
            "c.ole",
3047 6ea83fed bellard
            "c.ule",
3048 6ea83fed bellard
            "c.sf",
3049 6ea83fed bellard
            "c.ngle",
3050 6ea83fed bellard
            "c.seq",
3051 6ea83fed bellard
            "c.ngl",
3052 6ea83fed bellard
            "c.lt",
3053 6ea83fed bellard
            "c.nge",
3054 6ea83fed bellard
            "c.le",
3055 6ea83fed bellard
            "c.ngt",
3056 6ea83fed bellard
    };
3057 6ea83fed bellard
    int binary = 0;
3058 7a387fff ths
    uint32_t func = ctx->opcode & 0x3f;
3059 7a387fff ths
3060 6ea83fed bellard
    switch (ctx->opcode & FOP(0x3f, 0x1f)) {
3061 6ea83fed bellard
    case FOP(0, 17):
3062 6ea83fed bellard
        CHECK_FR(ctx, fs | ft | fd);
3063 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, fs);
3064 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT1, ft);
3065 6ea83fed bellard
        gen_op_float_add_d();
3066 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, DT2);
3067 6ea83fed bellard
        opn = "add.d";
3068 6ea83fed bellard
        binary = 1;
3069 6ea83fed bellard
        break;
3070 6ea83fed bellard
    case FOP(1, 17):
3071 6ea83fed bellard
        CHECK_FR(ctx, fs | ft | fd);
3072 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, fs);
3073 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT1, ft);
3074 6ea83fed bellard
        gen_op_float_sub_d();
3075 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, DT2);
3076 6ea83fed bellard
        opn = "sub.d";
3077 6ea83fed bellard
        binary = 1;
3078 6ea83fed bellard
        break;
3079 6ea83fed bellard
    case FOP(2, 17):
3080 6ea83fed bellard
        CHECK_FR(ctx, fs | ft | fd);
3081 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, fs);
3082 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT1, ft);
3083 6ea83fed bellard
        gen_op_float_mul_d();
3084 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, DT2);
3085 6ea83fed bellard
        opn = "mul.d";
3086 6ea83fed bellard
        binary = 1;
3087 6ea83fed bellard
        break;
3088 6ea83fed bellard
    case FOP(3, 17):
3089 6ea83fed bellard
        CHECK_FR(ctx, fs | ft | fd);
3090 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, fs);
3091 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT1, ft);
3092 6ea83fed bellard
        gen_op_float_div_d();
3093 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, DT2);
3094 6ea83fed bellard
        opn = "div.d";
3095 6ea83fed bellard
        binary = 1;
3096 6ea83fed bellard
        break;
3097 6ea83fed bellard
    case FOP(4, 17):
3098 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
3099 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, fs);
3100 6ea83fed bellard
        gen_op_float_sqrt_d();
3101 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, DT2);
3102 6ea83fed bellard
        opn = "sqrt.d";
3103 6ea83fed bellard
        break;
3104 6ea83fed bellard
    case FOP(5, 17):
3105 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
3106 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, fs);
3107 6ea83fed bellard
        gen_op_float_abs_d();
3108 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, DT2);
3109 6ea83fed bellard
        opn = "abs.d";
3110 6ea83fed bellard
        break;
3111 6ea83fed bellard
    case FOP(6, 17):
3112 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
3113 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, fs);
3114 6ea83fed bellard
        gen_op_float_mov_d();
3115 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, DT2);
3116 6ea83fed bellard
        opn = "mov.d";
3117 6ea83fed bellard
        break;
3118 6ea83fed bellard
    case FOP(7, 17):
3119 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
3120 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, fs);
3121 6ea83fed bellard
        gen_op_float_chs_d();
3122 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, DT2);
3123 6ea83fed bellard
        opn = "neg.d";
3124 6ea83fed bellard
        break;
3125 6ea83fed bellard
    /*  8 - round.l */
3126 6ea83fed bellard
    /*  9 - trunc.l */
3127 6ea83fed bellard
    /* 10 - ceil.l  */
3128 6ea83fed bellard
    /* 11 - floor.l */
3129 6ea83fed bellard
    case FOP(12, 17):
3130 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
3131 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, fs);
3132 6ea83fed bellard
        gen_op_float_roundw_d();
3133 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
3134 6ea83fed bellard
        opn = "round.w.d";
3135 6ea83fed bellard
        break;
3136 6ea83fed bellard
    case FOP(13, 17):
3137 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
3138 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, fs);
3139 6ea83fed bellard
        gen_op_float_truncw_d();
3140 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
3141 6ea83fed bellard
        opn = "trunc.w.d";
3142 6ea83fed bellard
        break;
3143 6ea83fed bellard
    case FOP(14, 17):
3144 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
3145 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, fs);
3146 6ea83fed bellard
        gen_op_float_ceilw_d();
3147 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
3148 6ea83fed bellard
        opn = "ceil.w.d";
3149 6ea83fed bellard
        break;
3150 6ea83fed bellard
    case FOP(15, 17):
3151 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
3152 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, fs);
3153 6ea83fed bellard
        gen_op_float_floorw_d();
3154 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
3155 7a387fff ths
        opn = "floor.w.d";
3156 6ea83fed bellard
        break;
3157 dd016883 bellard
    case FOP(33, 16): /* cvt.d.s */
3158 dd016883 bellard
        CHECK_FR(ctx, fs | fd);
3159 dd016883 bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
3160 dd016883 bellard
        gen_op_float_cvtd_s();
3161 dd016883 bellard
        GEN_STORE_FTN_FREG(fd, DT2);
3162 dd016883 bellard
        opn = "cvt.d.s";
3163 dd016883 bellard
        break;
3164 6ea83fed bellard
    case FOP(33, 20): /* cvt.d.w */
3165 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
3166 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
3167 6ea83fed bellard
        gen_op_float_cvtd_w();
3168 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, DT2);
3169 6ea83fed bellard
        opn = "cvt.d.w";
3170 6ea83fed bellard
        break;
3171 6ea83fed bellard
    case FOP(48, 17):
3172 6ea83fed bellard
    case FOP(49, 17):
3173 6ea83fed bellard
    case FOP(50, 17):
3174 6ea83fed bellard
    case FOP(51, 17):
3175 6ea83fed bellard
    case FOP(52, 17):
3176 6ea83fed bellard
    case FOP(53, 17):
3177 6ea83fed bellard
    case FOP(54, 17):
3178 6ea83fed bellard
    case FOP(55, 17):
3179 6ea83fed bellard
    case FOP(56, 17):
3180 6ea83fed bellard
    case FOP(57, 17):
3181 6ea83fed bellard
    case FOP(58, 17):
3182 6ea83fed bellard
    case FOP(59, 17):
3183 6ea83fed bellard
    case FOP(60, 17):
3184 6ea83fed bellard
    case FOP(61, 17):
3185 6ea83fed bellard
    case FOP(62, 17):
3186 6ea83fed bellard
    case FOP(63, 17):
3187 6ea83fed bellard
        CHECK_FR(ctx, fs | ft);
3188 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, fs);
3189 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT1, ft);
3190 6ea83fed bellard
        gen_cmp_d(func-48);
3191 6ea83fed bellard
        opn = condnames[func-48];
3192 6ea83fed bellard
        break;
3193 6ea83fed bellard
    case FOP(0, 16):
3194 6ea83fed bellard
        CHECK_FR(ctx, fs | ft | fd);
3195 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
3196 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT1, ft);
3197 6ea83fed bellard
        gen_op_float_add_s();
3198 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
3199 6ea83fed bellard
        opn = "add.s";
3200 6ea83fed bellard
        binary = 1;
3201 6ea83fed bellard
        break;
3202 6ea83fed bellard
    case FOP(1, 16):
3203 6ea83fed bellard
        CHECK_FR(ctx, fs | ft | fd);
3204 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
3205 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT1, ft);
3206 6ea83fed bellard
        gen_op_float_sub_s();
3207 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
3208 6ea83fed bellard
        opn = "sub.s";
3209 6ea83fed bellard
        binary = 1;
3210 6ea83fed bellard
        break;
3211 6ea83fed bellard
    case FOP(2, 16):
3212 6ea83fed bellard
        CHECK_FR(ctx, fs | ft | fd);
3213 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
3214 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT1, ft);
3215 6ea83fed bellard
        gen_op_float_mul_s();
3216 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
3217 6ea83fed bellard
        opn = "mul.s";
3218 6ea83fed bellard
        binary = 1;
3219 6ea83fed bellard
        break;
3220 6ea83fed bellard
    case FOP(3, 16):
3221 6ea83fed bellard
        CHECK_FR(ctx, fs | ft | fd);
3222 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
3223 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT1, ft);
3224 6ea83fed bellard
        gen_op_float_div_s();
3225 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
3226 6ea83fed bellard
        opn = "div.s";
3227 6ea83fed bellard
        binary = 1;
3228 6ea83fed bellard
        break;
3229 6ea83fed bellard
    case FOP(4, 16):
3230 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
3231 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
3232 6ea83fed bellard
        gen_op_float_sqrt_s();
3233 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
3234 6ea83fed bellard
        opn = "sqrt.s";
3235 6ea83fed bellard
        break;
3236 6ea83fed bellard
    case FOP(5, 16):
3237 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
3238 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
3239 6ea83fed bellard
        gen_op_float_abs_s();
3240 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
3241 6ea83fed bellard
        opn = "abs.s";
3242 6ea83fed bellard
        break;
3243 6ea83fed bellard
    case FOP(6, 16):
3244 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
3245 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
3246 6ea83fed bellard
        gen_op_float_mov_s();
3247 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
3248 6ea83fed bellard
        opn = "mov.s";
3249 6ea83fed bellard
        break;
3250 6ea83fed bellard
    case FOP(7, 16):
3251 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
3252 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
3253 6ea83fed bellard
        gen_op_float_chs_s();
3254 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
3255 6ea83fed bellard
        opn = "neg.s";
3256 6ea83fed bellard
        break;
3257 6ea83fed bellard
    case FOP(12, 16):
3258 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
3259 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
3260 6ea83fed bellard
        gen_op_float_roundw_s();
3261 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
3262 6ea83fed bellard
        opn = "round.w.s";
3263 6ea83fed bellard
        break;
3264 6ea83fed bellard
    case FOP(13, 16):
3265 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
3266 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
3267 6ea83fed bellard
        gen_op_float_truncw_s();
3268 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
3269 6ea83fed bellard
        opn = "trunc.w.s";
3270 6ea83fed bellard
        break;
3271 dd016883 bellard
    case FOP(32, 17): /* cvt.s.d */
3272 dd016883 bellard
        CHECK_FR(ctx, fs | fd);
3273 417f38f0 pbrook
        GEN_LOAD_FREG_FTN(DT0, fs);
3274 dd016883 bellard
        gen_op_float_cvts_d();
3275 dd016883 bellard
        GEN_STORE_FTN_FREG(fd, WT2);
3276 dd016883 bellard
        opn = "cvt.s.d";
3277 dd016883 bellard
        break;
3278 6ea83fed bellard
    case FOP(32, 20): /* cvt.s.w */
3279 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
3280 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
3281 6ea83fed bellard
        gen_op_float_cvts_w();
3282 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
3283 6ea83fed bellard
        opn = "cvt.s.w";
3284 6ea83fed bellard
        break;
3285 6ea83fed bellard
    case FOP(36, 16): /* cvt.w.s */
3286 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
3287 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
3288 6ea83fed bellard
        gen_op_float_cvtw_s();
3289 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
3290 6ea83fed bellard
        opn = "cvt.w.s";
3291 6ea83fed bellard
        break;
3292 6ea83fed bellard
    case FOP(36, 17): /* cvt.w.d */
3293 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
3294 417f38f0 pbrook
        GEN_LOAD_FREG_FTN(DT0, fs);
3295 6ea83fed bellard
        gen_op_float_cvtw_d();
3296 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
3297 6ea83fed bellard
        opn = "cvt.w.d";
3298 6ea83fed bellard
        break;
3299 6ea83fed bellard
    case FOP(48, 16):
3300 6ea83fed bellard
    case FOP(49, 16):
3301 6ea83fed bellard
    case FOP(50, 16):
3302 6ea83fed bellard
    case FOP(51, 16):
3303 6ea83fed bellard
    case FOP(52, 16):
3304 6ea83fed bellard
    case FOP(53, 16):
3305 6ea83fed bellard
    case FOP(54, 16):
3306 6ea83fed bellard
    case FOP(55, 16):
3307 6ea83fed bellard
    case FOP(56, 16):
3308 6ea83fed bellard
    case FOP(57, 16):
3309 6ea83fed bellard
    case FOP(58, 16):
3310 6ea83fed bellard
    case FOP(59, 16):
3311 6ea83fed bellard
    case FOP(60, 16):
3312 6ea83fed bellard
    case FOP(61, 16):
3313 6ea83fed bellard
    case FOP(62, 16):
3314 6ea83fed bellard
    case FOP(63, 16):
3315 6ea83fed bellard
        CHECK_FR(ctx, fs | ft);
3316 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
3317 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT1, ft);
3318 6ea83fed bellard
        gen_cmp_s(func-48);
3319 6ea83fed bellard
        opn = condnames[func-48];
3320 6ea83fed bellard
        break;
3321 6ea83fed bellard
    default:    
3322 6ea83fed bellard
        if (loglevel & CPU_LOG_TB_IN_ASM) {
3323 7a387fff ths
            fprintf(logfile, "Invalid FP arith function: %08x %03x %03x %03x\n",
3324 6ea83fed bellard
                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
3325 6ea83fed bellard
                    ((ctx->opcode >> 16) & 0x1F));
3326 6ea83fed bellard
        }
3327 7a387fff ths
        generate_exception_err (ctx, EXCP_RI, 1);
3328 6ea83fed bellard
        return;
3329 6ea83fed bellard
    }
3330 6ea83fed bellard
    if (binary)
3331 6ea83fed bellard
        MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
3332 6ea83fed bellard
    else
3333 6ea83fed bellard
        MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
3334 6ea83fed bellard
}
3335 6af0bf9c bellard
3336 7a387fff ths
static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
3337 7a387fff ths
{
3338 7a387fff ths
    uint32_t ccbit;
3339 7a387fff ths
3340 7a387fff ths
    if (cc)
3341 7a387fff ths
        ccbit = 1 << (24 + cc);
3342 7a387fff ths
    else
3343 7a387fff ths
        ccbit = 1 << 23;
3344 7a387fff ths
    if (!tf)
3345 7a387fff ths
        gen_op_movf(ccbit, rd, rs);
3346 7a387fff ths
    else
3347 7a387fff ths
       gen_op_movt(ccbit, rd, rs);
3348 7a387fff ths
}
3349 7a387fff ths
3350 71fb7241 ths
#endif /* MIPS_USES_FPU */
3351 71fb7241 ths
3352 7a387fff ths
/* ISA extensions (ASEs) */
3353 6af0bf9c bellard
/* MIPS16 extension to MIPS32 */
3354 6af0bf9c bellard
/* SmartMIPS extension to MIPS32 */
3355 6af0bf9c bellard
3356 7a387fff ths
#ifdef MIPS_HAS_MIPS64
3357 6af0bf9c bellard
/* Coprocessor 3 (FPU) */
3358 6af0bf9c bellard
3359 6af0bf9c bellard
/* MDMX extension to MIPS64 */
3360 6af0bf9c bellard
/* MIPS-3D extension to MIPS64 */
3361 6af0bf9c bellard
3362 6af0bf9c bellard
#endif
3363 6af0bf9c bellard
3364 c53be334 bellard
static void gen_blikely(DisasContext *ctx)
3365 c53be334 bellard
{
3366 eeef26cd bellard
    int l1;
3367 eeef26cd bellard
    l1 = gen_new_label();
3368 eeef26cd bellard
    gen_op_jnz_T2(l1);
3369 4ad40f36 bellard
    gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
3370 eeef26cd bellard
    gen_goto_tb(ctx, 1, ctx->pc + 4);
3371 eeef26cd bellard
    gen_set_label(l1);
3372 c53be334 bellard
}
3373 c53be334 bellard
3374 6af0bf9c bellard
static void decode_opc (DisasContext *ctx)
3375 6af0bf9c bellard
{
3376 6af0bf9c bellard
    int32_t offset;
3377 6af0bf9c bellard
    int rs, rt, rd, sa;
3378 7a387fff ths
    uint32_t op, op1, op2;
3379 6af0bf9c bellard
    int16_t imm;
3380 6af0bf9c bellard
3381 d796321b bellard
    /* make sure instructions are on a word boundary */
3382 d796321b bellard
    if (ctx->pc & 0x3) {
3383 d796321b bellard
        generate_exception(ctx, EXCP_AdEL);
3384 d796321b bellard
        return;
3385 d796321b bellard
    }
3386 d796321b bellard
3387 4ad40f36 bellard
    if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
3388 6af0bf9c bellard
        /* Handle blikely not taken case */
3389 c570fd16 ths
        MIPS_DEBUG("blikely condition (" TLSZ ")", ctx->pc + 4);
3390 c53be334 bellard
        gen_blikely(ctx);
3391 6af0bf9c bellard
    }
3392 7a387fff ths
    op = MASK_OP_MAJOR(ctx->opcode);
3393 7a387fff ths
    rs = (ctx->opcode >> 21) & 0x1f;
3394 7a387fff ths
    rt = (ctx->opcode >> 16) & 0x1f;
3395 7a387fff ths
    rd = (ctx->opcode >> 11) & 0x1f;
3396 7a387fff ths
    sa = (ctx->opcode >> 6) & 0x1f;
3397 6af0bf9c bellard
    imm = (int16_t)ctx->opcode;
3398 6af0bf9c bellard
    switch (op) {
3399 7a387fff ths
    case OPC_SPECIAL:
3400 7a387fff ths
        op1 = MASK_SPECIAL(ctx->opcode);
3401 6af0bf9c bellard
        switch (op1) {
3402 7a387fff ths
        case OPC_SLL:          /* Arithmetic with immediate */
3403 7a387fff ths
        case OPC_SRL ... OPC_SRA:
3404 7a387fff ths
            gen_arith_imm(ctx, op1, rd, rt, sa);
3405 7a387fff ths
            break;
3406 7a387fff ths
        case OPC_SLLV:         /* Arithmetic */
3407 7a387fff ths
        case OPC_SRLV ... OPC_SRAV:
3408 7a387fff ths
        case OPC_MOVZ ... OPC_MOVN:
3409 7a387fff ths
        case OPC_ADD ... OPC_NOR:
3410 7a387fff ths
        case OPC_SLT ... OPC_SLTU:
3411 7a387fff ths
            gen_arith(ctx, op1, rd, rs, rt);
3412 7a387fff ths
            break;
3413 7a387fff ths
        case OPC_MULT ... OPC_DIVU:
3414 7a387fff ths
            gen_muldiv(ctx, op1, rs, rt);
3415 7a387fff ths
            break;
3416 7a387fff ths
        case OPC_JR ... OPC_JALR:
3417 7a387fff ths
            gen_compute_branch(ctx, op1, rs, rd, sa);
3418 6af0bf9c bellard
            return;
3419 7a387fff ths
        case OPC_TGE ... OPC_TEQ: /* Traps */
3420 7a387fff ths
        case OPC_TNE:
3421 7a387fff ths
            gen_trap(ctx, op1, rs, rt, -1);
3422 6af0bf9c bellard
            break;
3423 7a387fff ths
        case OPC_MFHI:          /* Move from HI/LO */
3424 7a387fff ths
        case OPC_MFLO:
3425 7a387fff ths
            gen_HILO(ctx, op1, rd);
3426 6af0bf9c bellard
            break;
3427 7a387fff ths
        case OPC_MTHI:
3428 7a387fff ths
        case OPC_MTLO:          /* Move to HI/LO */
3429 7a387fff ths
            gen_HILO(ctx, op1, rs);
3430 6af0bf9c bellard
            break;
3431 7a387fff ths
        case OPC_PMON:          /* Pmon entry point */
3432 7a387fff ths
            gen_op_pmon(sa);
3433 7a387fff ths
            break;
3434 7a387fff ths
        case OPC_SYSCALL:
3435 6af0bf9c bellard
            generate_exception(ctx, EXCP_SYSCALL);
3436 7a387fff ths
            ctx->bstate = BS_EXCP;
3437 6af0bf9c bellard
            break;
3438 7a387fff ths
        case OPC_BREAK:
3439 6af0bf9c bellard
            generate_exception(ctx, EXCP_BREAK);
3440 6af0bf9c bellard
            break;
3441 7a387fff ths
        case OPC_SPIM:        /* SPIM ? */
3442 7a387fff ths
           /* Implemented as RI exception for now. */
3443 7a387fff ths
            MIPS_INVAL("spim (unofficial)");
3444 7a387fff ths
            generate_exception(ctx, EXCP_RI);
3445 6af0bf9c bellard
            break;
3446 7a387fff ths
        case OPC_SYNC:
3447 7a387fff ths
            /* Treat as a noop. */
3448 6af0bf9c bellard
            break;
3449 4ad40f36 bellard
3450 71fb7241 ths
#ifdef MIPS_USES_FPU
3451 7a387fff ths
        case OPC_MOVCI:
3452 7a387fff ths
            gen_op_cp1_enabled();
3453 7a387fff ths
            gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
3454 7a387fff ths
                      (ctx->opcode >> 16) & 1);
3455 4ad40f36 bellard
            break;
3456 71fb7241 ths
#endif
3457 4ad40f36 bellard
3458 7a387fff ths
#ifdef MIPS_HAS_MIPS64
3459 7a387fff ths
       /* MIPS64 specific opcodes */
3460 7a387fff ths
        case OPC_DSLL:
3461 7a387fff ths
        case OPC_DSRL ... OPC_DSRA:
3462 7a387fff ths
        case OPC_DSLL32:
3463 7a387fff ths
        case OPC_DSRL32 ... OPC_DSRA32:
3464 7a387fff ths
            gen_arith_imm(ctx, op1, rd, rt, sa);
3465 7a387fff ths
            break;
3466 7a387fff ths
        case OPC_DSLLV:
3467 7a387fff ths
        case OPC_DSRLV ... OPC_DSRAV:
3468 7a387fff ths
        case OPC_DADD ... OPC_DSUBU:
3469 7a387fff ths
            gen_arith(ctx, op1, rd, rs, rt);
3470 7a387fff ths
            break;
3471 7a387fff ths
        case OPC_DMULT ... OPC_DDIVU:
3472 7a387fff ths
            gen_muldiv(ctx, op1, rs, rt);
3473 7a387fff ths
            break;
3474 6af0bf9c bellard
#endif
3475 6af0bf9c bellard
        default:            /* Invalid */
3476 6af0bf9c bellard
            MIPS_INVAL("special");
3477 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
3478 6af0bf9c bellard
            break;
3479 6af0bf9c bellard
        }
3480 6af0bf9c bellard
        break;
3481 7a387fff ths
    case OPC_SPECIAL2:
3482 7a387fff ths
        op1 = MASK_SPECIAL2(ctx->opcode);
3483 6af0bf9c bellard
        switch (op1) {
3484 7a387fff ths
        case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
3485 7a387fff ths
        case OPC_MSUB ... OPC_MSUBU:
3486 7a387fff ths
            gen_muldiv(ctx, op1, rs, rt);
3487 6af0bf9c bellard
            break;
3488 7a387fff ths
        case OPC_MUL:
3489 7a387fff ths
            gen_arith(ctx, op1, rd, rs, rt);
3490 6af0bf9c bellard
            break;
3491 7a387fff ths
        case OPC_CLZ ... OPC_CLO:
3492 7a387fff ths
            gen_cl(ctx, op1, rd, rs);
3493 6af0bf9c bellard
            break;
3494 7a387fff ths
        case OPC_SDBBP:
3495 6af0bf9c bellard
            /* XXX: not clear which exception should be raised
3496 6af0bf9c bellard
             *      when in debug mode...
3497 6af0bf9c bellard
             */
3498 6af0bf9c bellard
            if (!(ctx->hflags & MIPS_HFLAG_DM)) {
3499 6af0bf9c bellard
                generate_exception(ctx, EXCP_DBp);
3500 6af0bf9c bellard
            } else {
3501 6af0bf9c bellard
                generate_exception(ctx, EXCP_DBp);
3502 6af0bf9c bellard
            }
3503 6af0bf9c bellard
            /* Treat as a noop */
3504 6af0bf9c bellard
            break;
3505 7a387fff ths
#ifdef MIPS_HAS_MIPS64
3506 7a387fff ths
        case OPC_DCLZ ... OPC_DCLO:
3507 7a387fff ths
            gen_cl(ctx, op1, rd, rs);
3508 7a387fff ths
            break;
3509 7a387fff ths
#endif
3510 6af0bf9c bellard
        default:            /* Invalid */
3511 6af0bf9c bellard
            MIPS_INVAL("special2");
3512 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
3513 6af0bf9c bellard
            break;
3514 6af0bf9c bellard
        }
3515 6af0bf9c bellard
        break;
3516 7a387fff ths
    case OPC_SPECIAL3:
3517 7a387fff ths
        op1 = MASK_SPECIAL3(ctx->opcode);
3518 6af0bf9c bellard
        switch (op1) {
3519 7a387fff ths
        case OPC_EXT:
3520 7a387fff ths
        case OPC_INS:
3521 7a387fff ths
            gen_bitops(ctx, op1, rt, rs, sa, rd);
3522 7a387fff ths
            break;
3523 7a387fff ths
        case OPC_BSHFL:
3524 7a387fff ths
            op2 = MASK_BSHFL(ctx->opcode);
3525 7a387fff ths
            switch (op2) {
3526 7a387fff ths
            case OPC_WSBH:
3527 7a387fff ths
                GEN_LOAD_REG_TN(T1, rt);
3528 7a387fff ths
                gen_op_wsbh();
3529 7a387fff ths
                break;
3530 7a387fff ths
            case OPC_SEB:
3531 7a387fff ths
                GEN_LOAD_REG_TN(T1, rt);
3532 7a387fff ths
                gen_op_seb();
3533 7a387fff ths
                break;
3534 7a387fff ths
            case OPC_SEH:
3535 7a387fff ths
                GEN_LOAD_REG_TN(T1, rt);
3536 7a387fff ths
                gen_op_seh();
3537 7a387fff ths
                break;
3538 7a387fff ths
             default:            /* Invalid */
3539 7a387fff ths
                MIPS_INVAL("bshfl");
3540 7a387fff ths
                generate_exception(ctx, EXCP_RI);
3541 7a387fff ths
                break;
3542 7a387fff ths
           }
3543 7a387fff ths
           GEN_STORE_TN_REG(rd, T0);
3544 7a387fff ths
           break;
3545 7a387fff ths
       case OPC_RDHWR:
3546 7a387fff ths
           switch (rd) {
3547 7a387fff ths
           case 0:
3548 7a387fff ths
               gen_op_rdhwr_cpunum();
3549 7a387fff ths
               break;
3550 7a387fff ths
           case 1:
3551 7a387fff ths
               gen_op_rdhwr_synci_step();
3552 7a387fff ths
               break;
3553 7a387fff ths
           case 2:
3554 7a387fff ths
               gen_op_rdhwr_cc();
3555 7a387fff ths
               break;
3556 7a387fff ths
           case 3:
3557 7a387fff ths
               gen_op_rdhwr_ccres();
3558 7a387fff ths
               break;
3559 7a387fff ths
           default:            /* Invalid */
3560 7a387fff ths
               MIPS_INVAL("rdhwr");
3561 7a387fff ths
               generate_exception(ctx, EXCP_RI);
3562 7a387fff ths
               break;
3563 7a387fff ths
           }
3564 7a387fff ths
           GEN_STORE_TN_REG(rt, T0);
3565 7a387fff ths
           break;
3566 7a387fff ths
#ifdef MIPS_HAS_MIPS64
3567 7a387fff ths
       case OPC_DEXTM ... OPC_DEXT:
3568 7a387fff ths
       case OPC_DINSM ... OPC_DINS:
3569 7a387fff ths
           gen_bitops(ctx, op1, rt, rs, sa, rd);
3570 7a387fff ths
            break;
3571 7a387fff ths
       case OPC_DBSHFL:
3572 7a387fff ths
           op2 = MASK_DBSHFL(ctx->opcode);
3573 7a387fff ths
           switch (op2) {
3574 7a387fff ths
           case OPC_DSBH:
3575 7a387fff ths
               GEN_LOAD_REG_TN(T1, rt);
3576 7a387fff ths
               gen_op_dsbh();
3577 7a387fff ths
               break;
3578 7a387fff ths
           case OPC_DSHD:
3579 7a387fff ths
               GEN_LOAD_REG_TN(T1, rt);
3580 7a387fff ths
               gen_op_dshd();
3581 7a387fff ths
               break;
3582 7a387fff ths
            default:            /* Invalid */
3583 7a387fff ths
                MIPS_INVAL("dbshfl");
3584 7a387fff ths
                generate_exception(ctx, EXCP_RI);
3585 7a387fff ths
                break;
3586 7a387fff ths
           }
3587 7a387fff ths
           GEN_STORE_TN_REG(rd, T0);
3588 7a387fff ths
#endif
3589 7a387fff ths
        default:            /* Invalid */
3590 7a387fff ths
            MIPS_INVAL("special3");
3591 7a387fff ths
            generate_exception(ctx, EXCP_RI);
3592 7a387fff ths
            break;
3593 7a387fff ths
        }
3594 7a387fff ths
        break;
3595 7a387fff ths
    case OPC_REGIMM:
3596 7a387fff ths
        op1 = MASK_REGIMM(ctx->opcode);
3597 7a387fff ths
        switch (op1) {
3598 7a387fff ths
        case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
3599 7a387fff ths
        case OPC_BLTZAL ... OPC_BGEZALL:
3600 7a387fff ths
            gen_compute_branch(ctx, op1, rs, -1, imm << 2);
3601 6af0bf9c bellard
            return;
3602 7a387fff ths
        case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
3603 7a387fff ths
        case OPC_TNEI:
3604 7a387fff ths
            gen_trap(ctx, op1, rs, -1, imm);
3605 7a387fff ths
            break;
3606 7a387fff ths
        case OPC_SYNCI:
3607 7a387fff ths
           /* treat as noop */
3608 6af0bf9c bellard
            break;
3609 6af0bf9c bellard
        default:            /* Invalid */
3610 6af0bf9c bellard
            MIPS_INVAL("REGIMM");
3611 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
3612 6af0bf9c bellard
            break;
3613 6af0bf9c bellard
        }
3614 6af0bf9c bellard
        break;
3615 7a387fff ths
    case OPC_CP0:
3616 7a387fff ths
        op1 = MASK_CP0(ctx->opcode);
3617 6af0bf9c bellard
        switch (op1) {
3618 7a387fff ths
        case OPC_MFC0:
3619 7a387fff ths
        case OPC_MTC0:
3620 7a387fff ths
#ifdef MIPS_HAS_MIPS64
3621 7a387fff ths
        case OPC_DMFC0:
3622 7a387fff ths
        case OPC_DMTC0:
3623 7a387fff ths
#endif
3624 7a387fff ths
            gen_cp0(ctx, op1, rt, rd);
3625 7a387fff ths
            break;
3626 7a387fff ths
        case OPC_C0_FIRST ... OPC_C0_LAST:
3627 7a387fff ths
            gen_cp0(ctx, MASK_C0(ctx->opcode), rt, rd);
3628 7a387fff ths
            break;
3629 7a387fff ths
        case OPC_MFMC0:
3630 7a387fff ths
            op2 = MASK_MFMC0(ctx->opcode);
3631 7a387fff ths
            switch (op2) {
3632 7a387fff ths
            case OPC_DI:
3633 7a387fff ths
                gen_op_di();
3634 7a387fff ths
                /* Stop translation as we may have switched the execution mode */
3635 7a387fff ths
                ctx->bstate = BS_STOP;
3636 7a387fff ths
                break;
3637 7a387fff ths
            case OPC_EI:
3638 7a387fff ths
                gen_op_ei();
3639 7a387fff ths
                /* Stop translation as we may have switched the execution mode */
3640 7a387fff ths
                ctx->bstate = BS_STOP;
3641 7a387fff ths
                break;
3642 7a387fff ths
            default:            /* Invalid */
3643 7a387fff ths
                MIPS_INVAL("MFMC0");
3644 7a387fff ths
                generate_exception(ctx, EXCP_RI);
3645 7a387fff ths
                break;
3646 7a387fff ths
            }
3647 7a387fff ths
            GEN_STORE_TN_REG(rt, T0);
3648 6af0bf9c bellard
            break;
3649 7a387fff ths
        /* Shadow registers (not implemented). */
3650 7a387fff ths
        case OPC_RDPGPR:
3651 7a387fff ths
        case OPC_WRPGPR:
3652 6af0bf9c bellard
        default:
3653 7a387fff ths
            generate_exception(ctx, EXCP_RI);
3654 6af0bf9c bellard
            break;
3655 6af0bf9c bellard
        }
3656 6af0bf9c bellard
        break;
3657 7a387fff ths
    case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
3658 7a387fff ths
         gen_arith_imm(ctx, op, rt, rs, imm);
3659 7a387fff ths
         break;
3660 7a387fff ths
    case OPC_J ... OPC_JAL: /* Jump */
3661 7a387fff ths
         offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
3662 7a387fff ths
         gen_compute_branch(ctx, op, rs, rt, offset);
3663 7a387fff ths
         return;
3664 7a387fff ths
    case OPC_BEQ ... OPC_BGTZ: /* Branch */
3665 7a387fff ths
    case OPC_BEQL ... OPC_BGTZL:
3666 7a387fff ths
         gen_compute_branch(ctx, op, rs, rt, imm << 2);
3667 7a387fff ths
         return;
3668 7a387fff ths
    case OPC_LB ... OPC_LWR: /* Load and stores */
3669 7a387fff ths
    case OPC_SB ... OPC_SW:
3670 7a387fff ths
    case OPC_SWR:
3671 7a387fff ths
    case OPC_LL:
3672 7a387fff ths
    case OPC_SC:
3673 7a387fff ths
         gen_ldst(ctx, op, rt, rs, imm);
3674 7a387fff ths
         break;
3675 7a387fff ths
    case OPC_CACHE:
3676 7a387fff ths
         /* Treat as a noop */
3677 7a387fff ths
         break;
3678 7a387fff ths
    case OPC_PREF:
3679 6af0bf9c bellard
        /* Treat as a noop */
3680 6af0bf9c bellard
        break;
3681 4ad40f36 bellard
3682 4ad40f36 bellard
    /* Floating point.  */
3683 7a387fff ths
    case OPC_LWC1:
3684 7a387fff ths
    case OPC_LDC1:
3685 7a387fff ths
    case OPC_SWC1:
3686 7a387fff ths
    case OPC_SDC1:
3687 6ea83fed bellard
#if defined(MIPS_USES_FPU)
3688 417f38f0 pbrook
        save_cpu_state(ctx, 1);
3689 6ea83fed bellard
        gen_op_cp1_enabled();
3690 6ea83fed bellard
        gen_flt_ldst(ctx, op, rt, rs, imm);
3691 6ea83fed bellard
#else
3692 6ea83fed bellard
        generate_exception_err(ctx, EXCP_CpU, 1);
3693 6ea83fed bellard
#endif
3694 6ea83fed bellard
        break;
3695 6ea83fed bellard
3696 7a387fff ths
    case OPC_CP1:
3697 6af0bf9c bellard
#if defined(MIPS_USES_FPU)
3698 417f38f0 pbrook
        save_cpu_state(ctx, 1);
3699 6ea83fed bellard
        gen_op_cp1_enabled();
3700 7a387fff ths
        op1 = MASK_CP1(ctx->opcode);
3701 6ea83fed bellard
        switch (op1) {
3702 7a387fff ths
        case OPC_MFC1:
3703 7a387fff ths
        case OPC_CFC1:
3704 7a387fff ths
        case OPC_MTC1:
3705 7a387fff ths
        case OPC_CTC1:
3706 7a387fff ths
            gen_cp1(ctx, op1, rt, rd);
3707 7a387fff ths
            break;
3708 7a387fff ths
        case OPC_BC1:
3709 7a387fff ths
            gen_compute_branch1(ctx, MASK_CP1_BCOND(ctx->opcode), imm << 2);
3710 6ea83fed bellard
            return;
3711 7a387fff ths
        case OPC_S_FMT:
3712 7a387fff ths
        case OPC_D_FMT:
3713 7a387fff ths
        case OPC_W_FMT:
3714 7a387fff ths
        case OPC_L_FMT:
3715 7a387fff ths
            gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa);
3716 6ea83fed bellard
            break;
3717 6ea83fed bellard
        default:
3718 6ea83fed bellard
            generate_exception_err(ctx, EXCP_RI, 1);
3719 6ea83fed bellard
            break;
3720 6ea83fed bellard
        }
3721 4ad40f36 bellard
#else
3722 4ad40f36 bellard
        generate_exception_err(ctx, EXCP_CpU, 1);
3723 6af0bf9c bellard
#endif
3724 4ad40f36 bellard
        break;
3725 4ad40f36 bellard
3726 4ad40f36 bellard
    /* COP2.  */
3727 7a387fff ths
    case OPC_LWC2:
3728 7a387fff ths
    case OPC_LDC2:
3729 7a387fff ths
    case OPC_SWC2:
3730 7a387fff ths
    case OPC_SDC2:
3731 7a387fff ths
    case OPC_CP2:
3732 7a387fff ths
        /* COP2: Not implemented. */
3733 4ad40f36 bellard
        generate_exception_err(ctx, EXCP_CpU, 2);
3734 4ad40f36 bellard
        break;
3735 4ad40f36 bellard
3736 71fb7241 ths
#ifdef MIPS_USES_FPU
3737 7a387fff ths
    case OPC_CP3:
3738 7a387fff ths
        gen_op_cp1_enabled();
3739 7a387fff ths
        op1 = MASK_CP3(ctx->opcode);
3740 7a387fff ths
        switch (op1) {
3741 6af0bf9c bellard
        /* Not implemented */
3742 7a387fff ths
        default:
3743 7a387fff ths
            generate_exception_err(ctx, EXCP_RI, 1);
3744 7a387fff ths
            break;
3745 7a387fff ths
        }
3746 4ad40f36 bellard
        break;
3747 71fb7241 ths
#endif
3748 4ad40f36 bellard
3749 7a387fff ths
#ifdef MIPS_HAS_MIPS64
3750 7a387fff ths
    /* MIPS64 opcodes */
3751 7a387fff ths
    case OPC_LWU:
3752 7a387fff ths
    case OPC_LDL ... OPC_LDR:
3753 7a387fff ths
    case OPC_SDL ... OPC_SDR:
3754 7a387fff ths
    case OPC_LLD:
3755 7a387fff ths
    case OPC_LD:
3756 7a387fff ths
    case OPC_SCD:
3757 7a387fff ths
    case OPC_SD:
3758 7a387fff ths
        gen_ldst(ctx, op, rt, rs, imm);
3759 7a387fff ths
        break;
3760 7a387fff ths
    case OPC_DADDI ... OPC_DADDIU:
3761 7a387fff ths
        gen_arith_imm(ctx, op, rt, rs, imm);
3762 7a387fff ths
        break;
3763 6af0bf9c bellard
#endif
3764 7a387fff ths
#ifdef MIPS_HAS_MIPS16
3765 7a387fff ths
    case OPC_JALX:
3766 7a387fff ths
        /* MIPS16: Not implemented. */
3767 7a387fff ths
#endif
3768 7a387fff ths
#ifdef MIPS_HAS_MDMX
3769 7a387fff ths
    case OPC_MDMX:
3770 7a387fff ths
        /* MDMX: Not implemented. */
3771 6af0bf9c bellard
#endif
3772 6af0bf9c bellard
    default:            /* Invalid */
3773 6af0bf9c bellard
        MIPS_INVAL("");
3774 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
3775 6af0bf9c bellard
        break;
3776 6af0bf9c bellard
    }
3777 4ad40f36 bellard
    if (ctx->hflags & MIPS_HFLAG_BMASK) {
3778 6af0bf9c bellard
        int hflags = ctx->hflags;
3779 6af0bf9c bellard
        /* Branches completion */
3780 4ad40f36 bellard
        ctx->hflags &= ~MIPS_HFLAG_BMASK;
3781 6af0bf9c bellard
        ctx->bstate = BS_BRANCH;
3782 6af0bf9c bellard
        save_cpu_state(ctx, 0);
3783 6af0bf9c bellard
        switch (hflags & MIPS_HFLAG_BMASK) {
3784 6af0bf9c bellard
        case MIPS_HFLAG_B:
3785 6af0bf9c bellard
            /* unconditional branch */
3786 6af0bf9c bellard
            MIPS_DEBUG("unconditional branch");
3787 6e256c93 bellard
            gen_goto_tb(ctx, 0, ctx->btarget);
3788 6af0bf9c bellard
            break;
3789 6af0bf9c bellard
        case MIPS_HFLAG_BL:
3790 6af0bf9c bellard
            /* blikely taken case */
3791 6af0bf9c bellard
            MIPS_DEBUG("blikely branch taken");
3792 6e256c93 bellard
            gen_goto_tb(ctx, 0, ctx->btarget);
3793 6af0bf9c bellard
            break;
3794 6af0bf9c bellard
        case MIPS_HFLAG_BC:
3795 6af0bf9c bellard
            /* Conditional branch */
3796 6af0bf9c bellard
            MIPS_DEBUG("conditional branch");
3797 c53be334 bellard
            {
3798 c53be334 bellard
              int l1;
3799 c53be334 bellard
              l1 = gen_new_label();
3800 c53be334 bellard
              gen_op_jnz_T2(l1);
3801 6e256c93 bellard
              gen_goto_tb(ctx, 1, ctx->pc + 4);
3802 eeef26cd bellard
              gen_set_label(l1);
3803 eeef26cd bellard
              gen_goto_tb(ctx, 0, ctx->btarget);
3804 c53be334 bellard
            }
3805 6af0bf9c bellard
            break;
3806 6af0bf9c bellard
        case MIPS_HFLAG_BR:
3807 6af0bf9c bellard
            /* unconditional branch to register */
3808 6af0bf9c bellard
            MIPS_DEBUG("branch to register");
3809 6af0bf9c bellard
            gen_op_breg();
3810 6af0bf9c bellard
            break;
3811 6af0bf9c bellard
        default:
3812 6af0bf9c bellard
            MIPS_DEBUG("unknown branch");
3813 6af0bf9c bellard
            break;
3814 6af0bf9c bellard
        }
3815 6af0bf9c bellard
    }
3816 6af0bf9c bellard
}
3817 6af0bf9c bellard
3818 6af0bf9c bellard
int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
3819 6af0bf9c bellard
                                    int search_pc)
3820 6af0bf9c bellard
{
3821 6af0bf9c bellard
    DisasContext ctx, *ctxp = &ctx;
3822 6af0bf9c bellard
    target_ulong pc_start;
3823 6af0bf9c bellard
    uint16_t *gen_opc_end;
3824 6af0bf9c bellard
    int j, lj = -1;
3825 6af0bf9c bellard
3826 4ad40f36 bellard
    if (search_pc && loglevel)
3827 6ea83fed bellard
        fprintf (logfile, "search pc %d\n", search_pc);
3828 4ad40f36 bellard
3829 6af0bf9c bellard
    pc_start = tb->pc;
3830 6af0bf9c bellard
    gen_opc_ptr = gen_opc_buf;
3831 6af0bf9c bellard
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3832 6af0bf9c bellard
    gen_opparam_ptr = gen_opparam_buf;
3833 c53be334 bellard
    nb_gen_labels = 0;
3834 6af0bf9c bellard
    ctx.pc = pc_start;
3835 4ad40f36 bellard
    ctx.saved_pc = -1;
3836 6af0bf9c bellard
    ctx.tb = tb;
3837 6af0bf9c bellard
    ctx.bstate = BS_NONE;
3838 4ad40f36 bellard
    /* Restore delay slot state from the tb context.  */
3839 4ad40f36 bellard
    ctx.hflags = tb->flags;
3840 6af0bf9c bellard
    ctx.saved_hflags = ctx.hflags;
3841 6af0bf9c bellard
    if (ctx.hflags & MIPS_HFLAG_BR) {
3842 6af0bf9c bellard
        gen_op_restore_breg_target();
3843 6af0bf9c bellard
    } else if (ctx.hflags & MIPS_HFLAG_B) {
3844 6af0bf9c bellard
        ctx.btarget = env->btarget;
3845 6af0bf9c bellard
    } else if (ctx.hflags & MIPS_HFLAG_BMASK) {
3846 6af0bf9c bellard
        /* If we are in the delay slot of a conditional branch,
3847 6af0bf9c bellard
         * restore the branch condition from env->bcond to T2
3848 6af0bf9c bellard
         */
3849 6af0bf9c bellard
        ctx.btarget = env->btarget;
3850 6af0bf9c bellard
        gen_op_restore_bcond();
3851 6af0bf9c bellard
    }
3852 6af0bf9c bellard
#if defined(CONFIG_USER_ONLY)
3853 6af0bf9c bellard
    ctx.mem_idx = 0;
3854 6af0bf9c bellard
#else
3855 3d9fb9fe bellard
    ctx.mem_idx = !((ctx.hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM);
3856 6af0bf9c bellard
#endif
3857 6af0bf9c bellard
    ctx.CP0_Status = env->CP0_Status;
3858 6af0bf9c bellard
#ifdef DEBUG_DISAS
3859 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_CPU) {
3860 6af0bf9c bellard
        fprintf(logfile, "------------------------------------------------\n");
3861 4ad40f36 bellard
        /* FIXME: This may print out stale hflags from env... */
3862 6af0bf9c bellard
        cpu_dump_state(env, logfile, fprintf, 0);
3863 6af0bf9c bellard
    }
3864 6af0bf9c bellard
#endif
3865 6af0bf9c bellard
#if defined MIPS_DEBUG_DISAS
3866 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_IN_ASM)
3867 4ad40f36 bellard
        fprintf(logfile, "\ntb %p super %d cond %04x\n",
3868 4ad40f36 bellard
                tb, ctx.mem_idx, ctx.hflags);
3869 6af0bf9c bellard
#endif
3870 6af0bf9c bellard
    while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
3871 4ad40f36 bellard
        if (env->nb_breakpoints > 0) {
3872 4ad40f36 bellard
            for(j = 0; j < env->nb_breakpoints; j++) {
3873 4ad40f36 bellard
                if (env->breakpoints[j] == ctx.pc) {
3874 4ad40f36 bellard
                    save_cpu_state(ctxp, 1);
3875 4ad40f36 bellard
                    ctx.bstate = BS_BRANCH;
3876 4ad40f36 bellard
                    gen_op_debug();
3877 4ad40f36 bellard
                    goto done_generating;
3878 4ad40f36 bellard
                }
3879 4ad40f36 bellard
            }
3880 4ad40f36 bellard
        }
3881 4ad40f36 bellard
3882 6af0bf9c bellard
        if (search_pc) {
3883 6af0bf9c bellard
            j = gen_opc_ptr - gen_opc_buf;
3884 6af0bf9c bellard
            if (lj < j) {
3885 6af0bf9c bellard
                lj++;
3886 6af0bf9c bellard
                while (lj < j)
3887 6af0bf9c bellard
                    gen_opc_instr_start[lj++] = 0;
3888 6af0bf9c bellard
            }
3889 4ad40f36 bellard
            gen_opc_pc[lj] = ctx.pc;
3890 4ad40f36 bellard
            gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
3891 4ad40f36 bellard
            gen_opc_instr_start[lj] = 1;
3892 6af0bf9c bellard
        }
3893 6af0bf9c bellard
        ctx.opcode = ldl_code(ctx.pc);
3894 6af0bf9c bellard
        decode_opc(&ctx);
3895 6af0bf9c bellard
        ctx.pc += 4;
3896 4ad40f36 bellard
3897 4ad40f36 bellard
        if (env->singlestep_enabled)
3898 4ad40f36 bellard
            break;
3899 4ad40f36 bellard
3900 6af0bf9c bellard
        if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
3901 6af0bf9c bellard
            break;
3902 4ad40f36 bellard
3903 6af0bf9c bellard
#if defined (MIPS_SINGLE_STEP)
3904 6af0bf9c bellard
        break;
3905 6af0bf9c bellard
#endif
3906 6af0bf9c bellard
    }
3907 4ad40f36 bellard
    if (env->singlestep_enabled) {
3908 4ad40f36 bellard
        save_cpu_state(ctxp, ctx.bstate == BS_NONE);
3909 4ad40f36 bellard
        gen_op_debug();
3910 4ad40f36 bellard
        goto done_generating;
3911 4ad40f36 bellard
    }
3912 4ad40f36 bellard
    else if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) {
3913 6af0bf9c bellard
        save_cpu_state(ctxp, 0);
3914 6e256c93 bellard
        gen_goto_tb(&ctx, 0, ctx.pc);
3915 6af0bf9c bellard
    }
3916 6af0bf9c bellard
    gen_op_reset_T0();
3917 6af0bf9c bellard
    /* Generate the return instruction */
3918 6af0bf9c bellard
    gen_op_exit_tb();
3919 4ad40f36 bellard
done_generating:
3920 6af0bf9c bellard
    *gen_opc_ptr = INDEX_op_end;
3921 6af0bf9c bellard
    if (search_pc) {
3922 6af0bf9c bellard
        j = gen_opc_ptr - gen_opc_buf;
3923 6af0bf9c bellard
        lj++;
3924 6af0bf9c bellard
        while (lj <= j)
3925 6af0bf9c bellard
            gen_opc_instr_start[lj++] = 0;
3926 6af0bf9c bellard
        tb->size = 0;
3927 6af0bf9c bellard
    } else {
3928 6af0bf9c bellard
        tb->size = ctx.pc - pc_start;
3929 6af0bf9c bellard
    }
3930 6af0bf9c bellard
#ifdef DEBUG_DISAS
3931 6af0bf9c bellard
#if defined MIPS_DEBUG_DISAS
3932 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_IN_ASM)
3933 6af0bf9c bellard
        fprintf(logfile, "\n");
3934 6af0bf9c bellard
#endif
3935 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_IN_ASM) {
3936 6af0bf9c bellard
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
3937 6ea83fed bellard
    target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
3938 6af0bf9c bellard
        fprintf(logfile, "\n");
3939 6af0bf9c bellard
    }
3940 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_OP) {
3941 6af0bf9c bellard
        fprintf(logfile, "OP:\n");
3942 6af0bf9c bellard
        dump_ops(gen_opc_buf, gen_opparam_buf);
3943 6af0bf9c bellard
        fprintf(logfile, "\n");
3944 6af0bf9c bellard
    }
3945 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_CPU) {
3946 6af0bf9c bellard
        fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
3947 6af0bf9c bellard
    }
3948 6af0bf9c bellard
#endif
3949 6af0bf9c bellard
    
3950 6af0bf9c bellard
    return 0;
3951 6af0bf9c bellard
}
3952 6af0bf9c bellard
3953 6af0bf9c bellard
int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
3954 6af0bf9c bellard
{
3955 6af0bf9c bellard
    return gen_intermediate_code_internal(env, tb, 0);
3956 6af0bf9c bellard
}
3957 6af0bf9c bellard
3958 6af0bf9c bellard
int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
3959 6af0bf9c bellard
{
3960 6af0bf9c bellard
    return gen_intermediate_code_internal(env, tb, 1);
3961 6af0bf9c bellard
}
3962 6af0bf9c bellard
3963 71fb7241 ths
#ifdef MIPS_USES_FPU
3964 71fb7241 ths
3965 6ea83fed bellard
void fpu_dump_state(CPUState *env, FILE *f, 
3966 6ea83fed bellard
                    int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
3967 6ea83fed bellard
                    int flags)
3968 6ea83fed bellard
{
3969 6ea83fed bellard
    int i;
3970 6ea83fed bellard
3971 6ea83fed bellard
#   define printfpr(fp) do { \
3972 6ea83fed bellard
        fpu_fprintf(f, "w:%08x d:%08lx%08lx fd:%g fs:%g\n", \
3973 6ea83fed bellard
                (fp)->w[FP_ENDIAN_IDX], (fp)->w[0], (fp)->w[1], (fp)->fd, (fp)->fs[FP_ENDIAN_IDX]); \
3974 6ea83fed bellard
    } while(0)
3975 6ea83fed bellard
3976 6ea83fed bellard
    fpu_fprintf(f, "CP1 FCR0 0x%08x  FCR31 0x%08x  SR.FR %d\n",
3977 6ea83fed bellard
                env->fcr0, env->fcr31,
3978 7a387fff ths
                (env->CP0_Status & (1 << CP0St_FR)) != 0);
3979 6ea83fed bellard
    fpu_fprintf(f, "FT0: "); printfpr(&env->ft0);
3980 6ea83fed bellard
    fpu_fprintf(f, "FT1: "); printfpr(&env->ft1);
3981 6ea83fed bellard
    fpu_fprintf(f, "FT2: "); printfpr(&env->ft2);
3982 7a387fff ths
    for(i = 0; i < 32; i += 2) {
3983 7a387fff ths
        fpu_fprintf(f, "%s: ", fregnames[i]);
3984 6ea83fed bellard
        printfpr(FPR(env, i));
3985 6ea83fed bellard
    }
3986 6ea83fed bellard
3987 6ea83fed bellard
#undef printfpr
3988 6ea83fed bellard
}
3989 6ea83fed bellard
3990 7a387fff ths
void dump_fpu (CPUState *env)
3991 6ea83fed bellard
{
3992 6ea83fed bellard
    if (loglevel) { 
3993 c570fd16 ths
       fprintf(logfile, "pc=0x" TLSZ " HI=0x" TLSZ " LO=0x" TLSZ " ds %04x " TLSZ " %d\n",
3994 6ea83fed bellard
               env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
3995 6ea83fed bellard
       fpu_dump_state(env, logfile, fprintf, 0);
3996 6ea83fed bellard
    }
3997 6ea83fed bellard
}
3998 6ea83fed bellard
3999 71fb7241 ths
#endif /* MIPS_USES_FPU */
4000 71fb7241 ths
4001 c570fd16 ths
#if defined(MIPS_HAS_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
4002 c570fd16 ths
/* Debug help: The architecture requires 32bit code to maintain proper
4003 c570fd16 ths
   sign-extened values on 64bit machines.  */
4004 c570fd16 ths
4005 c570fd16 ths
#define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
4006 c570fd16 ths
4007 c570fd16 ths
void cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
4008 c570fd16 ths
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
4009 c570fd16 ths
                     int flags)
4010 c570fd16 ths
{
4011 c570fd16 ths
    int i;
4012 c570fd16 ths
4013 c570fd16 ths
    if (!SIGN_EXT_P(env->PC))
4014 c570fd16 ths
        cpu_fprintf(f, "BROKEN: pc=0x" TLSZ "\n", env->PC);
4015 c570fd16 ths
    if (!SIGN_EXT_P(env->HI))
4016 c570fd16 ths
        cpu_fprintf(f, "BROKEN: HI=0x" TLSZ "\n", env->HI);
4017 c570fd16 ths
    if (!SIGN_EXT_P(env->LO))
4018 c570fd16 ths
        cpu_fprintf(f, "BROKEN: LO=0x" TLSZ "\n", env->LO);
4019 c570fd16 ths
    if (!SIGN_EXT_P(env->btarget))
4020 c570fd16 ths
        cpu_fprintf(f, "BROKEN: btarget=0x" TLSZ "\n", env->btarget);
4021 c570fd16 ths
4022 c570fd16 ths
    for (i = 0; i < 32; i++) {
4023 c570fd16 ths
        if (!SIGN_EXT_P(env->gpr[i]))
4024 c570fd16 ths
            cpu_fprintf(f, "BROKEN: %s=0x" TLSZ "\n", regnames[i], env->gpr[i]);
4025 c570fd16 ths
    }
4026 c570fd16 ths
4027 c570fd16 ths
    if (!SIGN_EXT_P(env->CP0_EPC))
4028 c570fd16 ths
        cpu_fprintf(f, "BROKEN: EPC=0x" TLSZ "\n", env->CP0_EPC);
4029 c570fd16 ths
    if (!SIGN_EXT_P(env->CP0_LLAddr))
4030 c570fd16 ths
        cpu_fprintf(f, "BROKEN: LLAddr=0x" TLSZ "\n", env->CP0_LLAddr);
4031 c570fd16 ths
}
4032 c570fd16 ths
#endif
4033 c570fd16 ths
4034 6af0bf9c bellard
void cpu_dump_state (CPUState *env, FILE *f, 
4035 6af0bf9c bellard
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
4036 6af0bf9c bellard
                     int flags)
4037 6af0bf9c bellard
{
4038 568b600d bellard
    uint32_t c0_status;
4039 6af0bf9c bellard
    int i;
4040 6af0bf9c bellard
    
4041 c570fd16 ths
    cpu_fprintf(f, "pc=0x" TLSZ " HI=0x" TLSZ " LO=0x" TLSZ " ds %04x " TLSZ " %d\n",
4042 6af0bf9c bellard
                env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
4043 6af0bf9c bellard
    for (i = 0; i < 32; i++) {
4044 6af0bf9c bellard
        if ((i & 3) == 0)
4045 6af0bf9c bellard
            cpu_fprintf(f, "GPR%02d:", i);
4046 c570fd16 ths
        cpu_fprintf(f, " %s " TLSZ, regnames[i], env->gpr[i]);
4047 6af0bf9c bellard
        if ((i & 3) == 3)
4048 6af0bf9c bellard
            cpu_fprintf(f, "\n");
4049 6af0bf9c bellard
    }
4050 568b600d bellard
4051 568b600d bellard
    c0_status = env->CP0_Status;
4052 568b600d bellard
    if (env->hflags & MIPS_HFLAG_UM)
4053 568b600d bellard
        c0_status |= (1 << CP0St_UM);
4054 568b600d bellard
    if (env->hflags & MIPS_HFLAG_ERL)
4055 568b600d bellard
        c0_status |= (1 << CP0St_ERL);
4056 568b600d bellard
    if (env->hflags & MIPS_HFLAG_EXL)
4057 568b600d bellard
        c0_status |= (1 << CP0St_EXL);
4058 568b600d bellard
4059 c570fd16 ths
    cpu_fprintf(f, "CP0 Status  0x%08x Cause   0x%08x EPC    0x" TLSZ "\n",
4060 568b600d bellard
                c0_status, env->CP0_Cause, env->CP0_EPC);
4061 c570fd16 ths
    cpu_fprintf(f, "    Config0 0x%08x Config1 0x%08x LLAddr 0x" TLSZ "\n",
4062 6af0bf9c bellard
                env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
4063 71fb7241 ths
#ifdef MIPS_USES_FPU
4064 7a387fff ths
    if (c0_status & (1 << CP0St_CU1))
4065 7a387fff ths
        fpu_dump_state(env, f, cpu_fprintf, flags);
4066 71fb7241 ths
#endif
4067 c570fd16 ths
#if defined(MIPS_HAS_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
4068 c570fd16 ths
    cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
4069 c570fd16 ths
#endif
4070 6af0bf9c bellard
}
4071 6af0bf9c bellard
4072 6af0bf9c bellard
CPUMIPSState *cpu_mips_init (void)
4073 6af0bf9c bellard
{
4074 6af0bf9c bellard
    CPUMIPSState *env;
4075 6af0bf9c bellard
4076 6af0bf9c bellard
    env = qemu_mallocz(sizeof(CPUMIPSState));
4077 6af0bf9c bellard
    if (!env)
4078 6af0bf9c bellard
        return NULL;
4079 173d6cfe bellard
    cpu_exec_init(env);
4080 6ae81775 ths
    cpu_reset(env);
4081 6ae81775 ths
    return env;
4082 6ae81775 ths
}
4083 6ae81775 ths
4084 6ae81775 ths
void cpu_reset (CPUMIPSState *env)
4085 6ae81775 ths
{
4086 6ae81775 ths
    memset(env, 0, offsetof(CPUMIPSState, breakpoints));
4087 6ae81775 ths
4088 6af0bf9c bellard
    tlb_flush(env, 1);
4089 6ae81775 ths
4090 6af0bf9c bellard
    /* Minimal init */
4091 ca7c2b1b ths
#if !defined(CONFIG_USER_ONLY)
4092 aa328add ths
    if (env->hflags & MIPS_HFLAG_BMASK) {
4093 aa328add ths
        /* If the exception was raised from a delay slot,
4094 aa328add ths
         * come back to the jump.  */
4095 aa328add ths
        env->CP0_ErrorEPC = env->PC - 4;
4096 aa328add ths
        env->hflags &= ~MIPS_HFLAG_BMASK;
4097 aa328add ths
    } else {
4098 aa328add ths
        env->CP0_ErrorEPC = env->PC;
4099 aa328add ths
    }
4100 5dc4b744 ths
    env->PC = (int32_t)0xBFC00000;
4101 6af0bf9c bellard
#if defined (MIPS_USES_R4K_TLB)
4102 6af0bf9c bellard
    env->CP0_random = MIPS_TLB_NB - 1;
4103 814b9a47 ths
    env->tlb_in_use = MIPS_TLB_NB;
4104 6af0bf9c bellard
#endif
4105 6af0bf9c bellard
    env->CP0_Wired = 0;
4106 7a387fff ths
    /* SMP not implemented */
4107 5dc4b744 ths
    env->CP0_EBase = (int32_t)0x80000000;
4108 6af0bf9c bellard
    env->CP0_Config0 = MIPS_CONFIG0;
4109 7a387fff ths
    env->CP0_Config1 = MIPS_CONFIG1;
4110 7a387fff ths
    env->CP0_Config2 = MIPS_CONFIG2;
4111 7a387fff ths
    env->CP0_Config3 = MIPS_CONFIG3;
4112 aa328add ths
    env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
4113 6af0bf9c bellard
    env->CP0_WatchLo = 0;
4114 6af0bf9c bellard
    env->hflags = MIPS_HFLAG_ERL;
4115 6af0bf9c bellard
    /* Count register increments in debug mode, EJTAG version 1 */
4116 6af0bf9c bellard
    env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
4117 6af0bf9c bellard
    env->CP0_PRid = MIPS_CPU;
4118 ca7c2b1b ths
#endif
4119 6af0bf9c bellard
    env->exception_index = EXCP_NONE;
4120 eeef26cd bellard
#if defined(CONFIG_USER_ONLY)
4121 eeef26cd bellard
    env->hflags |= MIPS_HFLAG_UM;
4122 ca7c2b1b ths
    env->user_mode_only = 1;
4123 eeef26cd bellard
#endif
4124 6ea83fed bellard
#ifdef MIPS_USES_FPU
4125 6ea83fed bellard
    env->fcr0 = MIPS_FCR0;        
4126 6ea83fed bellard
#endif
4127 7a387fff ths
    /* XXX some guesswork here, values are CPU specific */
4128 7a387fff ths
    env->SYNCI_Step = 16;
4129 7a387fff ths
    env->CCRes = 2;
4130 6af0bf9c bellard
}