Statistics
| Branch: | Revision:

root / target-mips / translate.c @ 43057ab1

History | View | Annotate | Download (69.8 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 6af0bf9c bellard
 *
7 6af0bf9c bellard
 * This library is free software; you can redistribute it and/or
8 6af0bf9c bellard
 * modify it under the terms of the GNU Lesser General Public
9 6af0bf9c bellard
 * License as published by the Free Software Foundation; either
10 6af0bf9c bellard
 * version 2 of the License, or (at your option) any later version.
11 6af0bf9c bellard
 *
12 6af0bf9c bellard
 * This library is distributed in the hope that it will be useful,
13 6af0bf9c bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 6af0bf9c bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 6af0bf9c bellard
 * Lesser General Public License for more details.
16 6af0bf9c bellard
 *
17 6af0bf9c bellard
 * You should have received a copy of the GNU Lesser General Public
18 6af0bf9c bellard
 * License along with this library; if not, write to the Free Software
19 6af0bf9c bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 6af0bf9c bellard
 */
21 6af0bf9c bellard
22 6af0bf9c bellard
#include <stdarg.h>
23 6af0bf9c bellard
#include <stdlib.h>
24 6af0bf9c bellard
#include <stdio.h>
25 6af0bf9c bellard
#include <string.h>
26 6af0bf9c bellard
#include <inttypes.h>
27 6af0bf9c bellard
28 6af0bf9c bellard
#include "cpu.h"
29 6af0bf9c bellard
#include "exec-all.h"
30 6af0bf9c bellard
#include "disas.h"
31 6af0bf9c bellard
32 eeef26cd bellard
//#define MIPS_DEBUG_DISAS
33 6af0bf9c bellard
//#define MIPS_SINGLE_STEP
34 6af0bf9c bellard
35 c53be334 bellard
#ifdef USE_DIRECT_JUMP
36 c53be334 bellard
#define TBPARAM(x)
37 c53be334 bellard
#else
38 c53be334 bellard
#define TBPARAM(x) (long)(x)
39 c53be334 bellard
#endif
40 c53be334 bellard
41 6af0bf9c bellard
enum {
42 6af0bf9c bellard
#define DEF(s, n, copy_size) INDEX_op_ ## s,
43 6af0bf9c bellard
#include "opc.h"
44 6af0bf9c bellard
#undef DEF
45 6af0bf9c bellard
    NB_OPS,
46 6af0bf9c bellard
};
47 6af0bf9c bellard
48 6af0bf9c bellard
static uint16_t *gen_opc_ptr;
49 6af0bf9c bellard
static uint32_t *gen_opparam_ptr;
50 6af0bf9c bellard
51 6af0bf9c bellard
#include "gen-op.h"
52 6af0bf9c bellard
53 e37e863f bellard
/* MIPS opcodes */
54 e37e863f bellard
#define EXT_SPECIAL  0x100
55 e37e863f bellard
#define EXT_SPECIAL2 0x200
56 e37e863f bellard
#define EXT_REGIMM   0x300
57 e37e863f bellard
#define EXT_CP0      0x400
58 e37e863f bellard
#define EXT_CP1      0x500
59 e37e863f bellard
#define EXT_CP2      0x600
60 e37e863f bellard
#define EXT_CP3      0x700
61 e37e863f bellard
62 e37e863f bellard
enum {
63 e37e863f bellard
    /* indirect opcode tables */
64 e37e863f bellard
    OPC_SPECIAL  = 0x00,
65 e37e863f bellard
    OPC_BREGIMM  = 0x01,
66 e37e863f bellard
    OPC_CP0      = 0x10,
67 e37e863f bellard
    OPC_CP1      = 0x11,
68 e37e863f bellard
    OPC_CP2      = 0x12,
69 e37e863f bellard
    OPC_CP3      = 0x13,
70 e37e863f bellard
    OPC_SPECIAL2 = 0x1C,
71 e37e863f bellard
    /* arithmetic with immediate */
72 e37e863f bellard
    OPC_ADDI     = 0x08,
73 e37e863f bellard
    OPC_ADDIU    = 0x09,
74 e37e863f bellard
    OPC_SLTI     = 0x0A,
75 e37e863f bellard
    OPC_SLTIU    = 0x0B,
76 e37e863f bellard
    OPC_ANDI     = 0x0C,
77 e37e863f bellard
    OPC_ORI      = 0x0D,
78 e37e863f bellard
    OPC_XORI     = 0x0E,
79 e37e863f bellard
    OPC_LUI      = 0x0F,
80 e37e863f bellard
    /* Jump and branches */
81 e37e863f bellard
    OPC_J        = 0x02,
82 e37e863f bellard
    OPC_JAL      = 0x03,
83 e37e863f bellard
    OPC_BEQ      = 0x04,  /* Unconditional if rs = rt = 0 (B) */
84 e37e863f bellard
    OPC_BEQL     = 0x14,
85 e37e863f bellard
    OPC_BNE      = 0x05,
86 e37e863f bellard
    OPC_BNEL     = 0x15,
87 e37e863f bellard
    OPC_BLEZ     = 0x06,
88 e37e863f bellard
    OPC_BLEZL    = 0x16,
89 e37e863f bellard
    OPC_BGTZ     = 0x07,
90 e37e863f bellard
    OPC_BGTZL    = 0x17,
91 e37e863f bellard
    OPC_JALX     = 0x1D,  /* MIPS 16 only */
92 e37e863f bellard
    /* Load and stores */
93 e37e863f bellard
    OPC_LB       = 0x20,
94 e37e863f bellard
    OPC_LH       = 0x21,
95 e37e863f bellard
    OPC_LWL      = 0x22,
96 e37e863f bellard
    OPC_LW       = 0x23,
97 e37e863f bellard
    OPC_LBU      = 0x24,
98 e37e863f bellard
    OPC_LHU      = 0x25,
99 e37e863f bellard
    OPC_LWR      = 0x26,
100 e37e863f bellard
    OPC_SB       = 0x28,
101 e37e863f bellard
    OPC_SH       = 0x29,
102 e37e863f bellard
    OPC_SWL      = 0x2A,
103 e37e863f bellard
    OPC_SW       = 0x2B,
104 e37e863f bellard
    OPC_SWR      = 0x2E,
105 e37e863f bellard
    OPC_LL       = 0x30,
106 e37e863f bellard
    OPC_SC       = 0x38,
107 e37e863f bellard
    /* Floating point load/store */
108 e37e863f bellard
    OPC_LWC1     = 0x31,
109 e37e863f bellard
    OPC_LWC2     = 0x32,
110 e37e863f bellard
    OPC_LDC1     = 0x35,
111 e37e863f bellard
    OPC_LDC2     = 0x36,
112 e37e863f bellard
    OPC_SWC1     = 0x39,
113 e37e863f bellard
    OPC_SWC2     = 0x3A,
114 e37e863f bellard
    OPC_SDC1     = 0x3D,
115 e37e863f bellard
    OPC_SDC2     = 0x3E,
116 e37e863f bellard
    /* Cache and prefetch */
117 e37e863f bellard
    OPC_CACHE    = 0x2F,
118 e37e863f bellard
    OPC_PREF     = 0x33,
119 e37e863f bellard
};
120 e37e863f bellard
121 e37e863f bellard
/* MIPS special opcodes */
122 e37e863f bellard
enum {
123 e37e863f bellard
    /* Shifts */
124 e37e863f bellard
    OPC_SLL      = 0x00 | EXT_SPECIAL,
125 e37e863f bellard
    /* NOP is SLL r0, r0, 0   */
126 e37e863f bellard
    /* SSNOP is SLL r0, r0, 1 */
127 e37e863f bellard
    OPC_SRL      = 0x02 | EXT_SPECIAL,
128 e37e863f bellard
    OPC_SRA      = 0x03 | EXT_SPECIAL,
129 e37e863f bellard
    OPC_SLLV     = 0x04 | EXT_SPECIAL,
130 e37e863f bellard
    OPC_SRLV     = 0x06 | EXT_SPECIAL,
131 e37e863f bellard
    OPC_SRAV     = 0x07 | EXT_SPECIAL,
132 e37e863f bellard
    /* Multiplication / division */
133 e37e863f bellard
    OPC_MULT     = 0x18 | EXT_SPECIAL,
134 e37e863f bellard
    OPC_MULTU    = 0x19 | EXT_SPECIAL,
135 e37e863f bellard
    OPC_DIV      = 0x1A | EXT_SPECIAL,
136 e37e863f bellard
    OPC_DIVU     = 0x1B | EXT_SPECIAL,
137 e37e863f bellard
    /* 2 registers arithmetic / logic */
138 e37e863f bellard
    OPC_ADD      = 0x20 | EXT_SPECIAL,
139 e37e863f bellard
    OPC_ADDU     = 0x21 | EXT_SPECIAL,
140 e37e863f bellard
    OPC_SUB      = 0x22 | EXT_SPECIAL,
141 e37e863f bellard
    OPC_SUBU     = 0x23 | EXT_SPECIAL,
142 e37e863f bellard
    OPC_AND      = 0x24 | EXT_SPECIAL,
143 e37e863f bellard
    OPC_OR       = 0x25 | EXT_SPECIAL,
144 e37e863f bellard
    OPC_XOR      = 0x26 | EXT_SPECIAL,
145 e37e863f bellard
    OPC_NOR      = 0x27 | EXT_SPECIAL,
146 e37e863f bellard
    OPC_SLT      = 0x2A | EXT_SPECIAL,
147 e37e863f bellard
    OPC_SLTU     = 0x2B | EXT_SPECIAL,
148 e37e863f bellard
    /* Jumps */
149 e37e863f bellard
    OPC_JR       = 0x08 | EXT_SPECIAL,
150 e37e863f bellard
    OPC_JALR     = 0x09 | EXT_SPECIAL,
151 e37e863f bellard
    /* Traps */
152 e37e863f bellard
    OPC_TGE      = 0x30 | EXT_SPECIAL,
153 e37e863f bellard
    OPC_TGEU     = 0x31 | EXT_SPECIAL,
154 e37e863f bellard
    OPC_TLT      = 0x32 | EXT_SPECIAL,
155 e37e863f bellard
    OPC_TLTU     = 0x33 | EXT_SPECIAL,
156 e37e863f bellard
    OPC_TEQ      = 0x34 | EXT_SPECIAL,
157 e37e863f bellard
    OPC_TNE      = 0x36 | EXT_SPECIAL,
158 e37e863f bellard
    /* HI / LO registers load & stores */
159 e37e863f bellard
    OPC_MFHI     = 0x10 | EXT_SPECIAL,
160 e37e863f bellard
    OPC_MTHI     = 0x11 | EXT_SPECIAL,
161 e37e863f bellard
    OPC_MFLO     = 0x12 | EXT_SPECIAL,
162 e37e863f bellard
    OPC_MTLO     = 0x13 | EXT_SPECIAL,
163 e37e863f bellard
    /* Conditional moves */
164 e37e863f bellard
    OPC_MOVZ     = 0x0A | EXT_SPECIAL,
165 e37e863f bellard
    OPC_MOVN     = 0x0B | EXT_SPECIAL,
166 e37e863f bellard
167 e37e863f bellard
    OPC_MOVCI    = 0x01 | EXT_SPECIAL,
168 e37e863f bellard
169 e37e863f bellard
    /* Special */
170 e37e863f bellard
    OPC_PMON     = 0x05 | EXT_SPECIAL,
171 e37e863f bellard
    OPC_SYSCALL  = 0x0C | EXT_SPECIAL,
172 e37e863f bellard
    OPC_BREAK    = 0x0D | EXT_SPECIAL,
173 e37e863f bellard
    OPC_SYNC     = 0x0F | EXT_SPECIAL,
174 e37e863f bellard
};
175 e37e863f bellard
176 e37e863f bellard
enum {
177 e37e863f bellard
    /* Mutiply & xxx operations */
178 e37e863f bellard
    OPC_MADD     = 0x00 | EXT_SPECIAL2,
179 e37e863f bellard
    OPC_MADDU    = 0x01 | EXT_SPECIAL2,
180 e37e863f bellard
    OPC_MUL      = 0x02 | EXT_SPECIAL2,
181 e37e863f bellard
    OPC_MSUB     = 0x04 | EXT_SPECIAL2,
182 e37e863f bellard
    OPC_MSUBU    = 0x05 | EXT_SPECIAL2,
183 e37e863f bellard
    /* Misc */
184 e37e863f bellard
    OPC_CLZ      = 0x20 | EXT_SPECIAL2,
185 e37e863f bellard
    OPC_CLO      = 0x21 | EXT_SPECIAL2,
186 e37e863f bellard
    /* Special */
187 e37e863f bellard
    OPC_SDBBP    = 0x3F | EXT_SPECIAL2,
188 e37e863f bellard
};
189 e37e863f bellard
190 e37e863f bellard
/* Branch REGIMM */
191 e37e863f bellard
enum {
192 e37e863f bellard
    OPC_BLTZ     = 0x00 | EXT_REGIMM,
193 e37e863f bellard
    OPC_BLTZL    = 0x02 | EXT_REGIMM,
194 e37e863f bellard
    OPC_BGEZ     = 0x01 | EXT_REGIMM,
195 e37e863f bellard
    OPC_BGEZL    = 0x03 | EXT_REGIMM,
196 e37e863f bellard
    OPC_BLTZAL   = 0x10 | EXT_REGIMM,
197 e37e863f bellard
    OPC_BLTZALL  = 0x12 | EXT_REGIMM,
198 e37e863f bellard
    OPC_BGEZAL   = 0x11 | EXT_REGIMM,
199 e37e863f bellard
    OPC_BGEZALL  = 0x13 | EXT_REGIMM,
200 e37e863f bellard
    OPC_TGEI     = 0x08 | EXT_REGIMM,
201 e37e863f bellard
    OPC_TGEIU    = 0x09 | EXT_REGIMM,
202 e37e863f bellard
    OPC_TLTI     = 0x0A | EXT_REGIMM,
203 e37e863f bellard
    OPC_TLTIU    = 0x0B | EXT_REGIMM,
204 e37e863f bellard
    OPC_TEQI     = 0x0C | EXT_REGIMM,
205 e37e863f bellard
    OPC_TNEI     = 0x0E | EXT_REGIMM,
206 e37e863f bellard
};
207 e37e863f bellard
208 e37e863f bellard
enum {
209 e37e863f bellard
    /* Coprocessor 0 (MMU) */
210 e37e863f bellard
    OPC_MFC0     = 0x00 | EXT_CP0,
211 e37e863f bellard
    OPC_MTC0     = 0x04 | EXT_CP0,
212 e37e863f bellard
    OPC_TLBR     = 0x01 | EXT_CP0,
213 e37e863f bellard
    OPC_TLBWI    = 0x02 | EXT_CP0,
214 e37e863f bellard
    OPC_TLBWR    = 0x06 | EXT_CP0,
215 e37e863f bellard
    OPC_TLBP     = 0x08 | EXT_CP0,
216 e37e863f bellard
    OPC_ERET     = 0x18 | EXT_CP0,
217 e37e863f bellard
    OPC_DERET    = 0x1F | EXT_CP0,
218 e37e863f bellard
    OPC_WAIT     = 0x20 | EXT_CP0,
219 e37e863f bellard
};
220 e37e863f bellard
221 6ea83fed bellard
#ifdef MIPS_USES_FPU
222 6ea83fed bellard
enum {
223 6ea83fed bellard
    /* Coprocessor 1 (FPU) */
224 6ea83fed bellard
    OPC_MFC1     = 0x00 | EXT_CP1,
225 6ea83fed bellard
    OPC_MTC1     = 0x04 | EXT_CP1,
226 6ea83fed bellard
    OPC_CFC1     = 0x02 | EXT_CP1,
227 6ea83fed bellard
    OPC_CTC1     = 0x06 | EXT_CP1,
228 6ea83fed bellard
};
229 6ea83fed bellard
#endif
230 6ea83fed bellard
231 6af0bf9c bellard
const unsigned char *regnames[] =
232 6af0bf9c bellard
    { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
233 6af0bf9c bellard
      "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
234 6af0bf9c bellard
      "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
235 6af0bf9c bellard
      "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
236 6af0bf9c bellard
237 6af0bf9c bellard
/* Warning: no function for r0 register (hard wired to zero) */
238 6af0bf9c bellard
#define GEN32(func, NAME) \
239 6af0bf9c bellard
static GenOpFunc *NAME ## _table [32] = {                                     \
240 6af0bf9c bellard
NULL,       NAME ## 1, NAME ## 2, NAME ## 3,                                  \
241 6af0bf9c bellard
NAME ## 4,  NAME ## 5, NAME ## 6, NAME ## 7,                                  \
242 6af0bf9c bellard
NAME ## 8,  NAME ## 9, NAME ## 10, NAME ## 11,                                \
243 6af0bf9c bellard
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
244 6af0bf9c bellard
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
245 6af0bf9c bellard
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
246 6af0bf9c bellard
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
247 6af0bf9c bellard
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
248 6af0bf9c bellard
};                                                                            \
249 6af0bf9c bellard
static inline void func(int n)                                                \
250 6af0bf9c bellard
{                                                                             \
251 6af0bf9c bellard
    NAME ## _table[n]();                                                      \
252 6af0bf9c bellard
}
253 6af0bf9c bellard
254 6af0bf9c bellard
/* General purpose registers moves */
255 6af0bf9c bellard
GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
256 6af0bf9c bellard
GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
257 6af0bf9c bellard
GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr);
258 6af0bf9c bellard
259 6af0bf9c bellard
GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
260 6af0bf9c bellard
GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
261 6af0bf9c bellard
262 6ea83fed bellard
#ifdef MIPS_USES_FPU
263 6ea83fed bellard
const unsigned char *fregnames[] =
264 6ea83fed bellard
    { "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
265 6ea83fed bellard
      "f8",  "f9",  "f10", "f11", "f12", "f13", "f14", "f15",
266 6ea83fed bellard
      "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
267 6ea83fed bellard
      "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
268 6ea83fed bellard
269 6ea83fed bellard
# define SFGEN32(func, NAME) \
270 6ea83fed bellard
static GenOpFunc *NAME ## _table [32] = {                                     \
271 6ea83fed bellard
NAME ## 0,  NAME ## 1,  NAME ## 2,  NAME ## 3,                                \
272 6ea83fed bellard
NAME ## 4,  NAME ## 5,  NAME ## 6,  NAME ## 7,                                \
273 6ea83fed bellard
NAME ## 8,  NAME ## 9,  NAME ## 10, NAME ## 11,                               \
274 6ea83fed bellard
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
275 6ea83fed bellard
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
276 6ea83fed bellard
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
277 6ea83fed bellard
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
278 6ea83fed bellard
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
279 6ea83fed bellard
};                                                                            \
280 6ea83fed bellard
static inline void func(int n)                                                \
281 6ea83fed bellard
{                                                                             \
282 6ea83fed bellard
    NAME ## _table[n]();                                                      \
283 6ea83fed bellard
}
284 6ea83fed bellard
285 6ea83fed bellard
# define DFGEN32(func, NAME) \
286 6ea83fed bellard
static GenOpFunc *NAME ## _table [32] = {                                     \
287 6ea83fed bellard
NAME ## 0,  0, NAME ## 2,  0,                                                 \
288 6ea83fed bellard
NAME ## 4,  0, NAME ## 6,  0,                                                 \
289 6ea83fed bellard
NAME ## 8,  0, NAME ## 10, 0,                                                 \
290 6ea83fed bellard
NAME ## 12, 0, NAME ## 14, 0,                                                 \
291 6ea83fed bellard
NAME ## 16, 0, NAME ## 18, 0,                                                 \
292 6ea83fed bellard
NAME ## 20, 0, NAME ## 22, 0,                                                 \
293 6ea83fed bellard
NAME ## 24, 0, NAME ## 26, 0,                                                 \
294 6ea83fed bellard
NAME ## 28, 0, NAME ## 30, 0,                                                 \
295 6ea83fed bellard
};                                                                            \
296 6ea83fed bellard
static inline void func(int n)                                                \
297 6ea83fed bellard
{                                                                             \
298 6ea83fed bellard
    NAME ## _table[n]();                                                      \
299 6ea83fed bellard
}
300 6ea83fed bellard
301 6ea83fed bellard
SFGEN32(gen_op_load_fpr_WT0,  gen_op_load_fpr_WT0_fpr);
302 6ea83fed bellard
SFGEN32(gen_op_store_fpr_WT0, gen_op_store_fpr_WT0_fpr);
303 6ea83fed bellard
304 6ea83fed bellard
SFGEN32(gen_op_load_fpr_WT1,  gen_op_load_fpr_WT1_fpr);
305 6ea83fed bellard
SFGEN32(gen_op_store_fpr_WT1, gen_op_store_fpr_WT1_fpr);
306 6ea83fed bellard
307 6ea83fed bellard
SFGEN32(gen_op_load_fpr_WT2,  gen_op_load_fpr_WT2_fpr);
308 6ea83fed bellard
SFGEN32(gen_op_store_fpr_WT2, gen_op_store_fpr_WT2_fpr);
309 6ea83fed bellard
310 6ea83fed bellard
DFGEN32(gen_op_load_fpr_DT0,  gen_op_load_fpr_DT0_fpr);
311 6ea83fed bellard
DFGEN32(gen_op_store_fpr_DT0, gen_op_store_fpr_DT0_fpr);
312 6ea83fed bellard
313 6ea83fed bellard
DFGEN32(gen_op_load_fpr_DT1,  gen_op_load_fpr_DT1_fpr);
314 6ea83fed bellard
DFGEN32(gen_op_store_fpr_DT1, gen_op_store_fpr_DT1_fpr);
315 6ea83fed bellard
316 6ea83fed bellard
DFGEN32(gen_op_load_fpr_DT2,  gen_op_load_fpr_DT2_fpr);
317 6ea83fed bellard
DFGEN32(gen_op_store_fpr_DT2, gen_op_store_fpr_DT2_fpr);
318 6ea83fed bellard
319 6ea83fed bellard
#define FOP_CONDS(fmt) \
320 6ea83fed bellard
static GenOpFunc * cond_ ## fmt ## _table[16] = {                       \
321 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _f,                                           \
322 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _un,                                          \
323 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _eq,                                          \
324 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _ueq,                                         \
325 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _olt,                                         \
326 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _ult,                                         \
327 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _ole,                                         \
328 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _ule,                                         \
329 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _sf,                                          \
330 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _ngle,                                        \
331 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _seq,                                         \
332 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _ngl,                                         \
333 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _lt,                                          \
334 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _nge,                                         \
335 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _le,                                          \
336 6ea83fed bellard
    gen_op_cmp_ ## fmt ## _ngt,                                         \
