Statistics
| Branch: | Revision:

root / target-mips / translate.c @ e37e863f

History | View | Annotate | Download (47.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 6af0bf9c bellard
 *
6 6af0bf9c bellard
 * This library is free software; you can redistribute it and/or
7 6af0bf9c bellard
 * modify it under the terms of the GNU Lesser General Public
8 6af0bf9c bellard
 * License as published by the Free Software Foundation; either
9 6af0bf9c bellard
 * version 2 of the License, or (at your option) any later version.
10 6af0bf9c bellard
 *
11 6af0bf9c bellard
 * This library is distributed in the hope that it will be useful,
12 6af0bf9c bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 6af0bf9c bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 6af0bf9c bellard
 * Lesser General Public License for more details.
15 6af0bf9c bellard
 *
16 6af0bf9c bellard
 * You should have received a copy of the GNU Lesser General Public
17 6af0bf9c bellard
 * License along with this library; if not, write to the Free Software
18 6af0bf9c bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 6af0bf9c bellard
 */
20 6af0bf9c bellard
21 6af0bf9c bellard
#include <stdarg.h>
22 6af0bf9c bellard
#include <stdlib.h>
23 6af0bf9c bellard
#include <stdio.h>
24 6af0bf9c bellard
#include <string.h>
25 6af0bf9c bellard
#include <inttypes.h>
26 6af0bf9c bellard
27 6af0bf9c bellard
#include "cpu.h"
28 6af0bf9c bellard
#include "exec-all.h"
29 6af0bf9c bellard
#include "disas.h"
30 6af0bf9c bellard
31 6af0bf9c bellard
#define MIPS_DEBUG_DISAS
32 6af0bf9c bellard
//#define MIPS_SINGLE_STEP
33 6af0bf9c bellard
34 6af0bf9c bellard
enum {
35 6af0bf9c bellard
#define DEF(s, n, copy_size) INDEX_op_ ## s,
36 6af0bf9c bellard
#include "opc.h"
37 6af0bf9c bellard
#undef DEF
38 6af0bf9c bellard
    NB_OPS,
39 6af0bf9c bellard
};
40 6af0bf9c bellard
41 6af0bf9c bellard
static uint16_t *gen_opc_ptr;
42 6af0bf9c bellard
static uint32_t *gen_opparam_ptr;
43 6af0bf9c bellard
44 6af0bf9c bellard
#include "gen-op.h"
45 6af0bf9c bellard
46 e37e863f bellard
/* MIPS opcodes */
47 e37e863f bellard
#define EXT_SPECIAL  0x100
48 e37e863f bellard
#define EXT_SPECIAL2 0x200
49 e37e863f bellard
#define EXT_REGIMM   0x300
50 e37e863f bellard
#define EXT_CP0      0x400
51 e37e863f bellard
#define EXT_CP1      0x500
52 e37e863f bellard
#define EXT_CP2      0x600
53 e37e863f bellard
#define EXT_CP3      0x700
54 e37e863f bellard
55 e37e863f bellard
enum {
56 e37e863f bellard
    /* indirect opcode tables */
57 e37e863f bellard
    OPC_SPECIAL  = 0x00,
58 e37e863f bellard
    OPC_BREGIMM  = 0x01,
59 e37e863f bellard
    OPC_CP0      = 0x10,
60 e37e863f bellard
    OPC_CP1      = 0x11,
61 e37e863f bellard
    OPC_CP2      = 0x12,
62 e37e863f bellard
    OPC_CP3      = 0x13,
63 e37e863f bellard
    OPC_SPECIAL2 = 0x1C,
64 e37e863f bellard
    /* arithmetic with immediate */
65 e37e863f bellard
    OPC_ADDI     = 0x08,
66 e37e863f bellard
    OPC_ADDIU    = 0x09,
67 e37e863f bellard
    OPC_SLTI     = 0x0A,
68 e37e863f bellard
    OPC_SLTIU    = 0x0B,
69 e37e863f bellard
    OPC_ANDI     = 0x0C,
70 e37e863f bellard
    OPC_ORI      = 0x0D,
71 e37e863f bellard
    OPC_XORI     = 0x0E,
72 e37e863f bellard
    OPC_LUI      = 0x0F,
73 e37e863f bellard
    /* Jump and branches */
74 e37e863f bellard
    OPC_J        = 0x02,
75 e37e863f bellard
    OPC_JAL      = 0x03,
76 e37e863f bellard
    OPC_BEQ      = 0x04,  /* Unconditional if rs = rt = 0 (B) */
77 e37e863f bellard
    OPC_BEQL     = 0x14,
78 e37e863f bellard
    OPC_BNE      = 0x05,
79 e37e863f bellard
    OPC_BNEL     = 0x15,
80 e37e863f bellard
    OPC_BLEZ     = 0x06,
81 e37e863f bellard
    OPC_BLEZL    = 0x16,
82 e37e863f bellard
    OPC_BGTZ     = 0x07,
83 e37e863f bellard
    OPC_BGTZL    = 0x17,
84 e37e863f bellard
    OPC_JALX     = 0x1D,  /* MIPS 16 only */
85 e37e863f bellard
    /* Load and stores */
86 e37e863f bellard
    OPC_LB       = 0x20,
87 e37e863f bellard
    OPC_LH       = 0x21,
88 e37e863f bellard
    OPC_LWL      = 0x22,
89 e37e863f bellard
    OPC_LW       = 0x23,
90 e37e863f bellard
    OPC_LBU      = 0x24,
91 e37e863f bellard
    OPC_LHU      = 0x25,
92 e37e863f bellard
    OPC_LWR      = 0x26,
93 e37e863f bellard
    OPC_SB       = 0x28,
94 e37e863f bellard
    OPC_SH       = 0x29,
95 e37e863f bellard
    OPC_SWL      = 0x2A,
96 e37e863f bellard
    OPC_SW       = 0x2B,
97 e37e863f bellard
    OPC_SWR      = 0x2E,
98 e37e863f bellard
    OPC_LL       = 0x30,
99 e37e863f bellard
    OPC_SC       = 0x38,
100 e37e863f bellard
    /* Floating point load/store */
101 e37e863f bellard
    OPC_LWC1     = 0x31,
102 e37e863f bellard
    OPC_LWC2     = 0x32,
103 e37e863f bellard
    OPC_LDC1     = 0x35,
104 e37e863f bellard
    OPC_LDC2     = 0x36,
105 e37e863f bellard
    OPC_SWC1     = 0x39,
106 e37e863f bellard
    OPC_SWC2     = 0x3A,
107 e37e863f bellard
    OPC_SDC1     = 0x3D,
108 e37e863f bellard
    OPC_SDC2     = 0x3E,
109 e37e863f bellard
    /* Cache and prefetch */
110 e37e863f bellard
    OPC_CACHE    = 0x2F,
111 e37e863f bellard
    OPC_PREF     = 0x33,
112 e37e863f bellard
};
113 e37e863f bellard
114 e37e863f bellard
/* MIPS special opcodes */
115 e37e863f bellard
enum {
116 e37e863f bellard
    /* Shifts */
117 e37e863f bellard
    OPC_SLL      = 0x00 | EXT_SPECIAL,
118 e37e863f bellard
    /* NOP is SLL r0, r0, 0   */
119 e37e863f bellard
    /* SSNOP is SLL r0, r0, 1 */
120 e37e863f bellard
    OPC_SRL      = 0x02 | EXT_SPECIAL,
121 e37e863f bellard
    OPC_SRA      = 0x03 | EXT_SPECIAL,
122 e37e863f bellard
    OPC_SLLV     = 0x04 | EXT_SPECIAL,
123 e37e863f bellard
    OPC_SRLV     = 0x06 | EXT_SPECIAL,
124 e37e863f bellard
    OPC_SRAV     = 0x07 | EXT_SPECIAL,
125 e37e863f bellard
    /* Multiplication / division */
126 e37e863f bellard
    OPC_MULT     = 0x18 | EXT_SPECIAL,
127 e37e863f bellard
    OPC_MULTU    = 0x19 | EXT_SPECIAL,
128 e37e863f bellard
    OPC_DIV      = 0x1A | EXT_SPECIAL,
129 e37e863f bellard
    OPC_DIVU     = 0x1B | EXT_SPECIAL,
130 e37e863f bellard
    /* 2 registers arithmetic / logic */
131 e37e863f bellard
    OPC_ADD      = 0x20 | EXT_SPECIAL,
132 e37e863f bellard
    OPC_ADDU     = 0x21 | EXT_SPECIAL,
133 e37e863f bellard
    OPC_SUB      = 0x22 | EXT_SPECIAL,
134 e37e863f bellard
    OPC_SUBU     = 0x23 | EXT_SPECIAL,
135 e37e863f bellard
    OPC_AND      = 0x24 | EXT_SPECIAL,
136 e37e863f bellard
    OPC_OR       = 0x25 | EXT_SPECIAL,
137 e37e863f bellard
    OPC_XOR      = 0x26 | EXT_SPECIAL,
138 e37e863f bellard
    OPC_NOR      = 0x27 | EXT_SPECIAL,
139 e37e863f bellard
    OPC_SLT      = 0x2A | EXT_SPECIAL,
140 e37e863f bellard
    OPC_SLTU     = 0x2B | EXT_SPECIAL,
141 e37e863f bellard
    /* Jumps */
142 e37e863f bellard
    OPC_JR       = 0x08 | EXT_SPECIAL,
143 e37e863f bellard
    OPC_JALR     = 0x09 | EXT_SPECIAL,
144 e37e863f bellard
    /* Traps */
145 e37e863f bellard
    OPC_TGE      = 0x30 | EXT_SPECIAL,
146 e37e863f bellard
    OPC_TGEU     = 0x31 | EXT_SPECIAL,
147 e37e863f bellard
    OPC_TLT      = 0x32 | EXT_SPECIAL,
148 e37e863f bellard
    OPC_TLTU     = 0x33 | EXT_SPECIAL,
149 e37e863f bellard
    OPC_TEQ      = 0x34 | EXT_SPECIAL,
150 e37e863f bellard
    OPC_TNE      = 0x36 | EXT_SPECIAL,
151 e37e863f bellard
    /* HI / LO registers load & stores */
152 e37e863f bellard
    OPC_MFHI     = 0x10 | EXT_SPECIAL,
153 e37e863f bellard
    OPC_MTHI     = 0x11 | EXT_SPECIAL,
154 e37e863f bellard
    OPC_MFLO     = 0x12 | EXT_SPECIAL,
155 e37e863f bellard
    OPC_MTLO     = 0x13 | EXT_SPECIAL,
156 e37e863f bellard
    /* Conditional moves */
157 e37e863f bellard
    OPC_MOVZ     = 0x0A | EXT_SPECIAL,
158 e37e863f bellard
    OPC_MOVN     = 0x0B | EXT_SPECIAL,
159 e37e863f bellard
160 e37e863f bellard
    OPC_MOVCI    = 0x01 | EXT_SPECIAL,
161 e37e863f bellard
162 e37e863f bellard
    /* Special */
163 e37e863f bellard
    OPC_PMON     = 0x05 | EXT_SPECIAL,
164 e37e863f bellard
    OPC_SYSCALL  = 0x0C | EXT_SPECIAL,
165 e37e863f bellard
    OPC_BREAK    = 0x0D | EXT_SPECIAL,
166 e37e863f bellard
    OPC_SYNC     = 0x0F | EXT_SPECIAL,
167 e37e863f bellard
};
168 e37e863f bellard
169 e37e863f bellard
enum {
170 e37e863f bellard
    /* Mutiply & xxx operations */
171 e37e863f bellard
    OPC_MADD     = 0x00 | EXT_SPECIAL2,
172 e37e863f bellard
    OPC_MADDU    = 0x01 | EXT_SPECIAL2,
173 e37e863f bellard
    OPC_MUL      = 0x02 | EXT_SPECIAL2,
174 e37e863f bellard
    OPC_MSUB     = 0x04 | EXT_SPECIAL2,
175 e37e863f bellard
    OPC_MSUBU    = 0x05 | EXT_SPECIAL2,
176 e37e863f bellard
    /* Misc */
177 e37e863f bellard
    OPC_CLZ      = 0x20 | EXT_SPECIAL2,
178 e37e863f bellard
    OPC_CLO      = 0x21 | EXT_SPECIAL2,
179 e37e863f bellard
    /* Special */
180 e37e863f bellard
    OPC_SDBBP    = 0x3F | EXT_SPECIAL2,
181 e37e863f bellard
};
182 e37e863f bellard
183 e37e863f bellard
/* Branch REGIMM */
184 e37e863f bellard
enum {
185 e37e863f bellard
    OPC_BLTZ     = 0x00 | EXT_REGIMM,
186 e37e863f bellard
    OPC_BLTZL    = 0x02 | EXT_REGIMM,
187 e37e863f bellard
    OPC_BGEZ     = 0x01 | EXT_REGIMM,
188 e37e863f bellard
    OPC_BGEZL    = 0x03 | EXT_REGIMM,
189 e37e863f bellard
    OPC_BLTZAL   = 0x10 | EXT_REGIMM,
190 e37e863f bellard
    OPC_BLTZALL  = 0x12 | EXT_REGIMM,
191 e37e863f bellard
    OPC_BGEZAL   = 0x11 | EXT_REGIMM,
192 e37e863f bellard
    OPC_BGEZALL  = 0x13 | EXT_REGIMM,
193 e37e863f bellard
    OPC_TGEI     = 0x08 | EXT_REGIMM,
194 e37e863f bellard
    OPC_TGEIU    = 0x09 | EXT_REGIMM,
195 e37e863f bellard
    OPC_TLTI     = 0x0A | EXT_REGIMM,
196 e37e863f bellard
    OPC_TLTIU    = 0x0B | EXT_REGIMM,
197 e37e863f bellard
    OPC_TEQI     = 0x0C | EXT_REGIMM,
198 e37e863f bellard
    OPC_TNEI     = 0x0E | EXT_REGIMM,
199 e37e863f bellard
};
200 e37e863f bellard
201 e37e863f bellard
enum {
202 e37e863f bellard
    /* Coprocessor 0 (MMU) */
203 e37e863f bellard
    OPC_MFC0     = 0x00 | EXT_CP0,
204 e37e863f bellard
    OPC_MTC0     = 0x04 | EXT_CP0,
205 e37e863f bellard
    OPC_TLBR     = 0x01 | EXT_CP0,
206 e37e863f bellard
    OPC_TLBWI    = 0x02 | EXT_CP0,
207 e37e863f bellard
    OPC_TLBWR    = 0x06 | EXT_CP0,
208 e37e863f bellard
    OPC_TLBP     = 0x08 | EXT_CP0,
209 e37e863f bellard
    OPC_ERET     = 0x18 | EXT_CP0,
210 e37e863f bellard
    OPC_DERET    = 0x1F | EXT_CP0,
211 e37e863f bellard
    OPC_WAIT     = 0x20 | EXT_CP0,
212 e37e863f bellard
};
213 e37e863f bellard
214 6af0bf9c bellard
const unsigned char *regnames[] =
215 6af0bf9c bellard
    { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
216 6af0bf9c bellard
      "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
217 6af0bf9c bellard
      "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
218 6af0bf9c bellard
      "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
219 6af0bf9c bellard
220 6af0bf9c bellard
/* Warning: no function for r0 register (hard wired to zero) */
221 6af0bf9c bellard
#define GEN32(func, NAME) \
222 6af0bf9c bellard
static GenOpFunc *NAME ## _table [32] = {                                     \
223 6af0bf9c bellard
NULL,       NAME ## 1, NAME ## 2, NAME ## 3,                                  \
224 6af0bf9c bellard
NAME ## 4,  NAME ## 5, NAME ## 6, NAME ## 7,                                  \
225 6af0bf9c bellard
NAME ## 8,  NAME ## 9, NAME ## 10, NAME ## 11,                                \
226 6af0bf9c bellard
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
227 6af0bf9c bellard
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
228 6af0bf9c bellard
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
229 6af0bf9c bellard
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
230 6af0bf9c bellard
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
231 6af0bf9c bellard
};                                                                            \
232 6af0bf9c bellard
static inline void func(int n)                                                \
233 6af0bf9c bellard
{                                                                             \
234 6af0bf9c bellard
    NAME ## _table[n]();                                                      \
235 6af0bf9c bellard
}
236 6af0bf9c bellard
237 6af0bf9c bellard
/* General purpose registers moves */
238 6af0bf9c bellard
GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
239 6af0bf9c bellard
GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
240 6af0bf9c bellard
GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr);
241 6af0bf9c bellard
242 6af0bf9c bellard
GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
243 6af0bf9c bellard
GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
244 6af0bf9c bellard
245 6af0bf9c bellard
typedef struct DisasContext {
246 6af0bf9c bellard
    struct TranslationBlock *tb;
247 6af0bf9c bellard
    target_ulong pc, saved_pc;
248 6af0bf9c bellard
    uint32_t opcode;
249 6af0bf9c bellard
    /* Routine used to access memory */
250 6af0bf9c bellard
    int mem_idx;
251 6af0bf9c bellard
    uint32_t hflags, saved_hflags;
252 6af0bf9c bellard
    uint32_t CP0_Status;
253 6af0bf9c bellard
    int bstate;
254 6af0bf9c bellard
    target_ulong btarget;
255 6af0bf9c bellard
} DisasContext;
256 6af0bf9c bellard
257 6af0bf9c bellard
enum {
258 6af0bf9c bellard
    BS_NONE     = 0, /* We go out of the TB without reaching a branch or an
259 6af0bf9c bellard
                      * exception condition
260 6af0bf9c bellard
                      */
261 6af0bf9c bellard
    BS_STOP     = 1, /* We want to stop translation for any reason */
262 6af0bf9c bellard
    BS_BRANCH   = 2, /* We reached a branch condition     */
263 6af0bf9c bellard
    BS_EXCP     = 3, /* We reached an exception condition */
264 6af0bf9c bellard
};
265 6af0bf9c bellard
266 6af0bf9c bellard
#if defined MIPS_DEBUG_DISAS
267 6af0bf9c bellard
#define MIPS_DEBUG(fmt, args...)                                              \
268 6af0bf9c bellard
do {                                                                          \
269 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_IN_ASM) {                                       \
270 6af0bf9c bellard
        fprintf(logfile, "%08x: %08x " fmt "\n",                              \
271 6af0bf9c bellard
                ctx->pc, ctx->opcode , ##args);                               \
272 6af0bf9c bellard
    }                                                                         \
273 6af0bf9c bellard
} while (0)
274 6af0bf9c bellard
#else
275 6af0bf9c bellard
#define MIPS_DEBUG(fmt, args...) do { } while(0)
276 6af0bf9c bellard
#endif
277 6af0bf9c bellard
278 6af0bf9c bellard
#define MIPS_INVAL(op)                                                        \
279 6af0bf9c bellard
do {                                                                          \
280 6af0bf9c bellard
    MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26,            \
281 6af0bf9c bellard
               ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F));             \
