Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (69.8 kB)

1
/*
2
 *  MIPS32 emulation for qemu: main translation routines.
3
 * 
4
 *  Copyright (c) 2004-2005 Jocelyn Mayer
5
 *  Copyright (c) 2006 Marius Groeger (FPU operations)
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library; if not, write to the Free Software
19
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
 */
21

    
22
#include <stdarg.h>
23
#include <stdlib.h>
24
#include <stdio.h>
25
#include <string.h>
26
#include <inttypes.h>
27

    
28
#include "cpu.h"
29
#include "exec-all.h"
30
#include "disas.h"
31

    
32
//#define MIPS_DEBUG_DISAS
33
//#define MIPS_SINGLE_STEP
34

    
35
#ifdef USE_DIRECT_JUMP
36
#define TBPARAM(x)
37
#else
38
#define TBPARAM(x) (long)(x)
39
#endif
40

    
41
enum {
42
#define DEF(s, n, copy_size) INDEX_op_ ## s,
43
#include "opc.h"
44
#undef DEF
45
    NB_OPS,
46
};
47

    
48
static uint16_t *gen_opc_ptr;
49
static uint32_t *gen_opparam_ptr;
50

    
51
#include "gen-op.h"
52

    
53
/* MIPS opcodes */
54
#define EXT_SPECIAL  0x100
55
#define EXT_SPECIAL2 0x200
56
#define EXT_REGIMM   0x300
57
#define EXT_CP0      0x400
58
#define EXT_CP1      0x500
59
#define EXT_CP2      0x600
60
#define EXT_CP3      0x700
61

    
62
enum {
63
    /* indirect opcode tables */
64
    OPC_SPECIAL  = 0x00,
65
    OPC_BREGIMM  = 0x01,
66
    OPC_CP0      = 0x10,
67
    OPC_CP1      = 0x11,
68
    OPC_CP2      = 0x12,
69
    OPC_CP3      = 0x13,
70
    OPC_SPECIAL2 = 0x1C,
71
    /* arithmetic with immediate */
72
    OPC_ADDI     = 0x08,
73
    OPC_ADDIU    = 0x09,
74
    OPC_SLTI     = 0x0A,
75
    OPC_SLTIU    = 0x0B,
76
    OPC_ANDI     = 0x0C,
77
    OPC_ORI      = 0x0D,
78
    OPC_XORI     = 0x0E,
79
    OPC_LUI      = 0x0F,
80
    /* Jump and branches */
81
    OPC_J        = 0x02,
82
    OPC_JAL      = 0x03,
83
    OPC_BEQ      = 0x04,  /* Unconditional if rs = rt = 0 (B) */
84
    OPC_BEQL     = 0x14,
85
    OPC_BNE      = 0x05,
86
    OPC_BNEL     = 0x15,
87
    OPC_BLEZ     = 0x06,
88
    OPC_BLEZL    = 0x16,
89
    OPC_BGTZ     = 0x07,
90
    OPC_BGTZL    = 0x17,
91
    OPC_JALX     = 0x1D,  /* MIPS 16 only */
92
    /* Load and stores */
93
    OPC_LB       = 0x20,
94
    OPC_LH       = 0x21,
95
    OPC_LWL      = 0x22,
96
    OPC_LW       = 0x23,
97
    OPC_LBU      = 0x24,
98
    OPC_LHU      = 0x25,
99
    OPC_LWR      = 0x26,
100
    OPC_SB       = 0x28,
101
    OPC_SH       = 0x29,
102
    OPC_SWL      = 0x2A,
103
    OPC_SW       = 0x2B,
104
    OPC_SWR      = 0x2E,
105
    OPC_LL       = 0x30,
106
    OPC_SC       = 0x38,
107
    /* Floating point load/store */
108
    OPC_LWC1     = 0x31,
109
    OPC_LWC2     = 0x32,
110
    OPC_LDC1     = 0x35,
111
    OPC_LDC2     = 0x36,
112
    OPC_SWC1     = 0x39,
113
    OPC_SWC2     = 0x3A,
114
    OPC_SDC1     = 0x3D,
115
    OPC_SDC2     = 0x3E,
116
    /* Cache and prefetch */
117
    OPC_CACHE    = 0x2F,
118
    OPC_PREF     = 0x33,
119
};
120

    
121
/* MIPS special opcodes */
122
enum {
123
    /* Shifts */
124
    OPC_SLL      = 0x00 | EXT_SPECIAL,
125
    /* NOP is SLL r0, r0, 0   */
126
    /* SSNOP is SLL r0, r0, 1 */
127
    OPC_SRL      = 0x02 | EXT_SPECIAL,
128
    OPC_SRA      = 0x03 | EXT_SPECIAL,
129
    OPC_SLLV     = 0x04 | EXT_SPECIAL,
130
    OPC_SRLV     = 0x06 | EXT_SPECIAL,
131
    OPC_SRAV     = 0x07 | EXT_SPECIAL,
132
    /* Multiplication / division */
133
    OPC_MULT     = 0x18 | EXT_SPECIAL,
134
    OPC_MULTU    = 0x19 | EXT_SPECIAL,
135
    OPC_DIV      = 0x1A | EXT_SPECIAL,
136
    OPC_DIVU     = 0x1B | EXT_SPECIAL,
137
    /* 2 registers arithmetic / logic */
138
    OPC_ADD      = 0x20 | EXT_SPECIAL,
139
    OPC_ADDU     = 0x21 | EXT_SPECIAL,
140
    OPC_SUB      = 0x22 | EXT_SPECIAL,
141
    OPC_SUBU     = 0x23 | EXT_SPECIAL,
142
    OPC_AND      = 0x24 | EXT_SPECIAL,
143
    OPC_OR       = 0x25 | EXT_SPECIAL,
144
    OPC_XOR      = 0x26 | EXT_SPECIAL,
145
    OPC_NOR      = 0x27 | EXT_SPECIAL,
146
    OPC_SLT      = 0x2A | EXT_SPECIAL,
147
    OPC_SLTU     = 0x2B | EXT_SPECIAL,
148
    /* Jumps */
149
    OPC_JR       = 0x08 | EXT_SPECIAL,
150
    OPC_JALR     = 0x09 | EXT_SPECIAL,
151
    /* Traps */
152
    OPC_TGE      = 0x30 | EXT_SPECIAL,
153
    OPC_TGEU     = 0x31 | EXT_SPECIAL,
154
    OPC_TLT      = 0x32 | EXT_SPECIAL,
155
    OPC_TLTU     = 0x33 | EXT_SPECIAL,
156
    OPC_TEQ      = 0x34 | EXT_SPECIAL,
157
    OPC_TNE      = 0x36 | EXT_SPECIAL,
158
    /* HI / LO registers load & stores */
159
    OPC_MFHI     = 0x10 | EXT_SPECIAL,
160
    OPC_MTHI     = 0x11 | EXT_SPECIAL,
161
    OPC_MFLO     = 0x12 | EXT_SPECIAL,
162
    OPC_MTLO     = 0x13 | EXT_SPECIAL,
163
    /* Conditional moves */
164
    OPC_MOVZ     = 0x0A | EXT_SPECIAL,
165
    OPC_MOVN     = 0x0B | EXT_SPECIAL,
166

    
167
    OPC_MOVCI    = 0x01 | EXT_SPECIAL,
168

    
169
    /* Special */
170
    OPC_PMON     = 0x05 | EXT_SPECIAL,
171
    OPC_SYSCALL  = 0x0C | EXT_SPECIAL,
172
    OPC_BREAK    = 0x0D | EXT_SPECIAL,
173
    OPC_SYNC     = 0x0F | EXT_SPECIAL,
174
};
175

    
176
enum {
177
    /* Mutiply & xxx operations */
178
    OPC_MADD     = 0x00 | EXT_SPECIAL2,
179
    OPC_MADDU    = 0x01 | EXT_SPECIAL2,
180
    OPC_MUL      = 0x02 | EXT_SPECIAL2,
181
    OPC_MSUB     = 0x04 | EXT_SPECIAL2,
182
    OPC_MSUBU    = 0x05 | EXT_SPECIAL2,
183
    /* Misc */
184
    OPC_CLZ      = 0x20 | EXT_SPECIAL2,
185
    OPC_CLO      = 0x21 | EXT_SPECIAL2,
186
    /* Special */
187
    OPC_SDBBP    = 0x3F | EXT_SPECIAL2,
188
};
189

    
190
/* Branch REGIMM */
191
enum {
192
    OPC_BLTZ     = 0x00 | EXT_REGIMM,
193
    OPC_BLTZL    = 0x02 | EXT_REGIMM,
194
    OPC_BGEZ     = 0x01 | EXT_REGIMM,
195
    OPC_BGEZL    = 0x03 | EXT_REGIMM,
196
    OPC_BLTZAL   = 0x10 | EXT_REGIMM,
197
    OPC_BLTZALL  = 0x12 | EXT_REGIMM,
198
    OPC_BGEZAL   = 0x11 | EXT_REGIMM,
199
    OPC_BGEZALL  = 0x13 | EXT_REGIMM,
200
    OPC_TGEI     = 0x08 | EXT_REGIMM,
201
    OPC_TGEIU    = 0x09 | EXT_REGIMM,
202
    OPC_TLTI     = 0x0A | EXT_REGIMM,
203
    OPC_TLTIU    = 0x0B | EXT_REGIMM,
204
    OPC_TEQI     = 0x0C | EXT_REGIMM,
205
    OPC_TNEI     = 0x0E | EXT_REGIMM,
206
};
207

    
208
enum {
209
    /* Coprocessor 0 (MMU) */
210
    OPC_MFC0     = 0x00 | EXT_CP0,
211
    OPC_MTC0     = 0x04 | EXT_CP0,
212
    OPC_TLBR     = 0x01 | EXT_CP0,
213
    OPC_TLBWI    = 0x02 | EXT_CP0,
214
    OPC_TLBWR    = 0x06 | EXT_CP0,
215
    OPC_TLBP     = 0x08 | EXT_CP0,
216
    OPC_ERET     = 0x18 | EXT_CP0,
217
    OPC_DERET    = 0x1F | EXT_CP0,
218
    OPC_WAIT     = 0x20 | EXT_CP0,
219
};
220

    
221
#ifdef MIPS_USES_FPU
222
enum {
223
    /* Coprocessor 1 (FPU) */
224
    OPC_MFC1     = 0x00 | EXT_CP1,
225
    OPC_MTC1     = 0x04 | EXT_CP1,
226
    OPC_CFC1     = 0x02 | EXT_CP1,
227
    OPC_CTC1     = 0x06 | EXT_CP1,
228
};
229
#endif
230

    
231
const unsigned char *regnames[] =
232
    { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
233
      "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
234
      "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
235
      "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
236

    
237
/* Warning: no function for r0 register (hard wired to zero) */
238
#define GEN32(func, NAME) \
239
static GenOpFunc *NAME ## _table [32] = {                                     \
240
NULL,       NAME ## 1, NAME ## 2, NAME ## 3,                                  \
241
NAME ## 4,  NAME ## 5, NAME ## 6, NAME ## 7,                                  \
242
NAME ## 8,  NAME ## 9, NAME ## 10, NAME ## 11,                                \
243
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
244
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
245
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
246
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
247
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
248
};                                                                            \
249
static inline void func(int n)                                                \
250
{                                                                             \
251
    NAME ## _table[n]();                                                      \
252
}
253

    
254
/* General purpose registers moves */
255
GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
256
GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
257
GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr);
258

    
259
GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
260
GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
261

    
262
#ifdef MIPS_USES_FPU
263
const unsigned char *fregnames[] =
264
    { "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
265
      "f8",  "f9",  "f10", "f11", "f12", "f13", "f14", "f15",
266
      "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
267
      "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
268

    
269
# define SFGEN32(func, NAME) \
270
static GenOpFunc *NAME ## _table [32] = {                                     \
271
NAME ## 0,  NAME ## 1,  NAME ## 2,  NAME ## 3,                                \
272
NAME ## 4,  NAME ## 5,  NAME ## 6,  NAME ## 7,                                \
273
NAME ## 8,  NAME ## 9,  NAME ## 10, NAME ## 11,                               \
274
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
275
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
276
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
277
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
278
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
279
};                                                                            \
280
static inline void func(int n)                                                \
281
{                                                                             \
282
    NAME ## _table[n]();                                                      \
283
}
284

    
285
# define DFGEN32(func, NAME) \
286
static GenOpFunc *NAME ## _table [32] = {                                     \
287
NAME ## 0,  0, NAME ## 2,  0,                                                 \
288
NAME ## 4,  0, NAME ## 6,  0,                                                 \
289
NAME ## 8,  0, NAME ## 10, 0,                                                 \
290
NAME ## 12, 0, NAME ## 14, 0,                                                 \
291
NAME ## 16, 0, NAME ## 18, 0,                                                 \
292
NAME ## 20, 0, NAME ## 22, 0,                                                 \
293
NAME ## 24, 0, NAME ## 26, 0,                                                 \
294
NAME ## 28, 0, NAME ## 30, 0,                                                 \
295
};                                                                            \
296
static inline void func(int n)                                                \
297
{                                                                             \
298
    NAME ## _table[n]();                                                      \
299
}
300

    
301
SFGEN32(gen_op_load_fpr_WT0,  gen_op_load_fpr_WT0_fpr);
302
SFGEN32(gen_op_store_fpr_WT0, gen_op_store_fpr_WT0_fpr);
303

    
304
SFGEN32(gen_op_load_fpr_WT1,  gen_op_load_fpr_WT1_fpr);
305
SFGEN32(gen_op_store_fpr_WT1, gen_op_store_fpr_WT1_fpr);
306

    
307
SFGEN32(gen_op_load_fpr_WT2,  gen_op_load_fpr_WT2_fpr);
308
SFGEN32(gen_op_store_fpr_WT2, gen_op_store_fpr_WT2_fpr);
309

    
310
DFGEN32(gen_op_load_fpr_DT0,  gen_op_load_fpr_DT0_fpr);
311
DFGEN32(gen_op_store_fpr_DT0, gen_op_store_fpr_DT0_fpr);
312

    
313
DFGEN32(gen_op_load_fpr_DT1,  gen_op_load_fpr_DT1_fpr);
314
DFGEN32(gen_op_store_fpr_DT1, gen_op_store_fpr_DT1_fpr);
315

    
316
DFGEN32(gen_op_load_fpr_DT2,  gen_op_load_fpr_DT2_fpr);
317
DFGEN32(gen_op_store_fpr_DT2, gen_op_store_fpr_DT2_fpr);
318

    
319
#define FOP_CONDS(fmt) \
320
static GenOpFunc * cond_ ## fmt ## _table[16] = {                       \
321
    gen_op_cmp_ ## fmt ## _f,                                           \