337 6ea83fed bellard
};                                                                      \
338 6ea83fed bellard
static inline void gen_cmp_ ## fmt(int n)                               \
339 6ea83fed bellard
{                                                                       \
340 6ea83fed bellard
    cond_ ## fmt ## _table[n]();                                        \
341 6ea83fed bellard
}
342 6ea83fed bellard
343 6ea83fed bellard
FOP_CONDS(d)
344 6ea83fed bellard
FOP_CONDS(s)
345 6ea83fed bellard
346 6ea83fed bellard
#endif
347 6ea83fed bellard
348 6af0bf9c bellard
typedef struct DisasContext {
349 6af0bf9c bellard
    struct TranslationBlock *tb;
350 6af0bf9c bellard
    target_ulong pc, saved_pc;
351 6af0bf9c bellard
    uint32_t opcode;
352 6af0bf9c bellard
    /* Routine used to access memory */
353 6af0bf9c bellard
    int mem_idx;
354 6af0bf9c bellard
    uint32_t hflags, saved_hflags;
355 6af0bf9c bellard
    uint32_t CP0_Status;
356 6af0bf9c bellard
    int bstate;
357 6af0bf9c bellard
    target_ulong btarget;
358 6af0bf9c bellard
} DisasContext;
359 6af0bf9c bellard
360 6af0bf9c bellard
enum {
361 6af0bf9c bellard
    BS_NONE     = 0, /* We go out of the TB without reaching a branch or an
362 6af0bf9c bellard
                      * exception condition
363 6af0bf9c bellard
                      */
364 6af0bf9c bellard
    BS_STOP     = 1, /* We want to stop translation for any reason */
365 6af0bf9c bellard
    BS_BRANCH   = 2, /* We reached a branch condition     */
366 6af0bf9c bellard
    BS_EXCP     = 3, /* We reached an exception condition */
367 6af0bf9c bellard
};
368 6af0bf9c bellard
369 6af0bf9c bellard
#if defined MIPS_DEBUG_DISAS
370 6af0bf9c bellard
#define MIPS_DEBUG(fmt, args...)                                              \
371 6af0bf9c bellard
do {                                                                          \
372 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_IN_ASM) {                                       \
373 6af0bf9c bellard
        fprintf(logfile, "%08x: %08x " fmt "\n",                              \
374 6af0bf9c bellard
                ctx->pc, ctx->opcode , ##args);                               \
375 6af0bf9c bellard
    }                                                                         \
376 6af0bf9c bellard
} while (0)
377 6af0bf9c bellard
#else
378 6af0bf9c bellard
#define MIPS_DEBUG(fmt, args...) do { } while(0)
379 6af0bf9c bellard
#endif
380 6af0bf9c bellard
381 6af0bf9c bellard
#define MIPS_INVAL(op)                                                        \
382 6af0bf9c bellard
do {                                                                          \
383 6af0bf9c bellard
    MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26,            \
384 6af0bf9c bellard
               ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F));             \
385 6af0bf9c bellard
} while (0)
386 6af0bf9c bellard
387 6af0bf9c bellard
#define GEN_LOAD_REG_TN(Tn, Rn)                                               \
388 6af0bf9c bellard
do {                                                                          \
389 6af0bf9c bellard
    if (Rn == 0) {                                                            \
390 6af0bf9c bellard
        glue(gen_op_reset_, Tn)();                                            \
391 6af0bf9c bellard
    } else {                                                                  \
392 6af0bf9c bellard
        glue(gen_op_load_gpr_, Tn)(Rn);                                       \
393 6af0bf9c bellard
    }                                                                         \
394 6af0bf9c bellard
} while (0)
395 6af0bf9c bellard
396 6af0bf9c bellard
#define GEN_LOAD_IMM_TN(Tn, Imm)                                              \
397 6af0bf9c bellard
do {                                                                          \
398 6af0bf9c bellard
    if (Imm == 0) {                                                           \
399 6af0bf9c bellard
        glue(gen_op_reset_, Tn)();                                            \
400 6af0bf9c bellard
    } else {                                                                  \
401 6af0bf9c bellard
        glue(gen_op_set_, Tn)(Imm);                                           \
402 6af0bf9c bellard
    }                                                                         \
403 6af0bf9c bellard
} while (0)
404 6af0bf9c bellard
405 6af0bf9c bellard
#define GEN_STORE_TN_REG(Rn, Tn)                                              \
406 6af0bf9c bellard
do {                                                                          \
407 6af0bf9c bellard
    if (Rn != 0) {                                                            \
408 6af0bf9c bellard
        glue(glue(gen_op_store_, Tn),_gpr)(Rn);                               \
409 6af0bf9c bellard
    }                                                                         \
410 6af0bf9c bellard
} while (0)
411 6af0bf9c bellard
412 6ea83fed bellard
#ifdef MIPS_USES_FPU
413 6ea83fed bellard
414 6ea83fed bellard
# define GEN_LOAD_FREG_FTN(FTn, Fn)                                           \
415 6ea83fed bellard
do {                                                                          \
416 6ea83fed bellard
    glue(gen_op_load_fpr_, FTn)(Fn);                                          \
417 6ea83fed bellard
} while (0)
418 6ea83fed bellard
419 6ea83fed bellard
#define GEN_STORE_FTN_FREG(Fn, FTn)                                           \
420 6ea83fed bellard
do {                                                                          \
421 6ea83fed bellard
    glue(gen_op_store_fpr_, FTn)(Fn);                                         \
422 6ea83fed bellard
} while (0)
423 6ea83fed bellard
424 6ea83fed bellard
#endif
425 6ea83fed bellard
426 6af0bf9c bellard
static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
427 6af0bf9c bellard
{
428 6af0bf9c bellard
#if defined MIPS_DEBUG_DISAS
429 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_IN_ASM) {
430 6af0bf9c bellard
            fprintf(logfile, "hflags %08x saved %08x\n",
431 6af0bf9c bellard
                    ctx->hflags, ctx->saved_hflags);
432 6af0bf9c bellard
    }
433 6af0bf9c bellard
#endif
434 6af0bf9c bellard
    if (do_save_pc && ctx->pc != ctx->saved_pc) {
435 6af0bf9c bellard
        gen_op_save_pc(ctx->pc);
436 6af0bf9c bellard
        ctx->saved_pc = ctx->pc;
437 6af0bf9c bellard
    }
438 6af0bf9c bellard
    if (ctx->hflags != ctx->saved_hflags) {
439 6af0bf9c bellard
        gen_op_save_state(ctx->hflags);
440 6af0bf9c bellard
        ctx->saved_hflags = ctx->hflags;
441 6af0bf9c bellard
        if (ctx->hflags & MIPS_HFLAG_BR) {
442 6af0bf9c bellard
            gen_op_save_breg_target();
443 6af0bf9c bellard
        } else if (ctx->hflags & MIPS_HFLAG_B) {
444 6af0bf9c bellard
            gen_op_save_btarget(ctx->btarget);
445 6af0bf9c bellard
        } else if (ctx->hflags & MIPS_HFLAG_BMASK) {
446 6af0bf9c bellard
            gen_op_save_bcond();
447 6af0bf9c bellard
            gen_op_save_btarget(ctx->btarget);
448 6af0bf9c bellard
        }
449 6af0bf9c bellard
    }
450 6af0bf9c bellard
}
451 6af0bf9c bellard
452 4ad40f36 bellard
static inline void generate_exception_err (DisasContext *ctx, int excp, int err)
453 6af0bf9c bellard
{
454 6af0bf9c bellard
#if defined MIPS_DEBUG_DISAS
455 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_IN_ASM)
456 6af0bf9c bellard
            fprintf(logfile, "%s: raise exception %d\n", __func__, excp);
457 6af0bf9c bellard
#endif
458 6af0bf9c bellard
    save_cpu_state(ctx, 1);
459 4ad40f36 bellard
    if (err == 0)
460 4ad40f36 bellard
        gen_op_raise_exception(excp);
461 4ad40f36 bellard
    else
462 4ad40f36 bellard
        gen_op_raise_exception_err(excp, err);
463 6af0bf9c bellard
    ctx->bstate = BS_EXCP;
464 6af0bf9c bellard
}
465 6af0bf9c bellard
466 4ad40f36 bellard
static inline void generate_exception (DisasContext *ctx, int excp)
467 4ad40f36 bellard
{
468 4ad40f36 bellard
    generate_exception_err (ctx, excp, 0);
469 4ad40f36 bellard
}
470 4ad40f36 bellard
471 6af0bf9c bellard
#if defined(CONFIG_USER_ONLY)
472 6af0bf9c bellard
#define op_ldst(name)        gen_op_##name##_raw()
473 6af0bf9c bellard
#define OP_LD_TABLE(width)
474 6af0bf9c bellard
#define OP_ST_TABLE(width)
475 6af0bf9c bellard
#else
476 6af0bf9c bellard
#define op_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
477 6af0bf9c bellard
#define OP_LD_TABLE(width)                                                    \
478 6af0bf9c bellard
static GenOpFunc *gen_op_l##width[] = {                                       \
479 6af0bf9c bellard
    &gen_op_l##width##_user,                                                  \
480 6af0bf9c bellard
    &gen_op_l##width##_kernel,                                                \
481 6af0bf9c bellard
}
482 6af0bf9c bellard
#define OP_ST_TABLE(width)                                                    \
483 6af0bf9c bellard
static GenOpFunc *gen_op_s##width[] = {                                       \
484 6af0bf9c bellard
    &gen_op_s##width##_user,                                                  \
485 6af0bf9c bellard
    &gen_op_s##width##_kernel,                                                \
486 6af0bf9c bellard
}
487 6af0bf9c bellard
#endif
488 6af0bf9c bellard
489 6af0bf9c bellard
#ifdef TARGET_MIPS64
490 6af0bf9c bellard
OP_LD_TABLE(d);
491 6af0bf9c bellard
OP_LD_TABLE(dl);
492 6af0bf9c bellard
OP_LD_TABLE(dr);
493 6af0bf9c bellard
OP_ST_TABLE(d);
494 6af0bf9c bellard
OP_ST_TABLE(dl);
495 6af0bf9c bellard
OP_ST_TABLE(dr);
496 6af0bf9c bellard
#endif
497 6af0bf9c bellard
OP_LD_TABLE(w);
498 6af0bf9c bellard
OP_LD_TABLE(wl);
499 6af0bf9c bellard
OP_LD_TABLE(wr);
500 6af0bf9c bellard
OP_ST_TABLE(w);
501 6af0bf9c bellard
OP_ST_TABLE(wl);
502 6af0bf9c bellard
OP_ST_TABLE(wr);
503 6af0bf9c bellard
OP_LD_TABLE(h);
504 6af0bf9c bellard
OP_LD_TABLE(hu);
505 6af0bf9c bellard
OP_ST_TABLE(h);
506 6af0bf9c bellard
OP_LD_TABLE(b);
507 6af0bf9c bellard
OP_LD_TABLE(bu);
508 6af0bf9c bellard
OP_ST_TABLE(b);
509 6af0bf9c bellard
OP_LD_TABLE(l);
510 6af0bf9c bellard
OP_ST_TABLE(c);
511 6ea83fed bellard
#ifdef MIPS_USES_FPU
512 6ea83fed bellard
OP_LD_TABLE(wc1);
513 6ea83fed bellard
OP_ST_TABLE(wc1);
514 6ea83fed bellard
OP_LD_TABLE(dc1);
515 6ea83fed bellard
OP_ST_TABLE(dc1);
516 6ea83fed bellard
#endif
517 6af0bf9c bellard
518 6af0bf9c bellard
/* Load and store */
519 6af0bf9c bellard
static void gen_ldst (DisasContext *ctx, uint16_t opc, int rt,
520 6af0bf9c bellard
                      int base, int16_t offset)