282 6af0bf9c bellard
} while (0)
283 6af0bf9c bellard
284 6af0bf9c bellard
#define GEN_LOAD_REG_TN(Tn, Rn)                                               \
285 6af0bf9c bellard
do {                                                                          \
286 6af0bf9c bellard
    if (Rn == 0) {                                                            \
287 6af0bf9c bellard
        glue(gen_op_reset_, Tn)();                                            \
288 6af0bf9c bellard
    } else {                                                                  \
289 6af0bf9c bellard
        glue(gen_op_load_gpr_, Tn)(Rn);                                       \
290 6af0bf9c bellard
    }                                                                         \
291 6af0bf9c bellard
} while (0)
292 6af0bf9c bellard
293 6af0bf9c bellard
#define GEN_LOAD_IMM_TN(Tn, Imm)                                              \
294 6af0bf9c bellard
do {                                                                          \
295 6af0bf9c bellard
    if (Imm == 0) {                                                           \
296 6af0bf9c bellard
        glue(gen_op_reset_, Tn)();                                            \
297 6af0bf9c bellard
    } else {                                                                  \
298 6af0bf9c bellard
        glue(gen_op_set_, Tn)(Imm);                                           \
299 6af0bf9c bellard
    }                                                                         \
300 6af0bf9c bellard
} while (0)
301 6af0bf9c bellard
302 6af0bf9c bellard
#define GEN_STORE_TN_REG(Rn, Tn)                                              \
303 6af0bf9c bellard
do {                                                                          \
304 6af0bf9c bellard
    if (Rn != 0) {                                                            \
305 6af0bf9c bellard
        glue(glue(gen_op_store_, Tn),_gpr)(Rn);                               \
306 6af0bf9c bellard
    }                                                                         \
307 6af0bf9c bellard
} while (0)
308 6af0bf9c bellard
309 6af0bf9c bellard
static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
310 6af0bf9c bellard
{
311 6af0bf9c bellard
#if defined MIPS_DEBUG_DISAS
312 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_IN_ASM) {
313 6af0bf9c bellard
            fprintf(logfile, "hflags %08x saved %08x\n",
314 6af0bf9c bellard
                    ctx->hflags, ctx->saved_hflags);
315 6af0bf9c bellard
    }
316 6af0bf9c bellard
#endif
317 6af0bf9c bellard
    if (do_save_pc && ctx->pc != ctx->saved_pc) {
318 6af0bf9c bellard
        gen_op_save_pc(ctx->pc);
319 6af0bf9c bellard
        ctx->saved_pc = ctx->pc;
320 6af0bf9c bellard
    }
321 6af0bf9c bellard
    if (ctx->hflags != ctx->saved_hflags) {
322 6af0bf9c bellard
        gen_op_save_state(ctx->hflags);
323 6af0bf9c bellard
        ctx->saved_hflags = ctx->hflags;
324 6af0bf9c bellard
        if (ctx->hflags & MIPS_HFLAG_BR) {
325 6af0bf9c bellard
            gen_op_save_breg_target();
326 6af0bf9c bellard
        } else if (ctx->hflags & MIPS_HFLAG_B) {
327 6af0bf9c bellard
            gen_op_save_btarget(ctx->btarget);
328 6af0bf9c bellard
        } else if (ctx->hflags & MIPS_HFLAG_BMASK) {
329 6af0bf9c bellard
            gen_op_save_bcond();
330 6af0bf9c bellard
            gen_op_save_btarget(ctx->btarget);
331 6af0bf9c bellard
        }
332 6af0bf9c bellard
    }
333 6af0bf9c bellard
}
334 6af0bf9c bellard
335 6af0bf9c bellard
static inline void generate_exception (DisasContext *ctx, int excp)
336 6af0bf9c bellard
{
337 6af0bf9c bellard
#if defined MIPS_DEBUG_DISAS
338 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_IN_ASM)
339 6af0bf9c bellard
            fprintf(logfile, "%s: raise exception %d\n", __func__, excp);
340 6af0bf9c bellard
#endif
341 6af0bf9c bellard
    save_cpu_state(ctx, 1);
342 6af0bf9c bellard
    gen_op_raise_exception(excp);
343 6af0bf9c bellard
    ctx->bstate = BS_EXCP;
344 6af0bf9c bellard
}
345 6af0bf9c bellard
346 6af0bf9c bellard
#if defined(CONFIG_USER_ONLY)
347 6af0bf9c bellard
#define op_ldst(name)        gen_op_##name##_raw()
348 6af0bf9c bellard
#define OP_LD_TABLE(width)
349 6af0bf9c bellard
#define OP_ST_TABLE(width)
350 6af0bf9c bellard
#else
351 6af0bf9c bellard
#define op_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
352 6af0bf9c bellard
#define OP_LD_TABLE(width)                                                    \
353 6af0bf9c bellard
static GenOpFunc *gen_op_l##width[] = {                                       \
354 6af0bf9c bellard
    &gen_op_l##width##_user,                                                  \
355 6af0bf9c bellard
    &gen_op_l##width##_kernel,                                                \
356 6af0bf9c bellard
}
357 6af0bf9c bellard
#define OP_ST_TABLE(width)                                                    \
358 6af0bf9c bellard
static GenOpFunc *gen_op_s##width[] = {                                       \
359 6af0bf9c bellard
    &gen_op_s##width##_user,                                                  \
360 6af0bf9c bellard
    &gen_op_s##width##_kernel,                                                \
361 6af0bf9c bellard
}
362 6af0bf9c bellard
#endif
363 6af0bf9c bellard
364 6af0bf9c bellard
#ifdef TARGET_MIPS64
365 6af0bf9c bellard
OP_LD_TABLE(d);
366 6af0bf9c bellard
OP_LD_TABLE(dl);
367 6af0bf9c bellard
OP_LD_TABLE(dr);
368 6af0bf9c bellard
OP_ST_TABLE(d);
369 6af0bf9c bellard
OP_ST_TABLE(dl);
370 6af0bf9c bellard
OP_ST_TABLE(dr);
371 6af0bf9c bellard
#endif
372 6af0bf9c bellard
OP_LD_TABLE(w);
373 6af0bf9c bellard
OP_LD_TABLE(wl);
374 6af0bf9c bellard
OP_LD_TABLE(wr);
375 6af0bf9c bellard
OP_ST_TABLE(w);
376 6af0bf9c bellard
OP_ST_TABLE(wl);
377 6af0bf9c bellard
OP_ST_TABLE(wr);
378 6af0bf9c bellard
OP_LD_TABLE(h);
379 6af0bf9c bellard
OP_LD_TABLE(hu);
380 6af0bf9c bellard
OP_ST_TABLE(h);
381 6af0bf9c bellard
OP_LD_TABLE(b);
382 6af0bf9c bellard
OP_LD_TABLE(bu);
383 6af0bf9c bellard
OP_ST_TABLE(b);
384 6af0bf9c bellard
OP_LD_TABLE(l);
385 6af0bf9c bellard
OP_ST_TABLE(c);
386 6af0bf9c bellard
387 6af0bf9c bellard
/* Load and store */
388 6af0bf9c bellard
static void gen_ldst (DisasContext *ctx, uint16_t opc, int rt,
389 6af0bf9c bellard
                      int base, int16_t offset)