322
    gen_op_cmp_ ## fmt ## _un,                                          \
323
    gen_op_cmp_ ## fmt ## _eq,                                          \
324
    gen_op_cmp_ ## fmt ## _ueq,                                         \
325
    gen_op_cmp_ ## fmt ## _olt,                                         \
326
    gen_op_cmp_ ## fmt ## _ult,                                         \
327
    gen_op_cmp_ ## fmt ## _ole,                                         \
328
    gen_op_cmp_ ## fmt ## _ule,                                         \
329
    gen_op_cmp_ ## fmt ## _sf,                                          \
330
    gen_op_cmp_ ## fmt ## _ngle,                                        \
331
    gen_op_cmp_ ## fmt ## _seq,                                         \
332
    gen_op_cmp_ ## fmt ## _ngl,                                         \
333
    gen_op_cmp_ ## fmt ## _lt,                                          \
334
    gen_op_cmp_ ## fmt ## _nge,                                         \
335
    gen_op_cmp_ ## fmt ## _le,                                          \
336
    gen_op_cmp_ ## fmt ## _ngt,                                         \
337
};                                                                      \
338
static inline void gen_cmp_ ## fmt(int n)                               \
339
{                                                                       \
340
    cond_ ## fmt ## _table[n]();                                        \
341
}
342

    
343
FOP_CONDS(d)
344
FOP_CONDS(s)
345

    
346
#endif
347

    
348
typedef struct DisasContext {
349
    struct TranslationBlock *tb;
350
    target_ulong pc, saved_pc;
351
    uint32_t opcode;
352
    /* Routine used to access memory */
353
    int mem_idx;
354
    uint32_t hflags, saved_hflags;
355
    uint32_t CP0_Status;
356
    int bstate;
357
    target_ulong btarget;
358
} DisasContext;
359

    
360
enum {
361
    BS_NONE     = 0, /* We go out of the TB without reaching a branch or an
362
                      * exception condition
363
                      */
364
    BS_STOP     = 1, /* We want to stop translation for any reason */
365
    BS_BRANCH   = 2, /* We reached a branch condition     */
366
    BS_EXCP     = 3, /* We reached an exception condition */
367
};
368

    
369
#if defined MIPS_DEBUG_DISAS
370
#define MIPS_DEBUG(fmt, args...)                                              \
371
do {                                                                          \
372
    if (loglevel & CPU_LOG_TB_IN_ASM) {                                       \
373
        fprintf(logfile, "%08x: %08x " fmt "\n",                              \
374
                ctx->pc, ctx->opcode , ##args);                               \
375
    }                                                                         \
376
} while (0)
377
#else
378
#define MIPS_DEBUG(fmt, args...) do { } while(0)
379
#endif
380

    
381
#define MIPS_INVAL(op)                                                        \
382
do {                                                                          \
383
    MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26,            \
384
               ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F));             \
385
} while (0)
386

    
387
#define GEN_LOAD_REG_TN(Tn, Rn)                                               \
388
do {                                                                          \
389
    if (Rn == 0) {                                                            \
390
        glue(gen_op_reset_, Tn)();                                            \
391
    } else {                                                                  \
392
        glue(gen_op_load_gpr_, Tn)(Rn);                                       \
393
    }                                                                         \
394
} while (0)
395

    
396
#define GEN_LOAD_IMM_TN(Tn, Imm)                                              \
397
do {                                                                          \
398
    if (Imm == 0) {                                                           \
399
        glue(gen_op_reset_, Tn)();                                            \
400
    } else {                                                                  \
401
        glue(gen_op_set_, Tn)(Imm);                                           \
402
    }                                                                         \
403
} while (0)
404

    
405
#define GEN_STORE_TN_REG(Rn, Tn)                                              \
406
do {                                                                          \
407
    if (Rn != 0) {                                                            \
408
        glue(glue(gen_op_store_, Tn),_gpr)(Rn);                               \
409
    }                                                                         \
410
} while (0)
411

    
412
#ifdef MIPS_USES_FPU
413

    
414
# define GEN_LOAD_FREG_FTN(FTn, Fn)                                           \
415
do {                                                                          \
416
    glue(gen_op_load_fpr_, FTn)(Fn);                                          \
417
} while (0)
418

    
419
#define GEN_STORE_FTN_FREG(Fn, FTn)                                           \
420
do {                                                                          \
421
    glue(gen_op_store_fpr_, FTn)(Fn);                                         \
422
} while (0)
423

    
424
#endif
425

    
426
static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
427
{
428
#if defined MIPS_DEBUG_DISAS
429
    if (loglevel & CPU_LOG_TB_IN_ASM) {
430
            fprintf(logfile, "hflags %08x saved %08x\n",
431
                    ctx->hflags, ctx->saved_hflags);
432
    }
433
#endif
434
    if (do_save_pc && ctx->pc != ctx->saved_pc) {
435
        gen_op_save_pc(ctx->pc);
436
        ctx->saved_pc = ctx->pc;
437
    }
438
    if (ctx->hflags != ctx->saved_hflags) {
439
        gen_op_save_state(ctx->hflags);
440
        ctx->saved_hflags = ctx->hflags;
441
        if (ctx->hflags & MIPS_HFLAG_BR) {
442
            gen_op_save_breg_target();
443
        } else if (ctx->hflags & MIPS_HFLAG_B) {
444
            gen_op_save_btarget(ctx->btarget);
445
        } else if (ctx->hflags & MIPS_HFLAG_BMASK) {
446
            gen_op_save_bcond();
447
            gen_op_save_btarget(ctx->btarget);
448
        }
449
    }
450
}
451

    
452
static inline void generate_exception_err (DisasContext *ctx, int excp, int err)
453
{
454
#if defined MIPS_DEBUG_DISAS
455
    if (loglevel & CPU_LOG_TB_IN_ASM)
456
            fprintf(logfile, "%s: raise exception %d\n", __func__, excp);
457
#endif
458
    save_cpu_state(ctx, 1);
459
    if (err == 0)
460
        gen_op_raise_exception(excp);
461
    else
462
        gen_op_raise_exception_err(excp, err);
463
    ctx->bstate = BS_EXCP;
464
}
465

    
466
static inline void generate_exception (DisasContext *ctx, int excp)
467
{
468
    generate_exception_err (ctx, excp, 0);
469
}
470

    
471
#if defined(CONFIG_USER_ONLY)
472
#define op_ldst(name)        gen_op_##name##_raw()
473
#define OP_LD_TABLE(width)
474
#define OP_ST_TABLE(width)
475
#else
476
#define op_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
477
#define OP_LD_TABLE(width)                                                    \
478
static GenOpFunc *gen_op_l##width[] = {                                       \
479
    &gen_op_l##width##_user,                                                  \
480
    &gen_op_l##width##_kernel,                                                \
481
}
482
#define OP_ST_TABLE(width)                                                    \
483
static GenOpFunc *gen_op_s##width[] = {                                       \
484
    &gen_op_s##width##_user,                                                  \
485
    &gen_op_s##width##_kernel,                                                \
486
}
487
#endif
488

    
489
#ifdef TARGET_MIPS64
490
OP_LD_TABLE(d);
491
OP_LD_TABLE(dl);
492
OP_LD_TABLE(dr);
493
OP_ST_TABLE(d);
494
OP_ST_TABLE(dl);
495
OP_ST_TABLE(dr);
496
#endif
497
OP_LD_TABLE(w);
498
OP_LD_TABLE(wl);
499
OP_LD_TABLE(wr);
500
OP_ST_TABLE(w);
501
OP_ST_TABLE(wl);
502
OP_ST_TABLE(wr);
503
OP_LD_TABLE(h);
504
OP_LD_TABLE(hu);
505
OP_ST_TABLE(h);
506
OP_LD_TABLE(b);
507
OP_LD_TABLE(bu);
508
OP_ST_TABLE(b);
509
OP_LD_TABLE(l);
510
OP_ST_TABLE(c);
511
#ifdef MIPS_USES_FPU
512
OP_LD_TABLE(wc1);
513
OP_ST_TABLE(wc1);
514
OP_LD_TABLE(dc1);
515
OP_ST_TABLE(dc1);
516
#endif
517

    
518
/* Load and store */
519
static void gen_ldst (DisasContext *ctx, uint16_t opc, int rt,
520
                      int base, int16_t offset)