521 6af0bf9c bellard
{
522 6af0bf9c bellard
    const unsigned char *opn = "unk";
523 6af0bf9c bellard
524 6af0bf9c bellard
    if (base == 0) {
525 6af0bf9c bellard
        GEN_LOAD_IMM_TN(T0, offset);
526 6af0bf9c bellard
    } else if (offset == 0) {
527 6af0bf9c bellard
        gen_op_load_gpr_T0(base);
528 6af0bf9c bellard
    } else {
529 6af0bf9c bellard
        gen_op_load_gpr_T0(base);
530 6af0bf9c bellard
        gen_op_set_T1(offset);
531 6af0bf9c bellard
        gen_op_add();
532 6af0bf9c bellard
    }
533 6af0bf9c bellard
    /* Don't do NOP if destination is zero: we must perform the actual
534 6af0bf9c bellard
     * memory access
535 6af0bf9c bellard
     */
536 6af0bf9c bellard
    switch (opc) {
537 6af0bf9c bellard
#if defined(TARGET_MIPS64)
538 6af0bf9c bellard
    case OPC_LD:
539 6af0bf9c bellard
#if defined (MIPS_HAS_UNALIGNED_LS)
540 6af0bf9c bellard
    case OPC_ULD:
541 6af0bf9c bellard
#endif
542 6af0bf9c bellard
        op_ldst(ld);
543 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
544 6af0bf9c bellard
        opn = "ld";
545 6af0bf9c bellard
        break;
546 6af0bf9c bellard
    case OPC_SD:
547 6af0bf9c bellard
#if defined (MIPS_HAS_UNALIGNED_LS)
548 6af0bf9c bellard
    case OPC_USD:
549 6af0bf9c bellard
#endif
550 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
551 6af0bf9c bellard
        op_ldst(sd);
552 6af0bf9c bellard
        opn = "sd";
553 6af0bf9c bellard
        break;
554 6af0bf9c bellard
    case OPC_LDL:
555 6af0bf9c bellard
        op_ldst(ldl);
556 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
557 6af0bf9c bellard
        opn = "ldl";
558 6af0bf9c bellard
        break;
559 6af0bf9c bellard
    case OPC_SDL:
560 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
561 6af0bf9c bellard
        op_ldst(sdl);
562 6af0bf9c bellard
        opn = "sdl";
563 6af0bf9c bellard
        break;
564 6af0bf9c bellard
    case OPC_LDR:
565 6af0bf9c bellard
        op_ldst(ldr);
566 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
567 6af0bf9c bellard
        opn = "ldr";
568 6af0bf9c bellard
        break;
569 6af0bf9c bellard
    case OPC_SDR:
570 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
571 6af0bf9c bellard
        op_ldst(sdr);
572 6af0bf9c bellard
        opn = "sdr";
573 6af0bf9c bellard
        break;
574 6af0bf9c bellard
#endif
575 6af0bf9c bellard
    case OPC_LW:
576 6af0bf9c bellard
#if defined (MIPS_HAS_UNALIGNED_LS)
577 6af0bf9c bellard
    case OPC_ULW:
578 6af0bf9c bellard
#endif
579 6af0bf9c bellard
        op_ldst(lw);
580 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
581 6af0bf9c bellard
        opn = "lw";
582 6af0bf9c bellard
        break;
583 6af0bf9c bellard
    case OPC_SW:
584 6af0bf9c bellard
#if defined (MIPS_HAS_UNALIGNED_LS)
585 6af0bf9c bellard
    case OPC_USW:
586 6af0bf9c bellard
#endif
587 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
588 6af0bf9c bellard
        op_ldst(sw);
589 6af0bf9c bellard
        opn = "sw";
590 6af0bf9c bellard
        break;
591 6af0bf9c bellard
    case OPC_LH:
592 6af0bf9c bellard
#if defined (MIPS_HAS_UNALIGNED_LS)
593 6af0bf9c bellard
    case OPC_ULH:
594 6af0bf9c bellard
#endif
595 6af0bf9c bellard
        op_ldst(lh);
596 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
597 6af0bf9c bellard
        opn = "lh";
598 6af0bf9c bellard
        break;
599 6af0bf9c bellard
    case OPC_SH:
600 6af0bf9c bellard
#if defined (MIPS_HAS_UNALIGNED_LS)
601 6af0bf9c bellard
    case OPC_USH:
602 6af0bf9c bellard
#endif
603 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
604 6af0bf9c bellard
        op_ldst(sh);
605 6af0bf9c bellard
        opn = "sh";
606 6af0bf9c bellard
        break;
607 6af0bf9c bellard
    case OPC_LHU:
608 6af0bf9c bellard
#if defined (MIPS_HAS_UNALIGNED_LS)
609 6af0bf9c bellard
    case OPC_ULHU:
610 6af0bf9c bellard
#endif
611 6af0bf9c bellard
        op_ldst(lhu);
612 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
613 6af0bf9c bellard
        opn = "lhu";
614 6af0bf9c bellard
        break;
615 6af0bf9c bellard
    case OPC_LB:
616 6af0bf9c bellard
        op_ldst(lb);
617 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
618 6af0bf9c bellard
        opn = "lb";
619 6af0bf9c bellard
        break;
620 6af0bf9c bellard
    case OPC_SB:
621 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
622 6af0bf9c bellard
        op_ldst(sb);
623 6af0bf9c bellard
        opn = "sb";
624 6af0bf9c bellard
        break;
625 6af0bf9c bellard
    case OPC_LBU:
626 6af0bf9c bellard
        op_ldst(lbu);
627 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
628 6af0bf9c bellard
        opn = "lbu";
629 6af0bf9c bellard
        break;
630 6af0bf9c bellard
    case OPC_LWL:
631 9d1d106a bellard
        GEN_LOAD_REG_TN(T1, rt);
632 6af0bf9c bellard
        op_ldst(lwl);
633 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
634 6af0bf9c bellard
        opn = "lwl";
635 6af0bf9c bellard
        break;
636 6af0bf9c bellard
    case OPC_SWL:
637 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
638 6af0bf9c bellard
        op_ldst(swl);
639 6af0bf9c bellard
        opn = "swr";
640 6af0bf9c bellard
        break;
641 6af0bf9c bellard
    case OPC_LWR:
642 9d1d106a bellard
        GEN_LOAD_REG_TN(T1, rt);
643 6af0bf9c bellard
        op_ldst(lwr);
644 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
645 6af0bf9c bellard
        opn = "lwr";
646 6af0bf9c bellard
        break;
647 6af0bf9c bellard
    case OPC_SWR:
648 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
649 6af0bf9c bellard
        op_ldst(swr);
650 6af0bf9c bellard
        opn = "swr";
651 6af0bf9c bellard
        break;
652 6af0bf9c bellard
    case OPC_LL:
653 6af0bf9c bellard
        op_ldst(ll);
654 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
655 6af0bf9c bellard
        opn = "ll";
656 6af0bf9c bellard
        break;
657 6af0bf9c bellard
    case OPC_SC:
658 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
659 6af0bf9c bellard
        op_ldst(sc);
660 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
661 6af0bf9c bellard
        opn = "sc";
662 6af0bf9c bellard
        break;
663 6af0bf9c bellard
    default:
664 6af0bf9c bellard
        MIPS_INVAL("load/store");
665 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
666 6af0bf9c bellard
        return;
667 6af0bf9c bellard
    }
668 6af0bf9c bellard
    MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
669 6af0bf9c bellard
}
670 6af0bf9c bellard
671 6ea83fed bellard
#ifdef MIPS_USES_FPU
672 6ea83fed bellard
673 6ea83fed bellard
/* Load and store */
674 6ea83fed bellard
static void gen_flt_ldst (DisasContext *ctx, uint16_t opc, int ft,
675 6ea83fed bellard
                      int base, int16_t offset)
676 6ea83fed bellard
{
677 6ea83fed bellard
    const unsigned char *opn = "unk";
678 6ea83fed bellard
679 6ea83fed bellard
    if (base == 0) {
680 6ea83fed bellard
        GEN_LOAD_IMM_TN(T0, offset);
681 6ea83fed bellard
    } else if (offset == 0) {
682 6ea83fed bellard
        gen_op_load_gpr_T0(base);
683 6ea83fed bellard
    } else {
684 6ea83fed bellard
        gen_op_load_gpr_T0(base);
685 6ea83fed bellard
        gen_op_set_T1(offset);
686 6ea83fed bellard
        gen_op_add();
687 6ea83fed bellard
    }
688 6ea83fed bellard
    /* Don't do NOP if destination is zero: we must perform the actual
689 6ea83fed bellard
     * memory access
690 6ea83fed bellard
     */
691 6ea83fed bellard
    switch (opc) {
692 6ea83fed bellard
    case OPC_LWC1:
693 6ea83fed bellard
        op_ldst(lwc1);
694 6ea83fed bellard
        GEN_STORE_FTN_FREG(ft, WT0);
695 6ea83fed bellard
        opn = "lwc1";
696 6ea83fed bellard
        break;
697 6ea83fed bellard
    case OPC_SWC1:
698 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, ft);
699 6ea83fed bellard
        op_ldst(swc1);
700 6ea83fed bellard
        opn = "swc1";
701 6ea83fed bellard
        break;
702 6ea83fed bellard
    case OPC_LDC1:
703 6ea83fed bellard
        op_ldst(ldc1);
704 6ea83fed bellard
        GEN_STORE_FTN_FREG(ft, DT0);
705 6ea83fed bellard
        opn = "ldc1";
706 6ea83fed bellard
        break;
707 6ea83fed bellard
    case OPC_SDC1:
708 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, ft);
709 6ea83fed bellard
        op_ldst(sdc1);
710 6ea83fed bellard
        opn = "sdc1";
711 6ea83fed bellard
        break;
712 6ea83fed bellard
    default:
713 6ea83fed bellard
        MIPS_INVAL("float load/store");
714 6ea83fed bellard
        generate_exception(ctx, EXCP_CpU);
715 6ea83fed bellard
        return;
716 6ea83fed bellard
    }
717 6ea83fed bellard
    MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
718 6ea83fed bellard
}
719 6ea83fed bellard
#endif
720 6ea83fed bellard
721 6af0bf9c bellard
/* Arithmetic with immediate operand */
722 6af0bf9c bellard
static void gen_arith_imm (DisasContext *ctx, uint16_t opc, int rt,
723 6af0bf9c bellard
                           int rs, int16_t imm)
724 6af0bf9c bellard
{
725 6af0bf9c bellard
    uint32_t uimm;
726 6af0bf9c bellard
    const unsigned char *opn = "unk";
727 6af0bf9c bellard
728 6af0bf9c bellard
    if (rt == 0 && opc != OPC_ADDI) {
729 6af0bf9c bellard
        /* if no destination, treat it as a NOP 
730 6af0bf9c bellard
         * For addi, we must generate the overflow exception when needed.
731 6af0bf9c bellard
         */
732 6af0bf9c bellard
        MIPS_DEBUG("NOP");
733 6af0bf9c bellard
        return;
734 6af0bf9c bellard
    }
735 6af0bf9c bellard
    if (opc == OPC_ADDI || opc == OPC_ADDIU ||
736 6af0bf9c bellard
        opc == OPC_SLTI || opc == OPC_SLTIU)
737 6af0bf9c bellard
        uimm = (int32_t)imm; /* Sign extent to 32 bits */
738 6af0bf9c bellard
    else
739 6af0bf9c bellard
        uimm = (uint16_t)imm;
740 6af0bf9c bellard
    if (opc != OPC_LUI) {
741 6af0bf9c bellard
        GEN_LOAD_REG_TN(T0, rs);
742 6af0bf9c bellard
        GEN_LOAD_IMM_TN(T1, uimm);
743 6af0bf9c bellard
    } else {
744 6af0bf9c bellard
        uimm = uimm << 16;
745 6af0bf9c bellard
        GEN_LOAD_IMM_TN(T0, uimm);
746 6af0bf9c bellard
    }
747 6af0bf9c bellard
    switch (opc) {
748 6af0bf9c bellard
    case OPC_ADDI:
749 6af0bf9c bellard
        save_cpu_state(ctx, 1);
750 6af0bf9c bellard
        gen_op_addo();
751 6af0bf9c bellard
        opn = "addi";
752 6af0bf9c bellard
        break;
753 6af0bf9c bellard
    case OPC_ADDIU:
754 6af0bf9c bellard
        gen_op_add();
755 6af0bf9c bellard
        opn = "addiu";
756 6af0bf9c bellard
        break;
757 6af0bf9c bellard
    case OPC_SLTI:
758 6af0bf9c bellard
        gen_op_lt();
759 6af0bf9c bellard
        opn = "slti";
760 6af0bf9c bellard
        break;
761 6af0bf9c bellard
    case OPC_SLTIU:
762 6af0bf9c bellard
        gen_op_ltu();
763 6af0bf9c bellard
        opn = "sltiu";
764 6af0bf9c bellard
        break;
765 6af0bf9c bellard
    case OPC_ANDI:
766 6af0bf9c bellard
        gen_op_and();
767 6af0bf9c bellard
        opn = "andi";
768 6af0bf9c bellard
        break;
769 6af0bf9c bellard
    case OPC_ORI:
770 6af0bf9c bellard
        gen_op_or();
771 6af0bf9c bellard
        opn = "ori";
772 6af0bf9c bellard
        break;
773 6af0bf9c bellard
    case OPC_XORI:
774 6af0bf9c bellard
        gen_op_xor();
775 6af0bf9c bellard
        opn = "xori";
776 6af0bf9c bellard
        break;
777 6af0bf9c bellard
    case OPC_LUI:
778 6af0bf9c bellard
        opn = "lui";
779 6af0bf9c bellard
        break;
780 6af0bf9c bellard
    case OPC_SLL:
781 6af0bf9c bellard
        gen_op_sll();
782 6af0bf9c bellard
        opn = "sll";
783 6af0bf9c bellard
        break;
784 6af0bf9c bellard
    case OPC_SRA:
785 6af0bf9c bellard
        gen_op_sra();
786 6af0bf9c bellard
        opn = "sra";
787 6af0bf9c bellard
        break;
788 6af0bf9c bellard
    case OPC_SRL:
789 6af0bf9c bellard
        gen_op_srl();
790 6af0bf9c bellard
        opn = "srl";
791 6af0bf9c bellard
        break;
792 6af0bf9c bellard
    default:
793 6af0bf9c bellard
        MIPS_INVAL("imm arith");
794 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
795 6af0bf9c bellard
        return;
796 6af0bf9c bellard
    }
797 6af0bf9c bellard
    GEN_STORE_TN_REG(rt, T0);
798 6af0bf9c bellard
    MIPS_DEBUG("%s %s, %s, %x", opn, regnames[rt], regnames[rs], uimm);
799 6af0bf9c bellard
}
800 6af0bf9c bellard
801 6af0bf9c bellard
/* Arithmetic */
802 6af0bf9c bellard
static void gen_arith (DisasContext *ctx, uint16_t opc,
803 6af0bf9c bellard
                       int rd, int rs, int rt)
804 6af0bf9c bellard
{
805 6af0bf9c bellard
    const unsigned char *opn = "unk";
806 6af0bf9c bellard
807 6af0bf9c bellard
    if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB) {
808 6af0bf9c bellard
        /* if no destination, treat it as a NOP 
809 6af0bf9c bellard
         * For add & sub, we must generate the overflow exception when needed.
810 6af0bf9c bellard
         */
811 6af0bf9c bellard
        MIPS_DEBUG("NOP");
812 6af0bf9c bellard
        return;
813 6af0bf9c bellard
    }
814 6af0bf9c bellard
    GEN_LOAD_REG_TN(T0, rs);
815 6af0bf9c bellard
    GEN_LOAD_REG_TN(T1, rt);
816 6af0bf9c bellard
    switch (opc) {
817 6af0bf9c bellard
    case OPC_ADD:
818 6af0bf9c bellard
        save_cpu_state(ctx, 1);
819 6af0bf9c bellard
        gen_op_addo();
820 6af0bf9c bellard
        opn = "add";
821 6af0bf9c bellard
        break;
822 6af0bf9c bellard
    case OPC_ADDU:
823 6af0bf9c bellard
        gen_op_add();
824 6af0bf9c bellard
        opn = "addu";
825 6af0bf9c bellard
        break;
826 6af0bf9c bellard
    case OPC_SUB:
827 6af0bf9c bellard
        save_cpu_state(ctx, 1);
828 6af0bf9c bellard
        gen_op_subo();
829 6af0bf9c bellard
        opn = "sub";
830 6af0bf9c bellard
        break;
831 6af0bf9c bellard
    case OPC_SUBU:
832 6af0bf9c bellard
        gen_op_sub();
833 6af0bf9c bellard
        opn = "subu";
834 6af0bf9c bellard
        break;
835 6af0bf9c bellard
    case OPC_SLT:
836 6af0bf9c bellard
        gen_op_lt();
837 6af0bf9c bellard
        opn = "slt";
838 6af0bf9c bellard
        break;
839 6af0bf9c bellard
    case OPC_SLTU:
840 6af0bf9c bellard
        gen_op_ltu();
841 6af0bf9c bellard
        opn = "sltu";
842 6af0bf9c bellard
        break;
843 6af0bf9c bellard
    case OPC_AND:
844 6af0bf9c bellard
        gen_op_and();
845 6af0bf9c bellard
        opn = "and";
846 6af0bf9c bellard
        break;
847 6af0bf9c bellard
    case OPC_NOR:
848 6af0bf9c bellard
        gen_op_nor();
849 6af0bf9c bellard
        opn = "nor";
850 6af0bf9c bellard
        break;
851 6af0bf9c bellard
    case OPC_OR:
852 6af0bf9c bellard
        gen_op_or();
853 6af0bf9c bellard
        opn = "or";
854 6af0bf9c bellard
        break;
855 6af0bf9c bellard
    case OPC_XOR:
856 6af0bf9c bellard
        gen_op_xor();
857 6af0bf9c bellard
        opn = "xor";
858 6af0bf9c bellard
        break;
859 6af0bf9c bellard
    case OPC_MUL:
860 6af0bf9c bellard
        gen_op_mul();
861 6af0bf9c bellard
        opn = "mul";
862 6af0bf9c bellard
        break;
863 6af0bf9c bellard
    case OPC_MOVN:
864 6af0bf9c bellard
        gen_op_movn(rd);
865 6af0bf9c bellard
        opn = "movn";
866 6af0bf9c bellard
        goto print;
867 6af0bf9c bellard
    case OPC_MOVZ:
868 6af0bf9c bellard
        gen_op_movz(rd);
869 6af0bf9c bellard
        opn = "movz";
870 6af0bf9c bellard
        goto print;
871 6af0bf9c bellard
    case OPC_SLLV:
872 6af0bf9c bellard
        gen_op_sllv();
873 6af0bf9c bellard
        opn = "sllv";
874 6af0bf9c bellard
        break;
875 6af0bf9c bellard
    case OPC_SRAV:
876 6af0bf9c bellard
        gen_op_srav();
877 6af0bf9c bellard
        opn = "srav";
878 6af0bf9c bellard
        break;
879 6af0bf9c bellard
    case OPC_SRLV:
880 6af0bf9c bellard
        gen_op_srlv();
881 6af0bf9c bellard
        opn = "srlv";
882 6af0bf9c bellard
        break;
883 6af0bf9c bellard
    default:
884 6af0bf9c bellard
        MIPS_INVAL("arith");
885 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
886 6af0bf9c bellard
        return;
887 6af0bf9c bellard
    }
888 6af0bf9c bellard
    GEN_STORE_TN_REG(rd, T0);
889 6af0bf9c bellard
 print:
890 6af0bf9c bellard
    MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
891 6af0bf9c bellard
}
892 6af0bf9c bellard
893 6af0bf9c bellard
/* Arithmetic on HI/LO registers */
894 6af0bf9c bellard
static void gen_HILO (DisasContext *ctx, uint16_t opc, int reg)
895 6af0bf9c bellard
{
896 6af0bf9c bellard
    const unsigned char *opn = "unk";
897 6af0bf9c bellard
898 6af0bf9c bellard
    if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
899 6af0bf9c bellard
        /* Treat as a NOP */
900 6af0bf9c bellard
        MIPS_DEBUG("NOP");
901 6af0bf9c bellard
        return;
902 6af0bf9c bellard
    }
903 6af0bf9c bellard
    switch (opc) {
904 6af0bf9c bellard
    case OPC_MFHI:
905 6af0bf9c bellard
        gen_op_load_HI();
906 6af0bf9c bellard
        GEN_STORE_TN_REG(reg, T0);
907 6af0bf9c bellard
        opn = "mfhi";
908 6af0bf9c bellard
        break;
909 6af0bf9c bellard
    case OPC_MFLO:
910 6af0bf9c bellard
        gen_op_load_LO();
911 6af0bf9c bellard
        GEN_STORE_TN_REG(reg, T0);
912 6af0bf9c bellard
        opn = "mflo";
913 6af0bf9c bellard
        break;
914 6af0bf9c bellard
    case OPC_MTHI:
915 6af0bf9c bellard
        GEN_LOAD_REG_TN(T0, reg);
916 6af0bf9c bellard
        gen_op_store_HI();
917 6af0bf9c bellard
        opn = "mthi";
918 6af0bf9c bellard
        break;
919 6af0bf9c bellard
    case OPC_MTLO:
920 6af0bf9c bellard
        GEN_LOAD_REG_TN(T0, reg);
921 6af0bf9c bellard
        gen_op_store_LO();
922 6af0bf9c bellard
        opn = "mtlo";
923 6af0bf9c bellard
        break;
924 6af0bf9c bellard
    default:
925 6af0bf9c bellard
        MIPS_INVAL("HILO");
926 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
927 6af0bf9c bellard
        return;
928 6af0bf9c bellard
    }