390 6af0bf9c bellard
{
391 6af0bf9c bellard
    const unsigned char *opn = "unk";
392 6af0bf9c bellard
393 6af0bf9c bellard
    if (base == 0) {
394 6af0bf9c bellard
        GEN_LOAD_IMM_TN(T0, offset);
395 6af0bf9c bellard
    } else if (offset == 0) {
396 6af0bf9c bellard
        gen_op_load_gpr_T0(base);
397 6af0bf9c bellard
    } else {
398 6af0bf9c bellard
        gen_op_load_gpr_T0(base);
399 6af0bf9c bellard
        gen_op_set_T1(offset);
400 6af0bf9c bellard
        gen_op_add();
401 6af0bf9c bellard
    }
402 6af0bf9c bellard
    /* Don't do NOP if destination is zero: we must perform the actual
403 6af0bf9c bellard
     * memory access
404 6af0bf9c bellard
     */
405 6af0bf9c bellard
    switch (opc) {
406 6af0bf9c bellard
#if defined(TARGET_MIPS64)
407 6af0bf9c bellard
    case OPC_LD:
408 6af0bf9c bellard
#if defined (MIPS_HAS_UNALIGNED_LS)
409 6af0bf9c bellard
    case OPC_ULD:
410 6af0bf9c bellard
#endif
411 6af0bf9c bellard
        op_ldst(ld);
412 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
413 6af0bf9c bellard
        opn = "ld";
414 6af0bf9c bellard
        break;
415 6af0bf9c bellard
    case OPC_SD:
416 6af0bf9c bellard
#if defined (MIPS_HAS_UNALIGNED_LS)
417 6af0bf9c bellard
    case OPC_USD:
418 6af0bf9c bellard
#endif
419 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
420 6af0bf9c bellard
        op_ldst(sd);
421 6af0bf9c bellard
        opn = "sd";
422 6af0bf9c bellard
        break;
423 6af0bf9c bellard
    case OPC_LDL:
424 6af0bf9c bellard
        op_ldst(ldl);
425 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
426 6af0bf9c bellard
        opn = "ldl";
427 6af0bf9c bellard
        break;
428 6af0bf9c bellard
    case OPC_SDL:
429 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
430 6af0bf9c bellard
        op_ldst(sdl);
431 6af0bf9c bellard
        opn = "sdl";
432 6af0bf9c bellard
        break;
433 6af0bf9c bellard
    case OPC_LDR:
434 6af0bf9c bellard
        op_ldst(ldr);
435 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
436 6af0bf9c bellard
        opn = "ldr";
437 6af0bf9c bellard
        break;
438 6af0bf9c bellard
    case OPC_SDR:
439 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
440 6af0bf9c bellard
        op_ldst(sdr);
441 6af0bf9c bellard
        opn = "sdr";
442 6af0bf9c bellard
        break;
443 6af0bf9c bellard
#endif
444 6af0bf9c bellard
    case OPC_LW:
445 6af0bf9c bellard
#if defined (MIPS_HAS_UNALIGNED_LS)
446 6af0bf9c bellard
    case OPC_ULW:
447 6af0bf9c bellard
#endif
448 6af0bf9c bellard
        op_ldst(lw);
449 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
450 6af0bf9c bellard
        opn = "lw";
451 6af0bf9c bellard
        break;
452 6af0bf9c bellard
    case OPC_SW:
453 6af0bf9c bellard
#if defined (MIPS_HAS_UNALIGNED_LS)
454 6af0bf9c bellard
    case OPC_USW:
455 6af0bf9c bellard
#endif
456 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
457 6af0bf9c bellard
        op_ldst(sw);
458 6af0bf9c bellard
        opn = "sw";
459 6af0bf9c bellard
        break;
460 6af0bf9c bellard
    case OPC_LH:
461 6af0bf9c bellard
#if defined (MIPS_HAS_UNALIGNED_LS)
462 6af0bf9c bellard
    case OPC_ULH:
463 6af0bf9c bellard
#endif
464 6af0bf9c bellard
        op_ldst(lh);
465 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
466 6af0bf9c bellard
        opn = "lh";
467 6af0bf9c bellard
        break;
468 6af0bf9c bellard
    case OPC_SH:
469 6af0bf9c bellard
#if defined (MIPS_HAS_UNALIGNED_LS)
470 6af0bf9c bellard
    case OPC_USH:
471 6af0bf9c bellard
#endif
472 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
473 6af0bf9c bellard
        op_ldst(sh);
474 6af0bf9c bellard
        opn = "sh";
475 6af0bf9c bellard
        break;
476 6af0bf9c bellard
    case OPC_LHU:
477 6af0bf9c bellard
#if defined (MIPS_HAS_UNALIGNED_LS)
478 6af0bf9c bellard
    case OPC_ULHU:
479 6af0bf9c bellard
#endif
480 6af0bf9c bellard
        op_ldst(lhu);
481 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
482 6af0bf9c bellard
        opn = "lhu";
483 6af0bf9c bellard
        break;
484 6af0bf9c bellard
    case OPC_LB:
485 6af0bf9c bellard
        op_ldst(lb);
486 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
487 6af0bf9c bellard
        opn = "lb";
488 6af0bf9c bellard
        break;
489 6af0bf9c bellard
    case OPC_SB:
490 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
491 6af0bf9c bellard
        op_ldst(sb);
492 6af0bf9c bellard
        opn = "sb";
493 6af0bf9c bellard
        break;
494 6af0bf9c bellard
    case OPC_LBU:
495 6af0bf9c bellard
        op_ldst(lbu);
496 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
497 6af0bf9c bellard
        opn = "lbu";
498 6af0bf9c bellard
        break;
499 6af0bf9c bellard
    case OPC_LWL:
500 9d1d106a bellard
        GEN_LOAD_REG_TN(T1, rt);
501 6af0bf9c bellard
        op_ldst(lwl);
502 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
503 6af0bf9c bellard
        opn = "lwl";
504 6af0bf9c bellard
        break;
505 6af0bf9c bellard
    case OPC_SWL:
506 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
507 6af0bf9c bellard
        op_ldst(swl);
508 6af0bf9c bellard
        opn = "swr";
509 6af0bf9c bellard
        break;
510 6af0bf9c bellard
    case OPC_LWR:
511 9d1d106a bellard
        GEN_LOAD_REG_TN(T1, rt);
512 6af0bf9c bellard
        op_ldst(lwr);
513 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
514 6af0bf9c bellard
        opn = "lwr";
515 6af0bf9c bellard
        break;
516 6af0bf9c bellard
    case OPC_SWR:
517 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
518 6af0bf9c bellard
        op_ldst(swr);
519 6af0bf9c bellard
        opn = "swr";
520 6af0bf9c bellard
        break;
521 6af0bf9c bellard
    case OPC_LL:
522 6af0bf9c bellard
        op_ldst(ll);
523 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
524 6af0bf9c bellard
        opn = "ll";
525 6af0bf9c bellard
        break;
526 6af0bf9c bellard
    case OPC_SC:
527 6af0bf9c bellard
        GEN_LOAD_REG_TN(T1, rt);
528 6af0bf9c bellard
        op_ldst(sc);
529 6af0bf9c bellard
        GEN_STORE_TN_REG(rt, T0);
530 6af0bf9c bellard
        opn = "sc";
531 6af0bf9c bellard
        break;
532 6af0bf9c bellard
    default:
533 6af0bf9c bellard
        MIPS_INVAL("load/store");
534 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
535 6af0bf9c bellard
        return;
536 6af0bf9c bellard
    }
537 6af0bf9c bellard
    MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
538 6af0bf9c bellard
}
539 6af0bf9c bellard
540 6af0bf9c bellard
/* Arithmetic with immediate operand */
541 6af0bf9c bellard
static void gen_arith_imm (DisasContext *ctx, uint16_t opc, int rt,
542 6af0bf9c bellard
                           int rs, int16_t imm)
543 6af0bf9c bellard
{
544 6af0bf9c bellard
    uint32_t uimm;
545 6af0bf9c bellard
    const unsigned char *opn = "unk";
546 6af0bf9c bellard
547 6af0bf9c bellard
    if (rt == 0 && opc != OPC_ADDI) {
548 6af0bf9c bellard
        /* if no destination, treat it as a NOP 
549 6af0bf9c bellard
         * For addi, we must generate the overflow exception when needed.
550 6af0bf9c bellard
         */
551 6af0bf9c bellard
        MIPS_DEBUG("NOP");
552 6af0bf9c bellard
        return;
553 6af0bf9c bellard
    }
554 6af0bf9c bellard
    if (opc == OPC_ADDI || opc == OPC_ADDIU ||
555 6af0bf9c bellard
        opc == OPC_SLTI || opc == OPC_SLTIU)
556 6af0bf9c bellard
        uimm = (int32_t)imm; /* Sign extent to 32 bits */
557 6af0bf9c bellard
    else
558 6af0bf9c bellard
        uimm = (uint16_t)imm;
559 6af0bf9c bellard
    if (opc != OPC_LUI) {
560 6af0bf9c bellard
        GEN_LOAD_REG_TN(T0, rs);
561 6af0bf9c bellard
        GEN_LOAD_IMM_TN(T1, uimm);
562 6af0bf9c bellard
    } else {
563 6af0bf9c bellard
        uimm = uimm << 16;
564 6af0bf9c bellard
        GEN_LOAD_IMM_TN(T0, uimm);
565 6af0bf9c bellard
    }
566 6af0bf9c bellard
    switch (opc) {
567 6af0bf9c bellard
    case OPC_ADDI:
568 6af0bf9c bellard
        save_cpu_state(ctx, 1);
569 6af0bf9c bellard
        gen_op_addo();
570 6af0bf9c bellard
        opn = "addi";
571 6af0bf9c bellard
        break;
572 6af0bf9c bellard
    case OPC_ADDIU:
573 6af0bf9c bellard
        gen_op_add();
574 6af0bf9c bellard
        opn = "addiu";
575 6af0bf9c bellard
        break;
576 6af0bf9c bellard
    case OPC_SLTI:
577 6af0bf9c bellard
        gen_op_lt();
578 6af0bf9c bellard
        opn = "slti";
579 6af0bf9c bellard
        break;
580 6af0bf9c bellard
    case OPC_SLTIU:
581 6af0bf9c bellard
        gen_op_ltu();
582 6af0bf9c bellard
        opn = "sltiu";
583 6af0bf9c bellard
        break;
584 6af0bf9c bellard
    case OPC_ANDI:
585 6af0bf9c bellard
        gen_op_and();
586 6af0bf9c bellard
        opn = "andi";
587 6af0bf9c bellard
        break;
588 6af0bf9c bellard
    case OPC_ORI:
589 6af0bf9c bellard
        gen_op_or();
590 6af0bf9c bellard
        opn = "ori";
591 6af0bf9c bellard
        break;
592 6af0bf9c bellard
    case OPC_XORI:
593 6af0bf9c bellard
        gen_op_xor();
594 6af0bf9c bellard
        opn = "xori";
595 6af0bf9c bellard
        break;
596 6af0bf9c bellard
    case OPC_LUI:
597 6af0bf9c bellard
        opn = "lui";
598 6af0bf9c bellard
        break;
599 6af0bf9c bellard
    case OPC_SLL:
600 6af0bf9c bellard
        gen_op_sll();
601 6af0bf9c bellard
        opn = "sll";
602 6af0bf9c bellard
        break;
603 6af0bf9c bellard
    case OPC_SRA:
604 6af0bf9c bellard
        gen_op_sra();
605 6af0bf9c bellard
        opn = "sra";
606 6af0bf9c bellard
        break;
607 6af0bf9c bellard
    case OPC_SRL:
608 6af0bf9c bellard
        gen_op_srl();
609 6af0bf9c bellard
        opn = "srl";
610 6af0bf9c bellard
        break;
611 6af0bf9c bellard
    default:
612 6af0bf9c bellard
        MIPS_INVAL("imm arith");
613 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
614 6af0bf9c bellard
        return;
615 6af0bf9c bellard
    }
616 6af0bf9c bellard
    GEN_STORE_TN_REG(rt, T0);
617 6af0bf9c bellard
    MIPS_DEBUG("%s %s, %s, %x", opn, regnames[rt], regnames[rs], uimm);
618 6af0bf9c bellard
}
619 6af0bf9c bellard
620 6af0bf9c bellard
/* Arithmetic */
621 6af0bf9c bellard
static void gen_arith (DisasContext *ctx, uint16_t opc,
622 6af0bf9c bellard
                       int rd, int rs, int rt)
623 6af0bf9c bellard
{
624 6af0bf9c bellard
    const unsigned char *opn = "unk";
625 6af0bf9c bellard
626 6af0bf9c bellard
    if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB) {
627 6af0bf9c bellard
        /* if no destination, treat it as a NOP 
628 6af0bf9c bellard
         * For add & sub, we must generate the overflow exception when needed.
629 6af0bf9c bellard
         */
630 6af0bf9c bellard
        MIPS_DEBUG("NOP");
631 6af0bf9c bellard
        return;
632 6af0bf9c bellard
    }
633 6af0bf9c bellard
    GEN_LOAD_REG_TN(T0, rs);
634 6af0bf9c bellard
    GEN_LOAD_REG_TN(T1, rt);