521
{
522
    const unsigned char *opn = "unk";
523

    
524
    if (base == 0) {
525
        GEN_LOAD_IMM_TN(T0, offset);
526
    } else if (offset == 0) {
527
        gen_op_load_gpr_T0(base);
528
    } else {
529
        gen_op_load_gpr_T0(base);
530
        gen_op_set_T1(offset);
531
        gen_op_add();
532
    }
533
    /* Don't do NOP if destination is zero: we must perform the actual
534
     * memory access
535
     */
536
    switch (opc) {
537
#if defined(TARGET_MIPS64)
538
    case OPC_LD:
539
#if defined (MIPS_HAS_UNALIGNED_LS)
540
    case OPC_ULD:
541
#endif
542
        op_ldst(ld);
543
        GEN_STORE_TN_REG(rt, T0);
544
        opn = "ld";
545
        break;
546
    case OPC_SD:
547
#if defined (MIPS_HAS_UNALIGNED_LS)
548
    case OPC_USD:
549
#endif
550
        GEN_LOAD_REG_TN(T1, rt);
551
        op_ldst(sd);
552
        opn = "sd";
553
        break;
554
    case OPC_LDL:
555
        op_ldst(ldl);
556
        GEN_STORE_TN_REG(rt, T0);
557
        opn = "ldl";
558
        break;
559
    case OPC_SDL:
560
        GEN_LOAD_REG_TN(T1, rt);
561
        op_ldst(sdl);
562
        opn = "sdl";
563
        break;
564
    case OPC_LDR:
565
        op_ldst(ldr);
566
        GEN_STORE_TN_REG(rt, T0);
567
        opn = "ldr";
568
        break;
569
    case OPC_SDR:
570
        GEN_LOAD_REG_TN(T1, rt);
571
        op_ldst(sdr);
572
        opn = "sdr";
573
        break;
574
#endif
575
    case OPC_LW:
576
#if defined (MIPS_HAS_UNALIGNED_LS)
577
    case OPC_ULW:
578
#endif
579
        op_ldst(lw);
580
        GEN_STORE_TN_REG(rt, T0);
581
        opn = "lw";
582
        break;
583
    case OPC_SW:
584
#if defined (MIPS_HAS_UNALIGNED_LS)
585
    case OPC_USW:
586
#endif
587
        GEN_LOAD_REG_TN(T1, rt);
588
        op_ldst(sw);
589
        opn = "sw";
590
        break;
591
    case OPC_LH:
592
#if defined (MIPS_HAS_UNALIGNED_LS)
593
    case OPC_ULH:
594
#endif
595
        op_ldst(lh);
596
        GEN_STORE_TN_REG(rt, T0);
597
        opn = "lh";
598
        break;
599
    case OPC_SH:
600
#if defined (MIPS_HAS_UNALIGNED_LS)
601
    case OPC_USH:
602
#endif
603
        GEN_LOAD_REG_TN(T1, rt);
604
        op_ldst(sh);
605
        opn = "sh";
606
        break;
607
    case OPC_LHU:
608
#if defined (MIPS_HAS_UNALIGNED_LS)
609
    case OPC_ULHU:
610
#endif
611
        op_ldst(lhu);
612
        GEN_STORE_TN_REG(rt, T0);
613
        opn = "lhu";
614
        break;
615
    case OPC_LB:
616
        op_ldst(lb);
617
        GEN_STORE_TN_REG(rt, T0);
618
        opn = "lb";
619
        break;
620
    case OPC_SB:
621
        GEN_LOAD_REG_TN(T1, rt);
622
        op_ldst(sb);
623
        opn = "sb";
624
        break;
625
    case OPC_LBU:
626
        op_ldst(lbu);
627
        GEN_STORE_TN_REG(rt, T0);
628
        opn = "lbu";
629
        break;
630
    case OPC_LWL:
631
        GEN_LOAD_REG_TN(T1, rt);
632
        op_ldst(lwl);
633
        GEN_STORE_TN_REG(rt, T0);
634
        opn = "lwl";
635
        break;
636
    case OPC_SWL:
637
        GEN_LOAD_REG_TN(T1, rt);
638
        op_ldst(swl);
639
        opn = "swr";
640
        break;
641
    case OPC_LWR:
642
        GEN_LOAD_REG_TN(T1, rt);
643
        op_ldst(lwr);
644
        GEN_STORE_TN_REG(rt, T0);
645
        opn = "lwr";
646
        break;
647
    case OPC_SWR:
648
        GEN_LOAD_REG_TN(T1, rt);
649
        op_ldst(swr);
650
        opn = "swr";
651
        break;
652
    case OPC_LL:
653
        op_ldst(ll);
654
        GEN_STORE_TN_REG(rt, T0);
655
        opn = "ll";
656
        break;
657
    case OPC_SC:
658
        GEN_LOAD_REG_TN(T1, rt);
659
        op_ldst(sc);
660
        GEN_STORE_TN_REG(rt, T0);
661
        opn = "sc";
662
        break;
663
    default:
664
        MIPS_INVAL("load/store");
665
        generate_exception(ctx, EXCP_RI);
666
        return;
667
    }
668
    MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
669
}
670

    
671
#ifdef MIPS_USES_FPU
672

    
673
/* Load and store */
674
static void gen_flt_ldst (DisasContext *ctx, uint16_t opc, int ft,
675
                      int base, int16_t offset)
676
{
677
    const unsigned char *opn = "unk";
678

    
679
    if (base == 0) {
680
        GEN_LOAD_IMM_TN(T0, offset);
681
    } else if (offset == 0) {
682
        gen_op_load_gpr_T0(base);
683
    } else {
684
        gen_op_load_gpr_T0(base);
685
        gen_op_set_T1(offset);
686
        gen_op_add();
687
    }
688
    /* Don't do NOP if destination is zero: we must perform the actual
689
     * memory access
690
     */
691
    switch (opc) {
692
    case OPC_LWC1:
693
        op_ldst(lwc1);
694
        GEN_STORE_FTN_FREG(ft, WT0);
695
        opn = "lwc1";
696
        break;
697
    case OPC_SWC1:
698
        GEN_LOAD_FREG_FTN(WT0, ft);
699
        op_ldst(swc1);
700
        opn = "swc1";
701
        break;
702
    case OPC_LDC1:
703
        op_ldst(ldc1);
704
        GEN_STORE_FTN_FREG(ft, DT0);
705
        opn = "ldc1";
706
        break;
707
    case OPC_SDC1:
708
        GEN_LOAD_FREG_FTN(DT0, ft);
709
        op_ldst(sdc1);
710
        opn = "sdc1";
711
        break;
712
    default:
713
        MIPS_INVAL("float load/store");
714
        generate_exception(ctx, EXCP_CpU);
715
        return;
716
    }
717
    MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
718
}
719
#endif
720

    
721
/* Arithmetic with immediate operand */
722
static void gen_arith_imm (DisasContext *ctx, uint16_t opc, int rt,
723
                           int rs, int16_t imm)
724
{
725
    uint32_t uimm;
726
    const unsigned char *opn = "unk";
727

    
728
    if (rt == 0 && opc != OPC_ADDI) {
729
        /* if no destination, treat it as a NOP 
730
         * For addi, we must generate the overflow exception when needed.
731
         */
732
        MIPS_DEBUG("NOP");
733
        return;
734
    }
735
    if (opc == OPC_ADDI || opc == OPC_ADDIU ||
736
        opc == OPC_SLTI || opc == OPC_SLTIU)
737
        uimm = (int32_t)imm; /* Sign extent to 32 bits */
738
    else
739
        uimm = (uint16_t)imm;
740
    if (opc != OPC_LUI) {
741
        GEN_LOAD_REG_TN(T0, rs);
742
        GEN_LOAD_IMM_TN(T1, uimm);
743
    } else {
744
        uimm = uimm << 16;
745
        GEN_LOAD_IMM_TN(T0, uimm);
746
    }
747
    switch (opc) {
748
    case OPC_ADDI:
749
        save_cpu_state(ctx, 1);
750
        gen_op_addo();
751
        opn = "addi";
752
        break;
753
    case OPC_ADDIU:
754
        gen_op_add();
755
        opn = "addiu";
756
        break;
757
    case OPC_SLTI:
758
        gen_op_lt();
759
        opn = "slti";
760
        break;
761
    case OPC_SLTIU:
762
        gen_op_ltu();
763
        opn = "sltiu";
764
        break;
765
    case OPC_ANDI:
766
        gen_op_and();
767
        opn = "andi";
768
        break;
769
    case OPC_ORI:
770
        gen_op_or();
771
        opn = "ori";
772
        break;
773
    case OPC_XORI:
774
        gen_op_xor();
775
        opn = "xori";
776
        break;
777
    case OPC_LUI:
778
        opn = "lui";
779
        break;
780
    case OPC_SLL:
781
        gen_op_sll();
782
        opn = "sll";
783
        break;
784
    case OPC_SRA:
785
        gen_op_sra();
786
        opn = "sra";
787
        break;
788
    case OPC_SRL:
789
        gen_op_srl();
790
        opn = "srl";
791
        break;
792
    default:
793
        MIPS_INVAL("imm arith");
794
        generate_exception(ctx, EXCP_RI);
795
        return;
796
    }
797
    GEN_STORE_TN_REG(rt, T0);
798
    MIPS_DEBUG("%s %s, %s, %x", opn, regnames[rt], regnames[rs], uimm);
799
}
800

    
801
/* Arithmetic */
802
static void gen_arith (DisasContext *ctx, uint16_t opc,
803
                       int rd, int rs, int rt)
804
{
805
    const unsigned char *opn = "unk";
806

    
807
    if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB) {
808
        /* if no destination, treat it as a NOP 
809
         * For add & sub, we must generate the overflow exception when needed.
810
         */
811
        MIPS_DEBUG("NOP");
812
        return;
813
    }
814
    GEN_LOAD_REG_TN(T0, rs);
815
    GEN_LOAD_REG_TN(T1, rt);
816
    switch (opc) {
817
    case OPC_ADD:
818
        save_cpu_state(ctx, 1);
819
        gen_op_addo();
820
        opn = "add";
821
        break;
822
    case OPC_ADDU:
823
        gen_op_add();
824
        opn = "addu";
825
        break;
826
    case OPC_SUB:
827
        save_cpu_state(ctx, 1);
828
        gen_op_subo();
829
        opn = "sub";
830
        break;
831
    case OPC_SUBU:
832
        gen_op_sub();
833
        opn = "subu";
834
        break;
835
    case OPC_SLT:
836
        gen_op_lt();
837
        opn = "slt";
838
        break;
839
    case OPC_SLTU:
840
        gen_op_ltu();
841
        opn = "sltu";
842
        break;
843
    case OPC_AND:
844
        gen_op_and();
845
        opn = "and";
846
        break;
847
    case OPC_NOR:
848
        gen_op_nor();
849
        opn = "nor";
850
        break;
851
    case OPC_OR:
852
        gen_op_or();
853
        opn = "or";
854
        break;
855
    case OPC_XOR:
856
        gen_op_xor();
857
        opn = "xor";
858
        break;
859
    case OPC_MUL:
860
        gen_op_mul();
861
        opn = "mul";
862
        break;
863
    case OPC_MOVN:
864
        gen_op_movn(rd);
865
        opn = "movn";
866
        goto print;
867
    case OPC_MOVZ:
868
        gen_op_movz(rd);
869
        opn = "movz";
870
        goto print;
871
    case OPC_SLLV:
872
        gen_op_sllv();
873
        opn = "sllv";
874
        break;
875
    case OPC_SRAV:
876
        gen_op_srav();
877
        opn = "srav";
878
        break;
879
    case OPC_SRLV:
880
        gen_op_srlv();
881
        opn = "srlv";
882
        break;
883
    default:
884
        MIPS_INVAL("arith");
885
        generate_exception(ctx, EXCP_RI);
886
        return;
887
    }
888
    GEN_STORE_TN_REG(rd, T0);
889
 print:
890
    MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
891
}
892

    
893
/* Arithmetic on HI/LO registers */
894
static void gen_HILO (DisasContext *ctx, uint16_t opc, int reg)
895
{
896
    const unsigned char *opn = "unk";
897

    
898
    if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
899
        /* Treat as a NOP */
900
        MIPS_DEBUG("NOP");
901
        return;
902
    }
903
    switch (opc) {
904
    case OPC_MFHI:
905
        gen_op_load_HI();
906
        GEN_STORE_TN_REG(reg, T0);
907
        opn = "mfhi";
908
        break;
909
    case OPC_MFLO:
910
        gen_op_load_LO();
911
        GEN_STORE_TN_REG(reg, T0);
912
        opn = "mflo";
913
        break;
914
    case OPC_MTHI:
915
        GEN_LOAD_REG_TN(T0, reg);
916
        gen_op_store_HI();
917
        opn = "mthi";
918
        break;
919
    case OPC_MTLO:
920
        GEN_LOAD_REG_TN(T0, reg);
921
        gen_op_store_LO();
922
        opn = "mtlo";
923
        break;
924
    default:
925
        MIPS_INVAL("HILO");
926
        generate_exception(ctx, EXCP_RI);
927
        return;
928
    }
929
    MIPS_DEBUG("%s %s", opn, regnames[reg]);
930
}
931

    
932
static void gen_muldiv (DisasContext *ctx, uint16_t opc,
933
                        int rs, int rt)
