Statistics
| Branch: | Revision:

root / target-mips / translate.c @ 6ae81775

History | View | Annotate | Download (70.7 kB)

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