635 6af0bf9c bellard
    switch (opc) {
636 6af0bf9c bellard
    case OPC_ADD:
637 6af0bf9c bellard
        save_cpu_state(ctx, 1);
638 6af0bf9c bellard
        gen_op_addo();
639 6af0bf9c bellard
        opn = "add";
640 6af0bf9c bellard
        break;
641 6af0bf9c bellard
    case OPC_ADDU:
642 6af0bf9c bellard
        gen_op_add();
643 6af0bf9c bellard
        opn = "addu";
644 6af0bf9c bellard
        break;
645 6af0bf9c bellard
    case OPC_SUB:
646 6af0bf9c bellard
        save_cpu_state(ctx, 1);
647 6af0bf9c bellard
        gen_op_subo();
648 6af0bf9c bellard
        opn = "sub";
649 6af0bf9c bellard
        break;
650 6af0bf9c bellard
    case OPC_SUBU:
651 6af0bf9c bellard
        gen_op_sub();
652 6af0bf9c bellard
        opn = "subu";
653 6af0bf9c bellard
        break;
654 6af0bf9c bellard
    case OPC_SLT:
655 6af0bf9c bellard
        gen_op_lt();
656 6af0bf9c bellard
        opn = "slt";
657 6af0bf9c bellard
        break;
658 6af0bf9c bellard
    case OPC_SLTU:
659 6af0bf9c bellard
        gen_op_ltu();
660 6af0bf9c bellard
        opn = "sltu";
661 6af0bf9c bellard
        break;
662 6af0bf9c bellard
    case OPC_AND:
663 6af0bf9c bellard
        gen_op_and();
664 6af0bf9c bellard
        opn = "and";
665 6af0bf9c bellard
        break;
666 6af0bf9c bellard
    case OPC_NOR:
667 6af0bf9c bellard
        gen_op_nor();
668 6af0bf9c bellard
        opn = "nor";
669 6af0bf9c bellard
        break;
670 6af0bf9c bellard
    case OPC_OR:
671 6af0bf9c bellard
        gen_op_or();
672 6af0bf9c bellard
        opn = "or";
673 6af0bf9c bellard
        break;
674 6af0bf9c bellard
    case OPC_XOR:
675 6af0bf9c bellard
        gen_op_xor();
676 6af0bf9c bellard
        opn = "xor";
677 6af0bf9c bellard
        break;
678 6af0bf9c bellard
    case OPC_MUL:
679 6af0bf9c bellard
        gen_op_mul();
680 6af0bf9c bellard
        opn = "mul";
681 6af0bf9c bellard
        break;
682 6af0bf9c bellard
    case OPC_MOVN:
683 6af0bf9c bellard
        gen_op_movn(rd);
684 6af0bf9c bellard
        opn = "movn";
685 6af0bf9c bellard
        goto print;
686 6af0bf9c bellard
    case OPC_MOVZ:
687 6af0bf9c bellard
        gen_op_movz(rd);
688 6af0bf9c bellard
        opn = "movz";
689 6af0bf9c bellard
        goto print;
690 6af0bf9c bellard
    case OPC_SLLV:
691 6af0bf9c bellard
        gen_op_sllv();
692 6af0bf9c bellard
        opn = "sllv";
693 6af0bf9c bellard
        break;
694 6af0bf9c bellard
    case OPC_SRAV:
695 6af0bf9c bellard
        gen_op_srav();
696 6af0bf9c bellard
        opn = "srav";
697 6af0bf9c bellard
        break;
698 6af0bf9c bellard
    case OPC_SRLV:
699 6af0bf9c bellard
        gen_op_srlv();
700 6af0bf9c bellard
        opn = "srlv";
701 6af0bf9c bellard
        break;
702 6af0bf9c bellard
    default:
703 6af0bf9c bellard
        MIPS_INVAL("arith");
704 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
705 6af0bf9c bellard
        return;
706 6af0bf9c bellard
    }
707 6af0bf9c bellard
    GEN_STORE_TN_REG(rd, T0);
708 6af0bf9c bellard
 print:
709 6af0bf9c bellard
    MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
710 6af0bf9c bellard
}
711 6af0bf9c bellard
712 6af0bf9c bellard
/* Arithmetic on HI/LO registers */
713 6af0bf9c bellard
static void gen_HILO (DisasContext *ctx, uint16_t opc, int reg)
714 6af0bf9c bellard
{
715 6af0bf9c bellard
    const unsigned char *opn = "unk";
716 6af0bf9c bellard
717 6af0bf9c bellard
    if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
718 6af0bf9c bellard
        /* Treat as a NOP */
719 6af0bf9c bellard
        MIPS_DEBUG("NOP");
720 6af0bf9c bellard
        return;
721 6af0bf9c bellard
    }
722 6af0bf9c bellard
    switch (opc) {
723 6af0bf9c bellard
    case OPC_MFHI:
724 6af0bf9c bellard
        gen_op_load_HI();
725 6af0bf9c bellard
        GEN_STORE_TN_REG(reg, T0);
726 6af0bf9c bellard
        opn = "mfhi";
727 6af0bf9c bellard
        break;
728 6af0bf9c bellard
    case OPC_MFLO:
729 6af0bf9c bellard
        gen_op_load_LO();
730 6af0bf9c bellard
        GEN_STORE_TN_REG(reg, T0);
731 6af0bf9c bellard
        opn = "mflo";
732 6af0bf9c bellard
        break;
733 6af0bf9c bellard
    case OPC_MTHI:
734 6af0bf9c bellard
        GEN_LOAD_REG_TN(T0, reg);
735 6af0bf9c bellard
        gen_op_store_HI();
736 6af0bf9c bellard
        opn = "mthi";
737 6af0bf9c bellard
        break;
738 6af0bf9c bellard
    case OPC_MTLO:
739 6af0bf9c bellard
        GEN_LOAD_REG_TN(T0, reg);
740 6af0bf9c bellard
        gen_op_store_LO();
741 6af0bf9c bellard
        opn = "mtlo";
742 6af0bf9c bellard
        break;
743 6af0bf9c bellard
    default:
744 6af0bf9c bellard
        MIPS_INVAL("HILO");
745 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
746 6af0bf9c bellard
        return;
747 6af0bf9c bellard
    }
748 6af0bf9c bellard
    MIPS_DEBUG("%s %s", opn, regnames[reg]);
749 6af0bf9c bellard
}
750 6af0bf9c bellard
751 6af0bf9c bellard
static void gen_muldiv (DisasContext *ctx, uint16_t opc,
752 6af0bf9c bellard
                        int rs, int rt)
753 6af0bf9c bellard
{
754 6af0bf9c bellard
    const unsigned char *opn = "unk";
755 6af0bf9c bellard
756 6af0bf9c bellard
    GEN_LOAD_REG_TN(T0, rs);
757 6af0bf9c bellard
    GEN_LOAD_REG_TN(T1, rt);
758 6af0bf9c bellard
    switch (opc) {
759 6af0bf9c bellard
    case OPC_DIV:
760 6af0bf9c bellard
        gen_op_div();
761 6af0bf9c bellard
        opn = "div";
762 6af0bf9c bellard
        break;
763 6af0bf9c bellard
    case OPC_DIVU:
764 6af0bf9c bellard
        gen_op_divu();
765 6af0bf9c bellard
        opn = "divu";
766 6af0bf9c bellard
        break;
767 6af0bf9c bellard
    case OPC_MULT:
768 6af0bf9c bellard
        gen_op_mult();
769 6af0bf9c bellard
        opn = "mult";
770 6af0bf9c bellard
        break;
771 6af0bf9c bellard
    case OPC_MULTU:
772 6af0bf9c bellard
        gen_op_multu();
773 6af0bf9c bellard
        opn = "multu";
774 6af0bf9c bellard
        break;
775 6af0bf9c bellard
    case OPC_MADD:
776 6af0bf9c bellard
        gen_op_madd();
777 6af0bf9c bellard
        opn = "madd";
778 6af0bf9c bellard
        break;
779 6af0bf9c bellard
    case OPC_MADDU:
780 6af0bf9c bellard
        gen_op_maddu();
781 6af0bf9c bellard
        opn = "maddu";
782 6af0bf9c bellard
        break;
783 6af0bf9c bellard
    case OPC_MSUB:
784 6af0bf9c bellard
        gen_op_msub();
785 6af0bf9c bellard
        opn = "msub";
786 6af0bf9c bellard
        break;
787 6af0bf9c bellard
    case OPC_MSUBU:
788 6af0bf9c bellard
        gen_op_msubu();
789 6af0bf9c bellard
        opn = "msubu";
790 6af0bf9c bellard
        break;
791 6af0bf9c bellard
    default:
792 6af0bf9c bellard
        MIPS_INVAL("mul/div");
793 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
794 6af0bf9c bellard
        return;
795 6af0bf9c bellard
    }
796 6af0bf9c bellard
    MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
797 6af0bf9c bellard
}
798 6af0bf9c bellard
799 6af0bf9c bellard
static void gen_cl (DisasContext *ctx, uint16_t opc,
800 6af0bf9c bellard
                    int rd, int rs)
801 6af0bf9c bellard
{
802 6af0bf9c bellard
    const unsigned char *opn = "unk";
803 6af0bf9c bellard
    if (rd == 0) {
804 6af0bf9c bellard
        /* Treat as a NOP */
805 6af0bf9c bellard
        MIPS_DEBUG("NOP");
806 6af0bf9c bellard
        return;
807 6af0bf9c bellard
    }
808 6af0bf9c bellard
    GEN_LOAD_REG_TN(T0, rs);
809 6af0bf9c bellard
    switch (opc) {
810 6af0bf9c bellard
    case OPC_CLO:
811 6af0bf9c bellard
        /* CLO */
812 6af0bf9c bellard
        gen_op_clo();
813 6af0bf9c bellard
        opn = "clo";
814 6af0bf9c bellard
        break;
815 6af0bf9c bellard
    case OPC_CLZ:
816 6af0bf9c bellard
        /* CLZ */
817 6af0bf9c bellard
        gen_op_clz();
818 6af0bf9c bellard
        opn = "clz";
819 6af0bf9c bellard
        break;
820 6af0bf9c bellard
    default:
821 6af0bf9c bellard
        MIPS_INVAL("CLx");
822 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
823 6af0bf9c bellard
        return;
824 6af0bf9c bellard
    }
825 6af0bf9c bellard
    gen_op_store_T0_gpr(rd);
826 6af0bf9c bellard
    MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
827 6af0bf9c bellard
}
828 6af0bf9c bellard
829 6af0bf9c bellard
/* Traps */
830 6af0bf9c bellard
static void gen_trap (DisasContext *ctx, uint16_t opc,
831 6af0bf9c bellard
                      int rs, int rt, int16_t imm)
832 6af0bf9c bellard
{
833 6af0bf9c bellard
    int cond;
834 6af0bf9c bellard
835 6af0bf9c bellard
    cond = 0;
836 6af0bf9c bellard
    /* Load needed operands */
837 6af0bf9c bellard
    switch (opc) {
838 6af0bf9c bellard
    case OPC_TEQ:
839 6af0bf9c bellard
    case OPC_TGE:
840 6af0bf9c bellard
    case OPC_TGEU:
841 6af0bf9c bellard
    case OPC_TLT:
842 6af0bf9c bellard
    case OPC_TLTU:
843 6af0bf9c bellard
    case OPC_TNE:
844 6af0bf9c bellard
        /* Compare two registers */
845 6af0bf9c bellard
        if (rs != rt) {
846 6af0bf9c bellard
            GEN_LOAD_REG_TN(T0, rs);
847 6af0bf9c bellard
            GEN_LOAD_REG_TN(T1, rt);
848 6af0bf9c bellard
            cond = 1;
849 6af0bf9c bellard
        }
850 6af0bf9c bellard
    case OPC_TEQI:
851 6af0bf9c bellard
    case OPC_TGEI:
852 6af0bf9c bellard
    case OPC_TGEIU:
853 6af0bf9c bellard
    case OPC_TLTI:
854 6af0bf9c bellard
    case OPC_TLTIU:
855 6af0bf9c bellard
    case OPC_TNEI:
856 6af0bf9c bellard
        /* Compare register to immediate */
857 6af0bf9c bellard
        if (rs != 0 || imm != 0) {
858 6af0bf9c bellard
            GEN_LOAD_REG_TN(T0, rs);
859 6af0bf9c bellard
            GEN_LOAD_IMM_TN(T1, (int32_t)imm);
860 6af0bf9c bellard
            cond = 1;
861 6af0bf9c bellard
        }
862 6af0bf9c bellard
        break;
863 6af0bf9c bellard
    }
864 6af0bf9c bellard
    if (cond == 0) {
865 6af0bf9c bellard
        switch (opc) {
866 6af0bf9c bellard
        case OPC_TEQ:   /* rs == rs */
867 6af0bf9c bellard
        case OPC_TEQI:  /* r0 == 0  */
868 6af0bf9c bellard
        case OPC_TGE:   /* rs >= rs */
869 6af0bf9c bellard
        case OPC_TGEI:  /* r0 >= 0  */
870 6af0bf9c bellard
        case OPC_TGEU:  /* rs >= rs unsigned */
871 6af0bf9c bellard
        case OPC_TGEIU: /* r0 >= 0  unsigned */
872 6af0bf9c bellard
            /* Always trap */
873 6af0bf9c bellard
            gen_op_set_T0(1);
874 6af0bf9c bellard
            break;
875 6af0bf9c bellard
        case OPC_TLT:   /* rs < rs           */
876 6af0bf9c bellard
        case OPC_TLTI:  /* r0 < 0            */
877 6af0bf9c bellard
        case OPC_TLTU:  /* rs < rs unsigned  */
878 6af0bf9c bellard
        case OPC_TLTIU: /* r0 < 0  unsigned  */
879 6af0bf9c bellard
        case OPC_TNE:   /* rs != rs          */
880 6af0bf9c bellard
        case OPC_TNEI:  /* r0 != 0           */
881 6af0bf9c bellard
            /* Never trap: treat as NOP */
882 6af0bf9c bellard
            return;
883 6af0bf9c bellard
        default:
884 6af0bf9c bellard
            MIPS_INVAL("TRAP");
885 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
886 6af0bf9c bellard
            return;
887 6af0bf9c bellard
        }
888 6af0bf9c bellard
    } else {
889 6af0bf9c bellard
        switch (opc) {
890 6af0bf9c bellard
        case OPC_TEQ:
891 6af0bf9c bellard
        case OPC_TEQI:
892 6af0bf9c bellard
            gen_op_eq();
893 6af0bf9c bellard
            break;
894 6af0bf9c bellard
        case OPC_TGE:
895 6af0bf9c bellard
        case OPC_TGEI:
896 6af0bf9c bellard
            gen_op_ge();
897 6af0bf9c bellard
            break;
898 6af0bf9c bellard
        case OPC_TGEU:
899 6af0bf9c bellard
        case OPC_TGEIU:
900 6af0bf9c bellard
            gen_op_geu();
901 6af0bf9c bellard
            break;
902 6af0bf9c bellard
        case OPC_TLT:
903 6af0bf9c bellard
        case OPC_TLTI:
904 6af0bf9c bellard
            gen_op_lt();
905 6af0bf9c bellard
            break;
906 6af0bf9c bellard
        case OPC_TLTU:
907 6af0bf9c bellard
        case OPC_TLTIU:
908 6af0bf9c bellard
            gen_op_ltu();
909 6af0bf9c bellard
            break;
910 6af0bf9c bellard
        case OPC_TNE:
911 6af0bf9c bellard
        case OPC_TNEI:
912 6af0bf9c bellard
            gen_op_ne();
913 6af0bf9c bellard
            break;
914 6af0bf9c bellard
        default:
915 6af0bf9c bellard
            MIPS_INVAL("TRAP");
916 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
917 6af0bf9c bellard
            return;
918 6af0bf9c bellard
        }
919 6af0bf9c bellard
    }
920 6af0bf9c bellard
    save_cpu_state(ctx, 1);
921 6af0bf9c bellard
    gen_op_trap();
922 6af0bf9c bellard
    ctx->bstate = BS_STOP;
923 6af0bf9c bellard
}
924 6af0bf9c bellard
925 6af0bf9c bellard
/* Branches (before delay slot) */
926 6af0bf9c bellard
static void gen_compute_branch (DisasContext *ctx, uint16_t opc,
927 6af0bf9c bellard
                                int rs, int rt, int32_t offset)