934
{
935
    const unsigned char *opn = "unk";
936

    
937
    GEN_LOAD_REG_TN(T0, rs);
938
    GEN_LOAD_REG_TN(T1, rt);
939
    switch (opc) {
940
    case OPC_DIV:
941
        gen_op_div();
942
        opn = "div";
943
        break;
944
    case OPC_DIVU:
945
        gen_op_divu();
946
        opn = "divu";
947
        break;
948
    case OPC_MULT:
949
        gen_op_mult();
950
        opn = "mult";
951
        break;
952
    case OPC_MULTU:
953
        gen_op_multu();
954
        opn = "multu";
955
        break;
956
    case OPC_MADD:
957
        gen_op_madd();
958
        opn = "madd";
959
        break;
960
    case OPC_MADDU:
961
        gen_op_maddu();
962
        opn = "maddu";
963
        break;
964
    case OPC_MSUB:
965
        gen_op_msub();
966
        opn = "msub";
967
        break;
968
    case OPC_MSUBU:
969
        gen_op_msubu();
970
        opn = "msubu";
971
        break;
972
    default:
973
        MIPS_INVAL("mul/div");
974
        generate_exception(ctx, EXCP_RI);
975
        return;
976
    }
977
    MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
978
}
979

    
980
static void gen_cl (DisasContext *ctx, uint16_t opc,
981
                    int rd, int rs)
982
{
983
    const unsigned char *opn = "unk";
984
    if (rd == 0) {
985
        /* Treat as a NOP */
986
        MIPS_DEBUG("NOP");
987
        return;
988
    }
989
    GEN_LOAD_REG_TN(T0, rs);
990
    switch (opc) {
991
    case OPC_CLO:
992
        /* CLO */
993
        gen_op_clo();
994
        opn = "clo";
995
        break;
996
    case OPC_CLZ:
997
        /* CLZ */
998
        gen_op_clz();
999
        opn = "clz";
1000
        break;
1001
    default:
1002
        MIPS_INVAL("CLx");
1003
        generate_exception(ctx, EXCP_RI);
1004
        return;
1005
    }
1006
    gen_op_store_T0_gpr(rd);
1007
    MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
1008
}
1009

    
1010
/* Traps */
1011
static void gen_trap (DisasContext *ctx, uint16_t opc,
1012
                      int rs, int rt, int16_t imm)
1013
{
1014
    int cond;
1015

    
1016
    cond = 0;
1017
    /* Load needed operands */
1018
    switch (opc) {
1019
    case OPC_TEQ:
1020
    case OPC_TGE:
1021
    case OPC_TGEU:
1022
    case OPC_TLT:
1023
    case OPC_TLTU:
1024
    case OPC_TNE:
1025
        /* Compare two registers */
1026
        if (rs != rt) {
1027
            GEN_LOAD_REG_TN(T0, rs);
1028
            GEN_LOAD_REG_TN(T1, rt);
1029
            cond = 1;
1030
        }
1031
    case OPC_TEQI:
1032
    case OPC_TGEI:
1033
    case OPC_TGEIU:
1034
    case OPC_TLTI:
1035
    case OPC_TLTIU:
1036
    case OPC_TNEI:
1037
        /* Compare register to immediate */
1038
        if (rs != 0 || imm != 0) {
1039
            GEN_LOAD_REG_TN(T0, rs);
1040
            GEN_LOAD_IMM_TN(T1, (int32_t)imm);
1041
            cond = 1;
1042
        }
1043
        break;
1044
    }
1045
    if (cond == 0) {
1046
        switch (opc) {
1047
        case OPC_TEQ:   /* rs == rs */
1048
        case OPC_TEQI:  /* r0 == 0  */
1049
        case OPC_TGE:   /* rs >= rs */
1050
        case OPC_TGEI:  /* r0 >= 0  */
1051
        case OPC_TGEU:  /* rs >= rs unsigned */
1052
        case OPC_TGEIU: /* r0 >= 0  unsigned */
1053
            /* Always trap */
1054
            gen_op_set_T0(1);
1055
            break;
1056
        case OPC_TLT:   /* rs < rs           */
1057
        case OPC_TLTI:  /* r0 < 0            */
1058
        case OPC_TLTU:  /* rs < rs unsigned  */
1059
        case OPC_TLTIU: /* r0 < 0  unsigned  */
1060
        case OPC_TNE:   /* rs != rs          */
1061
        case OPC_TNEI:  /* r0 != 0           */
1062
            /* Never trap: treat as NOP */
1063
            return;
1064
        default:
1065
            MIPS_INVAL("TRAP");
1066
            generate_exception(ctx, EXCP_RI);
1067
            return;
1068
        }
1069
    } else {
1070
        switch (opc) {
1071
        case OPC_TEQ:
1072
        case OPC_TEQI:
1073
            gen_op_eq();
1074
            break;
1075
        case OPC_TGE:
1076
        case OPC_TGEI:
1077
            gen_op_ge();
1078
            break;
1079
        case OPC_TGEU:
1080
        case OPC_TGEIU:
1081
            gen_op_geu();
1082
            break;
1083
        case OPC_TLT:
1084
        case OPC_TLTI:
1085
            gen_op_lt();
1086
            break;
1087
        case OPC_TLTU:
1088
        case OPC_TLTIU:
1089
            gen_op_ltu();
1090
            break;
1091
        case OPC_TNE:
1092
        case OPC_TNEI:
1093
            gen_op_ne();
1094
            break;
1095
        default:
1096
            MIPS_INVAL("TRAP");
1097
            generate_exception(ctx, EXCP_RI);
1098
            return;
1099
        }
1100
    }
1101
    save_cpu_state(ctx, 1);
1102
    gen_op_trap();
1103
    ctx->bstate = BS_STOP;
1104
}
1105

    
1106
static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
1107
{
1108
    TranslationBlock *tb;
1109
    tb = ctx->tb;
1110
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
1111
        if (n == 0)
1112
            gen_op_goto_tb0(TBPARAM(tb));
1113
        else
1114
            gen_op_goto_tb1(TBPARAM(tb));
1115
        gen_op_save_pc(dest);
1116
        gen_op_set_T0((long)tb + n);
1117
        gen_op_exit_tb();
1118
    } else {
1119
        gen_op_save_pc(dest);
1120
        gen_op_set_T0(0);
1121
        gen_op_exit_tb();
1122
    }
1123
}
1124

    
1125
/* Branches (before delay slot) */
1126
static void gen_compute_branch (DisasContext *ctx, uint16_t opc,
1127
                                int rs, int rt, int32_t offset)