929 6af0bf9c bellard
    MIPS_DEBUG("%s %s", opn, regnames[reg]);
930 6af0bf9c bellard
}
931 6af0bf9c bellard
932 6af0bf9c bellard
static void gen_muldiv (DisasContext *ctx, uint16_t opc,
933 6af0bf9c bellard
                        int rs, int rt)
934 6af0bf9c bellard
{
935 6af0bf9c bellard
    const unsigned char *opn = "unk";
936 6af0bf9c bellard
937 6af0bf9c bellard
    GEN_LOAD_REG_TN(T0, rs);
938 6af0bf9c bellard
    GEN_LOAD_REG_TN(T1, rt);
939 6af0bf9c bellard
    switch (opc) {
940 6af0bf9c bellard
    case OPC_DIV:
941 6af0bf9c bellard
        gen_op_div();
942 6af0bf9c bellard
        opn = "div";
943 6af0bf9c bellard
        break;
944 6af0bf9c bellard
    case OPC_DIVU:
945 6af0bf9c bellard
        gen_op_divu();
946 6af0bf9c bellard
        opn = "divu";
947 6af0bf9c bellard
        break;
948 6af0bf9c bellard
    case OPC_MULT:
949 6af0bf9c bellard
        gen_op_mult();
950 6af0bf9c bellard
        opn = "mult";
951 6af0bf9c bellard
        break;
952 6af0bf9c bellard
    case OPC_MULTU:
953 6af0bf9c bellard
        gen_op_multu();
954 6af0bf9c bellard
        opn = "multu";
955 6af0bf9c bellard
        break;
956 6af0bf9c bellard
    case OPC_MADD:
957 6af0bf9c bellard
        gen_op_madd();
958 6af0bf9c bellard
        opn = "madd";
959 6af0bf9c bellard
        break;
960 6af0bf9c bellard
    case OPC_MADDU:
961 6af0bf9c bellard
        gen_op_maddu();
962 6af0bf9c bellard
        opn = "maddu";
963 6af0bf9c bellard
        break;
964 6af0bf9c bellard
    case OPC_MSUB:
965 6af0bf9c bellard
        gen_op_msub();
966 6af0bf9c bellard
        opn = "msub";
967 6af0bf9c bellard
        break;
968 6af0bf9c bellard
    case OPC_MSUBU:
969 6af0bf9c bellard
        gen_op_msubu();
970 6af0bf9c bellard
        opn = "msubu";
971 6af0bf9c bellard
        break;
972 6af0bf9c bellard
    default:
973 6af0bf9c bellard
        MIPS_INVAL("mul/div");
974 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
975 6af0bf9c bellard
        return;
976 6af0bf9c bellard
    }
977 6af0bf9c bellard
    MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
978 6af0bf9c bellard
}
979 6af0bf9c bellard
980 6af0bf9c bellard
static void gen_cl (DisasContext *ctx, uint16_t opc,
981 6af0bf9c bellard
                    int rd, int rs)
982 6af0bf9c bellard
{
983 6af0bf9c bellard
    const unsigned char *opn = "unk";
984 6af0bf9c bellard
    if (rd == 0) {
985 6af0bf9c bellard
        /* Treat as a NOP */
986 6af0bf9c bellard
        MIPS_DEBUG("NOP");
987 6af0bf9c bellard
        return;
988 6af0bf9c bellard
    }
989 6af0bf9c bellard
    GEN_LOAD_REG_TN(T0, rs);
990 6af0bf9c bellard
    switch (opc) {
991 6af0bf9c bellard
    case OPC_CLO:
992 6af0bf9c bellard
        /* CLO */
993 6af0bf9c bellard
        gen_op_clo();
994 6af0bf9c bellard
        opn = "clo";
995 6af0bf9c bellard
        break;
996 6af0bf9c bellard
    case OPC_CLZ:
997 6af0bf9c bellard
        /* CLZ */
998 6af0bf9c bellard
        gen_op_clz();
999 6af0bf9c bellard
        opn = "clz";
1000 6af0bf9c bellard
        break;
1001 6af0bf9c bellard
    default:
1002 6af0bf9c bellard
        MIPS_INVAL("CLx");
1003 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
1004 6af0bf9c bellard
        return;
1005 6af0bf9c bellard
    }
1006 6af0bf9c bellard
    gen_op_store_T0_gpr(rd);
1007 6af0bf9c bellard
    MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
1008 6af0bf9c bellard
}
1009 6af0bf9c bellard
1010 6af0bf9c bellard
/* Traps */
1011 6af0bf9c bellard
static void gen_trap (DisasContext *ctx, uint16_t opc,
1012 6af0bf9c bellard
                      int rs, int rt, int16_t imm)
1013 6af0bf9c bellard
{
1014 6af0bf9c bellard
    int cond;
1015 6af0bf9c bellard
1016 6af0bf9c bellard
    cond = 0;
1017 6af0bf9c bellard
    /* Load needed operands */
1018 6af0bf9c bellard
    switch (opc) {
1019 6af0bf9c bellard
    case OPC_TEQ:
1020 6af0bf9c bellard
    case OPC_TGE:
1021 6af0bf9c bellard
    case OPC_TGEU:
1022 6af0bf9c bellard
    case OPC_TLT:
1023 6af0bf9c bellard
    case OPC_TLTU:
1024 6af0bf9c bellard
    case OPC_TNE:
1025 6af0bf9c bellard
        /* Compare two registers */
1026 6af0bf9c bellard
        if (rs != rt) {
1027 6af0bf9c bellard
            GEN_LOAD_REG_TN(T0, rs);
1028 6af0bf9c bellard
            GEN_LOAD_REG_TN(T1, rt);
1029 6af0bf9c bellard
            cond = 1;
1030 6af0bf9c bellard
        }
1031 6af0bf9c bellard
    case OPC_TEQI:
1032 6af0bf9c bellard
    case OPC_TGEI:
1033 6af0bf9c bellard
    case OPC_TGEIU:
1034 6af0bf9c bellard
    case OPC_TLTI:
1035 6af0bf9c bellard
    case OPC_TLTIU:
1036 6af0bf9c bellard
    case OPC_TNEI:
1037 6af0bf9c bellard
        /* Compare register to immediate */
1038 6af0bf9c bellard
        if (rs != 0 || imm != 0) {
1039 6af0bf9c bellard
            GEN_LOAD_REG_TN(T0, rs);
1040 6af0bf9c bellard
            GEN_LOAD_IMM_TN(T1, (int32_t)imm);
1041 6af0bf9c bellard
            cond = 1;
1042 6af0bf9c bellard
        }
1043 6af0bf9c bellard
        break;
1044 6af0bf9c bellard
    }
1045 6af0bf9c bellard
    if (cond == 0) {
1046 6af0bf9c bellard
        switch (opc) {
1047 6af0bf9c bellard
        case OPC_TEQ:   /* rs == rs */
1048 6af0bf9c bellard
        case OPC_TEQI:  /* r0 == 0  */
1049 6af0bf9c bellard
        case OPC_TGE:   /* rs >= rs */
1050 6af0bf9c bellard
        case OPC_TGEI:  /* r0 >= 0  */
1051 6af0bf9c bellard
        case OPC_TGEU:  /* rs >= rs unsigned */
1052 6af0bf9c bellard
        case OPC_TGEIU: /* r0 >= 0  unsigned */
1053 6af0bf9c bellard
            /* Always trap */
1054 6af0bf9c bellard
            gen_op_set_T0(1);
1055 6af0bf9c bellard
            break;
1056 6af0bf9c bellard
        case OPC_TLT:   /* rs < rs           */
1057 6af0bf9c bellard
        case OPC_TLTI:  /* r0 < 0            */
1058 6af0bf9c bellard
        case OPC_TLTU:  /* rs < rs unsigned  */
1059 6af0bf9c bellard
        case OPC_TLTIU: /* r0 < 0  unsigned  */
1060 6af0bf9c bellard
        case OPC_TNE:   /* rs != rs          */
1061 6af0bf9c bellard
        case OPC_TNEI:  /* r0 != 0           */
1062 6af0bf9c bellard
            /* Never trap: treat as NOP */
1063 6af0bf9c bellard
            return;
1064 6af0bf9c bellard
        default:
1065 6af0bf9c bellard
            MIPS_INVAL("TRAP");
1066 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
1067 6af0bf9c bellard
            return;
1068 6af0bf9c bellard
        }
1069 6af0bf9c bellard
    } else {
1070 6af0bf9c bellard
        switch (opc) {
1071 6af0bf9c bellard
        case OPC_TEQ:
1072 6af0bf9c bellard
        case OPC_TEQI:
1073 6af0bf9c bellard
            gen_op_eq();
1074 6af0bf9c bellard
            break;
1075 6af0bf9c bellard
        case OPC_TGE:
1076 6af0bf9c bellard
        case OPC_TGEI:
1077 6af0bf9c bellard
            gen_op_ge();
1078 6af0bf9c bellard
            break;
1079 6af0bf9c bellard
        case OPC_TGEU:
1080 6af0bf9c bellard
        case OPC_TGEIU:
1081 6af0bf9c bellard
            gen_op_geu();
1082 6af0bf9c bellard
            break;
1083 6af0bf9c bellard
        case OPC_TLT:
1084 6af0bf9c bellard
        case OPC_TLTI:
1085 6af0bf9c bellard
            gen_op_lt();
1086 6af0bf9c bellard
            break;
1087 6af0bf9c bellard
        case OPC_TLTU:
1088 6af0bf9c bellard
        case OPC_TLTIU:
1089 6af0bf9c bellard
            gen_op_ltu();
1090 6af0bf9c bellard
            break;
1091 6af0bf9c bellard
        case OPC_TNE:
1092 6af0bf9c bellard
        case OPC_TNEI:
1093 6af0bf9c bellard
            gen_op_ne();
1094 6af0bf9c bellard
            break;
1095 6af0bf9c bellard
        default:
1096 6af0bf9c bellard
            MIPS_INVAL("TRAP");
1097 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
1098 6af0bf9c bellard
            return;
1099 6af0bf9c bellard
        }
1100 6af0bf9c bellard
    }
1101 6af0bf9c bellard
    save_cpu_state(ctx, 1);
1102 6af0bf9c bellard
    gen_op_trap();
1103 6af0bf9c bellard
    ctx->bstate = BS_STOP;
1104 6af0bf9c bellard
}
1105 6af0bf9c bellard
1106 6e256c93 bellard
static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
1107 c53be334 bellard
{
1108 6e256c93 bellard
    TranslationBlock *tb;
1109 6e256c93 bellard
    tb = ctx->tb;
1110 6e256c93 bellard
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
1111 6e256c93 bellard
        if (n == 0)
1112 6e256c93 bellard
            gen_op_goto_tb0(TBPARAM(tb));
1113 6e256c93 bellard
        else
1114 6e256c93 bellard
            gen_op_goto_tb1(TBPARAM(tb));
1115 6e256c93 bellard
        gen_op_save_pc(dest);
1116 6e256c93 bellard
        gen_op_set_T0((long)tb + n);
1117 6e256c93 bellard
        gen_op_exit_tb();
1118 6e256c93 bellard
    } else {
1119 6e256c93 bellard
        gen_op_save_pc(dest);
1120 6e256c93 bellard
        gen_op_set_T0(0);
1121 6e256c93 bellard
        gen_op_exit_tb();
1122 6e256c93 bellard
    }
1123 c53be334 bellard
}
1124 c53be334 bellard
1125 6af0bf9c bellard
/* Branches (before delay slot) */
1126 6af0bf9c bellard
static void gen_compute_branch (DisasContext *ctx, uint16_t opc,
1127 6af0bf9c bellard
                                int rs, int rt, int32_t offset)