928 6af0bf9c bellard
{
929 6af0bf9c bellard
    target_ulong btarget;
930 6af0bf9c bellard
    int blink, bcond;
931 6af0bf9c bellard
932 6af0bf9c bellard
    btarget = -1;
933 6af0bf9c bellard
    blink = 0;
934 6af0bf9c bellard
    bcond = 0;
935 6af0bf9c bellard
    /* Load needed operands */
936 6af0bf9c bellard
    switch (opc) {
937 6af0bf9c bellard
    case OPC_BEQ:
938 6af0bf9c bellard
    case OPC_BEQL:
939 6af0bf9c bellard
    case OPC_BNE:
940 6af0bf9c bellard
    case OPC_BNEL:
941 6af0bf9c bellard
        /* Compare two registers */
942 6af0bf9c bellard
        if (rs != rt) {
943 6af0bf9c bellard
            GEN_LOAD_REG_TN(T0, rs);
944 6af0bf9c bellard
            GEN_LOAD_REG_TN(T1, rt);
945 6af0bf9c bellard
            bcond = 1;
946 6af0bf9c bellard
        }
947 6af0bf9c bellard
        btarget = ctx->pc + 4 + offset;
948 6af0bf9c bellard
        break;
949 6af0bf9c bellard
    case OPC_BGEZ:
950 6af0bf9c bellard
    case OPC_BGEZAL:
951 6af0bf9c bellard
    case OPC_BGEZALL:
952 6af0bf9c bellard
    case OPC_BGEZL:
953 6af0bf9c bellard
    case OPC_BGTZ:
954 6af0bf9c bellard
    case OPC_BGTZL:
955 6af0bf9c bellard
    case OPC_BLEZ:
956 6af0bf9c bellard
    case OPC_BLEZL:
957 6af0bf9c bellard
    case OPC_BLTZ:
958 6af0bf9c bellard
    case OPC_BLTZAL:
959 6af0bf9c bellard
    case OPC_BLTZALL:
960 6af0bf9c bellard
    case OPC_BLTZL:
961 6af0bf9c bellard
        /* Compare to zero */
962 6af0bf9c bellard
        if (rs != 0) {
963 6af0bf9c bellard
            gen_op_load_gpr_T0(rs);
964 6af0bf9c bellard
            bcond = 1;
965 6af0bf9c bellard
        }
966 6af0bf9c bellard
        btarget = ctx->pc + 4 + offset;
967 6af0bf9c bellard
        break;
968 6af0bf9c bellard
    case OPC_J:
969 6af0bf9c bellard
    case OPC_JAL:
970 6af0bf9c bellard
        /* Jump to immediate */
971 bc9ed47b bellard
        btarget = ((ctx->pc + 4) & 0xF0000000) | offset;
972 6af0bf9c bellard
        break;
973 6af0bf9c bellard
    case OPC_JR:
974 6af0bf9c bellard
    case OPC_JALR:
975 6af0bf9c bellard
        /* Jump to register */
976 6af0bf9c bellard
        if (offset != 0) {
977 6af0bf9c bellard
            /* Only hint = 0 is valid */
978 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
979 6af0bf9c bellard
            return;
980 6af0bf9c bellard
        }
981 6af0bf9c bellard
        GEN_LOAD_REG_TN(T2, rs);
982 6af0bf9c bellard
        break;
983 6af0bf9c bellard
    default:
984 6af0bf9c bellard
        MIPS_INVAL("branch/jump");
985 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
986 6af0bf9c bellard
        return;
987 6af0bf9c bellard
    }
988 6af0bf9c bellard
    if (bcond == 0) {
989 6af0bf9c bellard
        /* No condition to be computed */
990 6af0bf9c bellard
        switch (opc) {
991 6af0bf9c bellard
        case OPC_BEQ:     /* rx == rx        */
992 6af0bf9c bellard
        case OPC_BEQL:    /* rx == rx likely */
993 6af0bf9c bellard
        case OPC_BGEZ:    /* 0 >= 0          */
994 6af0bf9c bellard
        case OPC_BGEZL:   /* 0 >= 0 likely   */
995 6af0bf9c bellard
        case OPC_BLEZ:    /* 0 <= 0          */
996 6af0bf9c bellard
        case OPC_BLEZL:   /* 0 <= 0 likely   */
997 6af0bf9c bellard
            /* Always take */
998 6af0bf9c bellard
            ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B;
999 6af0bf9c bellard
            MIPS_DEBUG("balways");
1000 6af0bf9c bellard
            break;
1001 6af0bf9c bellard
        case OPC_BGEZAL:  /* 0 >= 0          */
1002 6af0bf9c bellard
        case OPC_BGEZALL: /* 0 >= 0 likely   */
1003 6af0bf9c bellard
            /* Always take and link */
1004 6af0bf9c bellard
            blink = 31;
1005 6af0bf9c bellard
            ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B;
1006 6af0bf9c bellard
            MIPS_DEBUG("balways and link");
1007 6af0bf9c bellard
            break;
1008 6af0bf9c bellard
        case OPC_BNE:     /* rx != rx        */
1009 6af0bf9c bellard
        case OPC_BGTZ:    /* 0 > 0           */
1010 6af0bf9c bellard
        case OPC_BLTZ:    /* 0 < 0           */
1011 6af0bf9c bellard
        case OPC_BLTZAL:  /* 0 < 0           */
1012 6af0bf9c bellard
            /* Treated as NOP */
1013 6af0bf9c bellard
            MIPS_DEBUG("bnever (NOP)");
1014 6af0bf9c bellard
            return;
1015 6af0bf9c bellard
        case OPC_BNEL:    /* rx != rx likely */
1016 6af0bf9c bellard
        case OPC_BGTZL:   /* 0 > 0 likely */
1017 6af0bf9c bellard
        case OPC_BLTZALL: /* 0 < 0 likely */
1018 6af0bf9c bellard
        case OPC_BLTZL:   /* 0 < 0 likely */
1019 6af0bf9c bellard
            /* Skip the instruction in the delay slot */
1020 6af0bf9c bellard
            MIPS_DEBUG("bnever and skip");
1021 6af0bf9c bellard
            gen_op_branch((long)ctx->tb, ctx->pc + 4);
1022 6af0bf9c bellard
            return;
1023 6af0bf9c bellard
        case OPC_J:
1024 6af0bf9c bellard
            ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B;
1025 6af0bf9c bellard
            MIPS_DEBUG("j %08x", btarget);
1026 6af0bf9c bellard
            break;
1027 6af0bf9c bellard
        case OPC_JAL:
1028 6af0bf9c bellard
            blink = 31;
1029 6af0bf9c bellard
            ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B;
1030 6af0bf9c bellard
            MIPS_DEBUG("jal %08x", btarget);
1031 6af0bf9c bellard
            break;
1032 6af0bf9c bellard
        case OPC_JR:
1033 6af0bf9c bellard
            ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BR;
1034 6af0bf9c bellard
            MIPS_DEBUG("jr %s", regnames[rs]);
1035 6af0bf9c bellard
            break;
1036 6af0bf9c bellard
        case OPC_JALR:
1037 6af0bf9c bellard
            blink = rt;
1038 6af0bf9c bellard
            ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BR;
1039 6af0bf9c bellard
            MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
1040 6af0bf9c bellard
            break;
1041 6af0bf9c bellard
        default:
1042 6af0bf9c bellard
            MIPS_INVAL("branch/jump");
1043 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
1044 6af0bf9c bellard
            return;
1045 6af0bf9c bellard
        }
1046 6af0bf9c bellard
    } else {
1047 6af0bf9c bellard
        switch (opc) {
1048 6af0bf9c bellard
        case OPC_BEQ:
1049 6af0bf9c bellard
            gen_op_eq();
1050 6af0bf9c bellard
            MIPS_DEBUG("beq %s, %s, %08x",
1051 6af0bf9c bellard
                       regnames[rs], regnames[rt], btarget);
1052 6af0bf9c bellard
            goto not_likely;
1053 6af0bf9c bellard
        case OPC_BEQL:
1054 6af0bf9c bellard
            gen_op_eq();
1055 6af0bf9c bellard
            MIPS_DEBUG("beql %s, %s, %08x",
1056 6af0bf9c bellard
                       regnames[rs], regnames[rt], btarget);
1057 6af0bf9c bellard
            goto likely;
1058 6af0bf9c bellard
        case OPC_BNE:
1059 6af0bf9c bellard
            gen_op_ne();
1060 6af0bf9c bellard
            MIPS_DEBUG("bne %s, %s, %08x",
1061 6af0bf9c bellard
                       regnames[rs], regnames[rt], btarget);
1062 6af0bf9c bellard
            goto not_likely;
1063 6af0bf9c bellard
        case OPC_BNEL:
1064 6af0bf9c bellard
            gen_op_ne();
1065 6af0bf9c bellard
            MIPS_DEBUG("bnel %s, %s, %08x",
1066 6af0bf9c bellard
                       regnames[rs], regnames[rt], btarget);
1067 6af0bf9c bellard
            goto likely;
1068 6af0bf9c bellard
        case OPC_BGEZ:
1069 6af0bf9c bellard
            gen_op_gez();
1070 6af0bf9c bellard
            MIPS_DEBUG("bgez %s, %08x", regnames[rs], btarget);
1071 6af0bf9c bellard
            goto not_likely;
1072 6af0bf9c bellard
        case OPC_BGEZL:
1073 6af0bf9c bellard
            gen_op_gez();
1074 6af0bf9c bellard
            MIPS_DEBUG("bgezl %s, %08x", regnames[rs], btarget);
1075 6af0bf9c bellard
            goto likely;
1076 6af0bf9c bellard
        case OPC_BGEZAL:
1077 6af0bf9c bellard
            gen_op_gez();
1078 6af0bf9c bellard
            MIPS_DEBUG("bgezal %s, %08x", regnames[rs], btarget);
1079 6af0bf9c bellard
            blink = 31;
1080 6af0bf9c bellard
            goto not_likely;
1081 6af0bf9c bellard
        case OPC_BGEZALL:
1082 6af0bf9c bellard
            gen_op_gez();
1083 6af0bf9c bellard
            blink = 31;
1084 6af0bf9c bellard
            MIPS_DEBUG("bgezall %s, %08x", regnames[rs], btarget);
1085 6af0bf9c bellard
            goto likely;
1086 6af0bf9c bellard
        case OPC_BGTZ:
1087 6af0bf9c bellard
            gen_op_gtz();
1088 6af0bf9c bellard
            MIPS_DEBUG("bgtz %s, %08x", regnames[rs], btarget);
1089 6af0bf9c bellard
            goto not_likely;
1090 6af0bf9c bellard
        case OPC_BGTZL:
1091 6af0bf9c bellard
            gen_op_gtz();
1092 6af0bf9c bellard
            MIPS_DEBUG("bgtzl %s, %08x", regnames[rs], btarget);
1093 6af0bf9c bellard
            goto likely;
1094 6af0bf9c bellard
        case OPC_BLEZ:
1095 6af0bf9c bellard
            gen_op_lez();
1096 6af0bf9c bellard
            MIPS_DEBUG("blez %s, %08x", regnames[rs], btarget);
1097 6af0bf9c bellard
            goto not_likely;
1098 6af0bf9c bellard
        case OPC_BLEZL:
1099 6af0bf9c bellard
            gen_op_lez();
1100 6af0bf9c bellard
            MIPS_DEBUG("blezl %s, %08x", regnames[rs], btarget);
1101 6af0bf9c bellard
            goto likely;
1102 6af0bf9c bellard
        case OPC_BLTZ:
1103 6af0bf9c bellard
            gen_op_ltz();
1104 6af0bf9c bellard
            MIPS_DEBUG("bltz %s, %08x", regnames[rs], btarget);
1105 6af0bf9c bellard
            goto not_likely;
1106 6af0bf9c bellard
        case OPC_BLTZL:
1107 6af0bf9c bellard
            gen_op_ltz();
1108 6af0bf9c bellard
            MIPS_DEBUG("bltzl %s, %08x", regnames[rs], btarget);
1109 6af0bf9c bellard
            goto likely;
1110 6af0bf9c bellard
        case OPC_BLTZAL:
1111 6af0bf9c bellard
            gen_op_ltz();
1112 6af0bf9c bellard
            blink = 31;
1113 6af0bf9c bellard
            MIPS_DEBUG("bltzal %s, %08x", regnames[rs], btarget);
1114 6af0bf9c bellard
        not_likely:
1115 6af0bf9c bellard
            ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BC;
1116 6af0bf9c bellard
            break;
1117 6af0bf9c bellard
        case OPC_BLTZALL:
1118 6af0bf9c bellard
            gen_op_ltz();
1119 6af0bf9c bellard
            blink = 31;
1120 6af0bf9c bellard
            MIPS_DEBUG("bltzall %s, %08x", regnames[rs], btarget);
1121 6af0bf9c bellard
        likely:
1122 6af0bf9c bellard
            ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BL;
1123 6af0bf9c bellard
            break;
1124 6af0bf9c bellard
        }
1125 6af0bf9c bellard
        gen_op_set_bcond();
1126 6af0bf9c bellard
    }
1127 6af0bf9c bellard
    MIPS_DEBUG("enter ds: link %d cond %02x target %08x",
1128 6af0bf9c bellard
               blink, ctx->hflags, btarget);
1129 6af0bf9c bellard
    ctx->btarget = btarget;
1130 6af0bf9c bellard
    if (blink > 0) {
1131 6af0bf9c bellard
        gen_op_set_T0(ctx->pc + 8);
1132 6af0bf9c bellard
        gen_op_store_T0_gpr(blink);
1133 6af0bf9c bellard
    }
1134 6af0bf9c bellard
    return;
1135 6af0bf9c bellard
}
1136 6af0bf9c bellard
1137 6af0bf9c bellard
/* CP0 (MMU and control) */
1138 6af0bf9c bellard
static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd)
1139 6af0bf9c bellard
{
1140 6af0bf9c bellard
    const unsigned char *opn = "unk";
1141 6af0bf9c bellard
1142 bc2c3909 bellard
    if (!(ctx->CP0_Status & (1 << CP0St_CU0)) &&
1143 bc2c3909 bellard
        !(ctx->hflags & MIPS_HFLAG_UM) &&
1144 bc2c3909 bellard
        !(ctx->hflags & MIPS_HFLAG_ERL) &&
1145 bc2c3909 bellard
        !(ctx->hflags & MIPS_HFLAG_EXL)) {
1146 6af0bf9c bellard
        if (loglevel & CPU_LOG_TB_IN_ASM) {
1147 6af0bf9c bellard
            fprintf(logfile, "CP0 is not usable\n");
1148 6af0bf9c bellard
        }
1149 6af0bf9c bellard
        gen_op_raise_exception_err(EXCP_CpU, 0);
1150 6af0bf9c bellard
        return;
1151 6af0bf9c bellard
    }
1152 6af0bf9c bellard
    switch (opc) {
1153 6af0bf9c bellard
    case OPC_MFC0:
1154 6af0bf9c bellard
        if (rt == 0) {
1155 6af0bf9c bellard
            /* Treat as NOP */
1156 6af0bf9c bellard
            return;
1157 6af0bf9c bellard
        }
1158 6af0bf9c bellard
        gen_op_mfc0(rd, ctx->opcode & 0x7);
1159 6af0bf9c bellard
        gen_op_store_T0_gpr(rt);
1160 6af0bf9c bellard
        opn = "mfc0";
1161 6af0bf9c bellard
        break;
1162 6af0bf9c bellard
    case OPC_MTC0:
1163 6af0bf9c bellard
        /* If we get an exception, we want to restart at next instruction */
1164 6af0bf9c bellard
        ctx->pc += 4;
1165 6af0bf9c bellard
        save_cpu_state(ctx, 1);
1166 6af0bf9c bellard
        ctx->pc -= 4;
1167 6af0bf9c bellard
        GEN_LOAD_REG_TN(T0, rt);
1168 6af0bf9c bellard
        gen_op_mtc0(rd, ctx->opcode & 0x7);
1169 6af0bf9c bellard
        /* Stop translation as we may have switched the execution mode */
1170 6af0bf9c bellard
        ctx->bstate = BS_STOP;
1171 6af0bf9c bellard
        opn = "mtc0";
1172 6af0bf9c bellard
        break;
1173 6af0bf9c bellard
#if defined(MIPS_USES_R4K_TLB)
1174 6af0bf9c bellard
    case OPC_TLBWI:
1175 6af0bf9c bellard
        gen_op_tlbwi();
1176 6af0bf9c bellard
        opn = "tlbwi";
1177 6af0bf9c bellard
        break;
1178 6af0bf9c bellard
    case OPC_TLBWR:
1179 6af0bf9c bellard
        gen_op_tlbwr();
1180 6af0bf9c bellard
        opn = "tlbwr";
1181 6af0bf9c bellard
        break;
1182 6af0bf9c bellard
    case OPC_TLBP:
1183 6af0bf9c bellard
        gen_op_tlbp();
1184 6af0bf9c bellard
        opn = "tlbp";
1185 6af0bf9c bellard
        break;
1186 6af0bf9c bellard
    case OPC_TLBR:
1187 6af0bf9c bellard
        gen_op_tlbr();
1188 6af0bf9c bellard
        opn = "tlbr";
1189 6af0bf9c bellard
        break;
1190 6af0bf9c bellard
#endif
1191 6af0bf9c bellard
    case OPC_ERET:
1192 6af0bf9c bellard
        opn = "eret";
1193 6af0bf9c bellard
        save_cpu_state(ctx, 0);
1194 6af0bf9c bellard
        gen_op_eret();
1195 6af0bf9c bellard
        ctx->bstate = BS_EXCP;
1196 6af0bf9c bellard
        break;
1197 6af0bf9c bellard
    case OPC_DERET:
1198 6af0bf9c bellard
        opn = "deret";
1199 6af0bf9c bellard
        if (!(ctx->hflags & MIPS_HFLAG_DM)) {
1200 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
1201 6af0bf9c bellard
        } else {
1202 6af0bf9c bellard
            save_cpu_state(ctx, 0);
1203 6af0bf9c bellard
            gen_op_deret();
1204 6af0bf9c bellard
            ctx->bstate = BS_EXCP;
1205 6af0bf9c bellard
        }
1206 6af0bf9c bellard
        break;
1207 6af0bf9c bellard
    /* XXX: TODO: WAIT */
1208 6af0bf9c bellard
    default:
1209 6af0bf9c bellard
        if (loglevel & CPU_LOG_TB_IN_ASM) {
1210 6af0bf9c bellard
            fprintf(logfile, "Invalid CP0 opcode: %08x %03x %03x %03x\n",
1211 6af0bf9c bellard
                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
1212 6af0bf9c bellard
                    ((ctx->opcode >> 16) & 0x1F));
1213 6af0bf9c bellard
        }
1214 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
1215 6af0bf9c bellard
        return;
1216 6af0bf9c bellard
    }
1217 6af0bf9c bellard
    MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
1218 6af0bf9c bellard
}
1219 6af0bf9c bellard
1220 6af0bf9c bellard
/* Coprocessor 1 (FPU) */
1221 6af0bf9c bellard
1222 6af0bf9c bellard
/* ISA extensions */
1223 6af0bf9c bellard
/* MIPS16 extension to MIPS32 */
1224 6af0bf9c bellard
/* SmartMIPS extension to MIPS32 */
1225 6af0bf9c bellard
1226 6af0bf9c bellard
#ifdef TARGET_MIPS64
1227 6af0bf9c bellard
static void gen_arith64 (DisasContext *ctx, uint16_t opc)
1228 6af0bf9c bellard
{
1229 6af0bf9c bellard
    if (func == 0x02 && rd == 0) {
1230 6af0bf9c bellard
        /* NOP */
1231 6af0bf9c bellard
        return;
1232 6af0bf9c bellard
    }
1233 6af0bf9c bellard
    if (rs == 0 || rt == 0) {
1234 6af0bf9c bellard
        gen_op_reset_T0();
1235 6af0bf9c bellard
        gen_op_save64();
1236 6af0bf9c bellard
    } else {
1237 6af0bf9c bellard
        gen_op_load_gpr_T0(rs);
1238 6af0bf9c bellard
        gen_op_load_gpr_T1(rt);
1239 6af0bf9c bellard
        gen_op_save64();
1240 6af0bf9c bellard
        if (func & 0x01)
1241 6af0bf9c bellard
            gen_op_mul64u();
1242 6af0bf9c bellard
        else
1243 6af0bf9c bellard
            gen_op_mul64s();
1244 6af0bf9c bellard
    }
1245 6af0bf9c bellard
    if (func & 0x02)
1246 6af0bf9c bellard
        gen_op_add64();
1247 6af0bf9c bellard
    else
1248 6af0bf9c bellard
        gen_op_sub64();
1249 6af0bf9c bellard
}
1250 6af0bf9c bellard
1251 6af0bf9c bellard
/* Coprocessor 3 (FPU) */
1252 6af0bf9c bellard
1253 6af0bf9c bellard
/* MDMX extension to MIPS64 */
1254 6af0bf9c bellard
/* MIPS-3D extension to MIPS64 */
1255 6af0bf9c bellard
1256 6af0bf9c bellard
#endif
1257 6af0bf9c bellard
1258 6af0bf9c bellard
static void decode_opc (DisasContext *ctx)
1259 6af0bf9c bellard
{
1260 6af0bf9c bellard
    int32_t offset;
1261 6af0bf9c bellard
    int rs, rt, rd, sa;
1262 6af0bf9c bellard
    uint16_t op, op1;
1263 6af0bf9c bellard
    int16_t imm;
1264 6af0bf9c bellard
1265 6af0bf9c bellard
    if ((ctx->hflags & MIPS_HFLAG_DS) &&
1266 6af0bf9c bellard
        (ctx->hflags & MIPS_HFLAG_BL)) {
1267 6af0bf9c bellard
        /* Handle blikely not taken case */
1268 6af0bf9c bellard
        MIPS_DEBUG("blikely condition (%08x)", ctx->pc + 4);
1269 6af0bf9c bellard
        gen_op_blikely((long)ctx->tb, ctx->pc + 4,
1270 6af0bf9c bellard
                       ctx->hflags & ~(MIPS_HFLAG_BMASK | MIPS_HFLAG_DS));
1271 6af0bf9c bellard
    }
1272 6af0bf9c bellard
    op = ctx->opcode >> 26;
1273 6af0bf9c bellard
    rs = ((ctx->opcode >> 21) & 0x1F);
1274 6af0bf9c bellard
    rt = ((ctx->opcode >> 16) & 0x1F);
1275 6af0bf9c bellard
    rd = ((ctx->opcode >> 11) & 0x1F);
1276 6af0bf9c bellard
    sa = ((ctx->opcode >> 6) & 0x1F);
1277 6af0bf9c bellard
    imm = (int16_t)ctx->opcode;
1278 6af0bf9c bellard
    switch (op) {
1279 6af0bf9c bellard
    case 0x00:          /* Special opcode */
1280 6af0bf9c bellard
        op1 = ctx->opcode & 0x3F;
1281 6af0bf9c bellard
        switch (op1) {
1282 6af0bf9c bellard
        case 0x00:          /* Arithmetic with immediate */
1283 6af0bf9c bellard
        case 0x02 ... 0x03:
1284 6af0bf9c bellard
            gen_arith_imm(ctx, op1 | EXT_SPECIAL, rd, rt, sa);
1285 6af0bf9c bellard
            break;
1286 6af0bf9c bellard
        case 0x04:          /* Arithmetic */
1287 6af0bf9c bellard
        case 0x06 ... 0x07:
1288 6af0bf9c bellard
        case 0x0A ... 0x0B:
1289 6af0bf9c bellard
        case 0x20 ... 0x27:
1290 6af0bf9c bellard
        case 0x2A ... 0x2B:
1291 6af0bf9c bellard
            gen_arith(ctx, op1 | EXT_SPECIAL, rd, rs, rt);
1292 6af0bf9c bellard
            break;
1293 6af0bf9c bellard
        case 0x18 ... 0x1B: /* MULT / DIV */
1294 6af0bf9c bellard
            gen_muldiv(ctx, op1 | EXT_SPECIAL, rs, rt);
1295 6af0bf9c bellard
            break;
1296 6af0bf9c bellard
        case 0x08 ... 0x09: /* Jumps */
1297 6af0bf9c bellard
            gen_compute_branch(ctx, op1 | EXT_SPECIAL, rs, rd, sa);
1298 6af0bf9c bellard
            return;
1299 6af0bf9c bellard
        case 0x30 ... 0x34: /* Traps */
1300 6af0bf9c bellard
        case 0x36:
1301 6af0bf9c bellard
            gen_trap(ctx, op1 | EXT_SPECIAL, rs, rt, -1);
1302 6af0bf9c bellard
            break;
1303 6af0bf9c bellard
        case 0x10:          /* Move from HI/LO */
1304 6af0bf9c bellard
        case 0x12:
1305 6af0bf9c bellard
            gen_HILO(ctx, op1 | EXT_SPECIAL, rd);
1306 6af0bf9c bellard
            break;
1307 6af0bf9c bellard
        case 0x11:
1308 6af0bf9c bellard
        case 0x13:          /* Move to HI/LO */
1309 6af0bf9c bellard
            gen_HILO(ctx, op1 | EXT_SPECIAL, rs);
1310 6af0bf9c bellard
            break;
1311 6af0bf9c bellard
        case 0x0C:          /* SYSCALL */
1312 6af0bf9c bellard
            generate_exception(ctx, EXCP_SYSCALL);
1313 6af0bf9c bellard
            break;
1314 6af0bf9c bellard
        case 0x0D:          /* BREAK */
1315 6af0bf9c bellard
            generate_exception(ctx, EXCP_BREAK);
1316 6af0bf9c bellard
            break;
1317 6af0bf9c bellard
        case 0x0F:          /* SYNC */
1318 6af0bf9c bellard
            /* Treat as a noop */
1319 6af0bf9c bellard
            break;
1320 6af0bf9c bellard
        case 0x05:          /* Pmon entry point */
1321 6af0bf9c bellard
            gen_op_pmon((ctx->opcode >> 6) & 0x1F);
1322 6af0bf9c bellard
            break;
1323 6af0bf9c bellard
#if defined (MIPS_HAS_MOVCI)
1324 6af0bf9c bellard
        case 0x01:          /* MOVCI */
1325 6af0bf9c bellard
#endif
1326 6af0bf9c bellard
#if defined (TARGET_MIPS64)
1327 6af0bf9c bellard
        case 0x14: /* MIPS64 specific opcodes */
1328 6af0bf9c bellard
        case 0x16:
1329 6af0bf9c bellard
        case 0x17:
1330 6af0bf9c bellard
        case 0x1C ... 0x1F:
1331 6af0bf9c bellard
        case 0x2C ... 0x2F:
1332 6af0bf9c bellard
        case 0x37:
1333 6af0bf9c bellard
        case 0x39 ... 0x3B:
1334 6af0bf9c bellard
        case 0x3E ... 0x3F:
1335 6af0bf9c bellard
#endif
1336 6af0bf9c bellard
        default:            /* Invalid */
1337 6af0bf9c bellard
            MIPS_INVAL("special");
1338 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
1339 6af0bf9c bellard
            break;
1340 6af0bf9c bellard
        }
1341 6af0bf9c bellard
        break;
1342 6af0bf9c bellard
    case 0x1C:          /* Special2 opcode */
1343 6af0bf9c bellard
        op1 = ctx->opcode & 0x3F;
1344 6af0bf9c bellard
        switch (op1) {
1345 6af0bf9c bellard
#if defined (MIPS_USES_R4K_EXT)
1346 6af0bf9c bellard
        /* Those instructions are not part of MIPS32 core */
1347 6af0bf9c bellard
        case 0x00 ... 0x01: /* Multiply and add/sub */
1348 6af0bf9c bellard
        case 0x04 ... 0x05:
1349 6af0bf9c bellard
            gen_muldiv(ctx, op1 | EXT_SPECIAL2, rs, rt);
1350 6af0bf9c bellard
            break;
1351 6af0bf9c bellard
        case 0x02:          /* MUL */
1352 6af0bf9c bellard
            gen_arith(ctx, op1 | EXT_SPECIAL2, rd, rs, rt);
1353 6af0bf9c bellard
            break;
1354 6af0bf9c bellard
        case 0x20 ... 0x21: /* CLO / CLZ */
1355 6af0bf9c bellard
            gen_cl(ctx, op1 | EXT_SPECIAL2, rd, rs);
1356 6af0bf9c bellard
            break;
1357 6af0bf9c bellard
#endif
1358 6af0bf9c bellard
        case 0x3F:          /* SDBBP */
1359 6af0bf9c bellard
            /* XXX: not clear which exception should be raised
1360 6af0bf9c bellard
             *      when in debug mode...
1361 6af0bf9c bellard
             */
1362 6af0bf9c bellard
            if (!(ctx->hflags & MIPS_HFLAG_DM)) {
1363 6af0bf9c bellard
                generate_exception(ctx, EXCP_DBp);
1364 6af0bf9c bellard
            } else {
1365 6af0bf9c bellard
                generate_exception(ctx, EXCP_DBp);
1366 6af0bf9c bellard
            }
1367 6af0bf9c bellard
            /* Treat as a noop */
1368 6af0bf9c bellard
            break;
1369 6af0bf9c bellard
        default:            /* Invalid */
1370 6af0bf9c bellard
            MIPS_INVAL("special2");
1371 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
1372 6af0bf9c bellard
            break;
1373 6af0bf9c bellard
        }
1374 6af0bf9c bellard
        break;
1375 6af0bf9c bellard
    case 0x01:          /* B REGIMM opcode */
1376 6af0bf9c bellard
        op1 = ((ctx->opcode >> 16) & 0x1F);
1377 6af0bf9c bellard
        switch (op1) {
1378 6af0bf9c bellard
        case 0x00 ... 0x03: /* REGIMM branches */
1379 6af0bf9c bellard
        case 0x10 ... 0x13:
1380 6af0bf9c bellard
            gen_compute_branch(ctx, op1 | EXT_REGIMM, rs, -1, imm << 2);
1381 6af0bf9c bellard
            return;
1382 6af0bf9c bellard
        case 0x08 ... 0x0C: /* Traps */
1383 6af0bf9c bellard
        case 0x0E:
1384 6af0bf9c bellard
            gen_trap(ctx, op1 | EXT_REGIMM, rs, -1, imm);
1385 6af0bf9c bellard
            break;
1386 6af0bf9c bellard
        default:            /* Invalid */
1387 6af0bf9c bellard
            MIPS_INVAL("REGIMM");
1388 6af0bf9c bellard
            generate_exception(ctx, EXCP_RI);
1389 6af0bf9c bellard
            break;
1390 6af0bf9c bellard
        }
1391 6af0bf9c bellard
        break;
1392 6af0bf9c bellard
    case 0x10:          /* CP0 opcode */
1393 6af0bf9c bellard
        op1 = ((ctx->opcode >> 21) & 0x1F);
1394 6af0bf9c bellard
        switch (op1) {
1395 6af0bf9c bellard
        case 0x00:
1396 6af0bf9c bellard
        case 0x04:
1397 6af0bf9c bellard
            gen_cp0(ctx, op1 | EXT_CP0, rt, rd);
1398 6af0bf9c bellard
            break;
1399 6af0bf9c bellard
        default:
1400 6af0bf9c bellard
            gen_cp0(ctx, (ctx->opcode & 0x1F) | EXT_CP0, rt, rd);
1401 6af0bf9c bellard
            break;
1402 6af0bf9c bellard
        }
1403 6af0bf9c bellard
        break;
1404 6af0bf9c bellard
    case 0x08 ... 0x0F: /* Arithmetic with immediate opcode */
1405 6af0bf9c bellard
        gen_arith_imm(ctx, op, rt, rs, imm);
1406 6af0bf9c bellard
        break;
1407 6af0bf9c bellard
    case 0x02 ... 0x03: /* Jump */
1408 6af0bf9c bellard
        offset = (int32_t)(ctx->opcode & 0x03FFFFFF) << 2;
1409 6af0bf9c bellard
        gen_compute_branch(ctx, op, rs, rt, offset);
1410 6af0bf9c bellard
        return;
1411 6af0bf9c bellard
    case 0x04 ... 0x07: /* Branch */
1412 6af0bf9c bellard
    case 0x14 ... 0x17:
1413 6af0bf9c bellard
        gen_compute_branch(ctx, op, rs, rt, imm << 2);
1414 6af0bf9c bellard
        return;
1415 6af0bf9c bellard
    case 0x20 ... 0x26: /* Load and stores */
1416 6af0bf9c bellard
    case 0x28 ... 0x2E:
1417 6af0bf9c bellard
    case 0x30:
1418 6af0bf9c bellard
    case 0x38:
1419 6af0bf9c bellard
        gen_ldst(ctx, op, rt, rs, imm);
1420 6af0bf9c bellard
        break;
1421 6af0bf9c bellard
    case 0x2F:          /* Cache operation */
1422 6af0bf9c bellard
        /* Treat as a noop */
1423 6af0bf9c bellard
        break;
1424 6af0bf9c bellard
    case 0x33:          /* Prefetch */
1425 6af0bf9c bellard
        /* Treat as a noop */
1426 6af0bf9c bellard
        break;
1427 6af0bf9c bellard
    case 0x3F: /* HACK */
1428 6af0bf9c bellard
        break;
1429 6af0bf9c bellard
#if defined(MIPS_USES_FPU)
1430 6af0bf9c bellard
    case 0x31 ... 0x32: /* Floating point load/store */
1431 6af0bf9c bellard
    case 0x35 ... 0x36:
1432 6af0bf9c bellard
    case 0x3A ... 0x3B:
1433 6af0bf9c bellard
    case 0x3D ... 0x3E:
1434 6af0bf9c bellard
        /* Not implemented */
1435 6af0bf9c bellard
        /* XXX: not correct */
1436 6af0bf9c bellard
#endif
1437 6af0bf9c bellard
    case 0x11:          /* CP1 opcode */
1438 6af0bf9c bellard
        /* Not implemented */
1439 6af0bf9c bellard
        /* XXX: not correct */
1440 6af0bf9c bellard
    case 0x12:          /* CP2 opcode */
1441 6af0bf9c bellard
        /* Not implemented */
1442 6af0bf9c bellard
        /* XXX: not correct */
1443 6af0bf9c bellard
    case 0x13:          /* CP3 opcode */
1444 6af0bf9c bellard
        /* Not implemented */
1445 6af0bf9c bellard
        /* XXX: not correct */
1446 6af0bf9c bellard
#if defined (TARGET_MIPS64)
1447 6af0bf9c bellard
    case 0x18 ... 0x1B:
1448 6af0bf9c bellard
    case 0x27:
1449 6af0bf9c bellard
    case 0x34:
1450 6af0bf9c bellard
    case 0x37:
1451 6af0bf9c bellard
        /* MIPS64 opcodes */
1452 6af0bf9c bellard
#endif
1453 6af0bf9c bellard
#if defined (MIPS_HAS_JALX)
1454 6af0bf9c bellard
    case 0x1D:
1455 6af0bf9c bellard
        /* JALX: not implemented */
1456 6af0bf9c bellard
#endif
1457 6af0bf9c bellard
    case 0x1E:
1458 6af0bf9c bellard
        /* ASE specific */
1459 6af0bf9c bellard
#if defined (MIPS_HAS_LSC)
1460 6af0bf9c bellard
    case 0x31: /* LWC1 */
1461 6af0bf9c bellard
    case 0x32: /* LWC2 */
1462 6af0bf9c bellard
    case 0x35: /* SDC1 */
1463 6af0bf9c bellard
    case 0x36: /* SDC2 */
1464 6af0bf9c bellard
#endif
1465 6af0bf9c bellard
    default:            /* Invalid */
1466 6af0bf9c bellard
        MIPS_INVAL("");
1467 6af0bf9c bellard
        generate_exception(ctx, EXCP_RI);
1468 6af0bf9c bellard
        break;
1469 6af0bf9c bellard
    }
1470 6af0bf9c bellard
    if (ctx->hflags & MIPS_HFLAG_DS) {
1471 6af0bf9c bellard
        int hflags = ctx->hflags;
1472 6af0bf9c bellard
        /* Branches completion */
1473 6af0bf9c bellard
        ctx->hflags &= ~(MIPS_HFLAG_BMASK | MIPS_HFLAG_DS);
1474 6af0bf9c bellard
        ctx->bstate = BS_BRANCH;
1475 6af0bf9c bellard
        save_cpu_state(ctx, 0);
1476 6af0bf9c bellard
        switch (hflags & MIPS_HFLAG_BMASK) {
1477 6af0bf9c bellard
        case MIPS_HFLAG_B:
1478 6af0bf9c bellard
            /* unconditional branch */
1479 6af0bf9c bellard
            MIPS_DEBUG("unconditional branch");
1480 6af0bf9c bellard
            gen_op_branch((long)ctx->tb, ctx->btarget);
1481 6af0bf9c bellard
            break;
1482 6af0bf9c bellard
        case MIPS_HFLAG_BL:
1483 6af0bf9c bellard
            /* blikely taken case */
1484 6af0bf9c bellard
            MIPS_DEBUG("blikely branch taken");
1485 6af0bf9c bellard
            gen_op_branch((long)ctx->tb, ctx->btarget);
1486 6af0bf9c bellard
            break;
1487 6af0bf9c bellard
        case MIPS_HFLAG_BC:
1488 6af0bf9c bellard
            /* Conditional branch */
1489 6af0bf9c bellard
            MIPS_DEBUG("conditional branch");
1490 6af0bf9c bellard
            gen_op_bcond((long)ctx->tb, ctx->btarget, ctx->pc + 4);
1491 6af0bf9c bellard
            break;
1492 6af0bf9c bellard
        case MIPS_HFLAG_BR:
1493 6af0bf9c bellard
            /* unconditional branch to register */
1494 6af0bf9c bellard
            MIPS_DEBUG("branch to register");
1495 6af0bf9c bellard
            gen_op_breg();
1496 6af0bf9c bellard
            break;
1497 6af0bf9c bellard
        default:
1498 6af0bf9c bellard
            MIPS_DEBUG("unknown branch");
1499 6af0bf9c bellard
            break;
1500 6af0bf9c bellard
        }
1501 6af0bf9c bellard
    }
1502 6af0bf9c bellard
}
1503 6af0bf9c bellard
1504 6af0bf9c bellard
int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
1505 6af0bf9c bellard
                                    int search_pc)