1128
{
1129
    target_ulong btarget;
1130
    int blink, bcond;
1131

    
1132
    btarget = -1;
1133
    blink = 0;
1134
    bcond = 0;
1135
    /* Load needed operands */
1136
    switch (opc) {
1137
    case OPC_BEQ:
1138
    case OPC_BEQL:
1139
    case OPC_BNE:
1140
    case OPC_BNEL:
1141
        /* Compare two registers */
1142
        if (rs != rt) {
1143
            GEN_LOAD_REG_TN(T0, rs);
1144
            GEN_LOAD_REG_TN(T1, rt);
1145
            bcond = 1;
1146
        }
1147
        btarget = ctx->pc + 4 + offset;
1148
        break;
1149
    case OPC_BGEZ:
1150
    case OPC_BGEZAL:
1151
    case OPC_BGEZALL:
1152
    case OPC_BGEZL:
1153
    case OPC_BGTZ:
1154
    case OPC_BGTZL:
1155
    case OPC_BLEZ:
1156
    case OPC_BLEZL:
1157
    case OPC_BLTZ:
1158
    case OPC_BLTZAL:
1159
    case OPC_BLTZALL:
1160
    case OPC_BLTZL:
1161
        /* Compare to zero */
1162
        if (rs != 0) {
1163
            gen_op_load_gpr_T0(rs);
1164
            bcond = 1;
1165
        }
1166
        btarget = ctx->pc + 4 + offset;
1167
        break;
1168
    case OPC_J:
1169
    case OPC_JAL:
1170
        /* Jump to immediate */
1171
        btarget = ((ctx->pc + 4) & 0xF0000000) | offset;
1172
        break;
1173
    case OPC_JR:
1174
    case OPC_JALR:
1175
        /* Jump to register */
1176
        if (offset != 0) {
1177
            /* Only hint = 0 is valid */
1178
            generate_exception(ctx, EXCP_RI);
1179
            return;
1180
        }
1181
        GEN_LOAD_REG_TN(T2, rs);
1182
        break;
1183
    default:
1184
        MIPS_INVAL("branch/jump");
1185
        generate_exception(ctx, EXCP_RI);
1186
        return;
1187
    }
1188
    if (bcond == 0) {
1189
        /* No condition to be computed */
1190
        switch (opc) {
1191
        case OPC_BEQ:     /* rx == rx        */
1192
        case OPC_BEQL:    /* rx == rx likely */
1193
        case OPC_BGEZ:    /* 0 >= 0          */
1194
        case OPC_BGEZL:   /* 0 >= 0 likely   */
1195
        case OPC_BLEZ:    /* 0 <= 0          */
1196
        case OPC_BLEZL:   /* 0 <= 0 likely   */
1197
            /* Always take */
1198
            ctx->hflags |= MIPS_HFLAG_B;
1199
            MIPS_DEBUG("balways");
1200
            break;
1201
        case OPC_BGEZAL:  /* 0 >= 0          */
1202
        case OPC_BGEZALL: /* 0 >= 0 likely   */
1203
            /* Always take and link */
1204
            blink = 31;
1205
            ctx->hflags |= MIPS_HFLAG_B;
1206
            MIPS_DEBUG("balways and link");
1207
            break;
1208
        case OPC_BNE:     /* rx != rx        */
1209
        case OPC_BGTZ:    /* 0 > 0           */
1210
        case OPC_BLTZ:    /* 0 < 0           */
1211
            /* Treated as NOP */
1212
            MIPS_DEBUG("bnever (NOP)");
1213
            return;
1214
        case OPC_BLTZAL:  /* 0 < 0           */
1215
            gen_op_set_T0(ctx->pc + 8);
1216
            gen_op_store_T0_gpr(31);
1217
            return;
1218
        case OPC_BLTZALL: /* 0 < 0 likely */
1219
            gen_op_set_T0(ctx->pc + 8);
1220
            gen_op_store_T0_gpr(31);
1221
            gen_goto_tb(ctx, 0, ctx->pc + 4);
1222
            return;
1223
        case OPC_BNEL:    /* rx != rx likely */
1224
        case OPC_BGTZL:   /* 0 > 0 likely */
1225
        case OPC_BLTZL:   /* 0 < 0 likely */
1226
            /* Skip the instruction in the delay slot */
1227
            MIPS_DEBUG("bnever and skip");
1228
            gen_goto_tb(ctx, 0, ctx->pc + 4);
1229
            return;
1230
        case OPC_J:
1231
            ctx->hflags |= MIPS_HFLAG_B;
1232
            MIPS_DEBUG("j %08x", btarget);
1233
            break;
1234
        case OPC_JAL:
1235
            blink = 31;
1236
            ctx->hflags |= MIPS_HFLAG_B;
1237
            MIPS_DEBUG("jal %08x", btarget);
1238
            break;
1239
        case OPC_JR:
1240
            ctx->hflags |= MIPS_HFLAG_BR;
1241
            MIPS_DEBUG("jr %s", regnames[rs]);
1242
            break;
1243
        case OPC_JALR:
1244
            blink = rt;
1245
            ctx->hflags |= MIPS_HFLAG_BR;
1246
            MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
1247
            break;
1248
        default:
1249
            MIPS_INVAL("branch/jump");
1250
            generate_exception(ctx, EXCP_RI);
1251
            return;
1252
        }
1253
    } else {
1254
        switch (opc) {
1255
        case OPC_BEQ:
1256
            gen_op_eq();
1257
            MIPS_DEBUG("beq %s, %s, %08x",
1258
                       regnames[rs], regnames[rt], btarget);
1259
            goto not_likely;
1260
        case OPC_BEQL:
1261
            gen_op_eq();
1262
            MIPS_DEBUG("beql %s, %s, %08x",
1263
                       regnames[rs], regnames[rt], btarget);
1264
            goto likely;
1265
        case OPC_BNE:
1266
            gen_op_ne();
1267
            MIPS_DEBUG("bne %s, %s, %08x",
1268
                       regnames[rs], regnames[rt], btarget);
1269
            goto not_likely;
1270
        case OPC_BNEL:
1271
            gen_op_ne();
1272
            MIPS_DEBUG("bnel %s, %s, %08x",
1273
                       regnames[rs], regnames[rt], btarget);
1274
            goto likely;
1275
        case OPC_BGEZ:
1276
            gen_op_gez();
1277
            MIPS_DEBUG("bgez %s, %08x", regnames[rs], btarget);
1278
            goto not_likely;
1279
        case OPC_BGEZL:
1280
            gen_op_gez();
1281
            MIPS_DEBUG("bgezl %s, %08x", regnames[rs], btarget);
1282
            goto likely;
1283
        case OPC_BGEZAL:
1284
            gen_op_gez();
1285
            MIPS_DEBUG("bgezal %s, %08x", regnames[rs], btarget);
1286
            blink = 31;
1287
            goto not_likely;
1288
        case OPC_BGEZALL:
1289
            gen_op_gez();
1290
            blink = 31;
1291
            MIPS_DEBUG("bgezall %s, %08x", regnames[rs], btarget);
1292
            goto likely;
1293
        case OPC_BGTZ:
1294
            gen_op_gtz();
1295
            MIPS_DEBUG("bgtz %s, %08x", regnames[rs], btarget);
1296
            goto not_likely;
1297
        case OPC_BGTZL:
1298
            gen_op_gtz();
1299
            MIPS_DEBUG("bgtzl %s, %08x", regnames[rs], btarget);
1300
            goto likely;
1301
        case OPC_BLEZ:
1302
            gen_op_lez();
1303
            MIPS_DEBUG("blez %s, %08x", regnames[rs], btarget);
1304
            goto not_likely;
1305
        case OPC_BLEZL:
1306
            gen_op_lez();
1307
            MIPS_DEBUG("blezl %s, %08x", regnames[rs], btarget);
1308
            goto likely;
1309
        case OPC_BLTZ:
1310
            gen_op_ltz();
1311
            MIPS_DEBUG("bltz %s, %08x", regnames[rs], btarget);
1312
            goto not_likely;
1313
        case OPC_BLTZL:
1314
            gen_op_ltz();
1315
            MIPS_DEBUG("bltzl %s, %08x", regnames[rs], btarget);
1316
            goto likely;
1317
        case OPC_BLTZAL:
1318
            gen_op_ltz();
1319
            blink = 31;
1320
            MIPS_DEBUG("bltzal %s, %08x", regnames[rs], btarget);
1321
        not_likely:
1322
            ctx->hflags |= MIPS_HFLAG_BC;
1323
            break;
1324
        case OPC_BLTZALL:
1325
            gen_op_ltz();
1326
            blink = 31;
1327
            MIPS_DEBUG("bltzall %s, %08x", regnames[rs], btarget);
1328
        likely:
1329
            ctx->hflags |= MIPS_HFLAG_BL;
1330
            break;
1331
        }
1332
        gen_op_set_bcond();
1333
    }
1334
    MIPS_DEBUG("enter ds: link %d cond %02x target %08x",
1335
               blink, ctx->hflags, btarget);
1336
    ctx->btarget = btarget;
1337
    if (blink > 0) {
1338
        gen_op_set_T0(ctx->pc + 8);
1339
        gen_op_store_T0_gpr(blink);
1340
    }
1341
    return;
1342
}
1343

    
1344
/* CP0 (MMU and control) */
1345
static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd)
1346
{
1347
    const unsigned char *opn = "unk";
1348

    
1349
    if (!(ctx->CP0_Status & (1 << CP0St_CU0)) &&
1350
        (ctx->hflags & MIPS_HFLAG_UM) &&
1351
        !(ctx->hflags & MIPS_HFLAG_ERL) &&
1352
        !(ctx->hflags & MIPS_HFLAG_EXL)) {
1353
        if (loglevel & CPU_LOG_TB_IN_ASM) {
1354
            fprintf(logfile, "CP0 is not usable\n");
1355
        }
1356
        generate_exception_err (ctx, EXCP_CpU, 0);
1357
        return;
1358
    }
1359
    switch (opc) {
1360
    case OPC_MFC0:
1361
        if (rt == 0) {
1362
            /* Treat as NOP */
1363
            return;
1364
        }
1365
        gen_op_mfc0(rd, ctx->opcode & 0x7);
1366
        gen_op_store_T0_gpr(rt);
1367
        opn = "mfc0";
1368
        break;
1369
    case OPC_MTC0:
1370
        /* If we get an exception, we want to restart at next instruction */
1371
        ctx->pc += 4;
1372
        save_cpu_state(ctx, 1);
1373
        ctx->pc -= 4;
1374
        GEN_LOAD_REG_TN(T0, rt);
1375
        gen_op_mtc0(rd, ctx->opcode & 0x7);
1376
        /* Stop translation as we may have switched the execution mode */
1377
        ctx->bstate = BS_STOP;
1378
        opn = "mtc0";
1379
        break;
1380
#if defined(MIPS_USES_R4K_TLB)
1381
    case OPC_TLBWI:
1382
        gen_op_tlbwi();
1383
        opn = "tlbwi";
1384
        break;
1385
    case OPC_TLBWR:
1386
        gen_op_tlbwr();
1387
        opn = "tlbwr";
1388
        break;
1389
    case OPC_TLBP:
1390
        gen_op_tlbp();
1391
        opn = "tlbp";
1392
        break;
1393
    case OPC_TLBR:
1394
        gen_op_tlbr();
1395
        opn = "tlbr";
1396
        break;
1397
#endif
1398
    case OPC_ERET:
1399
        opn = "eret";
1400
        save_cpu_state(ctx, 0);
1401
        gen_op_eret();
1402
        ctx->bstate = BS_EXCP;
1403
        break;
1404
    case OPC_DERET:
1405
        opn = "deret";
1406
        if (!(ctx->hflags & MIPS_HFLAG_DM)) {
1407
            generate_exception(ctx, EXCP_RI);
1408
        } else {
1409
            save_cpu_state(ctx, 0);
1410
            gen_op_deret();
1411
            ctx->bstate = BS_EXCP;
1412
        }
1413
        break;
1414
    case OPC_WAIT:
1415
        opn = "wait";
1416
        /* If we get an exception, we want to restart at next instruction */
1417
        ctx->pc += 4;
1418
        save_cpu_state(ctx, 1);
1419
        ctx->pc -= 4;
1420
        gen_op_wait();
1421
        ctx->bstate = BS_EXCP;
1422
        break;
1423
    default:
1424
        if (loglevel & CPU_LOG_TB_IN_ASM) {
1425
            fprintf(logfile, "Invalid CP0 opcode: %08x %03x %03x %03x\n",
1426
                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
1427
                    ((ctx->opcode >> 16) & 0x1F));
1428
        }
1429
        generate_exception(ctx, EXCP_RI);
1430
        return;
1431
    }
1432
    MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
1433
}
1434

    
1435
#ifdef MIPS_USES_FPU
1436
/* CP1 Branches (before delay slot) */
1437
static void gen_compute_branch1 (DisasContext *ctx, uint16_t cond,
1438
                                 int32_t offset)
1439
{
1440
    target_ulong btarget;
1441

    
1442
    btarget = ctx->pc + 4 + offset;
1443

    
1444
    switch (cond) {
1445
    case 0x0000: /* bc1f */
1446
        gen_op_bc1f();
1447
        MIPS_DEBUG("bc1f %08x", btarget);
1448
        goto not_likely;
1449
    case 0x0002: /* bc1fl */
1450
        gen_op_bc1f();
1451
        MIPS_DEBUG("bc1fl %08x", btarget);
1452
        goto likely;
1453
    case 0x0001: /* bc1t */
1454
        gen_op_bc1t();
1455
        MIPS_DEBUG("bc1t %08x", btarget);
1456
    not_likely:
1457
        ctx->hflags |= MIPS_HFLAG_BC;
1458
        break;
1459
    case 0x0003: /* bc1tl */
1460
        gen_op_bc1t();
1461
        MIPS_DEBUG("bc1tl %08x", btarget);
1462
    likely:
1463
        ctx->hflags |= MIPS_HFLAG_BL;
1464
        break;
1465
    default:    
1466
        MIPS_INVAL("cp1 branch/jump");
1467
        generate_exception(ctx, EXCP_RI);
1468
        return;
1469
    }
1470
    gen_op_set_bcond();
1471

    
1472
    MIPS_DEBUG("enter ds: cond %02x target %08x",
1473
               ctx->hflags, btarget);
1474
    ctx->btarget = btarget;
1475

    
1476
    return;
1477
}
1478

    
1479
/* Coprocessor 1 (FPU) */
1480
static void gen_cp1 (DisasContext *ctx, uint16_t opc, int rt, int fs)
1481
{
1482
    const unsigned char *opn = "unk";
1483

    
1484
    switch (opc) {
1485
    case OPC_MFC1:
1486
        GEN_LOAD_FREG_FTN(WT0, fs);
1487
        gen_op_mfc1();
1488
        GEN_STORE_TN_REG(rt, T0);
1489
        opn = "mfc1";
1490
        break;
1491
    case OPC_MTC1:
1492
        GEN_LOAD_REG_TN(T0, rt);
1493
        gen_op_mtc1();
1494
        GEN_STORE_FTN_FREG(fs, WT0);
1495
        opn = "mtc1";
1496
        break;
1497
    case OPC_CFC1:
1498
        if (fs != 0 && fs != 31) {
1499
            MIPS_INVAL("cfc1 freg");
1500
            generate_exception(ctx, EXCP_RI);
1501
            return;
1502
        }
1503
        GEN_LOAD_IMM_TN(T1, fs);
1504
        gen_op_cfc1();
1505
        GEN_STORE_TN_REG(rt, T0);
1506
        opn = "cfc1";
1507
        break;
1508
    case OPC_CTC1:
1509
        if (fs != 0 && fs != 31) {
1510
            MIPS_INVAL("ctc1 freg");
1511
            generate_exception(ctx, EXCP_RI);
1512
            return;
1513
        }
1514
        GEN_LOAD_IMM_TN(T1, fs);
1515
        GEN_LOAD_REG_TN(T0, rt);
1516
        gen_op_ctc1();
1517
        opn = "ctc1";
1518
        break;
1519
    default:
1520
        if (loglevel & CPU_LOG_TB_IN_ASM) {
1521
            fprintf(logfile, "Invalid CP1 opcode: %08x %03x %03x %03x\n",
1522
                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
1523
                    ((ctx->opcode >> 16) & 0x1F));
1524
        }
1525
        generate_exception(ctx, EXCP_RI);
1526
        return;
1527
    }
1528
    MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
1529
}
1530

    
1531
/* verify if floating point register is valid; an operation is not defined
1532
 * if bit 0 of any register specification is set and the FR bit in the
1533
 * Status register equals zero, since the register numbers specify an
1534
 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1535
 * in the Status register equals one, both even and odd register numbers
1536
 * are valid.
1537
 * 
1538
 * Multiple float registers can be checked by calling
1539
 * CHECK_FR(ctx, freg1 | freg2 | ... | fregN);
1540
 */
1541
#define CHECK_FR(ctx, freg) do { \
1542
        if (!((ctx)->CP0_Status & (1<<CP0St_FR)) && ((freg) & 1)) { \
1543
            generate_exception(ctx, EXCP_RI); \
1544
            return; \
1545
        } \
1546
    } while(0)