1128 6af0bf9c bellard
{
1129 6af0bf9c bellard
    target_ulong btarget;
1130 6af0bf9c bellard
    int blink, bcond;
1131 6af0bf9c bellard
1132 6af0bf9c bellard
    btarget = -1;
1133 6af0bf9c bellard
    blink = 0;
1134 6af0bf9c bellard
    bcond = 0;
1135 6af0bf9c bellard
    /* Load needed operands */
1136 6af0bf9c bellard
    switch (opc) {
1137 6af0bf9c bellard
    case OPC_BEQ:
1138 6af0bf9c bellard
    case OPC_BEQL:
1139 6af0bf9c bellard
    case OPC_BNE:
1140 6af0bf9c bellard
    case OPC_BNEL:
1141 6af0bf9c bellard
        /* Compare two registers */
1142 6af0bf9c bellard
        if (rs != rt) {
1143 6af0bf9c bellard
            GEN_LOAD_REG_TN(T0, rs);
1144 6af0bf9c bellard
            GEN_LOAD_REG_TN(T1, rt);
1145 6af0bf9c bellard
            bcond = 1;
1146 6af0bf9c bellard
        }
1147 6af0bf9c bellard
        btarget = ctx->pc + 4 + offset;
1148 6af0bf9c bellard
        break;
1149 6af0bf9c bellard
    case OPC_BGEZ:
1150 6af0bf9c bellard
    case OPC_BGEZAL:
1151 6af0bf9c bellard
    case OPC_BGEZALL:
1152 6af0bf9c bellard
    case OPC_BGEZL:
1153 6af0bf9c bellard
    case OPC_BGTZ:
1154 6af0bf9c bellard
    case OPC_BGTZL:
1155 6af0bf9c bellard
    case OPC_BLEZ:
1156 6af0bf9c bellard
    case OPC_BLEZL:
1157 6af0bf9c bellard
    case OPC_BLTZ:
1158 6af0bf9c bellard
    case OPC_BLTZAL:
1159 6af0bf9c bellard
    case OPC_BLTZALL:
1160 6af0bf9c bellard
    case OPC_BLTZL:
1161 6af0bf9c bellard
        /* Compare to zero */
1162 6af0bf9c bellard
        if (rs != 0) {
1163 6af0bf9c bellard
            gen_op_load_gpr_T0(rs);
1164 6af0bf9c bellard
            bcond = 1;
1165 6af0bf9c bellard
        }
1166 6af0bf9c bellard
        btarget = ctx->pc + 4 + offset;
1167 6af0bf9c bellard
        break;
1168 6af0bf9c bellard
    case OPC_J:
1169 6af0bf9c bellard
    case OPC_JAL:
1170 6af0bf9c bellard
        /* Jump to immediate */
1171 bc9ed47b bellard
        btarget = ((ctx->pc + 4) & 0xF0000000) | offset;
1172 6af0bf9c bellard
        break;
1173 6af0bf9c bellard
    case OPC_JR:
1174 6af0bf9c bellard
    case OPC_JALR:
1175 6af0bf9c bellard
        /* Jump to register */
1176 6af0bf9c bellard
        if (offset != 0) {
1177 6af0bf9c bellard
            /* Only hint = 0 is valid */
1178 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
1179 6af0bf9c bellard
            return;
1180 6af0bf9c bellard
        }
1181 6af0bf9c bellard
        GEN_LOAD_REG_TN(T2, rs);
1182 6af0bf9c bellard
        break;
1183 6af0bf9c bellard
    default:
1184 6af0bf9c bellard
        MIPS_INVAL("branch/jump");
1185 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
1186 6af0bf9c bellard
        return;
1187 6af0bf9c bellard
    }
1188 6af0bf9c bellard
    if (bcond == 0) {
1189 6af0bf9c bellard
        /* No condition to be computed */
1190 6af0bf9c bellard
        switch (opc) {
1191 6af0bf9c bellard
        case OPC_BEQ:     /* rx == rx        */
1192 6af0bf9c bellard
        case OPC_BEQL:    /* rx == rx likely */
1193 6af0bf9c bellard
        case OPC_BGEZ:    /* 0 >= 0          */
1194 6af0bf9c bellard
        case OPC_BGEZL:   /* 0 >= 0 likely   */
1195 6af0bf9c bellard
        case OPC_BLEZ:    /* 0 <= 0          */
1196 6af0bf9c bellard
        case OPC_BLEZL:   /* 0 <= 0 likely   */
1197 6af0bf9c bellard
            /* Always take */
1198 4ad40f36 bellard
            ctx->hflags |= MIPS_HFLAG_B;
1199 6af0bf9c bellard
            MIPS_DEBUG("balways");
1200 6af0bf9c bellard
            break;
1201 6af0bf9c bellard
        case OPC_BGEZAL:  /* 0 >= 0          */
1202 6af0bf9c bellard
        case OPC_BGEZALL: /* 0 >= 0 likely   */
1203 6af0bf9c bellard
            /* Always take and link */
1204 6af0bf9c bellard
            blink = 31;
1205 4ad40f36 bellard
            ctx->hflags |= MIPS_HFLAG_B;
1206 6af0bf9c bellard
            MIPS_DEBUG("balways and link");
1207 6af0bf9c bellard
            break;
1208 6af0bf9c bellard
        case OPC_BNE:     /* rx != rx        */
1209 6af0bf9c bellard
        case OPC_BGTZ:    /* 0 > 0           */
1210 6af0bf9c bellard
        case OPC_BLTZ:    /* 0 < 0           */
1211 6af0bf9c bellard
            /* Treated as NOP */
1212 6af0bf9c bellard
            MIPS_DEBUG("bnever (NOP)");
1213 6af0bf9c bellard
            return;
1214 eeef26cd bellard
        case OPC_BLTZAL:  /* 0 < 0           */
1215 eeef26cd bellard
            gen_op_set_T0(ctx->pc + 8);
1216 eeef26cd bellard
            gen_op_store_T0_gpr(31);
1217 eeef26cd bellard
            return;
1218 eeef26cd bellard
        case OPC_BLTZALL: /* 0 < 0 likely */
1219 eeef26cd bellard
            gen_op_set_T0(ctx->pc + 8);
1220 eeef26cd bellard
            gen_op_store_T0_gpr(31);
1221 eeef26cd bellard
            gen_goto_tb(ctx, 0, ctx->pc + 4);
1222 eeef26cd bellard
            return;
1223 6af0bf9c bellard
        case OPC_BNEL:    /* rx != rx likely */
1224 6af0bf9c bellard
        case OPC_BGTZL:   /* 0 > 0 likely */
1225 6af0bf9c bellard
        case OPC_BLTZL:   /* 0 < 0 likely */
1226 6af0bf9c bellard
            /* Skip the instruction in the delay slot */
1227 6af0bf9c bellard
            MIPS_DEBUG("bnever and skip");
1228 6e256c93 bellard
            gen_goto_tb(ctx, 0, ctx->pc + 4);
1229 6af0bf9c bellard
            return;
1230 6af0bf9c bellard
        case OPC_J:
1231 4ad40f36 bellard
            ctx->hflags |= MIPS_HFLAG_B;
1232 6af0bf9c bellard
            MIPS_DEBUG("j %08x", btarget);
1233 6af0bf9c bellard
            break;
1234 6af0bf9c bellard
        case OPC_JAL:
1235 6af0bf9c bellard
            blink = 31;
1236 4ad40f36 bellard
            ctx->hflags |= MIPS_HFLAG_B;
1237 6af0bf9c bellard
            MIPS_DEBUG("jal %08x", btarget);
1238 6af0bf9c bellard
            break;
1239 6af0bf9c bellard
        case OPC_JR:
1240 4ad40f36 bellard
            ctx->hflags |= MIPS_HFLAG_BR;
1241 6af0bf9c bellard
            MIPS_DEBUG("jr %s", regnames[rs]);
1242 6af0bf9c bellard
            break;
1243 6af0bf9c bellard
        case OPC_JALR:
1244 6af0bf9c bellard
            blink = rt;
1245 4ad40f36 bellard
            ctx->hflags |= MIPS_HFLAG_BR;
1246 6af0bf9c bellard
            MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
1247 6af0bf9c bellard
            break;
1248 6af0bf9c bellard
        default:
1249 6af0bf9c bellard
            MIPS_INVAL("branch/jump");
1250 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
1251 6af0bf9c bellard
            return;
1252 6af0bf9c bellard
        }
1253 6af0bf9c bellard
    } else {
1254 6af0bf9c bellard
        switch (opc) {
1255 6af0bf9c bellard
        case OPC_BEQ:
1256 6af0bf9c bellard
            gen_op_eq();
1257 6af0bf9c bellard
            MIPS_DEBUG("beq %s, %s, %08x",
1258 6af0bf9c bellard
                       regnames[rs], regnames[rt], btarget);
1259 6af0bf9c bellard
            goto not_likely;
1260 6af0bf9c bellard
        case OPC_BEQL:
1261 6af0bf9c bellard
            gen_op_eq();
1262 6af0bf9c bellard
            MIPS_DEBUG("beql %s, %s, %08x",
1263 6af0bf9c bellard
                       regnames[rs], regnames[rt], btarget);
1264 6af0bf9c bellard
            goto likely;
1265 6af0bf9c bellard
        case OPC_BNE:
1266 6af0bf9c bellard
            gen_op_ne();
1267 6af0bf9c bellard
            MIPS_DEBUG("bne %s, %s, %08x",
1268 6af0bf9c bellard
                       regnames[rs], regnames[rt], btarget);
1269 6af0bf9c bellard
            goto not_likely;
1270 6af0bf9c bellard
        case OPC_BNEL:
1271 6af0bf9c bellard
            gen_op_ne();
1272 6af0bf9c bellard
            MIPS_DEBUG("bnel %s, %s, %08x",
1273 6af0bf9c bellard
                       regnames[rs], regnames[rt], btarget);
1274 6af0bf9c bellard
            goto likely;
1275 6af0bf9c bellard
        case OPC_BGEZ:
1276 6af0bf9c bellard
            gen_op_gez();
1277 6af0bf9c bellard
            MIPS_DEBUG("bgez %s, %08x", regnames[rs], btarget);
1278 6af0bf9c bellard
            goto not_likely;
1279 6af0bf9c bellard
        case OPC_BGEZL:
1280 6af0bf9c bellard
            gen_op_gez();
1281 6af0bf9c bellard
            MIPS_DEBUG("bgezl %s, %08x", regnames[rs], btarget);
1282 6af0bf9c bellard
            goto likely;
1283 6af0bf9c bellard
        case OPC_BGEZAL:
1284 6af0bf9c bellard
            gen_op_gez();
1285 6af0bf9c bellard
            MIPS_DEBUG("bgezal %s, %08x", regnames[rs], btarget);
1286 6af0bf9c bellard
            blink = 31;
1287 6af0bf9c bellard
            goto not_likely;
1288 6af0bf9c bellard
        case OPC_BGEZALL:
1289 6af0bf9c bellard
            gen_op_gez();
1290 6af0bf9c bellard
            blink = 31;
1291 6af0bf9c bellard
            MIPS_DEBUG("bgezall %s, %08x", regnames[rs], btarget);
1292 6af0bf9c bellard
            goto likely;
1293 6af0bf9c bellard
        case OPC_BGTZ:
1294 6af0bf9c bellard
            gen_op_gtz();
1295 6af0bf9c bellard
            MIPS_DEBUG("bgtz %s, %08x", regnames[rs], btarget);
1296 6af0bf9c bellard
            goto not_likely;
1297 6af0bf9c bellard
        case OPC_BGTZL:
1298 6af0bf9c bellard
            gen_op_gtz();
1299 6af0bf9c bellard
            MIPS_DEBUG("bgtzl %s, %08x", regnames[rs], btarget);
1300 6af0bf9c bellard
            goto likely;
1301 6af0bf9c bellard
        case OPC_BLEZ:
1302 6af0bf9c bellard
            gen_op_lez();
1303 6af0bf9c bellard
            MIPS_DEBUG("blez %s, %08x", regnames[rs], btarget);
1304 6af0bf9c bellard
            goto not_likely;
1305 6af0bf9c bellard
        case OPC_BLEZL:
1306 6af0bf9c bellard
            gen_op_lez();
1307 6af0bf9c bellard
            MIPS_DEBUG("blezl %s, %08x", regnames[rs], btarget);
1308 6af0bf9c bellard
            goto likely;
1309 6af0bf9c bellard
        case OPC_BLTZ:
1310 6af0bf9c bellard
            gen_op_ltz();
1311 6af0bf9c bellard
            MIPS_DEBUG("bltz %s, %08x", regnames[rs], btarget);
1312 6af0bf9c bellard
            goto not_likely;
1313 6af0bf9c bellard
        case OPC_BLTZL:
1314 6af0bf9c bellard
            gen_op_ltz();
1315 6af0bf9c bellard
            MIPS_DEBUG("bltzl %s, %08x", regnames[rs], btarget);
1316 6af0bf9c bellard
            goto likely;
1317 6af0bf9c bellard
        case OPC_BLTZAL:
1318 6af0bf9c bellard
            gen_op_ltz();
1319 6af0bf9c bellard
            blink = 31;
1320 6af0bf9c bellard
            MIPS_DEBUG("bltzal %s, %08x", regnames[rs], btarget);
1321 6af0bf9c bellard
        not_likely:
1322 4ad40f36 bellard
            ctx->hflags |= MIPS_HFLAG_BC;
1323 6af0bf9c bellard
            break;
1324 6af0bf9c bellard
        case OPC_BLTZALL:
1325 6af0bf9c bellard
            gen_op_ltz();
1326 6af0bf9c bellard
            blink = 31;
1327 6af0bf9c bellard
            MIPS_DEBUG("bltzall %s, %08x", regnames[rs], btarget);
1328 6af0bf9c bellard
        likely:
1329 4ad40f36 bellard
            ctx->hflags |= MIPS_HFLAG_BL;
1330 6af0bf9c bellard
            break;
1331 6af0bf9c bellard
        }
1332 6af0bf9c bellard
        gen_op_set_bcond();
1333 6af0bf9c bellard
    }
1334 6af0bf9c bellard
    MIPS_DEBUG("enter ds: link %d cond %02x target %08x",
1335 6af0bf9c bellard
               blink, ctx->hflags, btarget);
1336 6af0bf9c bellard
    ctx->btarget = btarget;
1337 6af0bf9c bellard
    if (blink > 0) {
1338 6af0bf9c bellard
        gen_op_set_T0(ctx->pc + 8);
1339 6af0bf9c bellard
        gen_op_store_T0_gpr(blink);
1340 6af0bf9c bellard
    }
1341 6af0bf9c bellard
    return;
1342 6af0bf9c bellard
}
1343 6af0bf9c bellard
1344 6af0bf9c bellard
/* CP0 (MMU and control) */
1345 6af0bf9c bellard
static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd)
1346 6af0bf9c bellard
{
1347 6af0bf9c bellard
    const unsigned char *opn = "unk";
1348 6af0bf9c bellard
1349 bc2c3909 bellard
    if (!(ctx->CP0_Status & (1 << CP0St_CU0)) &&
1350 cd7dd10f bellard
        (ctx->hflags & MIPS_HFLAG_UM) &&
1351 bc2c3909 bellard
        !(ctx->hflags & MIPS_HFLAG_ERL) &&
1352 bc2c3909 bellard
        !(ctx->hflags & MIPS_HFLAG_EXL)) {
1353 6af0bf9c bellard
        if (loglevel & CPU_LOG_TB_IN_ASM) {
1354 6af0bf9c bellard
            fprintf(logfile, "CP0 is not usable\n");
1355 6af0bf9c bellard
        }
1356 4ad40f36 bellard
        generate_exception_err (ctx, EXCP_CpU, 0);
1357 6af0bf9c bellard
        return;
1358 6af0bf9c bellard
    }
1359 6af0bf9c bellard
    switch (opc) {
1360 6af0bf9c bellard
    case OPC_MFC0:
1361 6af0bf9c bellard
        if (rt == 0) {
1362 6af0bf9c bellard
            /* Treat as NOP */
1363 6af0bf9c bellard
            return;
1364 6af0bf9c bellard
        }
1365 6af0bf9c bellard
        gen_op_mfc0(rd, ctx->opcode & 0x7);
1366 6af0bf9c bellard
        gen_op_store_T0_gpr(rt);
1367 6af0bf9c bellard
        opn = "mfc0";
1368 6af0bf9c bellard
        break;
1369 6af0bf9c bellard
    case OPC_MTC0:
1370 6af0bf9c bellard
        /* If we get an exception, we want to restart at next instruction */
1371 6af0bf9c bellard
        ctx->pc += 4;
1372 6af0bf9c bellard
        save_cpu_state(ctx, 1);
1373 6af0bf9c bellard
        ctx->pc -= 4;
1374 6af0bf9c bellard
        GEN_LOAD_REG_TN(T0, rt);
1375 6af0bf9c bellard
        gen_op_mtc0(rd, ctx->opcode & 0x7);
1376 6af0bf9c bellard
        /* Stop translation as we may have switched the execution mode */
1377 6af0bf9c bellard
        ctx->bstate = BS_STOP;
1378 6af0bf9c bellard
        opn = "mtc0";
1379 6af0bf9c bellard
        break;
1380 6af0bf9c bellard
#if defined(MIPS_USES_R4K_TLB)
1381 6af0bf9c bellard
    case OPC_TLBWI:
1382 6af0bf9c bellard
        gen_op_tlbwi();
1383 6af0bf9c bellard
        opn = "tlbwi";
1384 6af0bf9c bellard
        break;
1385 6af0bf9c bellard
    case OPC_TLBWR:
1386 6af0bf9c bellard
        gen_op_tlbwr();
1387 6af0bf9c bellard
        opn = "tlbwr";
1388 6af0bf9c bellard
        break;
1389 6af0bf9c bellard
    case OPC_TLBP:
1390 6af0bf9c bellard
        gen_op_tlbp();
1391 6af0bf9c bellard
        opn = "tlbp";
1392 6af0bf9c bellard
        break;
1393 6af0bf9c bellard
    case OPC_TLBR:
1394 6af0bf9c bellard
        gen_op_tlbr();
1395 6af0bf9c bellard
        opn = "tlbr";
1396 6af0bf9c bellard
        break;
1397 6af0bf9c bellard
#endif
1398 6af0bf9c bellard
    case OPC_ERET:
1399 6af0bf9c bellard
        opn = "eret";
1400 6af0bf9c bellard
        save_cpu_state(ctx, 0);
1401 6af0bf9c bellard
        gen_op_eret();
1402 6af0bf9c bellard
        ctx->bstate = BS_EXCP;
1403 6af0bf9c bellard
        break;
1404 6af0bf9c bellard
    case OPC_DERET:
1405 6af0bf9c bellard
        opn = "deret";
1406 6af0bf9c bellard
        if (!(ctx->hflags & MIPS_HFLAG_DM)) {
1407 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
1408 6af0bf9c bellard
        } else {
1409 6af0bf9c bellard
            save_cpu_state(ctx, 0);
1410 6af0bf9c bellard
            gen_op_deret();
1411 6af0bf9c bellard
            ctx->bstate = BS_EXCP;
1412 6af0bf9c bellard
        }
1413 6af0bf9c bellard
        break;
1414 4ad40f36 bellard
    case OPC_WAIT:
1415 4ad40f36 bellard
        opn = "wait";
1416 4ad40f36 bellard
        /* If we get an exception, we want to restart at next instruction */
1417 4ad40f36 bellard
        ctx->pc += 4;
1418 4ad40f36 bellard
        save_cpu_state(ctx, 1);
1419 4ad40f36 bellard
        ctx->pc -= 4;
1420 4ad40f36 bellard
        gen_op_wait();
1421 4ad40f36 bellard
        ctx->bstate = BS_EXCP;
1422 4ad40f36 bellard
        break;
1423 6af0bf9c bellard
    default:
1424 6af0bf9c bellard
        if (loglevel & CPU_LOG_TB_IN_ASM) {
1425 6af0bf9c bellard
            fprintf(logfile, "Invalid CP0 opcode: %08x %03x %03x %03x\n",
1426 6af0bf9c bellard
                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
1427 6af0bf9c bellard
                    ((ctx->opcode >> 16) & 0x1F));
1428 6af0bf9c bellard
        }
1429 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
1430 6af0bf9c bellard
        return;
1431 6af0bf9c bellard
    }
1432 6af0bf9c bellard
    MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
1433 6af0bf9c bellard
}
1434 6af0bf9c bellard
1435 6ea83fed bellard
#ifdef MIPS_USES_FPU
1436 6ea83fed bellard
/* CP1 Branches (before delay slot) */
1437 6ea83fed bellard
static void gen_compute_branch1 (DisasContext *ctx, uint16_t cond,
1438 6ea83fed bellard
                                 int32_t offset)
1439 6ea83fed bellard
{
1440 6ea83fed bellard
    target_ulong btarget;
1441 6ea83fed bellard
1442 6ea83fed bellard
    btarget = ctx->pc + 4 + offset;
1443 6ea83fed bellard
1444 6ea83fed bellard
    switch (cond) {
1445 6ea83fed bellard
    case 0x0000: /* bc1f */
1446 6ea83fed bellard
        gen_op_bc1f();
1447 6ea83fed bellard
        MIPS_DEBUG("bc1f %08x", btarget);
1448 6ea83fed bellard
        goto not_likely;
1449 6ea83fed bellard
    case 0x0002: /* bc1fl */
1450 6ea83fed bellard
        gen_op_bc1f();
1451 6ea83fed bellard
        MIPS_DEBUG("bc1fl %08x", btarget);
1452 6ea83fed bellard
        goto likely;
1453 6ea83fed bellard
    case 0x0001: /* bc1t */
1454 6ea83fed bellard
        gen_op_bc1t();
1455 6ea83fed bellard
        MIPS_DEBUG("bc1t %08x", btarget);
1456 6ea83fed bellard
    not_likely:
1457 6ea83fed bellard
        ctx->hflags |= MIPS_HFLAG_BC;
1458 6ea83fed bellard
        break;
1459 6ea83fed bellard
    case 0x0003: /* bc1tl */
1460 6ea83fed bellard
        gen_op_bc1t();
1461 6ea83fed bellard
        MIPS_DEBUG("bc1tl %08x", btarget);
1462 6ea83fed bellard
    likely:
1463 6ea83fed bellard
        ctx->hflags |= MIPS_HFLAG_BL;
1464 6ea83fed bellard
        break;
1465 6ea83fed bellard
    default:    
1466 6ea83fed bellard
        MIPS_INVAL("cp1 branch/jump");
1467 6ea83fed bellard
        generate_exception(ctx, EXCP_RI);
1468 6ea83fed bellard
        return;
1469 6ea83fed bellard
    }
1470 6ea83fed bellard
    gen_op_set_bcond();
1471 6ea83fed bellard
1472 6ea83fed bellard
    MIPS_DEBUG("enter ds: cond %02x target %08x",
1473 6ea83fed bellard
               ctx->hflags, btarget);
1474 6ea83fed bellard
    ctx->btarget = btarget;
1475 6ea83fed bellard
1476 6ea83fed bellard
    return;
1477 6ea83fed bellard
}
1478 6ea83fed bellard
1479 6af0bf9c bellard
/* Coprocessor 1 (FPU) */
1480 6ea83fed bellard
static void gen_cp1 (DisasContext *ctx, uint16_t opc, int rt, int fs)
1481 6ea83fed bellard
{
1482 6ea83fed bellard
    const unsigned char *opn = "unk";
1483 6ea83fed bellard
1484 6ea83fed bellard
    switch (opc) {
1485 6ea83fed bellard
    case OPC_MFC1:
1486 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
1487 6ea83fed bellard
        gen_op_mfc1();
1488 6ea83fed bellard
        GEN_STORE_TN_REG(rt, T0);
1489 6ea83fed bellard
        opn = "mfc1";
1490 6ea83fed bellard
        break;
1491 6ea83fed bellard
    case OPC_MTC1:
1492 6ea83fed bellard
        GEN_LOAD_REG_TN(T0, rt);
1493 6ea83fed bellard
        gen_op_mtc1();
1494 6ea83fed bellard
        GEN_STORE_FTN_FREG(fs, WT0);
1495 6ea83fed bellard
        opn = "mtc1";
1496 6ea83fed bellard
        break;
1497 6ea83fed bellard
    case OPC_CFC1:
1498 6ea83fed bellard
        if (fs != 0 && fs != 31) {
1499 6ea83fed bellard
            MIPS_INVAL("cfc1 freg");
1500 6ea83fed bellard
            generate_exception(ctx, EXCP_RI);
1501 6ea83fed bellard
            return;
1502 6ea83fed bellard
        }
1503 6ea83fed bellard
        GEN_LOAD_IMM_TN(T1, fs);
1504 6ea83fed bellard
        gen_op_cfc1();
1505 6ea83fed bellard
        GEN_STORE_TN_REG(rt, T0);
1506 6ea83fed bellard
        opn = "cfc1";
1507 6ea83fed bellard
        break;
1508 6ea83fed bellard
    case OPC_CTC1:
1509 6ea83fed bellard
        if (fs != 0 && fs != 31) {
1510 6ea83fed bellard
            MIPS_INVAL("ctc1 freg");
1511 6ea83fed bellard
            generate_exception(ctx, EXCP_RI);
1512 6ea83fed bellard
            return;
1513 6ea83fed bellard
        }
1514 6ea83fed bellard
        GEN_LOAD_IMM_TN(T1, fs);
1515 6ea83fed bellard
        GEN_LOAD_REG_TN(T0, rt);
1516 6ea83fed bellard
        gen_op_ctc1();
1517 6ea83fed bellard
        opn = "ctc1";
1518 6ea83fed bellard
        break;
1519 6ea83fed bellard
    default:
1520 6ea83fed bellard
        if (loglevel & CPU_LOG_TB_IN_ASM) {
1521 6ea83fed bellard
            fprintf(logfile, "Invalid CP1 opcode: %08x %03x %03x %03x\n",
1522 6ea83fed bellard
                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
1523 6ea83fed bellard
                    ((ctx->opcode >> 16) & 0x1F));
1524 6ea83fed bellard
        }
1525 6ea83fed bellard
        generate_exception(ctx, EXCP_RI);
1526 6ea83fed bellard
        return;
1527 6ea83fed bellard
    }
1528 6ea83fed bellard
    MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
1529 6ea83fed bellard
}
1530 6ea83fed bellard
1531 6ea83fed bellard
/* verify if floating point register is valid; an operation is not defined
1532 6ea83fed bellard
 * if bit 0 of any register specification is set and the FR bit in the
1533 6ea83fed bellard
 * Status register equals zero, since the register numbers specify an
1534 6ea83fed bellard
 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1535 6ea83fed bellard
 * in the Status register equals one, both even and odd register numbers
1536 6ea83fed bellard
 * are valid.
1537 6ea83fed bellard
 * 
1538 6ea83fed bellard
 * Multiple float registers can be checked by calling
1539 6ea83fed bellard
 * CHECK_FR(ctx, freg1 | freg2 | ... | fregN);
1540 6ea83fed bellard
 */