1506 6af0bf9c bellard
{
1507 6af0bf9c bellard
    DisasContext ctx, *ctxp = &ctx;
1508 6af0bf9c bellard
    target_ulong pc_start;
1509 6af0bf9c bellard
    uint16_t *gen_opc_end;
1510 6af0bf9c bellard
    int j, lj = -1;
1511 6af0bf9c bellard
1512 6af0bf9c bellard
    pc_start = tb->pc;
1513 6af0bf9c bellard
    gen_opc_ptr = gen_opc_buf;
1514 6af0bf9c bellard
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1515 6af0bf9c bellard
    gen_opparam_ptr = gen_opparam_buf;
1516 6af0bf9c bellard
    ctx.pc = pc_start;
1517 6af0bf9c bellard
    ctx.tb = tb;
1518 6af0bf9c bellard
    ctx.bstate = BS_NONE;
1519 6af0bf9c bellard
    /* Restore delay slot state */
1520 6af0bf9c bellard
    ctx.hflags = env->hflags;
1521 6af0bf9c bellard
    ctx.saved_hflags = ctx.hflags;
1522 6af0bf9c bellard
    if (ctx.hflags & MIPS_HFLAG_BR) {
1523 6af0bf9c bellard
        gen_op_restore_breg_target();
1524 6af0bf9c bellard
    } else if (ctx.hflags & MIPS_HFLAG_B) {
1525 6af0bf9c bellard
        ctx.btarget = env->btarget;
1526 6af0bf9c bellard
    } else if (ctx.hflags & MIPS_HFLAG_BMASK) {
1527 6af0bf9c bellard
        /* If we are in the delay slot of a conditional branch,
1528 6af0bf9c bellard
         * restore the branch condition from env->bcond to T2
1529 6af0bf9c bellard
         */
1530 6af0bf9c bellard
        ctx.btarget = env->btarget;
1531 6af0bf9c bellard
        gen_op_restore_bcond();
1532 6af0bf9c bellard
    }
1533 6af0bf9c bellard
#if defined(CONFIG_USER_ONLY)
1534 6af0bf9c bellard
    ctx.mem_idx = 0;
1535 6af0bf9c bellard
#else
1536 6af0bf9c bellard
    ctx.mem_idx = (ctx.hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM ? 0 : 1;
1537 6af0bf9c bellard
#endif
1538 6af0bf9c bellard
    ctx.CP0_Status = env->CP0_Status;
1539 6af0bf9c bellard
#ifdef DEBUG_DISAS
1540 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_CPU) {
1541 6af0bf9c bellard
        fprintf(logfile, "------------------------------------------------\n");
1542 6af0bf9c bellard
        cpu_dump_state(env, logfile, fprintf, 0);
1543 6af0bf9c bellard
    }
1544 6af0bf9c bellard
#endif
1545 6af0bf9c bellard
#if defined MIPS_DEBUG_DISAS
1546 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_IN_ASM)
1547 6af0bf9c bellard
        fprintf(logfile, "\ntb %p super %d cond %04x %04x\n",
1548 6af0bf9c bellard
                tb, ctx.mem_idx, ctx.hflags, env->hflags);