1547

    
1548
#define FOP(func, fmt) (((fmt) << 21) | (func))
1549

    
1550
static void gen_farith (DisasContext *ctx, int fmt, int ft, int fs, int fd, int func)
1551
{
1552
    const unsigned char *opn = "unk";
1553
    const char *condnames[] = {
1554
            "c.f",
1555
            "c.un",
1556
            "c.eq",
1557
            "c.ueq",
1558
            "c.olt",
1559
            "c.ult",
1560
            "c.ole",
1561
            "c.ule",
1562
            "c.sf",
1563
            "c.ngle",
1564
            "c.seq",
1565
            "c.ngl",
1566
            "c.lt",
1567
            "c.nge",
1568
            "c.le",
1569
            "c.ngt",
1570
    };
1571
    int binary = 0;
1572
    
1573
    switch (ctx->opcode & FOP(0x3f, 0x1f)) {
1574
    case FOP(0, 17):
1575
        CHECK_FR(ctx, fs | ft | fd);
1576
        GEN_LOAD_FREG_FTN(DT0, fs);
1577
        GEN_LOAD_FREG_FTN(DT1, ft);
1578
        gen_op_float_add_d();
1579
        GEN_STORE_FTN_FREG(fd, DT2);
1580
        opn = "add.d";
1581
        binary = 1;
1582
        break;
1583
    case FOP(1, 17):
1584
        CHECK_FR(ctx, fs | ft | fd);
1585
        GEN_LOAD_FREG_FTN(DT0, fs);
1586
        GEN_LOAD_FREG_FTN(DT1, ft);
1587
        gen_op_float_sub_d();
1588
        GEN_STORE_FTN_FREG(fd, DT2);
1589
        opn = "sub.d";
1590
        binary = 1;
1591
        break;
1592
    case FOP(2, 17):
1593
        CHECK_FR(ctx, fs | ft | fd);
1594
        GEN_LOAD_FREG_FTN(DT0, fs);
1595
        GEN_LOAD_FREG_FTN(DT1, ft);
1596
        gen_op_float_mul_d();
1597
        GEN_STORE_FTN_FREG(fd, DT2);
1598
        opn = "mul.d";
1599
        binary = 1;
1600
        break;
1601
    case FOP(3, 17):
1602
        CHECK_FR(ctx, fs | ft | fd);
1603
        GEN_LOAD_FREG_FTN(DT0, fs);
1604
        GEN_LOAD_FREG_FTN(DT1, ft);
1605
        gen_op_float_div_d();
1606
        GEN_STORE_FTN_FREG(fd, DT2);
1607
        opn = "div.d";
1608
        binary = 1;
1609
        break;
1610
    case FOP(4, 17):
1611
        CHECK_FR(ctx, fs | fd);
1612
        GEN_LOAD_FREG_FTN(DT0, fs);
1613
        gen_op_float_sqrt_d();
1614
        GEN_STORE_FTN_FREG(fd, DT2);
1615
        opn = "sqrt.d";
1616
        break;
1617
    case FOP(5, 17):
1618
        CHECK_FR(ctx, fs | fd);
1619
        GEN_LOAD_FREG_FTN(DT0, fs);
1620
        gen_op_float_abs_d();
1621
        GEN_STORE_FTN_FREG(fd, DT2);
1622
        opn = "abs.d";
1623
        break;
1624
    case FOP(6, 17):
1625
        CHECK_FR(ctx, fs | fd);
1626
        GEN_LOAD_FREG_FTN(DT0, fs);
1627
        gen_op_float_mov_d();
1628
        GEN_STORE_FTN_FREG(fd, DT2);
1629
        opn = "mov.d";
1630
        break;
1631
    case FOP(7, 17):
1632
        CHECK_FR(ctx, fs | fd);
1633
        GEN_LOAD_FREG_FTN(DT0, fs);
1634
        gen_op_float_chs_d();
1635
        GEN_STORE_FTN_FREG(fd, DT2);
1636
        opn = "neg.d";
1637
        break;
1638
    /*  8 - round.l */
1639
    /*  9 - trunc.l */
1640
    /* 10 - ceil.l  */
1641
    /* 11 - floor.l */
1642
    case FOP(12, 17):
1643
        CHECK_FR(ctx, fs | fd);
1644
        GEN_LOAD_FREG_FTN(DT0, fs);
1645
        gen_op_float_roundw_d();
1646
        GEN_STORE_FTN_FREG(fd, WT2);
1647
        opn = "round.w.d";
1648
        break;
1649
    case FOP(13, 17):
1650
        CHECK_FR(ctx, fs | fd);
1651
        GEN_LOAD_FREG_FTN(DT0, fs);
1652
        gen_op_float_truncw_d();
1653
        GEN_STORE_FTN_FREG(fd, WT2);
1654
        opn = "trunc.w.d";
1655
        break;
1656
    case FOP(14, 17):
1657
        CHECK_FR(ctx, fs | fd);
1658
        GEN_LOAD_FREG_FTN(DT0, fs);
1659
        gen_op_float_ceilw_d();
1660
        GEN_STORE_FTN_FREG(fd, WT2);
1661
        opn = "ceil.w.d";
1662
        break;
1663
    case FOP(15, 17):
1664
        CHECK_FR(ctx, fs | fd);
1665
        GEN_LOAD_FREG_FTN(DT0, fs);
1666
        gen_op_float_floorw_d();
1667
        GEN_STORE_FTN_FREG(fd, WT2);
1668
        opn = "ceil.w.d";
1669
        break;
1670
    case FOP(33, 20): /* cvt.d.w */
1671
        CHECK_FR(ctx, fs | fd);
1672
        GEN_LOAD_FREG_FTN(WT0, fs);
1673
        gen_op_float_cvtd_w();
1674
        GEN_STORE_FTN_FREG(fd, DT2);
1675
        opn = "cvt.d.w";
1676
        break;
1677
    case FOP(48, 17):
1678
    case FOP(49, 17):
1679
    case FOP(50, 17):
1680
    case FOP(51, 17):
1681
    case FOP(52, 17):
1682
    case FOP(53, 17):
1683
    case FOP(54, 17):
1684
    case FOP(55, 17):
1685
    case FOP(56, 17):
1686
    case FOP(57, 17):
1687
    case FOP(58, 17):
1688
    case FOP(59, 17):
1689
    case FOP(60, 17):
1690
    case FOP(61, 17):
1691
    case FOP(62, 17):
1692
    case FOP(63, 17):
1693
        CHECK_FR(ctx, fs | ft);
1694
        GEN_LOAD_FREG_FTN(DT0, fs);
1695
        GEN_LOAD_FREG_FTN(DT1, ft);
1696
        gen_cmp_d(func-48);
1697
        opn = condnames[func-48];
1698
        break;
1699
    case FOP(0, 16):
1700
        CHECK_FR(ctx, fs | ft | fd);
1701
        GEN_LOAD_FREG_FTN(WT0, fs);
1702
        GEN_LOAD_FREG_FTN(WT1, ft);
1703
        gen_op_float_add_s();
1704
        GEN_STORE_FTN_FREG(fd, WT2);
1705
        opn = "add.s";
1706
        binary = 1;
1707
        break;
1708
    case FOP(1, 16):
1709
        CHECK_FR(ctx, fs | ft | fd);
1710
        GEN_LOAD_FREG_FTN(WT0, fs);
1711
        GEN_LOAD_FREG_FTN(WT1, ft);
1712
        gen_op_float_sub_s();
1713
        GEN_STORE_FTN_FREG(fd, WT2);
1714
        opn = "sub.s";
1715
        binary = 1;
1716
        break;
1717
    case FOP(2, 16):
1718
        CHECK_FR(ctx, fs | ft | fd);
1719
        GEN_LOAD_FREG_FTN(WT0, fs);
1720
        GEN_LOAD_FREG_FTN(WT1, ft);
1721
        gen_op_float_mul_s();
1722
        GEN_STORE_FTN_FREG(fd, WT2);
1723
        opn = "mul.s";
1724
        binary = 1;
1725
        break;
1726
    case FOP(3, 16):
1727
        CHECK_FR(ctx, fs | ft | fd);
1728
        GEN_LOAD_FREG_FTN(WT0, fs);
1729
        GEN_LOAD_FREG_FTN(WT1, ft);
1730
        gen_op_float_div_s();
1731
        GEN_STORE_FTN_FREG(fd, WT2);
1732
        opn = "div.s";
1733
        binary = 1;
1734
        break;
1735
    case FOP(4, 16):
1736
        CHECK_FR(ctx, fs | fd);
1737
        GEN_LOAD_FREG_FTN(WT0, fs);
1738
        gen_op_float_sqrt_s();
1739
        GEN_STORE_FTN_FREG(fd, WT2);
1740
        opn = "sqrt.s";
1741
        break;
1742
    case FOP(5, 16):
1743
        CHECK_FR(ctx, fs | fd);
1744
        GEN_LOAD_FREG_FTN(WT0, fs);
1745
        gen_op_float_abs_s();
1746
        GEN_STORE_FTN_FREG(fd, WT2);
1747
        opn = "abs.s";
1748
        break;
1749
    case FOP(6, 16):
1750
        CHECK_FR(ctx, fs | fd);
1751
        GEN_LOAD_FREG_FTN(WT0, fs);
1752
        gen_op_float_mov_s();
1753
        GEN_STORE_FTN_FREG(fd, WT2);
1754
        opn = "mov.s";
1755
        break;
1756
    case FOP(7, 16):
1757
        CHECK_FR(ctx, fs | fd);
1758
        GEN_LOAD_FREG_FTN(WT0, fs);
1759
        gen_op_float_chs_s();
1760
        GEN_STORE_FTN_FREG(fd, WT2);
1761
        opn = "neg.s";
1762
        break;
1763
    case FOP(12, 16):
1764
        CHECK_FR(ctx, fs | fd);
1765
        GEN_LOAD_FREG_FTN(WT0, fs);
1766
        gen_op_float_roundw_s();
1767
        GEN_STORE_FTN_FREG(fd, WT2);
1768
        opn = "round.w.s";
1769
        break;
1770
    case FOP(13, 16):
1771
        CHECK_FR(ctx, fs | fd);
1772
        GEN_LOAD_FREG_FTN(WT0, fs);
1773
        gen_op_float_truncw_s();
1774
        GEN_STORE_FTN_FREG(fd, WT2);
1775
        opn = "trunc.w.s";
1776
        break;
1777
    case FOP(32, 20): /* cvt.s.w */
1778
        CHECK_FR(ctx, fs | fd);
1779
        GEN_LOAD_FREG_FTN(WT0, fs);
1780
        gen_op_float_cvts_w();
1781
        GEN_STORE_FTN_FREG(fd, WT2);
1782
        opn = "cvt.s.w";
1783
        break;
1784
    case FOP(36, 16): /* cvt.w.s */
1785
        CHECK_FR(ctx, fs | fd);
1786
        GEN_LOAD_FREG_FTN(WT0, fs);
1787
        gen_op_float_cvtw_s();
1788
        GEN_STORE_FTN_FREG(fd, WT2);
1789
        opn = "cvt.w.s";
1790
        break;
1791
    case FOP(36, 17): /* cvt.w.d */
1792
        CHECK_FR(ctx, fs | fd);
1793
        GEN_LOAD_FREG_FTN(WT0, fs);
1794
        gen_op_float_cvtw_d();
1795
        GEN_STORE_FTN_FREG(fd, WT2);
1796
        opn = "cvt.w.d";
1797
        break;
1798
    case FOP(48, 16):
1799
    case FOP(49, 16):
1800
    case FOP(50, 16):
1801
    case FOP(51, 16):
1802
    case FOP(52, 16):
1803
    case FOP(53, 16):
1804
    case FOP(54, 16):
1805
    case FOP(55, 16):
1806
    case FOP(56, 16):
1807
    case FOP(57, 16):
1808
    case FOP(58, 16):
1809
    case FOP(59, 16):
1810
    case FOP(60, 16):
1811
    case FOP(61, 16):
1812
    case FOP(62, 16):
1813
    case FOP(63, 16):
1814
        CHECK_FR(ctx, fs | ft);
1815
        GEN_LOAD_FREG_FTN(WT0, fs);
1816
        GEN_LOAD_FREG_FTN(WT1, ft);
1817
        gen_cmp_s(func-48);
1818
        opn = condnames[func-48];
1819
        break;
1820
    default:    
1821
        if (loglevel & CPU_LOG_TB_IN_ASM) {
1822
            fprintf(logfile, "Invalid arith function: %08x %03x %03x %03x\n",
1823
                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
1824
                    ((ctx->opcode >> 16) & 0x1F));
1825
        }
1826
        generate_exception(ctx, EXCP_RI);
1827
        return;
1828
    }
1829
    if (binary)
1830
        MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
1831
    else
1832
        MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
1833
}
1834
#endif
1835

    
1836
/* ISA extensions */
1837
/* MIPS16 extension to MIPS32 */
1838
/* SmartMIPS extension to MIPS32 */
1839

    
1840
#ifdef TARGET_MIPS64
1841
static void gen_arith64 (DisasContext *ctx, uint16_t opc)
1842
{
1843
    if (func == 0x02 && rd == 0) {
1844
        /* NOP */
1845
        return;
1846
    }
1847
    if (rs == 0 || rt == 0) {
1848
        gen_op_reset_T0();
1849
        gen_op_save64();
1850
    } else {
1851
        gen_op_load_gpr_T0(rs);
1852
        gen_op_load_gpr_T1(rt);
1853
        gen_op_save64();
1854
        if (func & 0x01)
1855
            gen_op_mul64u();
1856
        else
1857
            gen_op_mul64s();
1858
    }
1859
    if (func & 0x02)
1860
        gen_op_add64();
1861
    else
1862
        gen_op_sub64();
1863
}
1864

    
1865
/* Coprocessor 3 (FPU) */
1866

    
1867
/* MDMX extension to MIPS64 */
1868
/* MIPS-3D extension to MIPS64 */
1869

    
1870
#endif
1871

    
1872
static void gen_blikely(DisasContext *ctx)
1873
{
1874
    int l1;
1875
    l1 = gen_new_label();
1876
    gen_op_jnz_T2(l1);
1877
    gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
1878
    gen_goto_tb(ctx, 1, ctx->pc + 4);
1879
    gen_set_label(l1);
1880
}
1881

    
1882
static void decode_opc (DisasContext *ctx)
1883
{
1884
    int32_t offset;
1885
    int rs, rt, rd, sa;
1886
    uint16_t op, op1;
1887
    int16_t imm;
1888

    
1889
    if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
1890
        /* Handle blikely not taken case */
1891
        MIPS_DEBUG("blikely condition (%08x)", ctx->pc + 4);
1892
        gen_blikely(ctx);
1893
    }