1541 6ea83fed bellard
#define CHECK_FR(ctx, freg) do { \
1542 6ea83fed bellard
        if (!((ctx)->CP0_Status & (1<<CP0St_FR)) && ((freg) & 1)) { \
1543 6ea83fed bellard
            generate_exception(ctx, EXCP_RI); \
1544 6ea83fed bellard
            return; \
1545 6ea83fed bellard
        } \
1546 6ea83fed bellard
    } while(0)
1547 6ea83fed bellard
1548 6ea83fed bellard
#define FOP(func, fmt) (((fmt) << 21) | (func))
1549 6ea83fed bellard
1550 6ea83fed bellard
static void gen_farith (DisasContext *ctx, int fmt, int ft, int fs, int fd, int func)
1551 6ea83fed bellard
{
1552 6ea83fed bellard
    const unsigned char *opn = "unk";
1553 6ea83fed bellard
    const char *condnames[] = {
1554 6ea83fed bellard
            "c.f",
1555 6ea83fed bellard
            "c.un",
1556 6ea83fed bellard
            "c.eq",
1557 6ea83fed bellard
            "c.ueq",
1558 6ea83fed bellard
            "c.olt",
1559 6ea83fed bellard
            "c.ult",
1560 6ea83fed bellard
            "c.ole",
1561 6ea83fed bellard
            "c.ule",
1562 6ea83fed bellard
            "c.sf",
1563 6ea83fed bellard
            "c.ngle",
1564 6ea83fed bellard
            "c.seq",
1565 6ea83fed bellard
            "c.ngl",
1566 6ea83fed bellard
            "c.lt",
1567 6ea83fed bellard
            "c.nge",
1568 6ea83fed bellard
            "c.le",
1569 6ea83fed bellard
            "c.ngt",
1570 6ea83fed bellard
    };
1571 6ea83fed bellard
    int binary = 0;
1572 6ea83fed bellard
    
1573 6ea83fed bellard
    switch (ctx->opcode & FOP(0x3f, 0x1f)) {
1574 6ea83fed bellard
    case FOP(0, 17):
1575 6ea83fed bellard
        CHECK_FR(ctx, fs | ft | fd);
1576 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, fs);
1577 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT1, ft);
1578 6ea83fed bellard
        gen_op_float_add_d();
1579 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, DT2);
1580 6ea83fed bellard
        opn = "add.d";
1581 6ea83fed bellard
        binary = 1;
1582 6ea83fed bellard
        break;
1583 6ea83fed bellard
    case FOP(1, 17):
1584 6ea83fed bellard
        CHECK_FR(ctx, fs | ft | fd);
1585 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, fs);
1586 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT1, ft);
1587 6ea83fed bellard
        gen_op_float_sub_d();
1588 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, DT2);
1589 6ea83fed bellard
        opn = "sub.d";
1590 6ea83fed bellard
        binary = 1;
1591 6ea83fed bellard
        break;
1592 6ea83fed bellard
    case FOP(2, 17):
1593 6ea83fed bellard
        CHECK_FR(ctx, fs | ft | fd);
1594 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, fs);
1595 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT1, ft);
1596 6ea83fed bellard
        gen_op_float_mul_d();
1597 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, DT2);
1598 6ea83fed bellard
        opn = "mul.d";
1599 6ea83fed bellard
        binary = 1;
1600 6ea83fed bellard
        break;
1601 6ea83fed bellard
    case FOP(3, 17):
1602 6ea83fed bellard
        CHECK_FR(ctx, fs | ft | fd);
1603 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, fs);
1604 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT1, ft);
1605 6ea83fed bellard
        gen_op_float_div_d();
1606 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, DT2);
1607 6ea83fed bellard
        opn = "div.d";
1608 6ea83fed bellard
        binary = 1;
1609 6ea83fed bellard
        break;
1610 6ea83fed bellard
    case FOP(4, 17):
1611 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
1612 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, fs);
1613 6ea83fed bellard
        gen_op_float_sqrt_d();
1614 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, DT2);
1615 6ea83fed bellard
        opn = "sqrt.d";
1616 6ea83fed bellard
        break;
1617 6ea83fed bellard
    case FOP(5, 17):
1618 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
1619 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, fs);
1620 6ea83fed bellard
        gen_op_float_abs_d();
1621 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, DT2);
1622 6ea83fed bellard
        opn = "abs.d";
1623 6ea83fed bellard
        break;
1624 6ea83fed bellard
    case FOP(6, 17):
1625 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
1626 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, fs);
1627 6ea83fed bellard
        gen_op_float_mov_d();
1628 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, DT2);
1629 6ea83fed bellard
        opn = "mov.d";
1630 6ea83fed bellard
        break;
1631 6ea83fed bellard
    case FOP(7, 17):
1632 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
1633 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, fs);
1634 6ea83fed bellard
        gen_op_float_chs_d();
1635 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, DT2);
1636 6ea83fed bellard
        opn = "neg.d";
1637 6ea83fed bellard
        break;
1638 6ea83fed bellard
    /*  8 - round.l */
1639 6ea83fed bellard
    /*  9 - trunc.l */
1640 6ea83fed bellard
    /* 10 - ceil.l  */
1641 6ea83fed bellard
    /* 11 - floor.l */
1642 6ea83fed bellard
    case FOP(12, 17):
1643 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
1644 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, fs);
1645 6ea83fed bellard
        gen_op_float_roundw_d();
1646 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
1647 6ea83fed bellard
        opn = "round.w.d";
1648 6ea83fed bellard
        break;
1649 6ea83fed bellard
    case FOP(13, 17):
1650 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
1651 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, fs);
1652 6ea83fed bellard
        gen_op_float_truncw_d();
1653 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
1654 6ea83fed bellard
        opn = "trunc.w.d";
1655 6ea83fed bellard
        break;
1656 6ea83fed bellard
    case FOP(14, 17):
1657 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
1658 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, fs);
1659 6ea83fed bellard
        gen_op_float_ceilw_d();
1660 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
1661 6ea83fed bellard
        opn = "ceil.w.d";
1662 6ea83fed bellard
        break;
1663 6ea83fed bellard
    case FOP(15, 17):
1664 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
1665 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, fs);
1666 6ea83fed bellard
        gen_op_float_floorw_d();
1667 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
1668 6ea83fed bellard
        opn = "ceil.w.d";
1669 6ea83fed bellard
        break;
1670 6ea83fed bellard
    case FOP(33, 20): /* cvt.d.w */
1671 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
1672 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
1673 6ea83fed bellard
        gen_op_float_cvtd_w();
1674 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, DT2);
1675 6ea83fed bellard
        opn = "cvt.d.w";
1676 6ea83fed bellard
        break;
1677 6ea83fed bellard
    case FOP(48, 17):
1678 6ea83fed bellard
    case FOP(49, 17):
1679 6ea83fed bellard
    case FOP(50, 17):
1680 6ea83fed bellard
    case FOP(51, 17):
1681 6ea83fed bellard
    case FOP(52, 17):
1682 6ea83fed bellard
    case FOP(53, 17):
1683 6ea83fed bellard
    case FOP(54, 17):
1684 6ea83fed bellard
    case FOP(55, 17):
1685 6ea83fed bellard
    case FOP(56, 17):
1686 6ea83fed bellard
    case FOP(57, 17):
1687 6ea83fed bellard
    case FOP(58, 17):
1688 6ea83fed bellard
    case FOP(59, 17):
1689 6ea83fed bellard
    case FOP(60, 17):
1690 6ea83fed bellard
    case FOP(61, 17):
1691 6ea83fed bellard
    case FOP(62, 17):
1692 6ea83fed bellard
    case FOP(63, 17):
1693 6ea83fed bellard
        CHECK_FR(ctx, fs | ft);
1694 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT0, fs);
1695 6ea83fed bellard
        GEN_LOAD_FREG_FTN(DT1, ft);
1696 6ea83fed bellard
        gen_cmp_d(func-48);
1697 6ea83fed bellard
        opn = condnames[func-48];
1698 6ea83fed bellard
        break;
1699 6ea83fed bellard
    case FOP(0, 16):
1700 6ea83fed bellard
        CHECK_FR(ctx, fs | ft | fd);
1701 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
1702 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT1, ft);
1703 6ea83fed bellard
        gen_op_float_add_s();
1704 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
1705 6ea83fed bellard
        opn = "add.s";
1706 6ea83fed bellard
        binary = 1;
1707 6ea83fed bellard
        break;
1708 6ea83fed bellard
    case FOP(1, 16):
1709 6ea83fed bellard
        CHECK_FR(ctx, fs | ft | fd);
1710 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
1711 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT1, ft);
1712 6ea83fed bellard
        gen_op_float_sub_s();
1713 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
1714 6ea83fed bellard
        opn = "sub.s";
1715 6ea83fed bellard
        binary = 1;
1716 6ea83fed bellard
        break;
1717 6ea83fed bellard
    case FOP(2, 16):
1718 6ea83fed bellard
        CHECK_FR(ctx, fs | ft | fd);
1719 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
1720 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT1, ft);
1721 6ea83fed bellard
        gen_op_float_mul_s();
1722 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
1723 6ea83fed bellard
        opn = "mul.s";
1724 6ea83fed bellard
        binary = 1;
1725 6ea83fed bellard
        break;
1726 6ea83fed bellard
    case FOP(3, 16):
1727 6ea83fed bellard
        CHECK_FR(ctx, fs | ft | fd);
1728 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
1729 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT1, ft);
1730 6ea83fed bellard
        gen_op_float_div_s();
1731 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
1732 6ea83fed bellard
        opn = "div.s";
1733 6ea83fed bellard
        binary = 1;
1734 6ea83fed bellard
        break;
1735 6ea83fed bellard
    case FOP(4, 16):
1736 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
1737 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
1738 6ea83fed bellard
        gen_op_float_sqrt_s();
1739 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
1740 6ea83fed bellard
        opn = "sqrt.s";
1741 6ea83fed bellard
        break;
1742 6ea83fed bellard
    case FOP(5, 16):
1743 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
1744 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
1745 6ea83fed bellard
        gen_op_float_abs_s();
1746 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
1747 6ea83fed bellard
        opn = "abs.s";
1748 6ea83fed bellard
        break;
1749 6ea83fed bellard
    case FOP(6, 16):
1750 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
1751 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
1752 6ea83fed bellard
        gen_op_float_mov_s();
1753 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
1754 6ea83fed bellard
        opn = "mov.s";
1755 6ea83fed bellard
        break;
1756 6ea83fed bellard
    case FOP(7, 16):
1757 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
1758 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
1759 6ea83fed bellard
        gen_op_float_chs_s();
1760 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
1761 6ea83fed bellard
        opn = "neg.s";
1762 6ea83fed bellard
        break;
1763 6ea83fed bellard
    case FOP(12, 16):
1764 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
1765 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
1766 6ea83fed bellard
        gen_op_float_roundw_s();
1767 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
1768 6ea83fed bellard
        opn = "round.w.s";
1769 6ea83fed bellard
        break;
1770 6ea83fed bellard
    case FOP(13, 16):
1771 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
1772 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
1773 6ea83fed bellard
        gen_op_float_truncw_s();
1774 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
1775 6ea83fed bellard
        opn = "trunc.w.s";
1776 6ea83fed bellard
        break;
1777 6ea83fed bellard
    case FOP(32, 20): /* cvt.s.w */
1778 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
1779 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
1780 6ea83fed bellard
        gen_op_float_cvts_w();
1781 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
1782 6ea83fed bellard
        opn = "cvt.s.w";
1783 6ea83fed bellard
        break;
1784 6ea83fed bellard
    case FOP(36, 16): /* cvt.w.s */
1785 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
1786 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
1787 6ea83fed bellard
        gen_op_float_cvtw_s();
1788 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
1789 6ea83fed bellard
        opn = "cvt.w.s";
1790 6ea83fed bellard
        break;
1791 6ea83fed bellard
    case FOP(36, 17): /* cvt.w.d */
1792 6ea83fed bellard
        CHECK_FR(ctx, fs | fd);
1793 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
1794 6ea83fed bellard
        gen_op_float_cvtw_d();
1795 6ea83fed bellard
        GEN_STORE_FTN_FREG(fd, WT2);
1796 6ea83fed bellard
        opn = "cvt.w.d";
1797 6ea83fed bellard
        break;
1798 6ea83fed bellard
    case FOP(48, 16):
1799 6ea83fed bellard
    case FOP(49, 16):
1800 6ea83fed bellard
    case FOP(50, 16):
1801 6ea83fed bellard
    case FOP(51, 16):
1802 6ea83fed bellard
    case FOP(52, 16):
1803 6ea83fed bellard
    case FOP(53, 16):
1804 6ea83fed bellard
    case FOP(54, 16):
1805 6ea83fed bellard
    case FOP(55, 16):
1806 6ea83fed bellard
    case FOP(56, 16):
1807 6ea83fed bellard
    case FOP(57, 16):
1808 6ea83fed bellard
    case FOP(58, 16):
1809 6ea83fed bellard
    case FOP(59, 16):
1810 6ea83fed bellard
    case FOP(60, 16):
1811 6ea83fed bellard
    case FOP(61, 16):
1812 6ea83fed bellard
    case FOP(62, 16):
1813 6ea83fed bellard
    case FOP(63, 16):
1814 6ea83fed bellard
        CHECK_FR(ctx, fs | ft);
1815 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT0, fs);
1816 6ea83fed bellard
        GEN_LOAD_FREG_FTN(WT1, ft);
1817 6ea83fed bellard
        gen_cmp_s(func-48);
1818 6ea83fed bellard
        opn = condnames[func-48];
1819 6ea83fed bellard
        break;
1820 6ea83fed bellard
    default:    
1821 6ea83fed bellard
        if (loglevel & CPU_LOG_TB_IN_ASM) {
1822 6ea83fed bellard
            fprintf(logfile, "Invalid arith function: %08x %03x %03x %03x\n",
1823 6ea83fed bellard
                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
1824 6ea83fed bellard
                    ((ctx->opcode >> 16) & 0x1F));
1825 6ea83fed bellard
        }
1826 6ea83fed bellard
        generate_exception(ctx, EXCP_RI);
1827 6ea83fed bellard
        return;
1828 6ea83fed bellard
    }
1829 6ea83fed bellard
    if (binary)
1830 6ea83fed bellard
        MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
1831 6ea83fed bellard
    else
1832 6ea83fed bellard
        MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
1833 6ea83fed bellard
}
1834 6ea83fed bellard
#endif
1835 6af0bf9c bellard
1836 6af0bf9c bellard
/* ISA extensions */
1837 6af0bf9c bellard
/* MIPS16 extension to MIPS32 */
1838 6af0bf9c bellard
/* SmartMIPS extension to MIPS32 */
1839 6af0bf9c bellard
1840 6af0bf9c bellard
#ifdef TARGET_MIPS64
1841 6af0bf9c bellard
static void gen_arith64 (DisasContext *ctx, uint16_t opc)
1842 6af0bf9c bellard
{
1843 6af0bf9c bellard
    if (func == 0x02 && rd == 0) {
1844 6af0bf9c bellard
        /* NOP */
1845 6af0bf9c bellard
        return;
1846 6af0bf9c bellard
    }
1847 6af0bf9c bellard
    if (rs == 0 || rt == 0) {
1848 6af0bf9c bellard
        gen_op_reset_T0();
1849 6af0bf9c bellard
        gen_op_save64();
1850 6af0bf9c bellard
    } else {
1851 6af0bf9c bellard
        gen_op_load_gpr_T0(rs);
1852 6af0bf9c bellard
        gen_op_load_gpr_T1(rt);
1853 6af0bf9c bellard
        gen_op_save64();
1854 6af0bf9c bellard
        if (func & 0x01)
1855 6af0bf9c bellard
            gen_op_mul64u();
1856 6af0bf9c bellard
        else
1857 6af0bf9c bellard
            gen_op_mul64s();
1858 6af0bf9c bellard
    }
1859 6af0bf9c bellard
    if (func & 0x02)
1860 6af0bf9c bellard
        gen_op_add64();
1861 6af0bf9c bellard
    else
1862 6af0bf9c bellard
        gen_op_sub64();
1863 6af0bf9c bellard
}
1864 6af0bf9c bellard
1865 6af0bf9c bellard
/* Coprocessor 3 (FPU) */
1866 6af0bf9c bellard
1867 6af0bf9c bellard
/* MDMX extension to MIPS64 */
1868 6af0bf9c bellard
/* MIPS-3D extension to MIPS64 */
1869 6af0bf9c bellard
1870 6af0bf9c bellard
#endif
1871 6af0bf9c bellard
1872 c53be334 bellard
static void gen_blikely(DisasContext *ctx)
1873 c53be334 bellard
{
1874 eeef26cd bellard
    int l1;
1875 eeef26cd bellard
    l1 = gen_new_label();
1876 eeef26cd bellard
    gen_op_jnz_T2(l1);
1877 4ad40f36 bellard
    gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
1878 eeef26cd bellard
    gen_goto_tb(ctx, 1, ctx->pc + 4);
1879 eeef26cd bellard
    gen_set_label(l1);
1880 c53be334 bellard
}
1881 c53be334 bellard
1882 6af0bf9c bellard
static void decode_opc (DisasContext *ctx)
1883 6af0bf9c bellard
{
1884 6af0bf9c bellard
    int32_t offset;
1885 6af0bf9c bellard
    int rs, rt, rd, sa;
1886 6af0bf9c bellard
    uint16_t op, op1;
1887 6af0bf9c bellard
    int16_t imm;
1888 6af0bf9c bellard
1889 4ad40f36 bellard
    if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
1890 6af0bf9c bellard
        /* Handle blikely not taken case */
1891 6af0bf9c bellard
        MIPS_DEBUG("blikely condition (%08x)", ctx->pc + 4);
1892 c53be334 bellard
        gen_blikely(ctx);
1893 6af0bf9c bellard
    }