1549 6af0bf9c bellard
#endif
1550 6af0bf9c bellard
    while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
1551 6af0bf9c bellard
        if (search_pc) {
1552 6af0bf9c bellard
            j = gen_opc_ptr - gen_opc_buf;
1553 6af0bf9c bellard
            save_cpu_state(ctxp, 1);
1554 6af0bf9c bellard
            if (lj < j) {
1555 6af0bf9c bellard
                lj++;
1556 6af0bf9c bellard
                while (lj < j)
1557 6af0bf9c bellard
                    gen_opc_instr_start[lj++] = 0;
1558 6af0bf9c bellard
                gen_opc_pc[lj] = ctx.pc;
1559 6af0bf9c bellard
                gen_opc_instr_start[lj] = 1;
1560 6af0bf9c bellard
            }
1561 6af0bf9c bellard
        }
1562 6af0bf9c bellard
        ctx.opcode = ldl_code(ctx.pc);
1563 6af0bf9c bellard
        decode_opc(&ctx);
1564 6af0bf9c bellard
        ctx.pc += 4;
1565 6af0bf9c bellard
        if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
1566 6af0bf9c bellard
            break;
1567 6af0bf9c bellard
#if defined (MIPS_SINGLE_STEP)
1568 6af0bf9c bellard
        break;