1894
    op = ctx->opcode >> 26;
1895
    rs = ((ctx->opcode >> 21) & 0x1F);
1896
    rt = ((ctx->opcode >> 16) & 0x1F);
1897
    rd = ((ctx->opcode >> 11) & 0x1F);
1898
    sa = ((ctx->opcode >> 6) & 0x1F);
1899
    imm = (int16_t)ctx->opcode;
1900
    switch (op) {
1901
    case 0x00:          /* Special opcode */
1902
        op1 = ctx->opcode & 0x3F;
1903
        switch (op1) {
1904
        case 0x00:          /* Arithmetic with immediate */
1905
        case 0x02 ... 0x03:
1906
            gen_arith_imm(ctx, op1 | EXT_SPECIAL, rd, rt, sa);
1907
            break;
1908
        case 0x04:          /* Arithmetic */
1909
        case 0x06 ... 0x07:
1910
        case 0x0A ... 0x0B:
1911
        case 0x20 ... 0x27:
1912
        case 0x2A ... 0x2B:
1913
            gen_arith(ctx, op1 | EXT_SPECIAL, rd, rs, rt);
1914
            break;
1915
        case 0x18 ... 0x1B: /* MULT / DIV */
1916
            gen_muldiv(ctx, op1 | EXT_SPECIAL, rs, rt);
1917
            break;
1918
        case 0x08 ... 0x09: /* Jumps */
1919
            gen_compute_branch(ctx, op1 | EXT_SPECIAL, rs, rd, sa);
1920
            return;
1921
        case 0x30 ... 0x34: /* Traps */
1922
        case 0x36:
1923
            gen_trap(ctx, op1 | EXT_SPECIAL, rs, rt, -1);
1924
            break;
1925
        case 0x10:          /* Move from HI/LO */
1926
        case 0x12:
1927
            gen_HILO(ctx, op1 | EXT_SPECIAL, rd);
1928
            break;
1929
        case 0x11:
1930
        case 0x13:          /* Move to HI/LO */
1931
            gen_HILO(ctx, op1 | EXT_SPECIAL, rs);
1932
            break;
1933
        case 0x0C:          /* SYSCALL */
1934
            generate_exception(ctx, EXCP_SYSCALL);
1935
            break;
1936
        case 0x0D:          /* BREAK */
1937
            generate_exception(ctx, EXCP_BREAK);
1938
            break;
1939
        case 0x0F:          /* SYNC */
1940
            /* Treat as a noop */
1941
            break;
1942
        case 0x05:          /* Pmon entry point */
1943
            gen_op_pmon((ctx->opcode >> 6) & 0x1F);
1944
            break;
1945

    
1946
        case 0x01:          /* MOVCI */
1947
#if defined (MIPS_HAS_MOVCI)
1948
            /* XXX */
1949
#else
1950
            /* Not implemented */
1951
            generate_exception_err (ctx, EXCP_CpU, 1);
1952
#endif
1953
            break;
1954

    
1955
#if defined (TARGET_MIPS64)
1956
        case 0x14: /* MIPS64 specific opcodes */
1957
        case 0x16:
1958
        case 0x17:
1959
        case 0x1C ... 0x1F:
1960
        case 0x2C ... 0x2F:
1961
        case 0x37:
1962
        case 0x39 ... 0x3B:
1963
        case 0x3E ... 0x3F:
1964
#endif
1965
        default:            /* Invalid */
1966
            MIPS_INVAL("special");
1967
            generate_exception(ctx, EXCP_RI);
1968
            break;
1969
        }
1970
        break;
1971
    case 0x1C:          /* Special2 opcode */
1972
        op1 = ctx->opcode & 0x3F;
1973
        switch (op1) {
1974
#if defined (MIPS_USES_R4K_EXT)
1975
        /* Those instructions are not part of MIPS32 core */
1976
        case 0x00 ... 0x01: /* Multiply and add/sub */
1977
        case 0x04 ... 0x05:
1978
            gen_muldiv(ctx, op1 | EXT_SPECIAL2, rs, rt);
1979
            break;
1980
        case 0x02:          /* MUL */
1981
            gen_arith(ctx, op1 | EXT_SPECIAL2, rd, rs, rt);
1982
            break;
1983
        case 0x20 ... 0x21: /* CLO / CLZ */
1984
            gen_cl(ctx, op1 | EXT_SPECIAL2, rd, rs);
1985
            break;
1986
#endif
1987
        case 0x3F:          /* SDBBP */
1988
            /* XXX: not clear which exception should be raised
1989
             *      when in debug mode...
1990
             */
1991
            if (!(ctx->hflags & MIPS_HFLAG_DM)) {
1992
                generate_exception(ctx, EXCP_DBp);
1993
            } else {
1994
                generate_exception(ctx, EXCP_DBp);
1995
            }
1996
            /* Treat as a noop */
1997
            break;
1998
        default:            /* Invalid */
1999
            MIPS_INVAL("special2");
2000
            generate_exception(ctx, EXCP_RI);
2001
            break;
2002
        }
2003
        break;
2004
    case 0x01:          /* B REGIMM opcode */
2005
        op1 = ((ctx->opcode >> 16) & 0x1F);
2006
        switch (op1) {
2007
        case 0x00 ... 0x03: /* REGIMM branches */
2008
        case 0x10 ... 0x13:
2009
            gen_compute_branch(ctx, op1 | EXT_REGIMM, rs, -1, imm << 2);
2010
            return;
2011
        case 0x08 ... 0x0C: /* Traps */
2012
        case 0x0E:
2013
            gen_trap(ctx, op1 | EXT_REGIMM, rs, -1, imm);
2014
            break;
2015
        default:            /* Invalid */
2016
            MIPS_INVAL("REGIMM");
2017
            generate_exception(ctx, EXCP_RI);
2018
            break;
2019
        }
2020
        break;
2021
    case 0x10:          /* CP0 opcode */
2022
        op1 = ((ctx->opcode >> 21) & 0x1F);
2023
        switch (op1) {
2024
        case 0x00:
2025
        case 0x04:
2026
            gen_cp0(ctx, op1 | EXT_CP0, rt, rd);
2027
            break;
2028
        default:
2029
            gen_cp0(ctx, (ctx->opcode & 0x3F) | EXT_CP0, rt, rd);
2030
            break;
2031
        }
2032
        break;
2033
    case 0x08 ... 0x0F: /* Arithmetic with immediate opcode */
2034
        gen_arith_imm(ctx, op, rt, rs, imm);
2035
        break;
2036
    case 0x02 ... 0x03: /* Jump */
2037
        offset = (int32_t)(ctx->opcode & 0x03FFFFFF) << 2;
2038
        gen_compute_branch(ctx, op, rs, rt, offset);
2039
        return;
2040
    case 0x04 ... 0x07: /* Branch */
2041
    case 0x14 ... 0x17:
2042
        gen_compute_branch(ctx, op, rs, rt, imm << 2);
2043
        return;
2044
    case 0x20 ... 0x26: /* Load and stores */
2045
    case 0x28 ... 0x2E:
2046
    case 0x30:
2047
    case 0x38:
2048
        gen_ldst(ctx, op, rt, rs, imm);
2049
        break;
2050
    case 0x2F:          /* Cache operation */
2051
        /* Treat as a noop */
2052
        break;
2053
    case 0x33:          /* Prefetch */
2054
        /* Treat as a noop */
2055
        break;
2056
    case 0x3F: /* HACK */
2057
        break;
2058

    
2059
    /* Floating point.  */
2060
    case 0x31: /* LWC1 */
2061
    case 0x35: /* LDC1 */
2062
    case 0x39: /* SWC1 */
2063
    case 0x3D: /* SDC1 */
2064
#if defined(MIPS_USES_FPU)
2065
        gen_op_cp1_enabled();
2066
        gen_flt_ldst(ctx, op, rt, rs, imm);
2067
#else
2068
        generate_exception_err(ctx, EXCP_CpU, 1);
2069
#endif
2070
        break;
2071

    
2072
    case 0x11:          /* CP1 opcode */
2073
#if defined(MIPS_USES_FPU)
2074
        gen_op_cp1_enabled();
2075
        op1 = ((ctx->opcode >> 21) & 0x1F);
2076
        switch (op1) {
2077
        case 0x00: /* mfc1 */
2078
        case 0x02: /* cfc1 */
2079
        case 0x04: /* mtc1 */
2080
        case 0x06: /* ctc1 */
2081
            gen_cp1(ctx, op1 | EXT_CP1, rt, rd);
2082
            break;
2083
        case 0x08: /* bc */
2084
            gen_compute_branch1(ctx, rt, imm << 2);
2085
            return;
2086
        case 0x10: /* 16: fmt=single fp */
2087
        case 0x11: /* 17: fmt=double fp */
2088
        case 0x14: /* 20: fmt=32bit fixed */
2089
        case 0x15: /* 21: fmt=64bit fixed */
2090
            gen_farith(ctx, op1, rt, rd, sa, ctx->opcode & 0x3f);
2091
            break;
2092
        default:
2093
            generate_exception_err(ctx, EXCP_RI, 1);
2094
            break;
2095
        }
2096
        break;
2097
#else
2098
        generate_exception_err(ctx, EXCP_CpU, 1);
2099
#endif
2100
        break;
2101

    
2102
    /* COP2.  */
2103
    case 0x32: /* LWC2 */
2104
    case 0x36: /* LDC2 */
2105
    case 0x3A: /* SWC2 */
2106
    case 0x3E: /* SDC2 */
2107
    case 0x12:          /* CP2 opcode */
2108
        /* Not implemented */
2109
        generate_exception_err(ctx, EXCP_CpU, 2);
2110
        break;
2111

    
2112
    case 0x13:          /* CP3 opcode */
2113
        /* Not implemented */
2114
        generate_exception_err(ctx, EXCP_CpU, 3);
2115
        break;
2116

    
2117
#if defined (TARGET_MIPS64)
2118
    case 0x18 ... 0x1B:
2119
    case 0x27:
2120
    case 0x34:
2121
    case 0x37:
2122
        /* MIPS64 opcodes */
2123
#endif
2124
#if defined (MIPS_HAS_JALX)
2125
    case 0x1D:
2126
        /* JALX: not implemented */
2127
#endif
2128
    case 0x1E:
2129
        /* ASE specific */
2130
    default:            /* Invalid */
2131
        MIPS_INVAL("");
2132
        generate_exception(ctx, EXCP_RI);
2133
        break;
2134
    }