1894 6af0bf9c bellard
    op = ctx->opcode >> 26;
1895 6af0bf9c bellard
    rs = ((ctx->opcode >> 21) & 0x1F);
1896 6af0bf9c bellard
    rt = ((ctx->opcode >> 16) & 0x1F);
1897 6af0bf9c bellard
    rd = ((ctx->opcode >> 11) & 0x1F);
1898 6af0bf9c bellard
    sa = ((ctx->opcode >> 6) & 0x1F);
1899 6af0bf9c bellard
    imm = (int16_t)ctx->opcode;
1900 6af0bf9c bellard
    switch (op) {
1901 6af0bf9c bellard
    case 0x00:          /* Special opcode */
1902 6af0bf9c bellard
        op1 = ctx->opcode & 0x3F;
1903 6af0bf9c bellard
        switch (op1) {
1904 6af0bf9c bellard
        case 0x00:          /* Arithmetic with immediate */
1905 6af0bf9c bellard
        case 0x02 ... 0x03:
1906 6af0bf9c bellard
            gen_arith_imm(ctx, op1 | EXT_SPECIAL, rd, rt, sa);
1907 6af0bf9c bellard
            break;
1908 6af0bf9c bellard
        case 0x04:          /* Arithmetic */
1909 6af0bf9c bellard
        case 0x06 ... 0x07:
1910 6af0bf9c bellard
        case 0x0A ... 0x0B:
1911 6af0bf9c bellard
        case 0x20 ... 0x27:
1912 6af0bf9c bellard
        case 0x2A ... 0x2B:
1913 6af0bf9c bellard
            gen_arith(ctx, op1 | EXT_SPECIAL, rd, rs, rt);
1914 6af0bf9c bellard
            break;
1915 6af0bf9c bellard
        case 0x18 ... 0x1B: /* MULT / DIV */
1916 6af0bf9c bellard
            gen_muldiv(ctx, op1 | EXT_SPECIAL, rs, rt);
1917 6af0bf9c bellard
            break;
1918 6af0bf9c bellard
        case 0x08 ... 0x09: /* Jumps */
1919 6af0bf9c bellard
            gen_compute_branch(ctx, op1 | EXT_SPECIAL, rs, rd, sa);
1920 6af0bf9c bellard
            return;
1921 6af0bf9c bellard
        case 0x30 ... 0x34: /* Traps */
1922 6af0bf9c bellard
        case 0x36:
1923 6af0bf9c bellard
            gen_trap(ctx, op1 | EXT_SPECIAL, rs, rt, -1);
1924 6af0bf9c bellard
            break;
1925 6af0bf9c bellard
        case 0x10:          /* Move from HI/LO */
1926 6af0bf9c bellard
        case 0x12:
1927 6af0bf9c bellard
            gen_HILO(ctx, op1 | EXT_SPECIAL, rd);
1928 6af0bf9c bellard
            break;
1929 6af0bf9c bellard
        case 0x11:
1930 6af0bf9c bellard
        case 0x13:          /* Move to HI/LO */
1931 6af0bf9c bellard
            gen_HILO(ctx, op1 | EXT_SPECIAL, rs);
1932 6af0bf9c bellard
            break;
1933 6af0bf9c bellard
        case 0x0C:          /* SYSCALL */
1934 6af0bf9c bellard
            generate_exception(ctx, EXCP_SYSCALL);
1935 6af0bf9c bellard
            break;
1936 6af0bf9c bellard
        case 0x0D:          /* BREAK */
1937 6af0bf9c bellard
            generate_exception(ctx, EXCP_BREAK);
1938 6af0bf9c bellard
            break;
1939 6af0bf9c bellard
        case 0x0F:          /* SYNC */
1940 6af0bf9c bellard
            /* Treat as a noop */
1941 6af0bf9c bellard
            break;
1942 6af0bf9c bellard
        case 0x05:          /* Pmon entry point */
1943 6af0bf9c bellard
            gen_op_pmon((ctx->opcode >> 6) & 0x1F);
1944 6af0bf9c bellard
            break;
1945 4ad40f36 bellard
1946 6af0bf9c bellard
        case 0x01:          /* MOVCI */
1947 4ad40f36 bellard
#if defined (MIPS_HAS_MOVCI)
1948 4ad40f36 bellard
            /* XXX */
1949 4ad40f36 bellard
#else
1950 4ad40f36 bellard
            /* Not implemented */
1951 4ad40f36 bellard
            generate_exception_err (ctx, EXCP_CpU, 1);
1952 6af0bf9c bellard
#endif
1953 4ad40f36 bellard
            break;
1954 4ad40f36 bellard
1955 6af0bf9c bellard
#if defined (TARGET_MIPS64)
1956 6af0bf9c bellard
        case 0x14: /* MIPS64 specific opcodes */
1957 6af0bf9c bellard
        case 0x16:
1958 6af0bf9c bellard
        case 0x17:
1959 6af0bf9c bellard
        case 0x1C ... 0x1F:
1960 6af0bf9c bellard
        case 0x2C ... 0x2F:
1961 6af0bf9c bellard
        case 0x37:
1962 6af0bf9c bellard
        case 0x39 ... 0x3B:
1963 6af0bf9c bellard
        case 0x3E ... 0x3F:
1964 6af0bf9c bellard
#endif
1965 6af0bf9c bellard
        default:            /* Invalid */
1966 6af0bf9c bellard
            MIPS_INVAL("special");
1967 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
1968 6af0bf9c bellard
            break;
1969 6af0bf9c bellard
        }
1970 6af0bf9c bellard
        break;
1971 6af0bf9c bellard
    case 0x1C:          /* Special2 opcode */
1972 6af0bf9c bellard
        op1 = ctx->opcode & 0x3F;
1973 6af0bf9c bellard
        switch (op1) {
1974 6af0bf9c bellard
#if defined (MIPS_USES_R4K_EXT)
1975 6af0bf9c bellard
        /* Those instructions are not part of MIPS32 core */
1976 6af0bf9c bellard
        case 0x00 ... 0x01: /* Multiply and add/sub */
1977 6af0bf9c bellard
        case 0x04 ... 0x05:
1978 6af0bf9c bellard
            gen_muldiv(ctx, op1 | EXT_SPECIAL2, rs, rt);
1979 6af0bf9c bellard
            break;
1980 6af0bf9c bellard
        case 0x02:          /* MUL */
1981 6af0bf9c bellard
            gen_arith(ctx, op1 | EXT_SPECIAL2, rd, rs, rt);
1982 6af0bf9c bellard
            break;
1983 6af0bf9c bellard
        case 0x20 ... 0x21: /* CLO / CLZ */
1984 6af0bf9c bellard
            gen_cl(ctx, op1 | EXT_SPECIAL2, rd, rs);
1985 6af0bf9c bellard
            break;
1986 6af0bf9c bellard
#endif
1987 6af0bf9c bellard
        case 0x3F:          /* SDBBP */
1988 6af0bf9c bellard
            /* XXX: not clear which exception should be raised
1989 6af0bf9c bellard
             *      when in debug mode...
1990 6af0bf9c bellard
             */
1991 6af0bf9c bellard
            if (!(ctx->hflags & MIPS_HFLAG_DM)) {
1992 6af0bf9c bellard
                generate_exception(ctx, EXCP_DBp);
1993 6af0bf9c bellard
            } else {
1994 6af0bf9c bellard
                generate_exception(ctx, EXCP_DBp);
1995 6af0bf9c bellard
            }
1996 6af0bf9c bellard
            /* Treat as a noop */
1997 6af0bf9c bellard
            break;
1998 6af0bf9c bellard
        default:            /* Invalid */
1999 6af0bf9c bellard
            MIPS_INVAL("special2");
2000 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
2001 6af0bf9c bellard
            break;
2002 6af0bf9c bellard
        }
2003 6af0bf9c bellard
        break;
2004 6af0bf9c bellard
    case 0x01:          /* B REGIMM opcode */
2005 6af0bf9c bellard
        op1 = ((ctx->opcode >> 16) & 0x1F);
2006 6af0bf9c bellard
        switch (op1) {
2007 6af0bf9c bellard
        case 0x00 ... 0x03: /* REGIMM branches */
2008 6af0bf9c bellard
        case 0x10 ... 0x13:
2009 6af0bf9c bellard
            gen_compute_branch(ctx, op1 | EXT_REGIMM, rs, -1, imm << 2);
2010 6af0bf9c bellard
            return;
2011 6af0bf9c bellard
        case 0x08 ... 0x0C: /* Traps */
2012 6af0bf9c bellard
        case 0x0E:
2013 6af0bf9c bellard
            gen_trap(ctx, op1 | EXT_REGIMM, rs, -1, imm);
2014 6af0bf9c bellard
            break;
2015 6af0bf9c bellard
        default:            /* Invalid */
2016 6af0bf9c bellard
            MIPS_INVAL("REGIMM");
2017 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
2018 6af0bf9c bellard
            break;
2019 6af0bf9c bellard
        }
2020 6af0bf9c bellard
        break;
2021 6af0bf9c bellard
    case 0x10:          /* CP0 opcode */
2022 6af0bf9c bellard
        op1 = ((ctx->opcode >> 21) & 0x1F);
2023 6af0bf9c bellard
        switch (op1) {
2024 6af0bf9c bellard
        case 0x00:
2025 6af0bf9c bellard
        case 0x04:
2026 6af0bf9c bellard
            gen_cp0(ctx, op1 | EXT_CP0, rt, rd);
2027 6af0bf9c bellard
            break;
2028 6af0bf9c bellard
        default:
2029 4ad40f36 bellard
            gen_cp0(ctx, (ctx->opcode & 0x3F) | EXT_CP0, rt, rd);
2030 6af0bf9c bellard
            break;
2031 6af0bf9c bellard
        }
2032 6af0bf9c bellard
        break;
2033 6af0bf9c bellard
    case 0x08 ... 0x0F: /* Arithmetic with immediate opcode */
2034 6af0bf9c bellard
        gen_arith_imm(ctx, op, rt, rs, imm);
2035 6af0bf9c bellard
        break;
2036 6af0bf9c bellard
    case 0x02 ... 0x03: /* Jump */
2037 6af0bf9c bellard
        offset = (int32_t)(ctx->opcode & 0x03FFFFFF) << 2;
2038 6af0bf9c bellard
        gen_compute_branch(ctx, op, rs, rt, offset);
2039 6af0bf9c bellard
        return;
2040 6af0bf9c bellard
    case 0x04 ... 0x07: /* Branch */
2041 6af0bf9c bellard
    case 0x14 ... 0x17:
2042 6af0bf9c bellard
        gen_compute_branch(ctx, op, rs, rt, imm << 2);
2043 6af0bf9c bellard
        return;
2044 6af0bf9c bellard
    case 0x20 ... 0x26: /* Load and stores */
2045 6af0bf9c bellard
    case 0x28 ... 0x2E:
2046 6af0bf9c bellard
    case 0x30:
2047 6af0bf9c bellard
    case 0x38:
2048 6af0bf9c bellard
        gen_ldst(ctx, op, rt, rs, imm);
2049 6af0bf9c bellard
        break;
2050 6af0bf9c bellard
    case 0x2F:          /* Cache operation */
2051 6af0bf9c bellard
        /* Treat as a noop */
2052 6af0bf9c bellard
        break;
2053 6af0bf9c bellard
    case 0x33:          /* Prefetch */
2054 6af0bf9c bellard
        /* Treat as a noop */
2055 6af0bf9c bellard
        break;
2056 6af0bf9c bellard
    case 0x3F: /* HACK */
2057 6af0bf9c bellard
        break;
2058 4ad40f36 bellard
2059 4ad40f36 bellard
    /* Floating point.  */
2060 4ad40f36 bellard
    case 0x31: /* LWC1 */
2061 4ad40f36 bellard
    case 0x35: /* LDC1 */
2062 4ad40f36 bellard
    case 0x39: /* SWC1 */
2063 4ad40f36 bellard
    case 0x3D: /* SDC1 */
2064 6ea83fed bellard
#if defined(MIPS_USES_FPU)
2065 6ea83fed bellard
        gen_op_cp1_enabled();
2066 6ea83fed bellard
        gen_flt_ldst(ctx, op, rt, rs, imm);
2067 6ea83fed bellard
#else
2068 6ea83fed bellard
        generate_exception_err(ctx, EXCP_CpU, 1);
2069 6ea83fed bellard
#endif
2070 6ea83fed bellard
        break;
2071 6ea83fed bellard
2072 4ad40f36 bellard
    case 0x11:          /* CP1 opcode */
2073 6af0bf9c bellard
#if defined(MIPS_USES_FPU)
2074 6ea83fed bellard
        gen_op_cp1_enabled();
2075 6ea83fed bellard
        op1 = ((ctx->opcode >> 21) & 0x1F);
2076 6ea83fed bellard
        switch (op1) {
2077 6ea83fed bellard
        case 0x00: /* mfc1 */
2078 6ea83fed bellard
        case 0x02: /* cfc1 */
2079 6ea83fed bellard
        case 0x04: /* mtc1 */
2080 6ea83fed bellard
        case 0x06: /* ctc1 */
2081 6ea83fed bellard
            gen_cp1(ctx, op1 | EXT_CP1, rt, rd);
2082 6ea83fed bellard
            break;
2083 6ea83fed bellard
        case 0x08: /* bc */
2084 6ea83fed bellard
            gen_compute_branch1(ctx, rt, imm << 2);
2085 6ea83fed bellard
            return;
2086 6ea83fed bellard
        case 0x10: /* 16: fmt=single fp */
2087 6ea83fed bellard
        case 0x11: /* 17: fmt=double fp */
2088 6ea83fed bellard
        case 0x14: /* 20: fmt=32bit fixed */
2089 6ea83fed bellard
        case 0x15: /* 21: fmt=64bit fixed */
2090 6ea83fed bellard
            gen_farith(ctx, op1, rt, rd, sa, ctx->opcode & 0x3f);
2091 6ea83fed bellard
            break;
2092 6ea83fed bellard
        default:
2093 6ea83fed bellard
            generate_exception_err(ctx, EXCP_RI, 1);
2094 6ea83fed bellard
            break;
2095 6ea83fed bellard
        }
2096 6ea83fed bellard
        break;
2097 4ad40f36 bellard
#else
2098 4ad40f36 bellard
        generate_exception_err(ctx, EXCP_CpU, 1);
2099 6af0bf9c bellard
#endif
2100 4ad40f36 bellard
        break;
2101 4ad40f36 bellard
2102 4ad40f36 bellard
    /* COP2.  */
2103 4ad40f36 bellard
    case 0x32: /* LWC2 */
2104 4ad40f36 bellard
    case 0x36: /* LDC2 */
2105 4ad40f36 bellard
    case 0x3A: /* SWC2 */
2106 4ad40f36 bellard
    case 0x3E: /* SDC2 */
2107 6af0bf9c bellard
    case 0x12:          /* CP2 opcode */
2108 6af0bf9c bellard
        /* Not implemented */
2109 4ad40f36 bellard
        generate_exception_err(ctx, EXCP_CpU, 2);
2110 4ad40f36 bellard
        break;
2111 4ad40f36 bellard
2112 6af0bf9c bellard
    case 0x13:          /* CP3 opcode */
2113 6af0bf9c bellard
        /* Not implemented */
2114 4ad40f36 bellard
        generate_exception_err(ctx, EXCP_CpU, 3);
2115 4ad40f36 bellard
        break;
2116 4ad40f36 bellard
2117 6af0bf9c bellard
#if defined (TARGET_MIPS64)
2118 6af0bf9c bellard
    case 0x18 ... 0x1B:
2119 6af0bf9c bellard
    case 0x27:
2120 6af0bf9c bellard
    case 0x34:
2121 6af0bf9c bellard
    case 0x37:
2122 6af0bf9c bellard
        /* MIPS64 opcodes */
2123 6af0bf9c bellard
#endif
2124 6af0bf9c bellard
#if defined (MIPS_HAS_JALX)
2125 6af0bf9c bellard
    case 0x1D:
2126 6af0bf9c bellard
        /* JALX: not implemented */
2127 6af0bf9c bellard
#endif
2128 6af0bf9c bellard
    case 0x1E:
2129 6af0bf9c bellard
        /* ASE specific */
2130 6af0bf9c bellard
    default:            /* Invalid */
2131 6af0bf9c bellard
        MIPS_INVAL("");
2132 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
2133 6af0bf9c bellard
        break;
2134 6af0bf9c bellard
    }