1569 6af0bf9c bellard
#endif
1570 6af0bf9c bellard
    }
1571 6af0bf9c bellard
    if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) {
1572 6af0bf9c bellard
        save_cpu_state(ctxp, 0);
1573 6af0bf9c bellard
        gen_op_branch((long)ctx.tb, ctx.pc);
1574 6af0bf9c bellard
    }
1575 6af0bf9c bellard
    gen_op_reset_T0();
1576 6af0bf9c bellard
    /* Generate the return instruction */
1577 6af0bf9c bellard
    gen_op_exit_tb();
1578 6af0bf9c bellard
    *gen_opc_ptr = INDEX_op_end;
1579 6af0bf9c bellard
    if (search_pc) {
1580 6af0bf9c bellard
        j = gen_opc_ptr - gen_opc_buf;
1581 6af0bf9c bellard
        lj++;
1582 6af0bf9c bellard
        while (lj <= j)
1583 6af0bf9c bellard
            gen_opc_instr_start[lj++] = 0;
1584 6af0bf9c bellard
        tb->size = 0;
1585 6af0bf9c bellard
    } else {
1586 6af0bf9c bellard
        tb->size = ctx.pc - pc_start;
1587 6af0bf9c bellard
    }
1588 6af0bf9c bellard
#ifdef DEBUG_DISAS
1589 6af0bf9c bellard
#if defined MIPS_DEBUG_DISAS
1590 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_IN_ASM)
1591 6af0bf9c bellard
        fprintf(logfile, "\n");
1592 6af0bf9c bellard
#endif
1593 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_IN_ASM) {
1594 6af0bf9c bellard
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
1595 6af0bf9c bellard
        target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
1596 6af0bf9c bellard
        fprintf(logfile, "\n");
1597 6af0bf9c bellard
    }
1598 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_OP) {
1599 6af0bf9c bellard
        fprintf(logfile, "OP:\n");
1600 6af0bf9c bellard
        dump_ops(gen_opc_buf, gen_opparam_buf);
1601 6af0bf9c bellard
        fprintf(logfile, "\n");
1602 6af0bf9c bellard
    }
1603 6af0bf9c bellard
    if (loglevel & CPU_LOG_TB_CPU) {
1604 6af0bf9c bellard
        fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
1605 6af0bf9c bellard
    }
1606 6af0bf9c bellard
#endif
1607 6af0bf9c bellard
    
1608 6af0bf9c bellard
    return 0;
1609 6af0bf9c bellard
}
1610 6af0bf9c bellard
1611 6af0bf9c bellard
int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
1612 6af0bf9c bellard
{
1613 6af0bf9c bellard
    return gen_intermediate_code_internal(env, tb, 0);
1614 6af0bf9c bellard
}
1615 6af0bf9c bellard
1616 6af0bf9c bellard
int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
1617 6af0bf9c bellard
{
1618 6af0bf9c bellard
    return gen_intermediate_code_internal(env, tb, 1);
1619 6af0bf9c bellard
}
1620 6af0bf9c bellard
1621 6af0bf9c bellard
void cpu_dump_state (CPUState *env, FILE *f, 
1622 6af0bf9c bellard
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1623 6af0bf9c bellard
                     int flags)
1624 6af0bf9c bellard
{
1625 568b600d bellard
    uint32_t c0_status;
1626 6af0bf9c bellard
    int i;
1627 6af0bf9c bellard
    
1628 6af0bf9c bellard
    cpu_fprintf(f, "pc=0x%08x HI=0x%08x LO=0x%08x ds %04x %08x %d\n",
1629 6af0bf9c bellard
                env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
1630 6af0bf9c bellard
    for (i = 0; i < 32; i++) {
1631 6af0bf9c bellard
        if ((i & 3) == 0)
1632 6af0bf9c bellard
            cpu_fprintf(f, "GPR%02d:", i);
1633 6af0bf9c bellard
        cpu_fprintf(f, " %s %08x", regnames[i], env->gpr[i]);
1634 6af0bf9c bellard
        if ((i & 3) == 3)
1635 6af0bf9c bellard
            cpu_fprintf(f, "\n");
1636 6af0bf9c bellard
    }
1637 568b600d bellard
1638 568b600d bellard
    c0_status = env->CP0_Status;
1639 568b600d bellard
    if (env->hflags & MIPS_HFLAG_UM)
1640 568b600d bellard
        c0_status |= (1 << CP0St_UM);
1641 568b600d bellard
    if (env->hflags & MIPS_HFLAG_ERL)
1642 568b600d bellard
        c0_status |= (1 << CP0St_ERL);
1643 568b600d bellard
    if (env->hflags & MIPS_HFLAG_EXL)
1644 568b600d bellard
        c0_status |= (1 << CP0St_EXL);
1645 568b600d bellard
1646 6af0bf9c bellard
    cpu_fprintf(f, "CP0 Status  0x%08x Cause   0x%08x EPC    0x%08x\n",
1647 568b600d bellard
                c0_status, env->CP0_Cause, env->CP0_EPC);
1648 6af0bf9c bellard
    cpu_fprintf(f, "    Config0 0x%08x Config1 0x%08x LLAddr 0x%08x\n",
1649 6af0bf9c bellard
                env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
1650 6af0bf9c bellard
}
1651 6af0bf9c bellard
1652 6af0bf9c bellard
CPUMIPSState *cpu_mips_init (void)
1653 6af0bf9c bellard
{
1654 6af0bf9c bellard
    CPUMIPSState *env;
1655 6af0bf9c bellard
1656 6af0bf9c bellard
    cpu_exec_init();
1657 6af0bf9c bellard
    env = qemu_mallocz(sizeof(CPUMIPSState));
1658 6af0bf9c bellard
    if (!env)
1659 6af0bf9c bellard
        return NULL;
1660 6af0bf9c bellard
    tlb_flush(env, 1);
1661 6af0bf9c bellard
    /* Minimal init */
1662 6af0bf9c bellard
    env->PC = 0xBFC00000;
1663 6af0bf9c bellard
#if defined (MIPS_USES_R4K_TLB)
1664 6af0bf9c bellard
    env->CP0_random = MIPS_TLB_NB - 1;
1665 6af0bf9c bellard
#endif
1666 6af0bf9c bellard
    env->CP0_Wired = 0;
1667 6af0bf9c bellard
    env->CP0_Config0 = MIPS_CONFIG0;
1668 6af0bf9c bellard
#if defined (MIPS_CONFIG1)
1669 6af0bf9c bellard
        env->CP0_Config1 = MIPS_CONFIG1;
1670 6af0bf9c bellard
#endif
1671 6af0bf9c bellard
#if defined (MIPS_CONFIG2)
1672 6af0bf9c bellard
        env->CP0_Config2 = MIPS_CONFIG2;
1673 6af0bf9c bellard
#endif
1674 6af0bf9c bellard
#if defined (MIPS_CONFIG3)
1675 6af0bf9c bellard
        env->CP0_Config3 = MIPS_CONFIG3;
1676 6af0bf9c bellard
#endif
1677 6af0bf9c bellard
    env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV);
1678 6af0bf9c bellard
    env->CP0_WatchLo = 0;
1679 6af0bf9c bellard
    env->hflags = MIPS_HFLAG_ERL;
1680 6af0bf9c bellard
    /* Count register increments in debug mode, EJTAG version 1 */
1681 6af0bf9c bellard
    env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
1682 6af0bf9c bellard
    env->CP0_PRid = MIPS_CPU;
1683 6af0bf9c bellard
    env->exception_index = EXCP_NONE;
1684 6af0bf9c bellard
1685 6af0bf9c bellard
    cpu_single_env = env;
1686 6af0bf9c bellard
1687 6af0bf9c bellard
    return env;
1688 6af0bf9c bellard
}