2135
    if (ctx->hflags & MIPS_HFLAG_BMASK) {
2136
        int hflags = ctx->hflags;
2137
        /* Branches completion */
2138
        ctx->hflags &= ~MIPS_HFLAG_BMASK;
2139
        ctx->bstate = BS_BRANCH;
2140
        save_cpu_state(ctx, 0);
2141
        switch (hflags & MIPS_HFLAG_BMASK) {
2142
        case MIPS_HFLAG_B:
2143
            /* unconditional branch */
2144
            MIPS_DEBUG("unconditional branch");
2145
            gen_goto_tb(ctx, 0, ctx->btarget);
2146
            break;
2147
        case MIPS_HFLAG_BL:
2148
            /* blikely taken case */
2149
            MIPS_DEBUG("blikely branch taken");
2150
            gen_goto_tb(ctx, 0, ctx->btarget);
2151
            break;
2152
        case MIPS_HFLAG_BC:
2153
            /* Conditional branch */
2154
            MIPS_DEBUG("conditional branch");
2155
            {
2156
              int l1;
2157
              l1 = gen_new_label();
2158
              gen_op_jnz_T2(l1);
2159
              gen_goto_tb(ctx, 1, ctx->pc + 4);
2160
              gen_set_label(l1);
2161
              gen_goto_tb(ctx, 0, ctx->btarget);
2162
            }
2163
            break;
2164
        case MIPS_HFLAG_BR:
2165
            /* unconditional branch to register */
2166
            MIPS_DEBUG("branch to register");
2167
            gen_op_breg();
2168
            break;
2169
        default:
2170
            MIPS_DEBUG("unknown branch");
2171
            break;
2172
        }
2173
    }
2174
}
2175

    
2176
int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
2177
                                    int search_pc)
2178
{
2179
    DisasContext ctx, *ctxp = &ctx;
2180
    target_ulong pc_start;
2181
    uint16_t *gen_opc_end;
2182
    int j, lj = -1;
2183

    
2184
    if (search_pc && loglevel)
2185
        fprintf (logfile, "search pc %d\n", search_pc);
2186

    
2187
    pc_start = tb->pc;
2188
    gen_opc_ptr = gen_opc_buf;
2189
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2190
    gen_opparam_ptr = gen_opparam_buf;
2191
    nb_gen_labels = 0;
2192
    ctx.pc = pc_start;
2193
    ctx.saved_pc = -1;
2194
    ctx.tb = tb;
2195
    ctx.bstate = BS_NONE;
2196
    /* Restore delay slot state from the tb context.  */
2197
    ctx.hflags = tb->flags;
2198
    ctx.saved_hflags = ctx.hflags;
2199
    if (ctx.hflags & MIPS_HFLAG_BR) {
2200
        gen_op_restore_breg_target();
2201
    } else if (ctx.hflags & MIPS_HFLAG_B) {
2202
        ctx.btarget = env->btarget;
2203
    } else if (ctx.hflags & MIPS_HFLAG_BMASK) {
2204
        /* If we are in the delay slot of a conditional branch,
2205
         * restore the branch condition from env->bcond to T2
2206
         */
2207
        ctx.btarget = env->btarget;
2208
        gen_op_restore_bcond();
2209
    }
2210
#if defined(CONFIG_USER_ONLY)
2211
    ctx.mem_idx = 0;
2212
#else
2213
    ctx.mem_idx = !((ctx.hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM);
2214
#endif
2215
    ctx.CP0_Status = env->CP0_Status;
2216
#ifdef DEBUG_DISAS
2217
    if (loglevel & CPU_LOG_TB_CPU) {
2218
        fprintf(logfile, "------------------------------------------------\n");
2219
        /* FIXME: This may print out stale hflags from env... */
2220
        cpu_dump_state(env, logfile, fprintf, 0);
2221
    }
2222
#endif
2223
#if defined MIPS_DEBUG_DISAS
2224
    if (loglevel & CPU_LOG_TB_IN_ASM)
2225
        fprintf(logfile, "\ntb %p super %d cond %04x\n",
2226
                tb, ctx.mem_idx, ctx.hflags);
2227
#endif
2228
    while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
2229
        if (env->nb_breakpoints > 0) {
2230
            for(j = 0; j < env->nb_breakpoints; j++) {
2231
                if (env->breakpoints[j] == ctx.pc) {
2232
                    save_cpu_state(ctxp, 1);
2233
                    ctx.bstate = BS_BRANCH;
2234
                    gen_op_debug();
2235
                    goto done_generating;
2236
                }
2237
            }
2238
        }
2239

    
2240
        if (search_pc) {
2241
            j = gen_opc_ptr - gen_opc_buf;
2242
            if (lj < j) {
2243
                lj++;
2244
                while (lj < j)
2245
                    gen_opc_instr_start[lj++] = 0;
2246
            }
2247
            gen_opc_pc[lj] = ctx.pc;
2248
            gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
2249
            gen_opc_instr_start[lj] = 1;
2250
        }
2251
        ctx.opcode = ldl_code(ctx.pc);
2252
        decode_opc(&ctx);
2253
        ctx.pc += 4;
2254

    
2255
        if (env->singlestep_enabled)
2256
            break;
2257

    
2258
        if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
2259
            break;
2260

    
2261
#if defined (MIPS_SINGLE_STEP)
2262
        break;
2263
#endif
2264
    }
2265
    if (env->singlestep_enabled) {
2266
        save_cpu_state(ctxp, ctx.bstate == BS_NONE);
2267
        gen_op_debug();
2268
        goto done_generating;
2269
    }
2270
    else if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) {
2271
        save_cpu_state(ctxp, 0);
2272
        gen_goto_tb(&ctx, 0, ctx.pc);
2273
    }
2274
    gen_op_reset_T0();
2275
    /* Generate the return instruction */
2276
    gen_op_exit_tb();
2277
done_generating:
2278
    *gen_opc_ptr = INDEX_op_end;
2279
    if (search_pc) {
2280
        j = gen_opc_ptr - gen_opc_buf;
2281
        lj++;
2282
        while (lj <= j)
2283
            gen_opc_instr_start[lj++] = 0;
2284
        tb->size = 0;
2285
    } else {
2286
        tb->size = ctx.pc - pc_start;
2287
    }
2288
#ifdef DEBUG_DISAS
2289
#if defined MIPS_DEBUG_DISAS
2290
    if (loglevel & CPU_LOG_TB_IN_ASM)
2291
        fprintf(logfile, "\n");
2292
#endif
2293
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2294
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2295
    target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
2296
        fprintf(logfile, "\n");
2297
    }
2298
    if (loglevel & CPU_LOG_TB_OP) {
2299
        fprintf(logfile, "OP:\n");
2300
        dump_ops(gen_opc_buf, gen_opparam_buf);
2301
        fprintf(logfile, "\n");
2302
    }
2303
    if (loglevel & CPU_LOG_TB_CPU) {
2304
        fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
2305
    }
2306
#endif
2307
    
2308
    return 0;
2309
}
2310

    
2311
int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
2312
{
2313
    return gen_intermediate_code_internal(env, tb, 0);
2314
}
2315

    
2316
int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
2317
{
2318
    return gen_intermediate_code_internal(env, tb, 1);
2319
}
2320

    
2321
#ifdef MIPS_USES_FPU
2322
void fpu_dump_state(CPUState *env, FILE *f, 
2323
                    int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
2324
                    int flags)
2325
{
2326
    int i;
2327

    
2328
#   define printfpr(fp) do { \
2329
        fpu_fprintf(f, "w:%08x d:%08lx%08lx fd:%g fs:%g\n", \
2330
                (fp)->w[FP_ENDIAN_IDX], (fp)->w[0], (fp)->w[1], (fp)->fd, (fp)->fs[FP_ENDIAN_IDX]); \
2331
    } while(0)
2332

    
2333
    fpu_fprintf(f, "CP1 FCR0 0x%08x  FCR31 0x%08x  SR.FR %d\n",
2334
                env->fcr0, env->fcr31,
2335
                (env->CP0_Status & (1<<CP0St_FR)) != 0);
2336
    fpu_fprintf(f, "FT0: "); printfpr(&env->ft0);
2337
    fpu_fprintf(f, "FT1: "); printfpr(&env->ft1);
2338
    fpu_fprintf(f, "FT2: "); printfpr(&env->ft2);
2339
    for(i=0; i < 32; i+=2) {
2340
        fpu_fprintf(f, "f%02d: ", i);
2341
        printfpr(FPR(env, i));
2342
    }
2343

    
2344
#undef printfpr
2345
}
2346

    
2347
void dump_fpu(CPUState *env)
2348
{
2349
    if (loglevel) { 
2350
       fprintf(logfile, "pc=0x%08x HI=0x%08x LO=0x%08x ds %04x %08x %d\n",
2351
               env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
2352
       fpu_dump_state(env, logfile, fprintf, 0);
2353
    }
2354
}
2355
#endif /* MIPS_USES_FPU */
2356

    
2357
void cpu_dump_state (CPUState *env, FILE *f, 
2358
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2359
                     int flags)
2360
{
2361
    uint32_t c0_status;
2362
    int i;
2363
    
2364
    cpu_fprintf(f, "pc=0x%08x HI=0x%08x LO=0x%08x ds %04x %08x %d\n",
2365
                env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
2366
    for (i = 0; i < 32; i++) {
2367
        if ((i & 3) == 0)
2368
            cpu_fprintf(f, "GPR%02d:", i);
2369
        cpu_fprintf(f, " %s %08x", regnames[i], env->gpr[i]);
2370
        if ((i & 3) == 3)
2371
            cpu_fprintf(f, "\n");
2372
    }
2373

    
2374
    c0_status = env->CP0_Status;
2375
    if (env->hflags & MIPS_HFLAG_UM)
2376
        c0_status |= (1 << CP0St_UM);
2377
    if (env->hflags & MIPS_HFLAG_ERL)
2378
        c0_status |= (1 << CP0St_ERL);
2379
    if (env->hflags & MIPS_HFLAG_EXL)
2380
        c0_status |= (1 << CP0St_EXL);
2381

    
2382
    cpu_fprintf(f, "CP0 Status  0x%08x Cause   0x%08x EPC    0x%08x\n",
2383
                c0_status, env->CP0_Cause, env->CP0_EPC);
2384
    cpu_fprintf(f, "    Config0 0x%08x Config1 0x%08x LLAddr 0x%08x\n",
2385
                env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
2386
#ifdef MIPS_USES_FPU
2387
    fpu_dump_state(env, f, cpu_fprintf, flags);
2388
#endif
2389
}
2390

    
2391
CPUMIPSState *cpu_mips_init (void)
2392
{
2393
    CPUMIPSState *env;
2394

    
2395
    env = qemu_mallocz(sizeof(CPUMIPSState));
2396
    if (!env)
2397
        return NULL;
2398
    cpu_exec_init(env);
2399
    tlb_flush(env, 1);
2400
    /* Minimal init */
2401
    env->PC = 0xBFC00000;
2402
#if defined (MIPS_USES_R4K_TLB)
2403
    env->CP0_random = MIPS_TLB_NB - 1;
2404
#endif
2405
    env->CP0_Wired = 0;
2406
    env->CP0_Config0 = MIPS_CONFIG0;
2407
#if defined (MIPS_CONFIG1)
2408
        env->CP0_Config1 = MIPS_CONFIG1;
2409
#endif
2410
#if defined (MIPS_CONFIG2)
2411
        env->CP0_Config2 = MIPS_CONFIG2;
2412
#endif
2413
#if defined (MIPS_CONFIG3)
2414
        env->CP0_Config3 = MIPS_CONFIG3;
2415
#endif
2416
    env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV);
2417
    env->CP0_WatchLo = 0;
2418
    env->hflags = MIPS_HFLAG_ERL;
2419
    /* Count register increments in debug mode, EJTAG version 1 */
2420
    env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
2421
    env->CP0_PRid = MIPS_CPU;
2422
    env->exception_index = EXCP_NONE;
2423
#if defined(CONFIG_USER_ONLY)
2424
    env->hflags |= MIPS_HFLAG_UM;
2425
#endif
2426
#ifdef MIPS_USES_FPU
2427
    env->fcr0 = MIPS_FCR0;        
2428
#endif
2429
    return env;
2430
}