2135 4ad40f36 bellard
    if (ctx->hflags & MIPS_HFLAG_BMASK) {
2136 6af0bf9c bellard
        int hflags = ctx->hflags;
2137 6af0bf9c bellard
        /* Branches completion */
2138 4ad40f36 bellard
        ctx->hflags &= ~MIPS_HFLAG_BMASK;
2139 6af0bf9c bellard
        ctx->bstate = BS_BRANCH;
2140 6af0bf9c bellard
        save_cpu_state(ctx, 0);
2141 6af0bf9c bellard
        switch (hflags & MIPS_HFLAG_BMASK) {
2142 6af0bf9c bellard
        case MIPS_HFLAG_B:
2143 6af0bf9c bellard
            /* unconditional branch */
2144 6af0bf9c bellard
            MIPS_DEBUG("unconditional branch");
2145 6e256c93 bellard
            gen_goto_tb(ctx, 0, ctx->btarget);
2146 6af0bf9c bellard
            break;
2147 6af0bf9c bellard
        case MIPS_HFLAG_BL:
2148 6af0bf9c bellard
            /* blikely taken case */
2149 6af0bf9c bellard
            MIPS_DEBUG("blikely branch taken");
2150 6e256c93 bellard
            gen_goto_tb(ctx, 0, ctx->btarget);
2151 6af0bf9c bellard
            break;
2152 6af0bf9c bellard
        case MIPS_HFLAG_BC:
2153 6af0bf9c bellard
            /* Conditional branch */
2154 6af0bf9c bellard
            MIPS_DEBUG("conditional branch");
2155 c53be334 bellard
            {
2156 c53be334 bellard
              int l1;
2157 c53be334 bellard
              l1 = gen_new_label();
2158 c53be334 bellard
              gen_op_jnz_T2(l1);
2159 6e256c93 bellard
              gen_goto_tb(ctx, 1, ctx->pc + 4);
2160 eeef26cd bellard
              gen_set_label(l1);
2161 eeef26cd bellard
              gen_goto_tb(ctx, 0, ctx->btarget);
2162 c53be334 bellard
            }
2163 6af0bf9c bellard
            break;
2164 6af0bf9c bellard
        case MIPS_HFLAG_BR:
2165 6af0bf9c bellard
            /* unconditional branch to register */
2166 6af0bf9c bellard
            MIPS_DEBUG("branch to register");
2167 6af0bf9c bellard
            gen_op_breg();
2168 6af0bf9c bellard
            break;
2169 6af0bf9c bellard
        default:
2170 6af0bf9c bellard
            MIPS_DEBUG("unknown branch");
2171 6af0bf9c bellard
            break;
2172 6af0bf9c bellard
        }
2173 6af0bf9c bellard
    }
2174 6af0bf9c bellard
}
2175 6af0bf9c bellard
2176 6af0bf9c bellard
int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
2177 6af0bf9c bellard
                                    int search_pc)
2178 6af0bf9c bellard
{
2179 6af0bf9c bellard
    DisasContext ctx, *ctxp = &ctx;
2180 6af0bf9c bellard
    target_ulong pc_start;
2181 6af0bf9c bellard
    uint16_t *gen_opc_end;
2182 6af0bf9c bellard
    int j, lj = -1;
2183 6af0bf9c bellard
2184 4ad40f36 bellard
    if (search_pc && loglevel)
2185 6ea83fed bellard
        fprintf (logfile, "search pc %d\n", search_pc);
2186 4ad40f36 bellard
2187 6af0bf9c bellard
    pc_start = tb->pc;
2188 6af0bf9c bellard
    gen_opc_ptr = gen_opc_buf;
2189 6af0bf9c bellard
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2190 6af0bf9c bellard
    gen_opparam_ptr = gen_opparam_buf;
2191 c53be334 bellard
    nb_gen_labels = 0;
2192 6af0bf9c bellard
    ctx.pc = pc_start;
2193 4ad40f36 bellard
    ctx.saved_pc = -1;
2194 6af0bf9c bellard
    ctx.tb = tb;
2195 6af0bf9c bellard
    ctx.bstate = BS_NONE;
2196 4ad40f36 bellard
    /* Restore delay slot state from the tb context.  */
2197 4ad40f36 bellard
    ctx.hflags = tb->flags;
2198 6af0bf9c bellard
    ctx.saved_hflags = ctx.hflags;
2199 6af0bf9c bellard
    if (ctx.hflags & MIPS_HFLAG_BR) {
2200 6af0bf9c bellard
        gen_op_restore_breg_target();
2201 6af0bf9c bellard
    } else if (ctx.hflags & MIPS_HFLAG_B) {
2202 6af0bf9c bellard
        ctx.btarget = env->btarget;
2203 6af0bf9c bellard
    } else if (ctx.hflags & MIPS_HFLAG_BMASK) {
2204 6af0bf9c bellard
        /* If we are in the delay slot of a conditional branch,
2205 6af0bf9c bellard
         * restore the branch condition from env->bcond to T2
2206 6af0bf9c bellard
         */
2207 6af0bf9c bellard
        ctx.btarget = env->btarget;
2208 6af0bf9c bellard
        gen_op_restore_bcond();
2209 6af0bf9c bellard
    }
2210 6af0bf9c bellard
#if defined(CONFIG_USER_ONLY)
2211 6af0bf9c bellard
    ctx.mem_idx = 0;
2212 6af0bf9c bellard
#else
2213 3d9fb9fe bellard
    ctx.mem_idx = !((ctx.hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM);
2214 6af0bf9c bellard
#endif
2215 6af0bf9c bellard
    ctx.CP0_Status = env->CP0_Status;
2216 6af0bf9c bellard
#ifdef DEBUG_DISAS
2217 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_CPU) {
2218 6af0bf9c bellard
        fprintf(logfile, "------------------------------------------------\n");
2219 4ad40f36 bellard
        /* FIXME: This may print out stale hflags from env... */
2220 6af0bf9c bellard
        cpu_dump_state(env, logfile, fprintf, 0);
2221 6af0bf9c bellard
    }
2222 6af0bf9c bellard
#endif
2223 6af0bf9c bellard
#if defined MIPS_DEBUG_DISAS
2224 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_IN_ASM)
2225 4ad40f36 bellard
        fprintf(logfile, "\ntb %p super %d cond %04x\n",
2226 4ad40f36 bellard
                tb, ctx.mem_idx, ctx.hflags);
2227 6af0bf9c bellard
#endif
2228 6af0bf9c bellard
    while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
2229 4ad40f36 bellard
        if (env->nb_breakpoints > 0) {
2230 4ad40f36 bellard
            for(j = 0; j < env->nb_breakpoints; j++) {
2231 4ad40f36 bellard
                if (env->breakpoints[j] == ctx.pc) {
2232 4ad40f36 bellard
                    save_cpu_state(ctxp, 1);
2233 4ad40f36 bellard
                    ctx.bstate = BS_BRANCH;
2234 4ad40f36 bellard
                    gen_op_debug();
2235 4ad40f36 bellard
                    goto done_generating;
2236 4ad40f36 bellard
                }
2237 4ad40f36 bellard
            }
2238 4ad40f36 bellard
        }
2239 4ad40f36 bellard
2240 6af0bf9c bellard
        if (search_pc) {
2241 6af0bf9c bellard
            j = gen_opc_ptr - gen_opc_buf;
2242 6af0bf9c bellard
            if (lj < j) {
2243 6af0bf9c bellard
                lj++;
2244 6af0bf9c bellard
                while (lj < j)
2245 6af0bf9c bellard
                    gen_opc_instr_start[lj++] = 0;
2246 6af0bf9c bellard
            }
2247 4ad40f36 bellard
            gen_opc_pc[lj] = ctx.pc;
2248 4ad40f36 bellard
            gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
2249 4ad40f36 bellard
            gen_opc_instr_start[lj] = 1;
2250 6af0bf9c bellard
        }
2251 6af0bf9c bellard
        ctx.opcode = ldl_code(ctx.pc);
2252 6af0bf9c bellard
        decode_opc(&ctx);
2253 6af0bf9c bellard
        ctx.pc += 4;
2254 4ad40f36 bellard
2255 4ad40f36 bellard
        if (env->singlestep_enabled)
2256 4ad40f36 bellard
            break;
2257 4ad40f36 bellard
2258 6af0bf9c bellard
        if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
2259 6af0bf9c bellard
            break;
2260 4ad40f36 bellard
2261 6af0bf9c bellard
#if defined (MIPS_SINGLE_STEP)
2262 6af0bf9c bellard
        break;
2263 6af0bf9c bellard
#endif
2264 6af0bf9c bellard
    }
2265 4ad40f36 bellard
    if (env->singlestep_enabled) {
2266 4ad40f36 bellard
        save_cpu_state(ctxp, ctx.bstate == BS_NONE);
2267 4ad40f36 bellard
        gen_op_debug();
2268 4ad40f36 bellard
        goto done_generating;
2269 4ad40f36 bellard
    }
2270 4ad40f36 bellard
    else if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) {
2271 6af0bf9c bellard
        save_cpu_state(ctxp, 0);
2272 6e256c93 bellard
        gen_goto_tb(&ctx, 0, ctx.pc);
2273 6af0bf9c bellard
    }
2274 6af0bf9c bellard
    gen_op_reset_T0();
2275 6af0bf9c bellard
    /* Generate the return instruction */
2276 6af0bf9c bellard
    gen_op_exit_tb();
2277 4ad40f36 bellard
done_generating:
2278 6af0bf9c bellard
    *gen_opc_ptr = INDEX_op_end;
2279 6af0bf9c bellard
    if (search_pc) {
2280 6af0bf9c bellard
        j = gen_opc_ptr - gen_opc_buf;
2281 6af0bf9c bellard
        lj++;
2282 6af0bf9c bellard
        while (lj <= j)
2283 6af0bf9c bellard
            gen_opc_instr_start[lj++] = 0;
2284 6af0bf9c bellard
        tb->size = 0;
2285 6af0bf9c bellard
    } else {
2286 6af0bf9c bellard
        tb->size = ctx.pc - pc_start;
2287 6af0bf9c bellard
    }
2288 6af0bf9c bellard
#ifdef DEBUG_DISAS
2289 6af0bf9c bellard
#if defined MIPS_DEBUG_DISAS
2290 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_IN_ASM)
2291 6af0bf9c bellard
        fprintf(logfile, "\n");
2292 6af0bf9c bellard
#endif
2293 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2294 6af0bf9c bellard
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2295 6ea83fed bellard
    target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
2296 6af0bf9c bellard
        fprintf(logfile, "\n");
2297 6af0bf9c bellard
    }
2298 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_OP) {
2299 6af0bf9c bellard
        fprintf(logfile, "OP:\n");
2300 6af0bf9c bellard
        dump_ops(gen_opc_buf, gen_opparam_buf);
2301 6af0bf9c bellard
        fprintf(logfile, "\n");
2302 6af0bf9c bellard
    }
2303 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_CPU) {
2304 6af0bf9c bellard
        fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
2305 6af0bf9c bellard
    }
2306 6af0bf9c bellard
#endif
2307 6af0bf9c bellard
    
2308 6af0bf9c bellard
    return 0;
2309 6af0bf9c bellard
}
2310 6af0bf9c bellard
2311 6af0bf9c bellard
int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
2312 6af0bf9c bellard
{
2313 6af0bf9c bellard
    return gen_intermediate_code_internal(env, tb, 0);
2314 6af0bf9c bellard
}
2315 6af0bf9c bellard
2316 6af0bf9c bellard
int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
2317 6af0bf9c bellard
{
2318 6af0bf9c bellard
    return gen_intermediate_code_internal(env, tb, 1);
2319 6af0bf9c bellard
}
2320 6af0bf9c bellard
2321 6ea83fed bellard
#ifdef MIPS_USES_FPU
2322 6ea83fed bellard
void fpu_dump_state(CPUState *env, FILE *f, 
2323 6ea83fed bellard
                    int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
2324 6ea83fed bellard
                    int flags)
2325 6ea83fed bellard
{
2326 6ea83fed bellard
    int i;
2327 6ea83fed bellard
2328 6ea83fed bellard
#   define printfpr(fp) do { \
2329 6ea83fed bellard
        fpu_fprintf(f, "w:%08x d:%08lx%08lx fd:%g fs:%g\n", \
2330 6ea83fed bellard
                (fp)->w[FP_ENDIAN_IDX], (fp)->w[0], (fp)->w[1], (fp)->fd, (fp)->fs[FP_ENDIAN_IDX]); \
2331 6ea83fed bellard
    } while(0)
2332 6ea83fed bellard
2333 6ea83fed bellard
    fpu_fprintf(f, "CP1 FCR0 0x%08x  FCR31 0x%08x  SR.FR %d\n",
2334 6ea83fed bellard
                env->fcr0, env->fcr31,
2335 6ea83fed bellard
                (env->CP0_Status & (1<<CP0St_FR)) != 0);
2336 6ea83fed bellard
    fpu_fprintf(f, "FT0: "); printfpr(&env->ft0);
2337 6ea83fed bellard
    fpu_fprintf(f, "FT1: "); printfpr(&env->ft1);
2338 6ea83fed bellard
    fpu_fprintf(f, "FT2: "); printfpr(&env->ft2);
2339 6ea83fed bellard
    for(i=0; i < 32; i+=2) {
2340 6ea83fed bellard
        fpu_fprintf(f, "f%02d: ", i);
2341 6ea83fed bellard
        printfpr(FPR(env, i));
2342 6ea83fed bellard
    }
2343 6ea83fed bellard
2344 6ea83fed bellard
#undef printfpr
2345 6ea83fed bellard
}
2346 6ea83fed bellard
2347 6ea83fed bellard
void dump_fpu(CPUState *env)
2348 6ea83fed bellard
{
2349 6ea83fed bellard
    if (loglevel) { 
2350 6ea83fed bellard
       fprintf(logfile, "pc=0x%08x HI=0x%08x LO=0x%08x ds %04x %08x %d\n",
2351 6ea83fed bellard
               env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
2352 6ea83fed bellard
       fpu_dump_state(env, logfile, fprintf, 0);
2353 6ea83fed bellard
    }
2354 6ea83fed bellard
}
2355 6ea83fed bellard
#endif /* MIPS_USES_FPU */
2356 6ea83fed bellard
2357 6af0bf9c bellard
void cpu_dump_state (CPUState *env, FILE *f, 
2358 6af0bf9c bellard
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2359 6af0bf9c bellard
                     int flags)
2360 6af0bf9c bellard
{
2361 568b600d bellard
    uint32_t c0_status;
2362 6af0bf9c bellard
    int i;
2363 6af0bf9c bellard
    
2364 6af0bf9c bellard
    cpu_fprintf(f, "pc=0x%08x HI=0x%08x LO=0x%08x ds %04x %08x %d\n",
2365 6af0bf9c bellard
                env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
2366 6af0bf9c bellard
    for (i = 0; i < 32; i++) {
2367 6af0bf9c bellard
        if ((i & 3) == 0)
2368 6af0bf9c bellard
            cpu_fprintf(f, "GPR%02d:", i);
2369 6af0bf9c bellard
        cpu_fprintf(f, " %s %08x", regnames[i], env->gpr[i]);
2370 6af0bf9c bellard
        if ((i & 3) == 3)
2371 6af0bf9c bellard
            cpu_fprintf(f, "\n");
2372 6af0bf9c bellard
    }
2373 568b600d bellard
2374 568b600d bellard
    c0_status = env->CP0_Status;
2375 568b600d bellard
    if (env->hflags & MIPS_HFLAG_UM)
2376 568b600d bellard
        c0_status |= (1 << CP0St_UM);
2377 568b600d bellard
    if (env->hflags & MIPS_HFLAG_ERL)
2378 568b600d bellard
        c0_status |= (1 << CP0St_ERL);
2379 568b600d bellard
    if (env->hflags & MIPS_HFLAG_EXL)
2380 568b600d bellard
        c0_status |= (1 << CP0St_EXL);
2381 568b600d bellard
2382 6af0bf9c bellard
    cpu_fprintf(f, "CP0 Status  0x%08x Cause   0x%08x EPC    0x%08x\n",
2383 568b600d bellard
                c0_status, env->CP0_Cause, env->CP0_EPC);
2384 6af0bf9c bellard
    cpu_fprintf(f, "    Config0 0x%08x Config1 0x%08x LLAddr 0x%08x\n",
2385 6af0bf9c bellard
                env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
2386 6ea83fed bellard
#ifdef MIPS_USES_FPU
2387 6ea83fed bellard
    fpu_dump_state(env, f, cpu_fprintf, flags);
2388 6ea83fed bellard
#endif
2389 6af0bf9c bellard
}
2390 6af0bf9c bellard
2391 6af0bf9c bellard
CPUMIPSState *cpu_mips_init (void)
2392 6af0bf9c bellard
{
2393 6af0bf9c bellard
    CPUMIPSState *env;
2394 6af0bf9c bellard
2395 6af0bf9c bellard
    env = qemu_mallocz(sizeof(CPUMIPSState));
2396 6af0bf9c bellard
    if (!env)
2397 6af0bf9c bellard
        return NULL;
2398 173d6cfe bellard
    cpu_exec_init(env);
2399 6af0bf9c bellard
    tlb_flush(env, 1);
2400 6af0bf9c bellard
    /* Minimal init */
2401 6af0bf9c bellard
    env->PC = 0xBFC00000;
2402 6af0bf9c bellard
#if defined (MIPS_USES_R4K_TLB)
2403 6af0bf9c bellard
    env->CP0_random = MIPS_TLB_NB - 1;
2404 6af0bf9c bellard
#endif
2405 6af0bf9c bellard
    env->CP0_Wired = 0;
2406 6af0bf9c bellard
    env->CP0_Config0 = MIPS_CONFIG0;
2407 6af0bf9c bellard
#if defined (MIPS_CONFIG1)
2408 6af0bf9c bellard
        env->CP0_Config1 = MIPS_CONFIG1;
2409 6af0bf9c bellard
#endif
2410 6af0bf9c bellard
#if defined (MIPS_CONFIG2)
2411 6af0bf9c bellard
        env->CP0_Config2 = MIPS_CONFIG2;
2412 6af0bf9c bellard
#endif
2413 6af0bf9c bellard
#if defined (MIPS_CONFIG3)
2414 6af0bf9c bellard
        env->CP0_Config3 = MIPS_CONFIG3;
2415 6af0bf9c bellard
#endif
2416 6af0bf9c bellard
    env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV);
2417 6af0bf9c bellard
    env->CP0_WatchLo = 0;
2418 6af0bf9c bellard
    env->hflags = MIPS_HFLAG_ERL;
2419 6af0bf9c bellard
    /* Count register increments in debug mode, EJTAG version 1 */
2420 6af0bf9c bellard
    env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
2421 6af0bf9c bellard
    env->CP0_PRid = MIPS_CPU;
2422 6af0bf9c bellard
    env->exception_index = EXCP_NONE;
2423 eeef26cd bellard
#if defined(CONFIG_USER_ONLY)
2424 eeef26cd bellard
    env->hflags |= MIPS_HFLAG_UM;
2425 eeef26cd bellard
#endif
2426 6ea83fed bellard
#ifdef MIPS_USES_FPU
2427 6ea83fed bellard
    env->fcr0 = MIPS_FCR0;        
2428 6ea83fed bellard
#endif
2429 6af0bf9c bellard
    return env;
2430 6af0bf9c bellard
}