Statistics
| Branch: | Revision:

root / target-mips / translate.c @ 7a387fff

History | View | Annotate | Download (110 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 major opcodes */
54
#define MASK_OP_MAJOR(op)  (op & (0x3F << 26))
55

    
56
enum {
57
    /* indirect opcode tables */
58
    OPC_SPECIAL  = (0x00 << 26),
59
    OPC_REGIMM   = (0x01 << 26),
60
    OPC_CP0      = (0x10 << 26),
61
    OPC_CP1      = (0x11 << 26),
62
    OPC_CP2      = (0x12 << 26),
63
    OPC_CP3      = (0x13 << 26),
64
    OPC_SPECIAL2 = (0x1C << 26),
65
    OPC_SPECIAL3 = (0x1F << 26),
66
    /* arithmetic with immediate */
67
    OPC_ADDI     = (0x08 << 26),
68
    OPC_ADDIU    = (0x09 << 26),
69
    OPC_SLTI     = (0x0A << 26),
70
    OPC_SLTIU    = (0x0B << 26),
71
    OPC_ANDI     = (0x0C << 26),
72
    OPC_ORI      = (0x0D << 26),
73
    OPC_XORI     = (0x0E << 26),
74
    OPC_LUI      = (0x0F << 26),
75
    OPC_DADDI    = (0x18 << 26),
76
    OPC_DADDIU   = (0x19 << 26),
77
    /* Jump and branches */
78
    OPC_J        = (0x02 << 26),
79
    OPC_JAL      = (0x03 << 26),
80
    OPC_BEQ      = (0x04 << 26),  /* Unconditional if rs = rt = 0 (B) */
81
    OPC_BEQL     = (0x14 << 26),
82
    OPC_BNE      = (0x05 << 26),
83
    OPC_BNEL     = (0x15 << 26),
84
    OPC_BLEZ     = (0x06 << 26),
85
    OPC_BLEZL    = (0x16 << 26),
86
    OPC_BGTZ     = (0x07 << 26),
87
    OPC_BGTZL    = (0x17 << 26),
88
    OPC_JALX     = (0x1D << 26),  /* MIPS 16 only */
89
    /* Load and stores */
90
    OPC_LDL      = (0x1A << 26),
91
    OPC_LDR      = (0x1B << 26),
92
    OPC_LB       = (0x20 << 26),
93
    OPC_LH       = (0x21 << 26),
94
    OPC_LWL      = (0x22 << 26),
95
    OPC_LW       = (0x23 << 26),
96
    OPC_LBU      = (0x24 << 26),
97
    OPC_LHU      = (0x25 << 26),
98
    OPC_LWR      = (0x26 << 26),
99
    OPC_LWU      = (0x27 << 26),
100
    OPC_SB       = (0x28 << 26),
101
    OPC_SH       = (0x29 << 26),
102
    OPC_SWL      = (0x2A << 26),
103
    OPC_SW       = (0x2B << 26),
104
    OPC_SDL      = (0x2C << 26),
105
    OPC_SDR      = (0x2D << 26),
106
    OPC_SWR      = (0x2E << 26),
107
    OPC_LL       = (0x30 << 26),
108
    OPC_LLD      = (0x34 << 26),
109
    OPC_LD       = (0x37 << 26),
110
    OPC_SC       = (0x38 << 26),
111
    OPC_SCD      = (0x3C << 26),
112
    OPC_SD       = (0x3F << 26),
113
    /* Floating point load/store */
114
    OPC_LWC1     = (0x31 << 26),
115
    OPC_LWC2     = (0x32 << 26),
116
    OPC_LDC1     = (0x35 << 26),
117
    OPC_LDC2     = (0x36 << 26),
118
    OPC_SWC1     = (0x39 << 26),
119
    OPC_SWC2     = (0x3A << 26),
120
    OPC_SDC1     = (0x3D << 26),
121
    OPC_SDC2     = (0x3E << 26),
122
    /* MDMX ASE specific */
123
    OPC_MDMX     = (0x1E << 26),
124
    /* Cache and prefetch */
125
    OPC_CACHE    = (0x2F << 26),
126
    OPC_PREF     = (0x33 << 26),
127
    /* Reserved major opcode */
128
    OPC_MAJOR3B_RESERVED = (0x3B << 26),
129
};
130

    
131
/* MIPS special opcodes */
132
#define MASK_SPECIAL(op)   MASK_OP_MAJOR(op) | (op & 0x3F)
133

    
134
enum {
135
    /* Shifts */
136
    OPC_SLL      = 0x00 | OPC_SPECIAL,
137
    /* NOP is SLL r0, r0, 0   */
138
    /* SSNOP is SLL r0, r0, 1 */
139
    /* EHB is SLL r0, r0, 3 */
140
    OPC_SRL      = 0x02 | OPC_SPECIAL, /* also ROTR */
141
    OPC_SRA      = 0x03 | OPC_SPECIAL,
142
    OPC_SLLV     = 0x04 | OPC_SPECIAL,
143
    OPC_SRLV     = 0x06 | OPC_SPECIAL,
144
    OPC_SRAV     = 0x07 | OPC_SPECIAL,
145
    OPC_DSLLV    = 0x14 | OPC_SPECIAL,
146
    OPC_DSRLV    = 0x16 | OPC_SPECIAL, /* also DROTRV */
147
    OPC_DSRAV    = 0x17 | OPC_SPECIAL,
148
    OPC_DSLL     = 0x38 | OPC_SPECIAL,
149
    OPC_DSRL     = 0x3A | OPC_SPECIAL, /* also DROTR */
150
    OPC_DSRA     = 0x3B | OPC_SPECIAL,
151
    OPC_DSLL32   = 0x3C | OPC_SPECIAL,
152
    OPC_DSRL32   = 0x3E | OPC_SPECIAL, /* also DROTR32 */
153
    OPC_DSRA32   = 0x3F | OPC_SPECIAL,
154
    /* Multiplication / division */
155
    OPC_MULT     = 0x18 | OPC_SPECIAL,
156
    OPC_MULTU    = 0x19 | OPC_SPECIAL,
157
    OPC_DIV      = 0x1A | OPC_SPECIAL,
158
    OPC_DIVU     = 0x1B | OPC_SPECIAL,
159
    OPC_DMULT    = 0x1C | OPC_SPECIAL,
160
    OPC_DMULTU   = 0x1D | OPC_SPECIAL,
161
    OPC_DDIV     = 0x1E | OPC_SPECIAL,
162
    OPC_DDIVU    = 0x1F | OPC_SPECIAL,
163
    /* 2 registers arithmetic / logic */
164
    OPC_ADD      = 0x20 | OPC_SPECIAL,
165
    OPC_ADDU     = 0x21 | OPC_SPECIAL,
166
    OPC_SUB      = 0x22 | OPC_SPECIAL,
167
    OPC_SUBU     = 0x23 | OPC_SPECIAL,
168
    OPC_AND      = 0x24 | OPC_SPECIAL,
169
    OPC_OR       = 0x25 | OPC_SPECIAL,
170
    OPC_XOR      = 0x26 | OPC_SPECIAL,
171
    OPC_NOR      = 0x27 | OPC_SPECIAL,
172
    OPC_SLT      = 0x2A | OPC_SPECIAL,
173
    OPC_SLTU     = 0x2B | OPC_SPECIAL,
174
    OPC_DADD     = 0x2C | OPC_SPECIAL,
175
    OPC_DADDU    = 0x2D | OPC_SPECIAL,
176
    OPC_DSUB     = 0x2E | OPC_SPECIAL,
177
    OPC_DSUBU    = 0x2F | OPC_SPECIAL,
178
    /* Jumps */
179
    OPC_JR       = 0x08 | OPC_SPECIAL, /* Also JR.HB */
180
    OPC_JALR     = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
181
    /* Traps */
182
    OPC_TGE      = 0x30 | OPC_SPECIAL,
183
    OPC_TGEU     = 0x31 | OPC_SPECIAL,
184
    OPC_TLT      = 0x32 | OPC_SPECIAL,
185
    OPC_TLTU     = 0x33 | OPC_SPECIAL,
186
    OPC_TEQ      = 0x34 | OPC_SPECIAL,
187
    OPC_TNE      = 0x36 | OPC_SPECIAL,
188
    /* HI / LO registers load & stores */
189
    OPC_MFHI     = 0x10 | OPC_SPECIAL,
190
    OPC_MTHI     = 0x11 | OPC_SPECIAL,
191
    OPC_MFLO     = 0x12 | OPC_SPECIAL,
192
    OPC_MTLO     = 0x13 | OPC_SPECIAL,
193
    /* Conditional moves */
194
    OPC_MOVZ     = 0x0A | OPC_SPECIAL,
195
    OPC_MOVN     = 0x0B | OPC_SPECIAL,
196

    
197
    OPC_MOVCI    = 0x01 | OPC_SPECIAL,
198

    
199
    /* Special */
200
    OPC_PMON     = 0x05 | OPC_SPECIAL, /* inofficial */
201
    OPC_SYSCALL  = 0x0C | OPC_SPECIAL,
202
    OPC_BREAK    = 0x0D | OPC_SPECIAL,
203
    OPC_SPIM     = 0x0E | OPC_SPECIAL, /* inofficial */
204
    OPC_SYNC     = 0x0F | OPC_SPECIAL,
205

    
206
    OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
207
    OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
208
    OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
209
    OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
210
    OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
211
    OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
212
    OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
213
};
214

    
215
/* REGIMM (rt field) opcodes */
216
#define MASK_REGIMM(op)    MASK_OP_MAJOR(op) | (op & (0x1F << 16))
217

    
218
enum {
219
    OPC_BLTZ     = (0x00 << 16) | OPC_REGIMM,
220
    OPC_BLTZL    = (0x02 << 16) | OPC_REGIMM,
221
    OPC_BGEZ     = (0x01 << 16) | OPC_REGIMM,
222
    OPC_BGEZL    = (0x03 << 16) | OPC_REGIMM,
223
    OPC_BLTZAL   = (0x10 << 16) | OPC_REGIMM,
224
    OPC_BLTZALL  = (0x12 << 16) | OPC_REGIMM,
225
    OPC_BGEZAL   = (0x11 << 16) | OPC_REGIMM,
226
    OPC_BGEZALL  = (0x13 << 16) | OPC_REGIMM,
227
    OPC_TGEI     = (0x08 << 16) | OPC_REGIMM,
228
    OPC_TGEIU    = (0x09 << 16) | OPC_REGIMM,
229
    OPC_TLTI     = (0x0A << 16) | OPC_REGIMM,
230
    OPC_TLTIU    = (0x0B << 16) | OPC_REGIMM,
231
    OPC_TEQI     = (0x0C << 16) | OPC_REGIMM,
232
    OPC_TNEI     = (0x0E << 16) | OPC_REGIMM,
233
    OPC_SYNCI    = (0x1F << 16) | OPC_REGIMM,
234
};
235

    
236
/* Special2 opcodes */
237
#define MASK_SPECIAL2(op)  MASK_OP_MAJOR(op) | (op & 0x3F)
238

    
239
enum {
240
    /* Multiply & xxx operations */
241
    OPC_MADD     = 0x00 | OPC_SPECIAL2,
242
    OPC_MADDU    = 0x01 | OPC_SPECIAL2,
243
    OPC_MUL      = 0x02 | OPC_SPECIAL2,
244
    OPC_MSUB     = 0x04 | OPC_SPECIAL2,
245
    OPC_MSUBU    = 0x05 | OPC_SPECIAL2,
246
    /* Misc */
247
    OPC_CLZ      = 0x20 | OPC_SPECIAL2,
248
    OPC_CLO      = 0x21 | OPC_SPECIAL2,
249
    OPC_DCLZ     = 0x24 | OPC_SPECIAL2,
250
    OPC_DCLO     = 0x25 | OPC_SPECIAL2,
251
    /* Special */
252
    OPC_SDBBP    = 0x3F | OPC_SPECIAL2,
253
};
254

    
255
/* Special3 opcodes */
256
#define MASK_SPECIAL3(op)  MASK_OP_MAJOR(op) | (op & 0x3F)
257

    
258
enum {
259
    OPC_EXT      = 0x00 | OPC_SPECIAL3,
260
    OPC_DEXTM    = 0x01 | OPC_SPECIAL3,
261
    OPC_DEXTU    = 0x02 | OPC_SPECIAL3,
262
    OPC_DEXT     = 0x03 | OPC_SPECIAL3,
263
    OPC_INS      = 0x04 | OPC_SPECIAL3,
264
    OPC_DINSM    = 0x05 | OPC_SPECIAL3,
265
    OPC_DINSU    = 0x06 | OPC_SPECIAL3,
266
    OPC_DINS     = 0x07 | OPC_SPECIAL3,
267
    OPC_BSHFL    = 0x20 | OPC_SPECIAL3,
268
    OPC_DBSHFL   = 0x24 | OPC_SPECIAL3,
269
    OPC_RDHWR    = 0x3B | OPC_SPECIAL3,
270
};
271

    
272
/* BSHFL opcodes */
273
#define MASK_BSHFL(op)     MASK_SPECIAL3(op) | (op & (0x1F << 6))
274

    
275
enum {
276
    OPC_WSBH     = (0x02 << 6) | OPC_BSHFL,
277
    OPC_SEB      = (0x10 << 6) | OPC_BSHFL,
278
    OPC_SEH      = (0x18 << 6) | OPC_BSHFL,
279
};
280

    
281
/* DBSHFL opcodes */
282
#define MASK_DBSHFL(op)    MASK_SPECIAL3(op) | (op & (0x1F << 6))
283

    
284
enum {
285
    OPC_DSBH     = (0x02 << 6) | OPC_DBSHFL,
286
    OPC_DSHD     = (0x05 << 6) | OPC_DBSHFL,
287
};
288

    
289
/* Coprocessor 0 (rs field) */
290
#define MASK_CP0(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
291

    
292
enum {
293
    OPC_MFC0     = (0x00 << 21) | OPC_CP0,
294
    OPC_DMFC0    = (0x01 << 21) | OPC_CP0,
295
    OPC_MTC0     = (0x04 << 21) | OPC_CP0,
296
    OPC_DMTC0    = (0x05 << 21) | OPC_CP0,
297
    OPC_RDPGPR   = (0x0A << 21) | OPC_CP0,
298
    OPC_MFMC0    = (0x0B << 21) | OPC_CP0,
299
    OPC_WRPGPR   = (0x0E << 21) | OPC_CP0,
300
    OPC_C0       = (0x10 << 21) | OPC_CP0,
301
    OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
302
    OPC_C0_LAST  = (0x1F << 21) | OPC_CP0,
303
};
304

    
305
/* MFMC0 opcodes */
306
#define MASK_MFMC0(op)     MASK_CP0(op) | (op & ((0x0C << 11) | (1 << 5)))
307

    
308
enum {
309
    OPC_DI       = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
310
    OPC_EI       = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
311
};
312

    
313
/* Coprocessor 0 (with rs == C0) */
314
#define MASK_C0(op)        MASK_CP0(op) | (op & 0x3F)
315

    
316
enum {
317
    OPC_TLBR     = 0x01 | OPC_C0,
318
    OPC_TLBWI    = 0x02 | OPC_C0,
319
    OPC_TLBWR    = 0x06 | OPC_C0,
320
    OPC_TLBP     = 0x08 | OPC_C0,
321
    OPC_RFE      = 0x10 | OPC_C0,
322
    OPC_ERET     = 0x18 | OPC_C0,
323
    OPC_DERET    = 0x1F | OPC_C0,
324
    OPC_WAIT     = 0x20 | OPC_C0,
325
};
326

    
327
/* Coprocessor 1 (rs field) */
328
#define MASK_CP1(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
329

    
330
enum {
331
    OPC_MFC1     = (0x00 << 21) | OPC_CP1,
332
    OPC_DMFC1    = (0x01 << 21) | OPC_CP1,
333
    OPC_CFC1     = (0x02 << 21) | OPC_CP1,
334
    OPC_MFHCI    = (0x03 << 21) | OPC_CP1,
335
    OPC_MTC1     = (0x04 << 21) | OPC_CP1,
336
    OPC_DMTC1    = (0x05 << 21) | OPC_CP1,
337
    OPC_CTC1     = (0x06 << 21) | OPC_CP1,
338
    OPC_MTHCI    = (0x07 << 21) | OPC_CP1,
339
    OPC_BC1      = (0x08 << 21) | OPC_CP1, /* bc */
340
    OPC_S_FMT    = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */
341
    OPC_D_FMT    = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */
342
    OPC_E_FMT    = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */
343
    OPC_Q_FMT    = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */
344
    OPC_W_FMT    = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
345
    OPC_L_FMT    = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
346
};
347

    
348
enum {
349
    OPC_BC1F     = (0x00 << 16) | OPC_BC1,
350
    OPC_BC1T     = (0x01 << 16) | OPC_BC1,
351
    OPC_BC1FL    = (0x02 << 16) | OPC_BC1,
352
    OPC_BC1TL    = (0x03 << 16) | OPC_BC1,
353
};
354

    
355
#define MASK_CP1_BCOND(op)      MASK_CP1(op) | (op & ((0x1F << 21) | (0x3 << 16)))
356
#define MASK_CP1_FUNC(op)       MASK_CP1(op) | (op & ((0x1F << 21) | 0x3F))
357

    
358
#define MASK_CP2(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
359
#define MASK_CP3(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
360

    
361
const unsigned char *regnames[] =
362
    { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
363
      "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
364
      "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
365
      "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
366

    
367
/* Warning: no function for r0 register (hard wired to zero) */
368
#define GEN32(func, NAME) \
369
static GenOpFunc *NAME ## _table [32] = {                                     \
370
NULL,       NAME ## 1, NAME ## 2, NAME ## 3,                                  \
371
NAME ## 4,  NAME ## 5, NAME ## 6, NAME ## 7,                                  \
372
NAME ## 8,  NAME ## 9, NAME ## 10, NAME ## 11,                                \
373
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
374
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
375
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
376
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
377
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
378
};                                                                            \
379
static inline void func(int n)                                                \
380
{                                                                             \
381
    NAME ## _table[n]();                                                      \
382
}
383

    
384
/* General purpose registers moves */
385
GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
386
GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
387
GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr);
388

    
389
GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
390
GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
391

    
392
static const char *fregnames[] =
393
    { "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
394
      "f8",  "f9",  "f10", "f11", "f12", "f13", "f14", "f15",
395
      "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
396
      "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
397

    
398
# define SFGEN32(func, NAME) \
399
static GenOpFunc *NAME ## _table [32] = {                                     \
400
NAME ## 0,  NAME ## 1,  NAME ## 2,  NAME ## 3,                                \
401
NAME ## 4,  NAME ## 5,  NAME ## 6,  NAME ## 7,                                \
402
NAME ## 8,  NAME ## 9,  NAME ## 10, NAME ## 11,                               \
403
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
404
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
405
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
406
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
407
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
408
};                                                                            \
409
static inline void func(int n)                                                \
410
{                                                                             \
411
    NAME ## _table[n]();                                                      \
412
}
413

    
414
# define DFGEN32(func, NAME) \
415
static GenOpFunc *NAME ## _table [32] = {                                     \
416
NAME ## 0,  0, NAME ## 2,  0,                                                 \
417
NAME ## 4,  0, NAME ## 6,  0,                                                 \
418
NAME ## 8,  0, NAME ## 10, 0,                                                 \
419
NAME ## 12, 0, NAME ## 14, 0,                                                 \
420
NAME ## 16, 0, NAME ## 18, 0,                                                 \
421
NAME ## 20, 0, NAME ## 22, 0,                                                 \
422
NAME ## 24, 0, NAME ## 26, 0,                                                 \
423
NAME ## 28, 0, NAME ## 30, 0,                                                 \
424
};                                                                            \
425
static inline void func(int n)                                                \
426
{                                                                             \
427
    NAME ## _table[n]();                                                      \
428
}
429

    
430
SFGEN32(gen_op_load_fpr_WT0,  gen_op_load_fpr_WT0_fpr);
431
SFGEN32(gen_op_store_fpr_WT0, gen_op_store_fpr_WT0_fpr);
432

    
433
SFGEN32(gen_op_load_fpr_WT1,  gen_op_load_fpr_WT1_fpr);
434
SFGEN32(gen_op_store_fpr_WT1, gen_op_store_fpr_WT1_fpr);
435

    
436
SFGEN32(gen_op_load_fpr_WT2,  gen_op_load_fpr_WT2_fpr);
437
SFGEN32(gen_op_store_fpr_WT2, gen_op_store_fpr_WT2_fpr);
438

    
439
DFGEN32(gen_op_load_fpr_DT0,  gen_op_load_fpr_DT0_fpr);
440
DFGEN32(gen_op_store_fpr_DT0, gen_op_store_fpr_DT0_fpr);
441

    
442
DFGEN32(gen_op_load_fpr_DT1,  gen_op_load_fpr_DT1_fpr);
443
DFGEN32(gen_op_store_fpr_DT1, gen_op_store_fpr_DT1_fpr);
444

    
445
DFGEN32(gen_op_load_fpr_DT2,  gen_op_load_fpr_DT2_fpr);
446
DFGEN32(gen_op_store_fpr_DT2, gen_op_store_fpr_DT2_fpr);
447

    
448
#define FOP_CONDS(fmt) \
449
static GenOpFunc * cond_ ## fmt ## _table[16] = {                       \
450
    gen_op_cmp_ ## fmt ## _f,                                           \
451
    gen_op_cmp_ ## fmt ## _un,                                          \
452
    gen_op_cmp_ ## fmt ## _eq,                                          \
453
    gen_op_cmp_ ## fmt ## _ueq,                                         \
454
    gen_op_cmp_ ## fmt ## _olt,                                         \
455
    gen_op_cmp_ ## fmt ## _ult,                                         \
456
    gen_op_cmp_ ## fmt ## _ole,                                         \
457
    gen_op_cmp_ ## fmt ## _ule,                                         \
458
    gen_op_cmp_ ## fmt ## _sf,                                          \
459
    gen_op_cmp_ ## fmt ## _ngle,                                        \
460
    gen_op_cmp_ ## fmt ## _seq,                                         \
461
    gen_op_cmp_ ## fmt ## _ngl,                                         \
462
    gen_op_cmp_ ## fmt ## _lt,                                          \
463
    gen_op_cmp_ ## fmt ## _nge,                                         \
464
    gen_op_cmp_ ## fmt ## _le,                                          \
465
    gen_op_cmp_ ## fmt ## _ngt,                                         \
466
};                                                                      \
467
static inline void gen_cmp_ ## fmt(int n)                               \
468
{                                                                       \
469
    cond_ ## fmt ## _table[n]();                                        \
470
}
471

    
472
FOP_CONDS(d)
473
FOP_CONDS(s)
474

    
475
typedef struct DisasContext {
476
    struct TranslationBlock *tb;
477
    target_ulong pc, saved_pc;
478
    uint32_t opcode;
479
    /* Routine used to access memory */
480
    int mem_idx;
481
    uint32_t hflags, saved_hflags;
482
    uint32_t CP0_Status;
483
    int bstate;
484
    target_ulong btarget;
485
} DisasContext;
486

    
487
enum {
488
    BS_NONE     = 0, /* We go out of the TB without reaching a branch or an
489
                      * exception condition
490
                      */
491
    BS_STOP     = 1, /* We want to stop translation for any reason */
492
    BS_BRANCH   = 2, /* We reached a branch condition     */
493
    BS_EXCP     = 3, /* We reached an exception condition */
494
};
495

    
496
#if defined MIPS_DEBUG_DISAS
497
#define MIPS_DEBUG(fmt, args...)                                              \
498
do {                                                                          \
499
    if (loglevel & CPU_LOG_TB_IN_ASM) {                                       \
500
        fprintf(logfile, "%08x: %08x " fmt "\n",                              \
501
                ctx->pc, ctx->opcode , ##args);                               \
502
    }                                                                         \
503
} while (0)
504
#else
505
#define MIPS_DEBUG(fmt, args...) do { } while(0)
506
#endif
507

    
508
#define MIPS_INVAL(op)                                                        \
509
do {                                                                          \
510
    MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26,            \
511
               ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F));             \
512
} while (0)
513

    
514
#define GEN_LOAD_REG_TN(Tn, Rn)                                               \
515
do {                                                                          \
516
    if (Rn == 0) {                                                            \
517
        glue(gen_op_reset_, Tn)();                                            \
518
    } else {                                                                  \
519
        glue(gen_op_load_gpr_, Tn)(Rn);                                       \
520
    }                                                                         \
521
} while (0)
522

    
523
#define GEN_LOAD_IMM_TN(Tn, Imm)                                              \
524
do {                                                                          \
525
    if (Imm == 0) {                                                           \
526
        glue(gen_op_reset_, Tn)();                                            \
527
    } else {                                                                  \
528
        glue(gen_op_set_, Tn)(Imm);                                           \
529
    }                                                                         \
530
} while (0)
531

    
532
#define GEN_STORE_TN_REG(Rn, Tn)                                              \
533
do {                                                                          \
534
    if (Rn != 0) {                                                            \
535
        glue(glue(gen_op_store_, Tn),_gpr)(Rn);                               \
536
    }                                                                         \
537
} while (0)
538

    
539
#define GEN_LOAD_FREG_FTN(FTn, Fn)                                            \
540
do {                                                                          \
541
    glue(gen_op_load_fpr_, FTn)(Fn);                                          \
542
} while (0)
543

    
544
#define GEN_STORE_FTN_FREG(Fn, FTn)                                           \
545
do {                                                                          \
546
    glue(gen_op_store_fpr_, FTn)(Fn);                                         \
547
} while (0)
548

    
549
static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
550
{
551
#if defined MIPS_DEBUG_DISAS
552
    if (loglevel & CPU_LOG_TB_IN_ASM) {
553
            fprintf(logfile, "hflags %08x saved %08x\n",
554
                    ctx->hflags, ctx->saved_hflags);
555
    }
556
#endif
557
    if (do_save_pc && ctx->pc != ctx->saved_pc) {
558
        gen_op_save_pc(ctx->pc);
559
        ctx->saved_pc = ctx->pc;
560
    }
561
    if (ctx->hflags != ctx->saved_hflags) {
562
        gen_op_save_state(ctx->hflags);
563
        ctx->saved_hflags = ctx->hflags;
564
        if (ctx->hflags & MIPS_HFLAG_BR) {
565
            gen_op_save_breg_target();
566
        } else if (ctx->hflags & MIPS_HFLAG_B) {
567
            gen_op_save_btarget(ctx->btarget);
568
        } else if (ctx->hflags & MIPS_HFLAG_BMASK) {
569
            gen_op_save_bcond();
570
            gen_op_save_btarget(ctx->btarget);
571
        }
572
    }
573
}
574

    
575
static inline void generate_exception_err (DisasContext *ctx, int excp, int err)
576
{
577
#if defined MIPS_DEBUG_DISAS
578
    if (loglevel & CPU_LOG_TB_IN_ASM)
579
            fprintf(logfile, "%s: raise exception %d\n", __func__, excp);
580
#endif
581
    save_cpu_state(ctx, 1);
582
    if (err == 0)
583
        gen_op_raise_exception(excp);
584
    else
585
        gen_op_raise_exception_err(excp, err);
586
    ctx->bstate = BS_EXCP;
587
}
588

    
589
static inline void generate_exception (DisasContext *ctx, int excp)
590
{
591
    generate_exception_err (ctx, excp, 0);
592
}
593

    
594
#if defined(CONFIG_USER_ONLY)
595
#define op_ldst(name)        gen_op_##name##_raw()
596
#define OP_LD_TABLE(width)
597
#define OP_ST_TABLE(width)
598
#else
599
#define op_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
600
#define OP_LD_TABLE(width)                                                    \
601
static GenOpFunc *gen_op_l##width[] = {                                       \
602
    &gen_op_l##width##_user,                                                  \
603
    &gen_op_l##width##_kernel,                                                \
604
}
605
#define OP_ST_TABLE(width)                                                    \
606
static GenOpFunc *gen_op_s##width[] = {                                       \
607
    &gen_op_s##width##_user,                                                  \
608
    &gen_op_s##width##_kernel,                                                \
609
}
610
#endif
611

    
612
#ifdef MIPS_HAS_MIPS64
613
OP_LD_TABLE(d);
614
OP_LD_TABLE(dl);
615
OP_LD_TABLE(dr);
616
OP_ST_TABLE(d);
617
OP_ST_TABLE(dl);
618
OP_ST_TABLE(dr);
619
#endif
620
OP_LD_TABLE(w);
621
OP_LD_TABLE(wu);
622
OP_LD_TABLE(wl);
623
OP_LD_TABLE(wr);
624
OP_ST_TABLE(w);
625
OP_ST_TABLE(wl);
626
OP_ST_TABLE(wr);
627
OP_LD_TABLE(h);
628
OP_LD_TABLE(hu);
629
OP_ST_TABLE(h);
630
OP_LD_TABLE(b);
631
OP_LD_TABLE(bu);
632
OP_ST_TABLE(b);
633
OP_LD_TABLE(l);
634
OP_ST_TABLE(c);
635
OP_LD_TABLE(wc1);
636
OP_ST_TABLE(wc1);
637
OP_LD_TABLE(dc1);
638
OP_ST_TABLE(dc1);
639

    
640
/* Load and store */
641
static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
642
                      int base, int16_t offset)
643
{
644
    const char *opn = "unk";
645

    
646
    if (base == 0) {
647
        GEN_LOAD_IMM_TN(T0, offset);
648
    } else if (offset == 0) {
649
        gen_op_load_gpr_T0(base);
650
    } else {
651
        gen_op_load_gpr_T0(base);
652
        gen_op_set_T1(offset);
653
        gen_op_add();
654
    }
655
    /* Don't do NOP if destination is zero: we must perform the actual
656
     * memory access
657
     */
658
    switch (opc) {
659
#ifdef MIPS_HAS_MIPS64
660
    case OPC_LD:
661
        op_ldst(ld);
662
        GEN_STORE_TN_REG(rt, T0);
663
        opn = "ld";
664
        break;
665
    case OPC_LLD:
666
        op_ldst(lld);
667
        GEN_STORE_TN_REG(rt, T0);
668
        opn = "lld";
669
        break;
670
    case OPC_SD:
671
        GEN_LOAD_REG_TN(T1, rt);
672
        op_ldst(sd);
673
        opn = "sd";
674
        break;
675
    case OPC_SCD:
676
        GEN_LOAD_REG_TN(T1, rt);
677
        op_ldst(scd);
678
        opn = "scd";
679
        break;
680
    case OPC_LDL:
681
        op_ldst(ldl);
682
        GEN_STORE_TN_REG(rt, T0);
683
        opn = "ldl";
684
        break;
685
    case OPC_SDL:
686
        GEN_LOAD_REG_TN(T1, rt);
687
        op_ldst(sdl);
688
        opn = "sdl";
689
        break;
690
    case OPC_LDR:
691
        op_ldst(ldr);
692
        GEN_STORE_TN_REG(rt, T0);
693
        opn = "ldr";
694
        break;
695
    case OPC_SDR:
696
        GEN_LOAD_REG_TN(T1, rt);
697
        op_ldst(sdr);
698
        opn = "sdr";
699
        break;
700
#endif
701
    case OPC_LW:
702
        op_ldst(lw);
703
        GEN_STORE_TN_REG(rt, T0);
704
        opn = "lw";
705
        break;
706
    case OPC_LWU:
707
        op_ldst(lwu);
708
        GEN_STORE_TN_REG(rt, T0);
709
        opn = "lwu";
710
        break;
711
    case OPC_SW:
712
        GEN_LOAD_REG_TN(T1, rt);
713
        op_ldst(sw);
714
        opn = "sw";
715
        break;
716
    case OPC_LH:
717
        op_ldst(lh);
718
        GEN_STORE_TN_REG(rt, T0);
719
        opn = "lh";
720
        break;
721
    case OPC_SH:
722
        GEN_LOAD_REG_TN(T1, rt);
723
        op_ldst(sh);
724
        opn = "sh";
725
        break;
726
    case OPC_LHU:
727
        op_ldst(lhu);
728
        GEN_STORE_TN_REG(rt, T0);
729
        opn = "lhu";
730
        break;
731
    case OPC_LB:
732
        op_ldst(lb);
733
        GEN_STORE_TN_REG(rt, T0);
734
        opn = "lb";
735
        break;
736
    case OPC_SB:
737
        GEN_LOAD_REG_TN(T1, rt);
738
        op_ldst(sb);
739
        opn = "sb";
740
        break;
741
    case OPC_LBU:
742
        op_ldst(lbu);
743
        GEN_STORE_TN_REG(rt, T0);
744
        opn = "lbu";
745
        break;
746
    case OPC_LWL:
747
        GEN_LOAD_REG_TN(T1, rt);
748
        op_ldst(lwl);
749
        GEN_STORE_TN_REG(rt, T0);
750
        opn = "lwl";
751
        break;
752
    case OPC_SWL:
753
        GEN_LOAD_REG_TN(T1, rt);
754
        op_ldst(swl);
755
        opn = "swr";
756
        break;
757
    case OPC_LWR:
758
        GEN_LOAD_REG_TN(T1, rt);
759
        op_ldst(lwr);
760
        GEN_STORE_TN_REG(rt, T0);
761
        opn = "lwr";
762
        break;
763
    case OPC_SWR:
764
        GEN_LOAD_REG_TN(T1, rt);
765
        op_ldst(swr);
766
        opn = "swr";
767
        break;
768
    case OPC_LL:
769
        op_ldst(ll);
770
        GEN_STORE_TN_REG(rt, T0);
771
        opn = "ll";
772
        break;
773
    case OPC_SC:
774
        GEN_LOAD_REG_TN(T1, rt);
775
        op_ldst(sc);
776
        GEN_STORE_TN_REG(rt, T0);
777
        opn = "sc";
778
        break;
779
    default:
780
        MIPS_INVAL("load/store");
781
        generate_exception(ctx, EXCP_RI);
782
        return;
783
    }
784
    MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
785
}
786

    
787
/* Load and store */
788
static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
789
                      int base, int16_t offset)
790
{
791
    const char *opn = "unk";
792

    
793
    if (base == 0) {
794
        GEN_LOAD_IMM_TN(T0, offset);
795
    } else if (offset == 0) {
796
        gen_op_load_gpr_T0(base);
797
    } else {
798
        gen_op_load_gpr_T0(base);
799
        gen_op_set_T1(offset);
800
        gen_op_add();
801
    }
802
    /* Don't do NOP if destination is zero: we must perform the actual
803
     * memory access
804
     */
805
    switch (opc) {
806
    case OPC_LWC1:
807
        op_ldst(lwc1);
808
        GEN_STORE_FTN_FREG(ft, WT0);
809
        opn = "lwc1";
810
        break;
811
    case OPC_SWC1:
812
        GEN_LOAD_FREG_FTN(WT0, ft);
813
        op_ldst(swc1);
814
        opn = "swc1";
815
        break;
816
    case OPC_LDC1:
817
        op_ldst(ldc1);
818
        GEN_STORE_FTN_FREG(ft, DT0);
819
        opn = "ldc1";
820
        break;
821
    case OPC_SDC1:
822
        GEN_LOAD_FREG_FTN(DT0, ft);
823
        op_ldst(sdc1);
824
        opn = "sdc1";
825
        break;
826
    default:
827
        MIPS_INVAL("float load/store");
828
        generate_exception_err(ctx, EXCP_CpU, 1);
829
        return;
830
    }
831
    MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
832
}
833

    
834
/* Arithmetic with immediate operand */
835
static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt,
836
                           int rs, int16_t imm)
837
{
838
    uint32_t uimm;
839
    const char *opn = "unk";
840

    
841
    if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
842
        /* if no destination, treat it as a NOP 
843
         * For addi, we must generate the overflow exception when needed.
844
         */
845
        MIPS_DEBUG("NOP");
846
        return;
847
    }
848
    if (opc == OPC_ADDI || opc == OPC_ADDIU ||
849
        opc == OPC_DADDI || opc == OPC_DADDIU ||
850
        opc == OPC_SLTI || opc == OPC_SLTIU)
851
        uimm = (int32_t)imm; /* Sign extend to 32 bits */
852
    else
853
        uimm = (uint16_t)imm;
854
    if (opc != OPC_LUI) {
855
        GEN_LOAD_REG_TN(T0, rs);
856
        GEN_LOAD_IMM_TN(T1, uimm);
857
    } else {
858
        uimm = uimm << 16;
859
        GEN_LOAD_IMM_TN(T0, uimm);
860
    }
861
    switch (opc) {
862
    case OPC_ADDI:
863
        save_cpu_state(ctx, 1);
864
        gen_op_addo();
865
        opn = "addi";
866
        break;
867
    case OPC_ADDIU:
868
        gen_op_add();
869
        opn = "addiu";
870
        break;
871
#ifdef MIPS_HAS_MIPS64
872
    case OPC_DADDI:
873
        save_cpu_state(ctx, 1);
874
        gen_op_daddo();
875
        opn = "daddi";
876
        break;
877
    case OPC_DADDIU:
878
        gen_op_dadd();
879
        opn = "daddiu";
880
        break;
881
#endif
882
    case OPC_SLTI:
883
        gen_op_lt();
884
        opn = "slti";
885
        break;
886
    case OPC_SLTIU:
887
        gen_op_ltu();
888
        opn = "sltiu";
889
        break;
890
    case OPC_ANDI:
891
        gen_op_and();
892
        opn = "andi";
893
        break;
894
    case OPC_ORI:
895
        gen_op_or();
896
        opn = "ori";
897
        break;
898
    case OPC_XORI:
899
        gen_op_xor();
900
        opn = "xori";
901
        break;
902
    case OPC_LUI:
903
        opn = "lui";
904
        break;
905
    case OPC_SLL:
906
        gen_op_sll();
907
        opn = "sll";
908
        break;
909
    case OPC_SRA:
910
        gen_op_sra();
911
        opn = "sra";
912
        break;
913
    case OPC_SRL:
914
       if ((ctx->opcode >> 21) & 1) {
915
            gen_op_rotr();
916
            opn = "rotr";
917
       } else {
918
            gen_op_srl();
919
            opn = "srl";
920
       }
921
        break;
922
#ifdef MIPS_HAS_MIPS64
923
    case OPC_DSLL:
924
        gen_op_dsll();
925
        opn = "dsll";
926
        break;
927
    case OPC_DSRA:
928
        gen_op_dsra();
929
        opn = "dsra";
930
        break;
931
    case OPC_DSRL:
932
       if ((ctx->opcode >> 21) & 1) {
933
            gen_op_drotr();
934
            opn = "drotr";
935
       } else {
936
            gen_op_dsrl();
937
            opn = "dsrl";
938
       }
939
        break;
940
    case OPC_DSLL32:
941
        gen_op_dsll32();
942
        opn = "dsll32";
943
        break;
944
    case OPC_DSRA32:
945
        gen_op_dsra32();
946
        opn = "dsra32";
947
        break;
948
    case OPC_DSRL32:
949
       if ((ctx->opcode >> 21) & 1) {
950
            gen_op_drotr32();
951
            opn = "drotr32";
952
       } else {
953
            gen_op_dsrl32();
954
            opn = "dsrl32";
955
       }
956
        break;
957
#endif
958
    default:
959
        MIPS_INVAL("imm arith");
960
        generate_exception(ctx, EXCP_RI);
961
        return;
962
    }
963
    GEN_STORE_TN_REG(rt, T0);
964
    MIPS_DEBUG("%s %s, %s, %x", opn, regnames[rt], regnames[rs], uimm);
965
}
966

    
967
/* Arithmetic */
968
static void gen_arith (DisasContext *ctx, uint32_t opc,
969
                       int rd, int rs, int rt)
970
{
971
    const char *opn = "unk";
972

    
973
    if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
974
       && opc != OPC_DADD && opc != OPC_DSUB) {
975
        /* if no destination, treat it as a NOP 
976
         * For add & sub, we must generate the overflow exception when needed.
977
         */
978
        MIPS_DEBUG("NOP");
979
        return;
980
    }
981
    GEN_LOAD_REG_TN(T0, rs);
982
    GEN_LOAD_REG_TN(T1, rt);
983
    switch (opc) {
984
    case OPC_ADD:
985
        save_cpu_state(ctx, 1);
986
        gen_op_addo();
987
        opn = "add";
988
        break;
989
    case OPC_ADDU:
990
        gen_op_add();
991
        opn = "addu";
992
        break;
993
    case OPC_SUB:
994
        save_cpu_state(ctx, 1);
995
        gen_op_subo();
996
        opn = "sub";
997
        break;
998
    case OPC_SUBU:
999
        gen_op_sub();
1000
        opn = "subu";
1001
        break;
1002
#ifdef MIPS_HAS_MIPS64
1003
    case OPC_DADD:
1004
        save_cpu_state(ctx, 1);
1005
        gen_op_daddo();
1006
        opn = "dadd";
1007
        break;
1008
    case OPC_DADDU:
1009
        gen_op_dadd();
1010
        opn = "daddu";
1011
        break;
1012
    case OPC_DSUB:
1013
        save_cpu_state(ctx, 1);
1014
        gen_op_dsubo();
1015
        opn = "dsub";
1016
        break;
1017
    case OPC_DSUBU:
1018
        gen_op_dsub();
1019
        opn = "dsubu";
1020
        break;
1021
#endif
1022
    case OPC_SLT:
1023
        gen_op_lt();
1024
        opn = "slt";
1025
        break;
1026
    case OPC_SLTU:
1027
        gen_op_ltu();
1028
        opn = "sltu";
1029
        break;
1030
    case OPC_AND:
1031
        gen_op_and();
1032
        opn = "and";
1033
        break;
1034
    case OPC_NOR:
1035
        gen_op_nor();
1036
        opn = "nor";
1037
        break;
1038
    case OPC_OR:
1039
        gen_op_or();
1040
        opn = "or";
1041
        break;
1042
    case OPC_XOR:
1043
        gen_op_xor();
1044
        opn = "xor";
1045
        break;
1046
    case OPC_MUL:
1047
        gen_op_mul();
1048
        opn = "mul";
1049
        break;
1050
    case OPC_MOVN:
1051
        gen_op_movn(rd);
1052
        opn = "movn";
1053
        goto print;
1054
    case OPC_MOVZ:
1055
        gen_op_movz(rd);
1056
        opn = "movz";
1057
        goto print;
1058
    case OPC_SLLV:
1059
        gen_op_sllv();
1060
        opn = "sllv";
1061
        break;
1062
    case OPC_SRAV:
1063
        gen_op_srav();
1064
        opn = "srav";
1065
        break;
1066
    case OPC_SRLV:
1067
       if ((ctx->opcode >> 6) & 1) {
1068
            gen_op_rotrv();
1069
            opn = "rotrv";
1070
       } else {
1071
            gen_op_srlv();
1072
            opn = "srlv";
1073
       }
1074
        break;
1075
#ifdef MIPS_HAS_MIPS64
1076
    case OPC_DSLLV:
1077
        gen_op_dsllv();
1078
        opn = "dsllv";
1079
        break;
1080
    case OPC_DSRAV:
1081
        gen_op_dsrav();
1082
        opn = "dsrav";
1083
        break;
1084
    case OPC_DSRLV:
1085
       if ((ctx->opcode >> 6) & 1) {
1086
            gen_op_drotrv();
1087
            opn = "drotrv";
1088
       } else {
1089
            gen_op_dsrlv();
1090
            opn = "dsrlv";
1091
       }
1092
        break;
1093
#endif
1094
    default:
1095
        MIPS_INVAL("arith");
1096
        generate_exception(ctx, EXCP_RI);
1097
        return;
1098
    }
1099
    GEN_STORE_TN_REG(rd, T0);
1100
 print:
1101
    MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1102
}
1103

    
1104
/* Arithmetic on HI/LO registers */
1105
static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1106
{
1107
    const char *opn = "unk";
1108

    
1109
    if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1110
        /* Treat as a NOP */
1111
        MIPS_DEBUG("NOP");
1112
        return;
1113
    }
1114
    switch (opc) {
1115
    case OPC_MFHI:
1116
        gen_op_load_HI();
1117
        GEN_STORE_TN_REG(reg, T0);
1118
        opn = "mfhi";
1119
        break;
1120
    case OPC_MFLO:
1121
        gen_op_load_LO();
1122
        GEN_STORE_TN_REG(reg, T0);
1123
        opn = "mflo";
1124
        break;
1125
    case OPC_MTHI:
1126
        GEN_LOAD_REG_TN(T0, reg);
1127
        gen_op_store_HI();
1128
        opn = "mthi";
1129
        break;
1130
    case OPC_MTLO:
1131
        GEN_LOAD_REG_TN(T0, reg);
1132
        gen_op_store_LO();
1133
        opn = "mtlo";
1134
        break;
1135
    default:
1136
        MIPS_INVAL("HILO");
1137
        generate_exception(ctx, EXCP_RI);
1138
        return;
1139
    }
1140
    MIPS_DEBUG("%s %s", opn, regnames[reg]);
1141
}
1142

    
1143
static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1144
                        int rs, int rt)
1145
{
1146
    const char *opn = "unk";
1147

    
1148
    GEN_LOAD_REG_TN(T0, rs);
1149
    GEN_LOAD_REG_TN(T1, rt);
1150
    switch (opc) {
1151
    case OPC_DIV:
1152
        gen_op_div();
1153
        opn = "div";
1154
        break;
1155
    case OPC_DIVU:
1156
        gen_op_divu();
1157
        opn = "divu";
1158
        break;
1159
    case OPC_MULT:
1160
        gen_op_mult();
1161
        opn = "mult";
1162
        break;
1163
    case OPC_MULTU:
1164
        gen_op_multu();
1165
        opn = "multu";
1166
        break;
1167
#ifdef MIPS_HAS_MIPS64
1168
    case OPC_DDIV:
1169
        gen_op_ddiv();
1170
        opn = "ddiv";
1171
        break;
1172
    case OPC_DDIVU:
1173
        gen_op_ddivu();
1174
        opn = "ddivu";
1175
        break;
1176
    case OPC_DMULT:
1177
        gen_op_dmult();
1178
        opn = "dmult";
1179
        break;
1180
    case OPC_DMULTU:
1181
        gen_op_dmultu();
1182
        opn = "dmultu";
1183
        break;
1184
#endif
1185
    case OPC_MADD:
1186
        gen_op_madd();
1187
        opn = "madd";
1188
        break;
1189
    case OPC_MADDU:
1190
        gen_op_maddu();
1191
        opn = "maddu";
1192
        break;
1193
    case OPC_MSUB:
1194
        gen_op_msub();
1195
        opn = "msub";
1196
        break;
1197
    case OPC_MSUBU:
1198
        gen_op_msubu();
1199
        opn = "msubu";
1200
        break;
1201
    default:
1202
        MIPS_INVAL("mul/div");
1203
        generate_exception(ctx, EXCP_RI);
1204
        return;
1205
    }
1206
    MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
1207
}
1208

    
1209
static void gen_cl (DisasContext *ctx, uint32_t opc,
1210
                    int rd, int rs)
1211
{
1212
    const char *opn = "unk";
1213
    if (rd == 0) {
1214
        /* Treat as a NOP */
1215
        MIPS_DEBUG("NOP");
1216
        return;
1217
    }
1218
    GEN_LOAD_REG_TN(T0, rs);
1219
    switch (opc) {
1220
    case OPC_CLO:
1221
        gen_op_clo();
1222
        opn = "clo";
1223
        break;
1224
    case OPC_CLZ:
1225
        gen_op_clz();
1226
        opn = "clz";
1227
        break;
1228
#ifdef MIPS_HAS_MIPS64
1229
    case OPC_DCLO:
1230
        gen_op_dclo();
1231
        opn = "dclo";
1232
        break;
1233
    case OPC_DCLZ:
1234
        gen_op_dclz();
1235
        opn = "dclz";
1236
        break;
1237
#endif
1238
    default:
1239
        MIPS_INVAL("CLx");
1240
        generate_exception(ctx, EXCP_RI);
1241
        return;
1242
    }
1243
    gen_op_store_T0_gpr(rd);
1244
    MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
1245
}
1246

    
1247
/* Traps */
1248
static void gen_trap (DisasContext *ctx, uint32_t opc,
1249
                      int rs, int rt, int16_t imm)
1250
{
1251
    int cond;
1252

    
1253
    cond = 0;
1254
    /* Load needed operands */
1255
    switch (opc) {
1256
    case OPC_TEQ:
1257
    case OPC_TGE:
1258
    case OPC_TGEU:
1259
    case OPC_TLT:
1260
    case OPC_TLTU:
1261
    case OPC_TNE:
1262
        /* Compare two registers */
1263
        if (rs != rt) {
1264
            GEN_LOAD_REG_TN(T0, rs);
1265
            GEN_LOAD_REG_TN(T1, rt);
1266
            cond = 1;
1267
        }
1268
    case OPC_TEQI:
1269
    case OPC_TGEI:
1270
    case OPC_TGEIU:
1271
    case OPC_TLTI:
1272
    case OPC_TLTIU:
1273
    case OPC_TNEI:
1274
        /* Compare register to immediate */
1275
        if (rs != 0 || imm != 0) {
1276
            GEN_LOAD_REG_TN(T0, rs);
1277
            GEN_LOAD_IMM_TN(T1, (int32_t)imm);
1278
            cond = 1;
1279
        }
1280
        break;
1281
    }
1282
    if (cond == 0) {
1283
        switch (opc) {
1284
        case OPC_TEQ:   /* rs == rs */
1285
        case OPC_TEQI:  /* r0 == 0  */
1286
        case OPC_TGE:   /* rs >= rs */
1287
        case OPC_TGEI:  /* r0 >= 0  */
1288
        case OPC_TGEU:  /* rs >= rs unsigned */
1289
        case OPC_TGEIU: /* r0 >= 0  unsigned */
1290
            /* Always trap */
1291
            gen_op_set_T0(1);
1292
            break;
1293
        case OPC_TLT:   /* rs < rs           */
1294
        case OPC_TLTI:  /* r0 < 0            */
1295
        case OPC_TLTU:  /* rs < rs unsigned  */
1296
        case OPC_TLTIU: /* r0 < 0  unsigned  */
1297
        case OPC_TNE:   /* rs != rs          */
1298
        case OPC_TNEI:  /* r0 != 0           */
1299
            /* Never trap: treat as NOP */
1300
            return;
1301
        default:
1302
            MIPS_INVAL("TRAP");
1303
            generate_exception(ctx, EXCP_RI);
1304
            return;
1305
        }
1306
    } else {
1307
        switch (opc) {
1308
        case OPC_TEQ:
1309
        case OPC_TEQI:
1310
            gen_op_eq();
1311
            break;
1312
        case OPC_TGE:
1313
        case OPC_TGEI:
1314
            gen_op_ge();
1315
            break;
1316
        case OPC_TGEU:
1317
        case OPC_TGEIU:
1318
            gen_op_geu();
1319
            break;
1320
        case OPC_TLT:
1321
        case OPC_TLTI:
1322
            gen_op_lt();
1323
            break;
1324
        case OPC_TLTU:
1325
        case OPC_TLTIU:
1326
            gen_op_ltu();
1327
            break;
1328
        case OPC_TNE:
1329
        case OPC_TNEI:
1330
            gen_op_ne();
1331
            break;
1332
        default:
1333
            MIPS_INVAL("TRAP");
1334
            generate_exception(ctx, EXCP_RI);
1335
            return;
1336
        }
1337
    }
1338
    save_cpu_state(ctx, 1);
1339
    gen_op_trap();
1340
    ctx->bstate = BS_STOP;
1341
}
1342

    
1343
static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
1344
{
1345
    TranslationBlock *tb;
1346
    tb = ctx->tb;
1347
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
1348
        if (n == 0)
1349
            gen_op_goto_tb0(TBPARAM(tb));
1350
        else
1351
            gen_op_goto_tb1(TBPARAM(tb));
1352
        gen_op_save_pc(dest);
1353
        gen_op_set_T0((long)tb + n);
1354
        gen_op_exit_tb();
1355
    } else {
1356
        gen_op_save_pc(dest);
1357
        gen_op_set_T0(0);
1358
        gen_op_exit_tb();
1359
    }
1360
}
1361

    
1362
/* Branches (before delay slot) */
1363
static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
1364
                                int rs, int rt, int32_t offset)
1365
{
1366
    target_ulong btarget;
1367
    int blink, bcond;
1368

    
1369
    btarget = -1;
1370
    blink = 0;
1371
    bcond = 0;
1372
    /* Load needed operands */
1373
    switch (opc) {
1374
    case OPC_BEQ:
1375
    case OPC_BEQL:
1376
    case OPC_BNE:
1377
    case OPC_BNEL:
1378
        /* Compare two registers */
1379
        if (rs != rt) {
1380
            GEN_LOAD_REG_TN(T0, rs);
1381
            GEN_LOAD_REG_TN(T1, rt);
1382
            bcond = 1;
1383
        }
1384
        btarget = ctx->pc + 4 + offset;
1385
        break;
1386
    case OPC_BGEZ:
1387
    case OPC_BGEZAL:
1388
    case OPC_BGEZALL:
1389
    case OPC_BGEZL:
1390
    case OPC_BGTZ:
1391
    case OPC_BGTZL:
1392
    case OPC_BLEZ:
1393
    case OPC_BLEZL:
1394
    case OPC_BLTZ:
1395
    case OPC_BLTZAL:
1396
    case OPC_BLTZALL:
1397
    case OPC_BLTZL:
1398
        /* Compare to zero */
1399
        if (rs != 0) {
1400
            gen_op_load_gpr_T0(rs);
1401
            bcond = 1;
1402
        }
1403
        btarget = ctx->pc + 4 + offset;
1404
        break;
1405
    case OPC_J:
1406
    case OPC_JAL:
1407
        /* Jump to immediate */
1408
        btarget = ((ctx->pc + 4) & 0xF0000000) | offset;
1409
        break;
1410
    case OPC_JR:
1411
    case OPC_JALR:
1412
        /* Jump to register */
1413
        if (offset != 0 && offset != 16) {
1414
            /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
1415
              others are reserved. */
1416
            generate_exception(ctx, EXCP_RI);
1417
            return;
1418
        }
1419
        GEN_LOAD_REG_TN(T2, rs);
1420
        break;
1421
    default:
1422
        MIPS_INVAL("branch/jump");
1423
        generate_exception(ctx, EXCP_RI);
1424
        return;
1425
    }
1426
    if (bcond == 0) {
1427
        /* No condition to be computed */
1428
        switch (opc) {
1429
        case OPC_BEQ:     /* rx == rx        */
1430
        case OPC_BEQL:    /* rx == rx likely */
1431
        case OPC_BGEZ:    /* 0 >= 0          */
1432
        case OPC_BGEZL:   /* 0 >= 0 likely   */
1433
        case OPC_BLEZ:    /* 0 <= 0          */
1434
        case OPC_BLEZL:   /* 0 <= 0 likely   */
1435
            /* Always take */
1436
            ctx->hflags |= MIPS_HFLAG_B;
1437
            MIPS_DEBUG("balways");
1438
            break;
1439
        case OPC_BGEZAL:  /* 0 >= 0          */
1440
        case OPC_BGEZALL: /* 0 >= 0 likely   */
1441
            /* Always take and link */
1442
            blink = 31;
1443
            ctx->hflags |= MIPS_HFLAG_B;
1444
            MIPS_DEBUG("balways and link");
1445
            break;
1446
        case OPC_BNE:     /* rx != rx        */
1447
        case OPC_BGTZ:    /* 0 > 0           */
1448
        case OPC_BLTZ:    /* 0 < 0           */
1449
            /* Treated as NOP */
1450
            MIPS_DEBUG("bnever (NOP)");
1451
            return;
1452
        case OPC_BLTZAL:  /* 0 < 0           */
1453
            gen_op_set_T0(ctx->pc + 8);
1454
            gen_op_store_T0_gpr(31);
1455
            return;
1456
        case OPC_BLTZALL: /* 0 < 0 likely */
1457
            gen_op_set_T0(ctx->pc + 8);
1458
            gen_op_store_T0_gpr(31);
1459
            gen_goto_tb(ctx, 0, ctx->pc + 4);
1460
            return;
1461
        case OPC_BNEL:    /* rx != rx likely */
1462
        case OPC_BGTZL:   /* 0 > 0 likely */
1463
        case OPC_BLTZL:   /* 0 < 0 likely */
1464
            /* Skip the instruction in the delay slot */
1465
            MIPS_DEBUG("bnever and skip");
1466
            gen_goto_tb(ctx, 0, ctx->pc + 4);
1467
            return;
1468
        case OPC_J:
1469
            ctx->hflags |= MIPS_HFLAG_B;
1470
            MIPS_DEBUG("j %08x", btarget);
1471
            break;
1472
        case OPC_JAL:
1473
            blink = 31;
1474
            ctx->hflags |= MIPS_HFLAG_B;
1475
            MIPS_DEBUG("jal %08x", btarget);
1476
            break;
1477
        case OPC_JR:
1478
            ctx->hflags |= MIPS_HFLAG_BR;
1479
            MIPS_DEBUG("jr %s", regnames[rs]);
1480
            break;
1481
        case OPC_JALR:
1482
            blink = rt;
1483
            ctx->hflags |= MIPS_HFLAG_BR;
1484
            MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
1485
            break;
1486
        default:
1487
            MIPS_INVAL("branch/jump");
1488
            generate_exception(ctx, EXCP_RI);
1489
            return;
1490
        }
1491
    } else {
1492
        switch (opc) {
1493
        case OPC_BEQ:
1494
            gen_op_eq();
1495
            MIPS_DEBUG("beq %s, %s, %08x",
1496
                       regnames[rs], regnames[rt], btarget);
1497
            goto not_likely;
1498
        case OPC_BEQL:
1499
            gen_op_eq();
1500
            MIPS_DEBUG("beql %s, %s, %08x",
1501
                       regnames[rs], regnames[rt], btarget);
1502
            goto likely;
1503
        case OPC_BNE:
1504
            gen_op_ne();
1505
            MIPS_DEBUG("bne %s, %s, %08x",
1506
                       regnames[rs], regnames[rt], btarget);
1507
            goto not_likely;
1508
        case OPC_BNEL:
1509
            gen_op_ne();
1510
            MIPS_DEBUG("bnel %s, %s, %08x",
1511
                       regnames[rs], regnames[rt], btarget);
1512
            goto likely;
1513
        case OPC_BGEZ:
1514
            gen_op_gez();
1515
            MIPS_DEBUG("bgez %s, %08x", regnames[rs], btarget);
1516
            goto not_likely;
1517
        case OPC_BGEZL:
1518
            gen_op_gez();
1519
            MIPS_DEBUG("bgezl %s, %08x", regnames[rs], btarget);
1520
            goto likely;
1521
        case OPC_BGEZAL:
1522
            gen_op_gez();
1523
            MIPS_DEBUG("bgezal %s, %08x", regnames[rs], btarget);
1524
            blink = 31;
1525
            goto not_likely;
1526
        case OPC_BGEZALL:
1527
            gen_op_gez();
1528
            blink = 31;
1529
            MIPS_DEBUG("bgezall %s, %08x", regnames[rs], btarget);
1530
            goto likely;
1531
        case OPC_BGTZ:
1532
            gen_op_gtz();
1533
            MIPS_DEBUG("bgtz %s, %08x", regnames[rs], btarget);
1534
            goto not_likely;
1535
        case OPC_BGTZL:
1536
            gen_op_gtz();
1537
            MIPS_DEBUG("bgtzl %s, %08x", regnames[rs], btarget);
1538
            goto likely;
1539
        case OPC_BLEZ:
1540
            gen_op_lez();
1541
            MIPS_DEBUG("blez %s, %08x", regnames[rs], btarget);
1542
            goto not_likely;
1543
        case OPC_BLEZL:
1544
            gen_op_lez();
1545
            MIPS_DEBUG("blezl %s, %08x", regnames[rs], btarget);
1546
            goto likely;
1547
        case OPC_BLTZ:
1548
            gen_op_ltz();
1549
            MIPS_DEBUG("bltz %s, %08x", regnames[rs], btarget);
1550
            goto not_likely;
1551
        case OPC_BLTZL:
1552
            gen_op_ltz();
1553
            MIPS_DEBUG("bltzl %s, %08x", regnames[rs], btarget);
1554
            goto likely;
1555
        case OPC_BLTZAL:
1556
            gen_op_ltz();
1557
            blink = 31;
1558
            MIPS_DEBUG("bltzal %s, %08x", regnames[rs], btarget);
1559
        not_likely:
1560
            ctx->hflags |= MIPS_HFLAG_BC;
1561
            break;
1562
        case OPC_BLTZALL:
1563
            gen_op_ltz();
1564
            blink = 31;
1565
            MIPS_DEBUG("bltzall %s, %08x", regnames[rs], btarget);
1566
        likely:
1567
            ctx->hflags |= MIPS_HFLAG_BL;
1568
            break;
1569
        }
1570
        gen_op_set_bcond();
1571
    }
1572
    MIPS_DEBUG("enter ds: link %d cond %02x target %08x",
1573
               blink, ctx->hflags, btarget);
1574
    ctx->btarget = btarget;
1575
    if (blink > 0) {
1576
        gen_op_set_T0(ctx->pc + 8);
1577
        gen_op_store_T0_gpr(blink);
1578
    }
1579
    return;
1580
}
1581

    
1582
/* special3 bitfield operations */
1583
static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
1584
                       int rs, int lsb, int msb)
1585
{
1586
    GEN_LOAD_REG_TN(T1, rs);
1587
    switch (opc) {
1588
    case OPC_EXT:
1589
        if (lsb + msb > 31)
1590
            goto fail;
1591
        gen_op_ext(lsb, msb + 1);
1592
        break;
1593
    case OPC_DEXTM:
1594
        if (lsb + msb > 63)
1595
            goto fail;
1596
        gen_op_ext(lsb, msb + 1 + 32);
1597
        break;
1598
    case OPC_DEXTU:
1599
        if (lsb + msb > 63)
1600
            goto fail;
1601
        gen_op_ext(lsb + 32, msb + 1);
1602
        break;
1603
    case OPC_DEXT:
1604
        gen_op_ext(lsb, msb + 1);
1605
        break;
1606
    case OPC_INS:
1607
        if (lsb > msb)
1608
            goto fail;
1609
        GEN_LOAD_REG_TN(T2, rt);
1610
        gen_op_ins(lsb, msb - lsb + 1);
1611
        break;
1612
    case OPC_DINSM:
1613
        if (lsb > msb)
1614
            goto fail;
1615
        GEN_LOAD_REG_TN(T2, rt);
1616
        gen_op_ins(lsb, msb - lsb + 1 + 32);
1617
        break;
1618
    case OPC_DINSU:
1619
        if (lsb > msb)
1620
            goto fail;
1621
        GEN_LOAD_REG_TN(T2, rt);
1622
        gen_op_ins(lsb + 32, msb - lsb + 1);
1623
        break;
1624
    case OPC_DINS:
1625
        if (lsb > msb)
1626
            goto fail;
1627
        GEN_LOAD_REG_TN(T2, rt);
1628
        gen_op_ins(lsb, msb - lsb + 1);
1629
        break;
1630
    default:
1631
fail:
1632
        MIPS_INVAL("bitops");
1633
        generate_exception(ctx, EXCP_RI);
1634
        return;
1635
    }
1636
    GEN_STORE_TN_REG(rt, T0);
1637
}
1638

    
1639
/* CP0 (MMU and control) */
1640
static void gen_mfc0 (DisasContext *ctx, int reg, int sel)
1641
{
1642
    const char *rn = "invalid";
1643

    
1644
    switch (reg) {
1645
    case 0:
1646
        switch (sel) {
1647
        case 0:
1648
           gen_op_mfc0_index();
1649
            rn = "Index";
1650
            break;
1651
        case 1:
1652
//         gen_op_mfc0_mvpcontrol(); /* MT ASE */
1653
            rn = "MVPControl";
1654
//         break;
1655
        case 2:
1656
//         gen_op_mfc0_mvpconf0(); /* MT ASE */
1657
            rn = "MVPConf0";
1658
//         break;
1659
        case 3:
1660
//         gen_op_mfc0_mvpconf1(); /* MT ASE */
1661
            rn = "MVPConf1";
1662
//         break;
1663
        default:
1664
            goto die;
1665
        }
1666
        break;
1667
    case 1:
1668
        switch (sel) {
1669
        case 0:
1670
            gen_op_mfc0_random();
1671
            rn = "Random";
1672
           break;
1673
        case 1:
1674
//         gen_op_mfc0_vpecontrol(); /* MT ASE */
1675
            rn = "VPEControl";
1676
//         break;
1677
        case 2:
1678
//         gen_op_mfc0_vpeconf0(); /* MT ASE */
1679
            rn = "VPEConf0";
1680
//         break;
1681
        case 3:
1682
//         gen_op_mfc0_vpeconf1(); /* MT ASE */
1683
            rn = "VPEConf1";
1684
//         break;
1685
        case 4:
1686
//         gen_op_mfc0_YQMask(); /* MT ASE */
1687
            rn = "YQMask";
1688
//         break;
1689
        case 5:
1690
//         gen_op_mfc0_vpeschedule(); /* MT ASE */
1691
            rn = "VPESchedule";
1692
//         break;
1693
        case 6:
1694
//         gen_op_mfc0_vpeschefback(); /* MT ASE */
1695
            rn = "VPEScheFBack";
1696
//         break;
1697
        case 7:
1698
//         gen_op_mfc0_vpeopt(); /* MT ASE */
1699
            rn = "VPEOpt";
1700
//         break;
1701
        default:
1702
            goto die;
1703
        }
1704
        break;
1705
    case 2:
1706
        switch (sel) {
1707
        case 0:
1708
           gen_op_mfc0_entrylo0();
1709
           rn = "EntryLo0";
1710
           break;
1711
        case 1:
1712
//         gen_op_mfc0_tcstatus(); /* MT ASE */
1713
           rn = "TCStatus";
1714
//         break;
1715
        case 2:
1716
//         gen_op_mfc0_tcbind(); /* MT ASE */
1717
           rn = "TCBind";
1718
//         break;
1719
        case 3:
1720
//         gen_op_mfc0_tcrestart(); /* MT ASE */
1721
           rn = "TCRestart";
1722
//         break;
1723
        case 4:
1724
//         gen_op_mfc0_tchalt(); /* MT ASE */
1725
           rn = "TCHalt";
1726
//         break;
1727
        case 5:
1728
//         gen_op_mfc0_tccontext(); /* MT ASE */
1729
           rn = "TCContext";
1730
//         break;
1731
        case 6:
1732
//         gen_op_mfc0_tcschedule(); /* MT ASE */
1733
           rn = "TCSchedule";
1734
//         break;
1735
        case 7:
1736
//         gen_op_mfc0_tcschefback(); /* MT ASE */
1737
           rn = "TCScheFBack";
1738
//         break;
1739
        default:
1740
            goto die;
1741
        }
1742
        break;
1743
    case 3:
1744
        switch (sel) {
1745
        case 0:
1746
           gen_op_mfc0_entrylo1();
1747
           rn = "EntryLo1";
1748
           break;
1749
        default:
1750
            goto die;
1751
       }
1752
        break;
1753
    case 4:
1754
        switch (sel) {
1755
        case 0:
1756
           gen_op_mfc0_context();
1757
           rn = "Context";
1758
           break;
1759
        case 1:
1760
//         gen_op_mfc0_contextconfig(); /* SmartMIPS ASE */
1761
           rn = "ContextConfig";
1762
//         break;
1763
        default:
1764
            goto die;
1765
       }
1766
        break;
1767
    case 5:
1768
        switch (sel) {
1769
        case 0:
1770
           gen_op_mfc0_pagemask();
1771
           rn = "PageMask";
1772
           break;
1773
        case 1:
1774
           gen_op_mfc0_pagegrain();
1775
           rn = "PageGrain";
1776
           break;
1777
        default:
1778
            goto die;
1779
       }
1780
        break;
1781
    case 6:
1782
        switch (sel) {
1783
        case 0:
1784
           gen_op_mfc0_wired();
1785
           rn = "Wired";
1786
           break;
1787
        case 1:
1788
//         gen_op_mfc0_srsconf0(); /* shadow registers */
1789
           rn = "SRSConf0";
1790
//         break;
1791
        case 2:
1792
//         gen_op_mfc0_srsconf1(); /* shadow registers */
1793
           rn = "SRSConf1";
1794
//         break;
1795
        case 3:
1796
//         gen_op_mfc0_srsconf2(); /* shadow registers */
1797
           rn = "SRSConf2";
1798
//         break;
1799
        case 4:
1800
//         gen_op_mfc0_srsconf3(); /* shadow registers */
1801
           rn = "SRSConf3";
1802
//         break;
1803
        case 5:
1804
//         gen_op_mfc0_srsconf4(); /* shadow registers */
1805
           rn = "SRSConf4";
1806
//         break;
1807
        default:
1808
            goto die;
1809
       }
1810
        break;
1811
    case 7:
1812
        switch (sel) {
1813
        case 0:
1814
           gen_op_mfc0_hwrena();
1815
           rn = "HWREna";
1816
           break;
1817
        default:
1818
            goto die;
1819
       }
1820
        break;
1821
    case 8:
1822
        switch (sel) {
1823
        case 0:
1824
           gen_op_mfc0_badvaddr();
1825
           rn = "BadVaddr";
1826
           break;
1827
        default:
1828
            goto die;
1829
       }
1830
        break;
1831
    case 9:
1832
        switch (sel) {
1833
        case 0:
1834
           gen_op_mfc0_count();
1835
           rn = "Count";
1836
           break;
1837
       /* 6,7 are implementation dependent */
1838
        default:
1839
            goto die;
1840
       }
1841
        break;
1842
    case 10:
1843
        switch (sel) {
1844
        case 0:
1845
           gen_op_mfc0_entryhi();
1846
           rn = "EntryHi";
1847
           break;
1848
        default:
1849
            goto die;
1850
       }
1851
        break;
1852
    case 11:
1853
        switch (sel) {
1854
        case 0:
1855
           gen_op_mfc0_compare();
1856
           rn = "Compare";
1857
           break;
1858
       /* 6,7 are implementation dependent */
1859
        default:
1860
            goto die;
1861
       }
1862
        break;
1863
    case 12:
1864
        switch (sel) {
1865
        case 0:
1866
           gen_op_mfc0_status();
1867
           rn = "Status";
1868
           break;
1869
        case 1:
1870
           gen_op_mfc0_intctl();
1871
           rn = "IntCtl";
1872
           break;
1873
        case 2:
1874
           gen_op_mfc0_srsctl();
1875
           rn = "SRSCtl";
1876
           break;
1877
        case 3:
1878
//         gen_op_mfc0_srsmap(); /* shadow registers */
1879
           rn = "SRSMap";
1880
//         break;
1881
        default:
1882
            goto die;
1883
       }
1884
        break;
1885
    case 13:
1886
        switch (sel) {
1887
        case 0:
1888
           gen_op_mfc0_cause();
1889
           rn = "Cause";
1890
           break;
1891
        default:
1892
            goto die;
1893
       }
1894
        break;
1895
    case 14:
1896
        switch (sel) {
1897
        case 0:
1898
           gen_op_mfc0_epc();
1899
           rn = "EPC";
1900
           break;
1901
        default:
1902
            goto die;
1903
       }
1904
        break;
1905
    case 15:
1906
        switch (sel) {
1907
        case 0:
1908
           gen_op_mfc0_prid();
1909
           rn = "PRid";
1910
           break;
1911
        case 1:
1912
           gen_op_mfc0_ebase();
1913
           rn = "EBase";
1914
           break;
1915
        default:
1916
            goto die;
1917
       }
1918
        break;
1919
    case 16:
1920
        switch (sel) {
1921
        case 0:
1922
           gen_op_mfc0_config0();
1923
            rn = "Config";
1924
            break;
1925
        case 1:
1926
           gen_op_mfc0_config1();
1927
            rn = "Config1";
1928
            break;
1929
        case 2:
1930
           gen_op_mfc0_config2();
1931
            rn = "Config2";
1932
            break;
1933
        case 3:
1934
           gen_op_mfc0_config3();
1935
            rn = "Config3";
1936
            break;
1937
       /* 6,7 are implementation dependent */
1938
        default:
1939
            goto die;
1940
        }
1941
        break;
1942
    case 17:
1943
        switch (sel) {
1944
        case 0:
1945
           gen_op_mfc0_lladdr();
1946
           rn = "LLAddr";
1947
           break;
1948
        default:
1949
            goto die;
1950
        }
1951
        break;
1952
    case 18:
1953
        switch (sel) {
1954
        case 0:
1955
           gen_op_mfc0_watchlo0();
1956
           rn = "WatchLo";
1957
           break;
1958
        case 1:
1959
//         gen_op_mfc0_watchlo1();
1960
           rn = "WatchLo1";
1961
//         break;
1962
        case 2:
1963
//         gen_op_mfc0_watchlo2();
1964
           rn = "WatchLo2";
1965
//         break;
1966
        case 3:
1967
//         gen_op_mfc0_watchlo3();
1968
           rn = "WatchLo3";
1969
//         break;
1970
        case 4:
1971
//         gen_op_mfc0_watchlo4();
1972
           rn = "WatchLo4";
1973
//         break;
1974
        case 5:
1975
//         gen_op_mfc0_watchlo5();
1976
           rn = "WatchLo5";
1977
//         break;
1978
        case 6:
1979
//         gen_op_mfc0_watchlo6();
1980
           rn = "WatchLo6";
1981
//         break;
1982
        case 7:
1983
//         gen_op_mfc0_watchlo7();
1984
           rn = "WatchLo7";
1985
//         break;
1986
        default:
1987
            goto die;
1988
        }
1989
        break;
1990
    case 19:
1991
        switch (sel) {
1992
        case 0:
1993
           gen_op_mfc0_watchhi0();
1994
           rn = "WatchHi";
1995
           break;
1996
        case 1:
1997
//         gen_op_mfc0_watchhi1();
1998
           rn = "WatchHi1";
1999
//         break;
2000
        case 2:
2001
//         gen_op_mfc0_watchhi2();
2002
           rn = "WatchHi2";
2003
//         break;
2004
        case 3:
2005
//         gen_op_mfc0_watchhi3();
2006
           rn = "WatchHi3";
2007
//         break;
2008
        case 4:
2009
//         gen_op_mfc0_watchhi4();
2010
           rn = "WatchHi4";
2011
//         break;
2012
        case 5:
2013
//         gen_op_mfc0_watchhi5();
2014
           rn = "WatchHi5";
2015
//         break;
2016
        case 6:
2017
//         gen_op_mfc0_watchhi6();
2018
           rn = "WatchHi6";
2019
//         break;
2020
        case 7:
2021
//         gen_op_mfc0_watchhi7();
2022
           rn = "WatchHi7";
2023
//         break;
2024
        default:
2025
            goto die;
2026
        }
2027
        break;
2028
    case 20:
2029
        switch (sel) {
2030
        case 0:
2031
           /* 64 bit MMU only */
2032
           gen_op_mfc0_xcontext();
2033
           rn = "XContext";
2034
           break;
2035
        default:
2036
            goto die;
2037
        }
2038
        break;
2039
    case 21:
2040
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
2041
        switch (sel) {
2042
        case 0:
2043
           gen_op_mfc0_framemask();
2044
           rn = "Framemask";
2045
           break;
2046
        default:
2047
            goto die;
2048
        }
2049
        break;
2050
    case 22:
2051
       /* ignored */
2052
       rn = "'Diagnostic"; /* implementation dependent */
2053
       break;
2054
    case 23:
2055
        switch (sel) {
2056
        case 0:
2057
           gen_op_mfc0_debug(); /* EJTAG support */
2058
           rn = "Debug";
2059
           break;
2060
        case 1:
2061
//         gen_op_mfc0_tracecontrol(); /* PDtrace support */
2062
           rn = "TraceControl";
2063
//         break;
2064
        case 2:
2065
//         gen_op_mfc0_tracecontrol2(); /* PDtrace support */
2066
           rn = "TraceControl2";
2067
//         break;
2068
        case 3:
2069
//         gen_op_mfc0_usertracedata(); /* PDtrace support */
2070
           rn = "UserTraceData";
2071
//         break;
2072
        case 4:
2073
//         gen_op_mfc0_debug(); /* PDtrace support */
2074
           rn = "TraceBPC";
2075
//         break;
2076
        default:
2077
            goto die;
2078
        }
2079
        break;
2080
    case 24:
2081
        switch (sel) {
2082
        case 0:
2083
           gen_op_mfc0_depc(); /* EJTAG support */
2084
           rn = "DEPC";
2085
           break;
2086
        default:
2087
            goto die;
2088
        }
2089
        break;
2090
    case 25:
2091
        switch (sel) {
2092
        case 0:
2093
           gen_op_mfc0_performance0();
2094
           rn = "Performance0";
2095
            break;
2096
        case 1:
2097
//         gen_op_mfc0_performance1();
2098
           rn = "Performance1";
2099
//         break;
2100
        case 2:
2101
//         gen_op_mfc0_performance2();
2102
           rn = "Performance2";
2103
//         break;
2104
        case 3:
2105
//         gen_op_mfc0_performance3();
2106
           rn = "Performance3";
2107
//         break;
2108
        case 4:
2109
//         gen_op_mfc0_performance4();
2110
           rn = "Performance4";
2111
//         break;
2112
        case 5:
2113
//         gen_op_mfc0_performance5();
2114
           rn = "Performance5";
2115
//         break;
2116
        case 6:
2117
//         gen_op_mfc0_performance6();
2118
           rn = "Performance6";
2119
//         break;
2120
        case 7:
2121
//         gen_op_mfc0_performance7();
2122
           rn = "Performance7";
2123
//         break;
2124
        default:
2125
            goto die;
2126
        }
2127
        break;
2128
    case 26:
2129
       rn = "ECC";
2130
       break;
2131
    case 27:
2132
        switch (sel) {
2133
        /* ignored */
2134
        case 0 ... 3:
2135
           rn = "CacheErr";
2136
           break;
2137
        default:
2138
            goto die;
2139
        }
2140
        break;
2141
    case 28:
2142
        switch (sel) {
2143
        case 0:
2144
        case 2:
2145
        case 4:
2146
        case 6:
2147
            gen_op_mfc0_taglo();
2148
            rn = "TagLo";
2149
            break;
2150
        case 1:
2151
        case 3:
2152
        case 5:
2153
        case 7:
2154
            gen_op_mfc0_datalo();
2155
            rn = "DataLo";
2156
            break;
2157
        default:
2158
            goto die;
2159
        }
2160
        break;
2161
    case 29:
2162
        switch (sel) {
2163
        case 0:
2164
        case 2:
2165
        case 4:
2166
        case 6:
2167
            gen_op_mfc0_taghi();
2168
            rn = "TagHi";
2169
            break;
2170
        case 1:
2171
        case 3:
2172
        case 5:
2173
        case 7:
2174
            gen_op_mfc0_datahi();
2175
            rn = "DataHi";
2176
            break;
2177
        default:
2178
            goto die;
2179
        }
2180
        break;
2181
    case 30:
2182
        switch (sel) {
2183
        case 0:
2184
           gen_op_mfc0_errorepc();
2185
           rn = "ErrorEPC";
2186
           break;
2187
        default:
2188
            goto die;
2189
        }
2190
        break;
2191
    case 31:
2192
        switch (sel) {
2193
        case 0:
2194
           gen_op_mfc0_desave(); /* EJTAG support */
2195
           rn = "DESAVE";
2196
           break;
2197
        default:
2198
            goto die;
2199
        }
2200
        break;
2201
    default:
2202
       goto die;
2203
    }
2204
#if defined MIPS_DEBUG_DISAS
2205
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2206
        fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
2207
                rn, reg, sel);
2208
    }
2209
#endif
2210
    return;
2211

    
2212
die:
2213
#if defined MIPS_DEBUG_DISAS
2214
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2215
        fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
2216
                rn, reg, sel);
2217
    }
2218
#endif
2219
    generate_exception(ctx, EXCP_RI);
2220
}
2221

    
2222
static void gen_mtc0 (DisasContext *ctx, int reg, int sel)
2223
{
2224
    const char *rn = "invalid";
2225

    
2226
    switch (reg) {
2227
    case 0:
2228
        switch (sel) {
2229
        case 0:
2230
           gen_op_mtc0_index();
2231
            rn = "Index";
2232
            break;
2233
        case 1:
2234
//         gen_op_mtc0_mvpcontrol(); /* MT ASE */
2235
            rn = "MVPControl";
2236
//         break;
2237
        case 2:
2238
//         gen_op_mtc0_mvpconf0(); /* MT ASE */
2239
            rn = "MVPConf0";
2240
//         break;
2241
        case 3:
2242
//         gen_op_mtc0_mvpconf1(); /* MT ASE */
2243
            rn = "MVPConf1";
2244
//         break;
2245
        default:
2246
            goto die;
2247
        }
2248
        break;
2249
    case 1:
2250
        switch (sel) {
2251
        case 0:
2252
           /* ignored */
2253
            rn = "Random";
2254
           break;
2255
        case 1:
2256
//         gen_op_mtc0_vpecontrol(); /* MT ASE */
2257
            rn = "VPEControl";
2258
//         break;
2259
        case 2:
2260
//         gen_op_mtc0_vpeconf0(); /* MT ASE */
2261
            rn = "VPEConf0";
2262
//         break;
2263
        case 3:
2264
//         gen_op_mtc0_vpeconf1(); /* MT ASE */
2265
            rn = "VPEConf1";
2266
//         break;
2267
        case 4:
2268
//         gen_op_mtc0_YQMask(); /* MT ASE */
2269
            rn = "YQMask";
2270
//         break;
2271
        case 5:
2272
//         gen_op_mtc0_vpeschedule(); /* MT ASE */
2273
            rn = "VPESchedule";
2274
//         break;
2275
        case 6:
2276
//         gen_op_mtc0_vpeschefback(); /* MT ASE */
2277
            rn = "VPEScheFBack";
2278
//         break;
2279
        case 7:
2280
//         gen_op_mtc0_vpeopt(); /* MT ASE */
2281
            rn = "VPEOpt";
2282
//         break;
2283
        default:
2284
            goto die;
2285
        }
2286
        break;
2287
    case 2:
2288
        switch (sel) {
2289
        case 0:
2290
           gen_op_mtc0_entrylo0();
2291
           rn = "EntryLo0";
2292
           break;
2293
        case 1:
2294
//         gen_op_mtc0_tcstatus(); /* MT ASE */
2295
           rn = "TCStatus";
2296
//         break;
2297
        case 2:
2298
//         gen_op_mtc0_tcbind(); /* MT ASE */
2299
           rn = "TCBind";
2300
//         break;
2301
        case 3:
2302
//         gen_op_mtc0_tcrestart(); /* MT ASE */
2303
           rn = "TCRestart";
2304
//         break;
2305
        case 4:
2306
//         gen_op_mtc0_tchalt(); /* MT ASE */
2307
           rn = "TCHalt";
2308
//         break;
2309
        case 5:
2310
//         gen_op_mtc0_tccontext(); /* MT ASE */
2311
           rn = "TCContext";
2312
//         break;
2313
        case 6:
2314
//         gen_op_mtc0_tcschedule(); /* MT ASE */
2315
           rn = "TCSchedule";
2316
//         break;
2317
        case 7:
2318
//         gen_op_mtc0_tcschefback(); /* MT ASE */
2319
           rn = "TCScheFBack";
2320
//         break;
2321
        default:
2322
            goto die;
2323
        }
2324
        break;
2325
    case 3:
2326
        switch (sel) {
2327
        case 0:
2328
           gen_op_mtc0_entrylo1();
2329
           rn = "EntryLo1";
2330
           break;
2331
        default:
2332
            goto die;
2333
       }
2334
        break;
2335
    case 4:
2336
        switch (sel) {
2337
        case 0:
2338
           gen_op_mtc0_context();
2339
           rn = "Context";
2340
           break;
2341
        case 1:
2342
//         gen_op_mtc0_contextconfig(); /* SmartMIPS ASE */
2343
           rn = "ContextConfig";
2344
//         break;
2345
        default:
2346
            goto die;
2347
       }
2348
        break;
2349
    case 5:
2350
        switch (sel) {
2351
        case 0:
2352
           gen_op_mtc0_pagemask();
2353
           rn = "PageMask";
2354
           break;
2355
        case 1:
2356
           gen_op_mtc0_pagegrain();
2357
           rn = "PageGrain";
2358
           break;
2359
        default:
2360
            goto die;
2361
       }
2362
        break;
2363
    case 6:
2364
        switch (sel) {
2365
        case 0:
2366
           gen_op_mtc0_wired();
2367
           rn = "Wired";
2368
           break;
2369
        case 1:
2370
//         gen_op_mtc0_srsconf0(); /* shadow registers */
2371
           rn = "SRSConf0";
2372
//         break;
2373
        case 2:
2374
//         gen_op_mtc0_srsconf1(); /* shadow registers */
2375
           rn = "SRSConf1";
2376
//         break;
2377
        case 3:
2378
//         gen_op_mtc0_srsconf2(); /* shadow registers */
2379
           rn = "SRSConf2";
2380
//         break;
2381
        case 4:
2382
//         gen_op_mtc0_srsconf3(); /* shadow registers */
2383
           rn = "SRSConf3";
2384
//         break;
2385
        case 5:
2386
//         gen_op_mtc0_srsconf4(); /* shadow registers */
2387
           rn = "SRSConf4";
2388
//         break;
2389
        default:
2390
            goto die;
2391
       }
2392
        break;
2393
    case 7:
2394
        switch (sel) {
2395
        case 0:
2396
           gen_op_mtc0_hwrena();
2397
           rn = "HWREna";
2398
           break;
2399
        default:
2400
            goto die;
2401
       }
2402
        break;
2403
    case 8:
2404
        /* ignored */
2405
        rn = "BadVaddr";
2406
        break;
2407
    case 9:
2408
        switch (sel) {
2409
        case 0:
2410
           gen_op_mtc0_count();
2411
           rn = "Count";
2412
           break;
2413
       /* 6,7 are implementation dependent */
2414
        default:
2415
            goto die;
2416
       }
2417
       /* Stop translation as we may have switched the execution mode */
2418
       ctx->bstate = BS_STOP;
2419
        break;
2420
    case 10:
2421
        switch (sel) {
2422
        case 0:
2423
           gen_op_mtc0_entryhi();
2424
           rn = "EntryHi";
2425
           break;
2426
        default:
2427
            goto die;
2428
       }
2429
        break;
2430
    case 11:
2431
        switch (sel) {
2432
        case 0:
2433
           gen_op_mtc0_compare();
2434
           rn = "Compare";
2435
           break;
2436
       /* 6,7 are implementation dependent */
2437
        default:
2438
            goto die;
2439
       }
2440
       /* Stop translation as we may have switched the execution mode */
2441
       ctx->bstate = BS_STOP;
2442
        break;
2443
    case 12:
2444
        switch (sel) {
2445
        case 0:
2446
           gen_op_mtc0_status();
2447
           rn = "Status";
2448
           break;
2449
        case 1:
2450
           gen_op_mtc0_intctl();
2451
           rn = "IntCtl";
2452
           break;
2453
        case 2:
2454
           gen_op_mtc0_srsctl();
2455
           rn = "SRSCtl";
2456
           break;
2457
        case 3:
2458
//         gen_op_mtc0_srsmap(); /* shadow registers */
2459
           rn = "SRSMap";
2460
//         break;
2461
        default:
2462
            goto die;
2463
       }
2464
       /* Stop translation as we may have switched the execution mode */
2465
       ctx->bstate = BS_STOP;
2466
        break;
2467
    case 13:
2468
        switch (sel) {
2469
        case 0:
2470
           gen_op_mtc0_cause();
2471
           rn = "Cause";
2472
           break;
2473
        default:
2474
            goto die;
2475
       }
2476
       /* Stop translation as we may have switched the execution mode */
2477
       ctx->bstate = BS_STOP;
2478
        break;
2479
    case 14:
2480
        switch (sel) {
2481
        case 0:
2482
           gen_op_mtc0_epc();
2483
           rn = "EPC";
2484
           break;
2485
        default:
2486
            goto die;
2487
       }
2488
        break;
2489
    case 15:
2490
        switch (sel) {
2491
        case 0:
2492
           /* ignored */
2493
           rn = "PRid";
2494
           break;
2495
        case 1:
2496
           gen_op_mtc0_ebase();
2497
           rn = "EBase";
2498
           break;
2499
        default:
2500
            goto die;
2501
       }
2502
        break;
2503
    case 16:
2504
        switch (sel) {
2505
        case 0:
2506
           gen_op_mtc0_config0();
2507
            rn = "Config";
2508
            break;
2509
        case 1:
2510
           /* ignored */
2511
            rn = "Config1";
2512
            break;
2513
        case 2:
2514
           gen_op_mtc0_config2();
2515
            rn = "Config2";
2516
            break;
2517
        case 3:
2518
           /* ignored */
2519
            rn = "Config3";
2520
            break;
2521
       /* 6,7 are implementation dependent */
2522
        default:
2523
            rn = "Invalid config selector";
2524
            goto die;
2525
        }
2526
       /* Stop translation as we may have switched the execution mode */
2527
       ctx->bstate = BS_STOP;
2528
        break;
2529
    case 17:
2530
        switch (sel) {
2531
        case 0:
2532
           /* ignored */
2533
           rn = "LLAddr";
2534
           break;
2535
        default:
2536
            goto die;
2537
        }
2538
        break;
2539
    case 18:
2540
        switch (sel) {
2541
        case 0:
2542
           gen_op_mtc0_watchlo0();
2543
           rn = "WatchLo";
2544
           break;
2545
        case 1:
2546
//         gen_op_mtc0_watchlo1();
2547
           rn = "WatchLo1";
2548
//         break;
2549
        case 2:
2550
//         gen_op_mtc0_watchlo2();
2551
           rn = "WatchLo2";
2552
//         break;
2553
        case 3:
2554
//         gen_op_mtc0_watchlo3();
2555
           rn = "WatchLo3";
2556
//         break;
2557
        case 4:
2558
//         gen_op_mtc0_watchlo4();
2559
           rn = "WatchLo4";
2560
//         break;
2561
        case 5:
2562
//         gen_op_mtc0_watchlo5();
2563
           rn = "WatchLo5";
2564
//         break;
2565
        case 6:
2566
//         gen_op_mtc0_watchlo6();
2567
           rn = "WatchLo6";
2568
//         break;
2569
        case 7:
2570
//         gen_op_mtc0_watchlo7();
2571
           rn = "WatchLo7";
2572
//         break;
2573
        default:
2574
            goto die;
2575
        }
2576
        break;
2577
    case 19:
2578
        switch (sel) {
2579
        case 0:
2580
           gen_op_mtc0_watchhi0();
2581
           rn = "WatchHi";
2582
           break;
2583
        case 1:
2584
//         gen_op_mtc0_watchhi1();
2585
           rn = "WatchHi1";
2586
//         break;
2587
        case 2:
2588
//         gen_op_mtc0_watchhi2();
2589
           rn = "WatchHi2";
2590
//         break;
2591
        case 3:
2592
//         gen_op_mtc0_watchhi3();
2593
           rn = "WatchHi3";
2594
//         break;
2595
        case 4:
2596
//         gen_op_mtc0_watchhi4();
2597
           rn = "WatchHi4";
2598
//         break;
2599
        case 5:
2600
//         gen_op_mtc0_watchhi5();
2601
           rn = "WatchHi5";
2602
//         break;
2603
        case 6:
2604
//         gen_op_mtc0_watchhi6();
2605
           rn = "WatchHi6";
2606
//         break;
2607
        case 7:
2608
//         gen_op_mtc0_watchhi7();
2609
           rn = "WatchHi7";
2610
//         break;
2611
        default:
2612
            goto die;
2613
        }
2614
        break;
2615
    case 20:
2616
        switch (sel) {
2617
        case 0:
2618
           /* 64 bit MMU only */
2619
           gen_op_mtc0_xcontext();
2620
           rn = "XContext";
2621
           break;
2622
        default:
2623
            goto die;
2624
        }
2625
        break;
2626
    case 21:
2627
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
2628
        switch (sel) {
2629
        case 0:
2630
           gen_op_mtc0_framemask();
2631
           rn = "Framemask";
2632
           break;
2633
        default:
2634
            goto die;
2635
        }
2636
        break;
2637
    case 22:
2638
        /* ignored */
2639
        rn = "Diagnostic"; /* implementation dependent */
2640
       break;
2641
    case 23:
2642
        switch (sel) {
2643
        case 0:
2644
           gen_op_mtc0_debug(); /* EJTAG support */
2645
           rn = "Debug";
2646
           break;
2647
        case 1:
2648
//         gen_op_mtc0_tracecontrol(); /* PDtrace support */
2649
           rn = "TraceControl";
2650
//         break;
2651
        case 2:
2652
//         gen_op_mtc0_tracecontrol2(); /* PDtrace support */
2653
           rn = "TraceControl2";
2654
//         break;
2655
        case 3:
2656
//         gen_op_mtc0_usertracedata(); /* PDtrace support */
2657
           rn = "UserTraceData";
2658
//         break;
2659
        case 4:
2660
//         gen_op_mtc0_debug(); /* PDtrace support */
2661
           rn = "TraceBPC";
2662
//         break;
2663
        default:
2664
            goto die;
2665
        }
2666
       /* Stop translation as we may have switched the execution mode */
2667
       ctx->bstate = BS_STOP;
2668
        break;
2669
    case 24:
2670
        switch (sel) {
2671
        case 0:
2672
           gen_op_mtc0_depc(); /* EJTAG support */
2673
           rn = "DEPC";
2674
           break;
2675
        default:
2676
            goto die;
2677
        }
2678
        break;
2679
    case 25:
2680
        switch (sel) {
2681
        case 0:
2682
           gen_op_mtc0_performance0();
2683
           rn = "Performance0";
2684
           break;
2685
        case 1:
2686
//         gen_op_mtc0_performance1();
2687
           rn = "Performance1";
2688
//         break;
2689
        case 2:
2690
//         gen_op_mtc0_performance2();
2691
           rn = "Performance2";
2692
//         break;
2693
        case 3:
2694
//         gen_op_mtc0_performance3();
2695
           rn = "Performance3";
2696
//         break;
2697
        case 4:
2698
//         gen_op_mtc0_performance4();
2699
           rn = "Performance4";
2700
//         break;
2701
        case 5:
2702
//         gen_op_mtc0_performance5();
2703
           rn = "Performance5";
2704
//         break;
2705
        case 6:
2706
//         gen_op_mtc0_performance6();
2707
           rn = "Performance6";
2708
//         break;
2709
        case 7:
2710
//         gen_op_mtc0_performance7();
2711
           rn = "Performance7";
2712
//         break;
2713
        default:
2714
            goto die;
2715
        }
2716
       break;
2717
    case 26:
2718
       /* ignored */
2719
        rn = "ECC";
2720
       break;
2721
    case 27:
2722
        switch (sel) {
2723
        case 0 ... 3:
2724
           /* ignored */
2725
           rn = "CacheErr";
2726
           break;
2727
        default:
2728
            goto die;
2729
        }
2730
       break;
2731
    case 28:
2732
        switch (sel) {
2733
        case 0:
2734
        case 2:
2735
        case 4:
2736
        case 6:
2737
            gen_op_mtc0_taglo();
2738
            rn = "TagLo";
2739
            break;
2740
        case 1:
2741
        case 3:
2742
        case 5:
2743
        case 7:
2744
           gen_op_mtc0_datalo();
2745
            rn = "DataLo";
2746
            break;
2747
        default:
2748
            goto die;
2749
        }
2750
        break;
2751
    case 29:
2752
        switch (sel) {
2753
        case 0:
2754
        case 2:
2755
        case 4:
2756
        case 6:
2757
            gen_op_mtc0_taghi();
2758
            rn = "TagHi";
2759
            break;
2760
        case 1:
2761
        case 3:
2762
        case 5:
2763
        case 7:
2764
           gen_op_mtc0_datahi();
2765
            rn = "DataHi";
2766
            break;
2767
        default:
2768
            rn = "invalid sel";
2769
            goto die;
2770
        }
2771
       break;
2772
    case 30:
2773
        switch (sel) {
2774
        case 0:
2775
           gen_op_mtc0_errorepc();
2776
           rn = "ErrorEPC";
2777
           break;
2778
        default:
2779
            goto die;
2780
        }
2781
        break;
2782
    case 31:
2783
        switch (sel) {
2784
        case 0:
2785
           gen_op_mtc0_desave(); /* EJTAG support */
2786
           rn = "DESAVE";
2787
           break;
2788
        default:
2789
            goto die;
2790
        }
2791
       /* Stop translation as we may have switched the execution mode */
2792
       ctx->bstate = BS_STOP;
2793
        break;
2794
    default:
2795
       goto die;
2796
    }
2797
#if defined MIPS_DEBUG_DISAS
2798
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2799
        fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
2800
                rn, reg, sel);
2801
    }
2802
#endif
2803
    return;
2804

    
2805
die:
2806
#if defined MIPS_DEBUG_DISAS
2807
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2808
        fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
2809
                rn, reg, sel);
2810
    }
2811
#endif
2812
    generate_exception(ctx, EXCP_RI);
2813
}
2814

    
2815
static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd)
2816
{
2817
    const char *opn = "unk";
2818

    
2819
    if (!(ctx->CP0_Status & (1 << CP0St_CU0)) &&
2820
        (ctx->hflags & MIPS_HFLAG_UM) &&
2821
        !(ctx->hflags & MIPS_HFLAG_ERL) &&
2822
        !(ctx->hflags & MIPS_HFLAG_EXL)) {
2823
        if (loglevel & CPU_LOG_TB_IN_ASM) {
2824
            fprintf(logfile, "CP0 is not usable\n");
2825
        }
2826
        generate_exception (ctx, EXCP_CpU);
2827
        return;
2828
    }
2829

    
2830
    switch (opc) {
2831
    case OPC_MFC0:
2832
        if (rt == 0) {
2833
            /* Treat as NOP */
2834
            return;
2835
        }
2836
        gen_mfc0(ctx, rd, ctx->opcode & 0x7);
2837
        gen_op_store_T0_gpr(rt);
2838
        opn = "mfc0";
2839
        break;
2840
    case OPC_MTC0:
2841
        /* If we get an exception, we want to restart at next instruction */
2842
       /* XXX: breaks for mtc in delay slot */
2843
        ctx->pc += 4;
2844
        save_cpu_state(ctx, 1);
2845
        ctx->pc -= 4;
2846
        GEN_LOAD_REG_TN(T0, rt);
2847
        gen_mtc0(ctx, rd, ctx->opcode & 0x7);
2848
        opn = "mtc0";
2849
        break;
2850
#if defined(MIPS_USES_R4K_TLB)
2851
    case OPC_TLBWI:
2852
        gen_op_tlbwi();
2853
        opn = "tlbwi";
2854
        break;
2855
    case OPC_TLBWR:
2856
        gen_op_tlbwr();
2857
        opn = "tlbwr";
2858
        break;
2859
    case OPC_TLBP:
2860
        gen_op_tlbp();
2861
        opn = "tlbp";
2862
        break;
2863
    case OPC_TLBR:
2864
        gen_op_tlbr();
2865
        opn = "tlbr";
2866
        break;
2867
#endif
2868
    case OPC_ERET:
2869
        opn = "eret";
2870
        save_cpu_state(ctx, 0);
2871
        gen_op_eret();
2872
        ctx->bstate = BS_EXCP;
2873
        break;
2874
    case OPC_DERET:
2875
        opn = "deret";
2876
        if (!(ctx->hflags & MIPS_HFLAG_DM)) {
2877
            generate_exception(ctx, EXCP_RI);
2878
        } else {
2879
            save_cpu_state(ctx, 0);
2880
            gen_op_deret();
2881
            ctx->bstate = BS_EXCP;
2882
        }
2883
        break;
2884
    case OPC_WAIT:
2885
        opn = "wait";
2886
        /* If we get an exception, we want to restart at next instruction */
2887
        ctx->pc += 4;
2888
        save_cpu_state(ctx, 1);
2889
        ctx->pc -= 4;
2890
        gen_op_wait();
2891
        ctx->bstate = BS_EXCP;
2892
        break;
2893
    default:
2894
        if (loglevel & CPU_LOG_TB_IN_ASM) {
2895
            fprintf(logfile, "Invalid CP0 opcode: %08x %03x %03x %03x\n",
2896
                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
2897
                    ((ctx->opcode >> 16) & 0x1F));
2898
        }
2899
        generate_exception(ctx, EXCP_RI);
2900
        return;
2901
    }
2902
    MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
2903
}
2904

    
2905
/* CP1 Branches (before delay slot) */
2906
static void gen_compute_branch1 (DisasContext *ctx, uint32_t op,
2907
                                 int32_t offset)
2908
{
2909
    target_ulong btarget;
2910

    
2911
    btarget = ctx->pc + 4 + offset;
2912

    
2913
    switch (op) {
2914
    case OPC_BC1F:
2915
        gen_op_bc1f();
2916
        MIPS_DEBUG("bc1f %08x", btarget);
2917
        goto not_likely;
2918
    case OPC_BC1FL:
2919
        gen_op_bc1f();
2920
        MIPS_DEBUG("bc1fl %08x", btarget);
2921
        goto likely;
2922
    case OPC_BC1T:
2923
        gen_op_bc1t();
2924
        MIPS_DEBUG("bc1t %08x", btarget);
2925
    not_likely:
2926
        ctx->hflags |= MIPS_HFLAG_BC;
2927
        break;
2928
    case OPC_BC1TL:
2929
        gen_op_bc1t();
2930
        MIPS_DEBUG("bc1tl %08x", btarget);
2931
    likely:
2932
        ctx->hflags |= MIPS_HFLAG_BL;
2933
        break;
2934
    default:    
2935
        MIPS_INVAL("cp1 branch/jump");
2936
        generate_exception_err (ctx, EXCP_RI, 1);
2937
        return;
2938
    }
2939
    gen_op_set_bcond();
2940

    
2941
    MIPS_DEBUG("enter ds: cond %02x target %08x",
2942
               ctx->hflags, btarget);
2943
    ctx->btarget = btarget;
2944

    
2945
    return;
2946
}
2947

    
2948
/* Coprocessor 1 (FPU) */
2949
static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
2950
{
2951
    const char *opn = "unk";
2952

    
2953
    switch (opc) {
2954
    case OPC_MFC1:
2955
        GEN_LOAD_FREG_FTN(WT0, fs);
2956
        gen_op_mfc1();
2957
        GEN_STORE_TN_REG(rt, T0);
2958
        opn = "mfc1";
2959
        break;
2960
    case OPC_MTC1:
2961
        GEN_LOAD_REG_TN(T0, rt);
2962
        gen_op_mtc1();
2963
        GEN_STORE_FTN_FREG(fs, WT0);
2964
        opn = "mtc1";
2965
        break;
2966
    case OPC_CFC1:
2967
        if (fs != 0 && fs != 31) {
2968
            MIPS_INVAL("cfc1 freg");
2969
            generate_exception_err (ctx, EXCP_RI, 1);
2970
            return;
2971
        }
2972
        GEN_LOAD_IMM_TN(T1, fs);
2973
        gen_op_cfc1();
2974
        GEN_STORE_TN_REG(rt, T0);
2975
        opn = "cfc1";
2976
        break;
2977
    case OPC_CTC1:
2978
         if (fs != 0 && fs != 31) {
2979
            MIPS_INVAL("ctc1 freg");
2980
            generate_exception_err (ctx, EXCP_RI, 1);
2981
            return;
2982
        }
2983
        GEN_LOAD_IMM_TN(T1, fs);
2984
        GEN_LOAD_REG_TN(T0, rt);
2985
        gen_op_ctc1();
2986
        opn = "ctc1";
2987
        break;
2988
    default:
2989
        if (loglevel & CPU_LOG_TB_IN_ASM) {
2990
            fprintf(logfile, "Invalid CP1 opcode: %08x %03x %03x %03x\n",
2991
                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
2992
                    ((ctx->opcode >> 16) & 0x1F));
2993
        }
2994
        generate_exception_err (ctx, EXCP_RI, 1);
2995
        return;
2996
    }
2997
    MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
2998
}
2999

    
3000
/* verify if floating point register is valid; an operation is not defined
3001
 * if bit 0 of any register specification is set and the FR bit in the
3002
 * Status register equals zero, since the register numbers specify an
3003
 * even-odd pair of adjacent coprocessor general registers. When the FR bit
3004
 * in the Status register equals one, both even and odd register numbers
3005
 * are valid.
3006
 * 
3007
 * Multiple float registers can be checked by calling
3008
 * CHECK_FR(ctx, freg1 | freg2 | ... | fregN);
3009
 */
3010
#define CHECK_FR(ctx, freg) do { \
3011
        if (!((ctx)->CP0_Status & (1<<CP0St_FR)) && ((freg) & 1)) { \
3012
            generate_exception_err (ctx, EXCP_RI, 1); \
3013
            return; \
3014
        } \
3015
    } while(0)
3016

    
3017
#define FOP(func, fmt) (((fmt) << 21) | (func))
3018

    
3019
static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, int fs, int fd)
3020
{
3021
    const char *opn = "unk";
3022
    const char *condnames[] = {
3023
            "c.f",
3024
            "c.un",
3025
            "c.eq",
3026
            "c.ueq",
3027
            "c.olt",
3028
            "c.ult",
3029
            "c.ole",
3030
            "c.ule",
3031
            "c.sf",
3032
            "c.ngle",
3033
            "c.seq",
3034
            "c.ngl",
3035
            "c.lt",
3036
            "c.nge",
3037
            "c.le",
3038
            "c.ngt",
3039
    };
3040
    int binary = 0;
3041
    uint32_t func = ctx->opcode & 0x3f;
3042

    
3043
    switch (ctx->opcode & FOP(0x3f, 0x1f)) {
3044
    case FOP(0, 17):
3045
        CHECK_FR(ctx, fs | ft | fd);
3046
        GEN_LOAD_FREG_FTN(DT0, fs);
3047
        GEN_LOAD_FREG_FTN(DT1, ft);
3048
        gen_op_float_add_d();
3049
        GEN_STORE_FTN_FREG(fd, DT2);
3050
        opn = "add.d";
3051
        binary = 1;
3052
        break;
3053
    case FOP(1, 17):
3054
        CHECK_FR(ctx, fs | ft | fd);
3055
        GEN_LOAD_FREG_FTN(DT0, fs);
3056
        GEN_LOAD_FREG_FTN(DT1, ft);
3057
        gen_op_float_sub_d();
3058
        GEN_STORE_FTN_FREG(fd, DT2);
3059
        opn = "sub.d";
3060
        binary = 1;
3061
        break;
3062
    case FOP(2, 17):
3063
        CHECK_FR(ctx, fs | ft | fd);
3064
        GEN_LOAD_FREG_FTN(DT0, fs);
3065
        GEN_LOAD_FREG_FTN(DT1, ft);
3066
        gen_op_float_mul_d();
3067
        GEN_STORE_FTN_FREG(fd, DT2);
3068
        opn = "mul.d";
3069
        binary = 1;
3070
        break;
3071
    case FOP(3, 17):
3072
        CHECK_FR(ctx, fs | ft | fd);
3073
        GEN_LOAD_FREG_FTN(DT0, fs);
3074
        GEN_LOAD_FREG_FTN(DT1, ft);
3075
        gen_op_float_div_d();
3076
        GEN_STORE_FTN_FREG(fd, DT2);
3077
        opn = "div.d";
3078
        binary = 1;
3079
        break;
3080
    case FOP(4, 17):
3081
        CHECK_FR(ctx, fs | fd);
3082
        GEN_LOAD_FREG_FTN(DT0, fs);
3083
        gen_op_float_sqrt_d();
3084
        GEN_STORE_FTN_FREG(fd, DT2);
3085
        opn = "sqrt.d";
3086
        break;
3087
    case FOP(5, 17):
3088
        CHECK_FR(ctx, fs | fd);
3089
        GEN_LOAD_FREG_FTN(DT0, fs);
3090
        gen_op_float_abs_d();
3091
        GEN_STORE_FTN_FREG(fd, DT2);
3092
        opn = "abs.d";
3093
        break;
3094
    case FOP(6, 17):
3095
        CHECK_FR(ctx, fs | fd);
3096
        GEN_LOAD_FREG_FTN(DT0, fs);
3097
        gen_op_float_mov_d();
3098
        GEN_STORE_FTN_FREG(fd, DT2);
3099
        opn = "mov.d";
3100
        break;
3101
    case FOP(7, 17):
3102
        CHECK_FR(ctx, fs | fd);
3103
        GEN_LOAD_FREG_FTN(DT0, fs);
3104
        gen_op_float_chs_d();
3105
        GEN_STORE_FTN_FREG(fd, DT2);
3106
        opn = "neg.d";
3107
        break;
3108
    /*  8 - round.l */
3109
    /*  9 - trunc.l */
3110
    /* 10 - ceil.l  */
3111
    /* 11 - floor.l */
3112
    case FOP(12, 17):
3113
        CHECK_FR(ctx, fs | fd);
3114
        GEN_LOAD_FREG_FTN(DT0, fs);
3115
        gen_op_float_roundw_d();
3116
        GEN_STORE_FTN_FREG(fd, WT2);
3117
        opn = "round.w.d";
3118
        break;
3119
    case FOP(13, 17):
3120
        CHECK_FR(ctx, fs | fd);
3121
        GEN_LOAD_FREG_FTN(DT0, fs);
3122
        gen_op_float_truncw_d();
3123
        GEN_STORE_FTN_FREG(fd, WT2);
3124
        opn = "trunc.w.d";
3125
        break;
3126
    case FOP(14, 17):
3127
        CHECK_FR(ctx, fs | fd);
3128
        GEN_LOAD_FREG_FTN(DT0, fs);
3129
        gen_op_float_ceilw_d();
3130
        GEN_STORE_FTN_FREG(fd, WT2);
3131
        opn = "ceil.w.d";
3132
        break;
3133
    case FOP(15, 17):
3134
        CHECK_FR(ctx, fs | fd);
3135
        GEN_LOAD_FREG_FTN(DT0, fs);
3136
        gen_op_float_floorw_d();
3137
        GEN_STORE_FTN_FREG(fd, WT2);
3138
        opn = "floor.w.d";
3139
        break;
3140
    case FOP(33, 16): /* cvt.d.s */
3141
        CHECK_FR(ctx, fs | fd);
3142
        GEN_LOAD_FREG_FTN(WT0, fs);
3143
        gen_op_float_cvtd_s();
3144
        GEN_STORE_FTN_FREG(fd, DT2);
3145
        opn = "cvt.d.s";
3146
        break;
3147
    case FOP(33, 20): /* cvt.d.w */
3148
        CHECK_FR(ctx, fs | fd);
3149
        GEN_LOAD_FREG_FTN(WT0, fs);
3150
        gen_op_float_cvtd_w();
3151
        GEN_STORE_FTN_FREG(fd, DT2);
3152
        opn = "cvt.d.w";
3153
        break;
3154
    case FOP(48, 17):
3155
    case FOP(49, 17):
3156
    case FOP(50, 17):
3157
    case FOP(51, 17):
3158
    case FOP(52, 17):
3159
    case FOP(53, 17):
3160
    case FOP(54, 17):
3161
    case FOP(55, 17):
3162
    case FOP(56, 17):
3163
    case FOP(57, 17):
3164
    case FOP(58, 17):
3165
    case FOP(59, 17):
3166
    case FOP(60, 17):
3167
    case FOP(61, 17):
3168
    case FOP(62, 17):
3169
    case FOP(63, 17):
3170
        CHECK_FR(ctx, fs | ft);
3171
        GEN_LOAD_FREG_FTN(DT0, fs);
3172
        GEN_LOAD_FREG_FTN(DT1, ft);
3173
        gen_cmp_d(func-48);
3174
        opn = condnames[func-48];
3175
        break;
3176
    case FOP(0, 16):
3177
        CHECK_FR(ctx, fs | ft | fd);
3178
        GEN_LOAD_FREG_FTN(WT0, fs);
3179
        GEN_LOAD_FREG_FTN(WT1, ft);
3180
        gen_op_float_add_s();
3181
        GEN_STORE_FTN_FREG(fd, WT2);
3182
        opn = "add.s";
3183
        binary = 1;
3184
        break;
3185
    case FOP(1, 16):
3186
        CHECK_FR(ctx, fs | ft | fd);
3187
        GEN_LOAD_FREG_FTN(WT0, fs);
3188
        GEN_LOAD_FREG_FTN(WT1, ft);
3189
        gen_op_float_sub_s();
3190
        GEN_STORE_FTN_FREG(fd, WT2);
3191
        opn = "sub.s";
3192
        binary = 1;
3193
        break;
3194
    case FOP(2, 16):
3195
        CHECK_FR(ctx, fs | ft | fd);
3196
        GEN_LOAD_FREG_FTN(WT0, fs);
3197
        GEN_LOAD_FREG_FTN(WT1, ft);
3198
        gen_op_float_mul_s();
3199
        GEN_STORE_FTN_FREG(fd, WT2);
3200
        opn = "mul.s";
3201
        binary = 1;
3202
        break;
3203
    case FOP(3, 16):
3204
        CHECK_FR(ctx, fs | ft | fd);
3205
        GEN_LOAD_FREG_FTN(WT0, fs);
3206
        GEN_LOAD_FREG_FTN(WT1, ft);
3207
        gen_op_float_div_s();
3208
        GEN_STORE_FTN_FREG(fd, WT2);
3209
        opn = "div.s";
3210
        binary = 1;
3211
        break;
3212
    case FOP(4, 16):
3213
        CHECK_FR(ctx, fs | fd);
3214
        GEN_LOAD_FREG_FTN(WT0, fs);
3215
        gen_op_float_sqrt_s();
3216
        GEN_STORE_FTN_FREG(fd, WT2);
3217
        opn = "sqrt.s";
3218
        break;
3219
    case FOP(5, 16):
3220
        CHECK_FR(ctx, fs | fd);
3221
        GEN_LOAD_FREG_FTN(WT0, fs);
3222
        gen_op_float_abs_s();
3223
        GEN_STORE_FTN_FREG(fd, WT2);
3224
        opn = "abs.s";
3225
        break;
3226
    case FOP(6, 16):
3227
        CHECK_FR(ctx, fs | fd);
3228
        GEN_LOAD_FREG_FTN(WT0, fs);
3229
        gen_op_float_mov_s();
3230
        GEN_STORE_FTN_FREG(fd, WT2);
3231
        opn = "mov.s";
3232
        break;
3233
    case FOP(7, 16):
3234
        CHECK_FR(ctx, fs | fd);
3235
        GEN_LOAD_FREG_FTN(WT0, fs);
3236
        gen_op_float_chs_s();
3237
        GEN_STORE_FTN_FREG(fd, WT2);
3238
        opn = "neg.s";
3239
        break;
3240
    case FOP(12, 16):
3241
        CHECK_FR(ctx, fs | fd);
3242
        GEN_LOAD_FREG_FTN(WT0, fs);
3243
        gen_op_float_roundw_s();
3244
        GEN_STORE_FTN_FREG(fd, WT2);
3245
        opn = "round.w.s";
3246
        break;
3247
    case FOP(13, 16):
3248
        CHECK_FR(ctx, fs | fd);
3249
        GEN_LOAD_FREG_FTN(WT0, fs);
3250
        gen_op_float_truncw_s();
3251
        GEN_STORE_FTN_FREG(fd, WT2);
3252
        opn = "trunc.w.s";
3253
        break;
3254
    case FOP(32, 17): /* cvt.s.d */
3255
        CHECK_FR(ctx, fs | fd);
3256
        GEN_LOAD_FREG_FTN(DT0, fs);
3257
        gen_op_float_cvts_d();
3258
        GEN_STORE_FTN_FREG(fd, WT2);
3259
        opn = "cvt.s.d";
3260
        break;
3261
    case FOP(32, 20): /* cvt.s.w */
3262
        CHECK_FR(ctx, fs | fd);
3263
        GEN_LOAD_FREG_FTN(WT0, fs);
3264
        gen_op_float_cvts_w();
3265
        GEN_STORE_FTN_FREG(fd, WT2);
3266
        opn = "cvt.s.w";
3267
        break;
3268
    case FOP(36, 16): /* cvt.w.s */
3269
        CHECK_FR(ctx, fs | fd);
3270
        GEN_LOAD_FREG_FTN(WT0, fs);
3271
        gen_op_float_cvtw_s();
3272
        GEN_STORE_FTN_FREG(fd, WT2);
3273
        opn = "cvt.w.s";
3274
        break;
3275
    case FOP(36, 17): /* cvt.w.d */
3276
        CHECK_FR(ctx, fs | fd);
3277
        GEN_LOAD_FREG_FTN(DT0, fs);
3278
        gen_op_float_cvtw_d();
3279
        GEN_STORE_FTN_FREG(fd, WT2);
3280
        opn = "cvt.w.d";
3281
        break;
3282
    case FOP(48, 16):
3283
    case FOP(49, 16):
3284
    case FOP(50, 16):
3285
    case FOP(51, 16):
3286
    case FOP(52, 16):
3287
    case FOP(53, 16):
3288
    case FOP(54, 16):
3289
    case FOP(55, 16):
3290
    case FOP(56, 16):
3291
    case FOP(57, 16):
3292
    case FOP(58, 16):
3293
    case FOP(59, 16):
3294
    case FOP(60, 16):
3295
    case FOP(61, 16):
3296
    case FOP(62, 16):
3297
    case FOP(63, 16):
3298
        CHECK_FR(ctx, fs | ft);
3299
        GEN_LOAD_FREG_FTN(WT0, fs);
3300
        GEN_LOAD_FREG_FTN(WT1, ft);
3301
        gen_cmp_s(func-48);
3302
        opn = condnames[func-48];
3303
        break;
3304
    default:    
3305
        if (loglevel & CPU_LOG_TB_IN_ASM) {
3306
            fprintf(logfile, "Invalid FP arith function: %08x %03x %03x %03x\n",
3307
                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
3308
                    ((ctx->opcode >> 16) & 0x1F));
3309
        }
3310
        generate_exception_err (ctx, EXCP_RI, 1);
3311
        return;
3312
    }
3313
    if (binary)
3314
        MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
3315
    else
3316
        MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
3317
}
3318

    
3319
static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
3320
{
3321
    uint32_t ccbit;
3322

    
3323
    if (cc)
3324
        ccbit = 1 << (24 + cc);
3325
    else
3326
        ccbit = 1 << 23;
3327
    if (!tf)
3328
        gen_op_movf(ccbit, rd, rs);
3329
    else
3330
       gen_op_movt(ccbit, rd, rs);
3331
}
3332

    
3333
/* ISA extensions (ASEs) */
3334
/* MIPS16 extension to MIPS32 */
3335
/* SmartMIPS extension to MIPS32 */
3336

    
3337
#ifdef MIPS_HAS_MIPS64
3338
static void gen_arith64 (DisasContext *ctx, uint32_t opc)
3339
{
3340
    if (func == 0x02 && rd == 0) {
3341
        /* NOP */
3342
        return;
3343
    }
3344
    if (rs == 0 || rt == 0) {
3345
        gen_op_reset_T0();
3346
        gen_op_save64();
3347
    } else {
3348
        gen_op_load_gpr_T0(rs);
3349
        gen_op_load_gpr_T1(rt);
3350
        gen_op_save64();
3351
        if (func & 0x01)
3352
            gen_op_mul64u();
3353
        else
3354
            gen_op_mul64s();
3355
    }
3356
    if (func & 0x02)
3357
        gen_op_add64();
3358
    else
3359
        gen_op_sub64();
3360
}
3361

    
3362
/* Coprocessor 3 (FPU) */
3363

    
3364
/* MDMX extension to MIPS64 */
3365
/* MIPS-3D extension to MIPS64 */
3366

    
3367
#endif
3368

    
3369
static void gen_blikely(DisasContext *ctx)
3370
{
3371
    int l1;
3372
    l1 = gen_new_label();
3373
    gen_op_jnz_T2(l1);
3374
    gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
3375
    gen_goto_tb(ctx, 1, ctx->pc + 4);
3376
    gen_set_label(l1);
3377
}
3378

    
3379
static void decode_opc (DisasContext *ctx)
3380
{
3381
    int32_t offset;
3382
    int rs, rt, rd, sa;
3383
    uint32_t op, op1, op2;
3384
    int16_t imm;
3385

    
3386
    /* make sure instructions are on a word boundary */
3387
    if (ctx->pc & 0x3) {
3388
        generate_exception(ctx, EXCP_AdEL);
3389
        return;
3390
    }
3391

    
3392
    if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
3393
        /* Handle blikely not taken case */
3394
        MIPS_DEBUG("blikely condition (%08x)", ctx->pc + 4);
3395
        gen_blikely(ctx);
3396
    }
3397
    op = MASK_OP_MAJOR(ctx->opcode);
3398
    rs = (ctx->opcode >> 21) & 0x1f;
3399
    rt = (ctx->opcode >> 16) & 0x1f;
3400
    rd = (ctx->opcode >> 11) & 0x1f;
3401
    sa = (ctx->opcode >> 6) & 0x1f;
3402
    imm = (int16_t)ctx->opcode;
3403
    switch (op) {
3404
    case OPC_SPECIAL:
3405
        op1 = MASK_SPECIAL(ctx->opcode);
3406
        switch (op1) {
3407
        case OPC_SLL:          /* Arithmetic with immediate */
3408
        case OPC_SRL ... OPC_SRA:
3409
            gen_arith_imm(ctx, op1, rd, rt, sa);
3410
            break;
3411
        case OPC_SLLV:         /* Arithmetic */
3412
        case OPC_SRLV ... OPC_SRAV:
3413
        case OPC_MOVZ ... OPC_MOVN:
3414
        case OPC_ADD ... OPC_NOR:
3415
        case OPC_SLT ... OPC_SLTU:
3416
            gen_arith(ctx, op1, rd, rs, rt);
3417
            break;
3418
        case OPC_MULT ... OPC_DIVU:
3419
            gen_muldiv(ctx, op1, rs, rt);
3420
            break;
3421
        case OPC_JR ... OPC_JALR:
3422
            gen_compute_branch(ctx, op1, rs, rd, sa);
3423
            return;
3424
        case OPC_TGE ... OPC_TEQ: /* Traps */
3425
        case OPC_TNE:
3426
            gen_trap(ctx, op1, rs, rt, -1);
3427
            break;
3428
        case OPC_MFHI:          /* Move from HI/LO */
3429
        case OPC_MFLO:
3430
            gen_HILO(ctx, op1, rd);
3431
            break;
3432
        case OPC_MTHI:
3433
        case OPC_MTLO:          /* Move to HI/LO */
3434
            gen_HILO(ctx, op1, rs);
3435
            break;
3436
        case OPC_PMON:          /* Pmon entry point */
3437
            gen_op_pmon(sa);
3438
            break;
3439
        case OPC_SYSCALL:
3440
            generate_exception(ctx, EXCP_SYSCALL);
3441
            ctx->bstate = BS_EXCP;
3442
            break;
3443
        case OPC_BREAK:
3444
            generate_exception(ctx, EXCP_BREAK);
3445
            break;
3446
        case OPC_SPIM:        /* SPIM ? */
3447
           /* Implemented as RI exception for now. */
3448
            MIPS_INVAL("spim (unofficial)");
3449
            generate_exception(ctx, EXCP_RI);
3450
            break;
3451
        case OPC_SYNC:
3452
            /* Treat as a noop. */
3453
            break;
3454

    
3455
        case OPC_MOVCI:
3456
            gen_op_cp1_enabled();
3457
            gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
3458
                      (ctx->opcode >> 16) & 1);
3459
            break;
3460

    
3461
#ifdef MIPS_HAS_MIPS64
3462
       /* MIPS64 specific opcodes */
3463
        case OPC_DSLL:
3464
        case OPC_DSRL ... OPC_DSRA:
3465
        case OPC_DSLL32:
3466
        case OPC_DSRL32 ... OPC_DSRA32:
3467
            gen_arith_imm(ctx, op1, rd, rt, sa);
3468
            break;
3469
        case OPC_DSLLV:
3470
        case OPC_DSRLV ... OPC_DSRAV:
3471
        case OPC_DADD ... OPC_DSUBU:
3472
            gen_arith(ctx, op1, rd, rs, rt);
3473
            break;
3474
        case OPC_DMULT ... OPC_DDIVU:
3475
            gen_muldiv(ctx, op1, rs, rt);
3476
            break;
3477
#endif
3478
        default:            /* Invalid */
3479
            MIPS_INVAL("special");
3480
            generate_exception(ctx, EXCP_RI);
3481
            break;
3482
        }
3483
        break;
3484
    case OPC_SPECIAL2:
3485
        op1 = MASK_SPECIAL2(ctx->opcode);
3486
        switch (op1) {
3487
        case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
3488
        case OPC_MSUB ... OPC_MSUBU:
3489
            gen_muldiv(ctx, op1, rs, rt);
3490
            break;
3491
        case OPC_MUL:
3492
            gen_arith(ctx, op1, rd, rs, rt);
3493
            break;
3494
        case OPC_CLZ ... OPC_CLO:
3495
            gen_cl(ctx, op1, rd, rs);
3496
            break;
3497
        case OPC_SDBBP:
3498
            /* XXX: not clear which exception should be raised
3499
             *      when in debug mode...
3500
             */
3501
            if (!(ctx->hflags & MIPS_HFLAG_DM)) {
3502
                generate_exception(ctx, EXCP_DBp);
3503
            } else {
3504
                generate_exception(ctx, EXCP_DBp);
3505
            }
3506
            /* Treat as a noop */
3507
            break;
3508
#ifdef MIPS_HAS_MIPS64
3509
        case OPC_DCLZ ... OPC_DCLO:
3510
            gen_cl(ctx, op1, rd, rs);
3511
            break;
3512
#endif
3513
        default:            /* Invalid */
3514
            MIPS_INVAL("special2");
3515
            generate_exception(ctx, EXCP_RI);
3516
            break;
3517
        }
3518
        break;
3519
    case OPC_SPECIAL3:
3520
        op1 = MASK_SPECIAL3(ctx->opcode);
3521
        switch (op1) {
3522
        case OPC_EXT:
3523
        case OPC_INS:
3524
            gen_bitops(ctx, op1, rt, rs, sa, rd);
3525
            break;
3526
        case OPC_BSHFL:
3527
            op2 = MASK_BSHFL(ctx->opcode);
3528
            switch (op2) {
3529
            case OPC_WSBH:
3530
                GEN_LOAD_REG_TN(T1, rt);
3531
                gen_op_wsbh();
3532
                break;
3533
            case OPC_SEB:
3534
                GEN_LOAD_REG_TN(T1, rt);
3535
                gen_op_seb();
3536
                break;
3537
            case OPC_SEH:
3538
                GEN_LOAD_REG_TN(T1, rt);
3539
                gen_op_seh();
3540
                break;
3541
             default:            /* Invalid */
3542
                MIPS_INVAL("bshfl");
3543
                generate_exception(ctx, EXCP_RI);
3544
                break;
3545
           }
3546
           GEN_STORE_TN_REG(rd, T0);
3547
           break;
3548
       case OPC_RDHWR:
3549
           switch (rd) {
3550
           case 0:
3551
               gen_op_rdhwr_cpunum();
3552
               break;
3553
           case 1:
3554
               gen_op_rdhwr_synci_step();
3555
               break;
3556
           case 2:
3557
               gen_op_rdhwr_cc();
3558
               break;
3559
           case 3:
3560
               gen_op_rdhwr_ccres();
3561
               break;
3562
           default:            /* Invalid */
3563
               MIPS_INVAL("rdhwr");
3564
               generate_exception(ctx, EXCP_RI);
3565
               break;
3566
           }
3567
           GEN_STORE_TN_REG(rt, T0);
3568
           break;
3569
#ifdef MIPS_HAS_MIPS64
3570
       case OPC_DEXTM ... OPC_DEXT:
3571
       case OPC_DINSM ... OPC_DINS:
3572
           gen_bitops(ctx, op1, rt, rs, sa, rd);
3573
            break;
3574
       case OPC_DBSHFL:
3575
           op2 = MASK_DBSHFL(ctx->opcode);
3576
           switch (op2) {
3577
           case OPC_DSBH:
3578
               GEN_LOAD_REG_TN(T1, rt);
3579
               gen_op_dsbh();
3580
               break;
3581
           case OPC_DSHD:
3582
               GEN_LOAD_REG_TN(T1, rt);
3583
               gen_op_dshd();
3584
               break;
3585
            default:            /* Invalid */
3586
                MIPS_INVAL("dbshfl");
3587
                generate_exception(ctx, EXCP_RI);
3588
                break;
3589
           }
3590
           GEN_STORE_TN_REG(rd, T0);
3591
#endif
3592
        default:            /* Invalid */
3593
            MIPS_INVAL("special3");
3594
            generate_exception(ctx, EXCP_RI);
3595
            break;
3596
        }
3597
        break;
3598
    case OPC_REGIMM:
3599
        op1 = MASK_REGIMM(ctx->opcode);
3600
        switch (op1) {
3601
        case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
3602
        case OPC_BLTZAL ... OPC_BGEZALL:
3603
            gen_compute_branch(ctx, op1, rs, -1, imm << 2);
3604
            return;
3605
        case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
3606
        case OPC_TNEI:
3607
            gen_trap(ctx, op1, rs, -1, imm);
3608
            break;
3609
        case OPC_SYNCI:
3610
           /* treat as noop */
3611
            break;
3612
        default:            /* Invalid */
3613
            MIPS_INVAL("REGIMM");
3614
            generate_exception(ctx, EXCP_RI);
3615
            break;
3616
        }
3617
        break;
3618
    case OPC_CP0:
3619
        op1 = MASK_CP0(ctx->opcode);
3620
        switch (op1) {
3621
        case OPC_MFC0:
3622
        case OPC_MTC0:
3623
#ifdef MIPS_HAS_MIPS64
3624
        case OPC_DMFC0:
3625
        case OPC_DMTC0:
3626
#endif
3627
            gen_cp0(ctx, op1, rt, rd);
3628
            break;
3629
        case OPC_C0_FIRST ... OPC_C0_LAST:
3630
            gen_cp0(ctx, MASK_C0(ctx->opcode), rt, rd);
3631
            break;
3632
        case OPC_MFMC0:
3633
            op2 = MASK_MFMC0(ctx->opcode);
3634
            switch (op2) {
3635
            case OPC_DI:
3636
                gen_op_di();
3637
                /* Stop translation as we may have switched the execution mode */
3638
                ctx->bstate = BS_STOP;
3639
                break;
3640
            case OPC_EI:
3641
                gen_op_ei();
3642
                /* Stop translation as we may have switched the execution mode */
3643
                ctx->bstate = BS_STOP;
3644
                break;
3645
            default:            /* Invalid */
3646
                MIPS_INVAL("MFMC0");
3647
                generate_exception(ctx, EXCP_RI);
3648
                break;
3649
            }
3650
            GEN_STORE_TN_REG(rt, T0);
3651
            break;
3652
        /* Shadow registers (not implemented). */
3653
        case OPC_RDPGPR:
3654
        case OPC_WRPGPR:
3655
        default:
3656
            generate_exception(ctx, EXCP_RI);
3657
            break;
3658
        }
3659
        break;
3660
    case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
3661
         gen_arith_imm(ctx, op, rt, rs, imm);
3662
         break;
3663
    case OPC_J ... OPC_JAL: /* Jump */
3664
         offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
3665
         gen_compute_branch(ctx, op, rs, rt, offset);
3666
         return;
3667
    case OPC_BEQ ... OPC_BGTZ: /* Branch */
3668
    case OPC_BEQL ... OPC_BGTZL:
3669
         gen_compute_branch(ctx, op, rs, rt, imm << 2);
3670
         return;
3671
    case OPC_LB ... OPC_LWR: /* Load and stores */
3672
    case OPC_SB ... OPC_SW:
3673
    case OPC_SWR:
3674
    case OPC_LL:
3675
    case OPC_SC:
3676
         gen_ldst(ctx, op, rt, rs, imm);
3677
         break;
3678
    case OPC_CACHE:
3679
         /* Treat as a noop */
3680
         break;
3681
    case OPC_PREF:
3682
        /* Treat as a noop */
3683
        break;
3684

    
3685
    /* Floating point.  */
3686
    case OPC_LWC1:
3687
    case OPC_LDC1:
3688
    case OPC_SWC1:
3689
    case OPC_SDC1:
3690
#if defined(MIPS_USES_FPU)
3691
        save_cpu_state(ctx, 1);
3692
        gen_op_cp1_enabled();
3693
        gen_flt_ldst(ctx, op, rt, rs, imm);
3694
#else
3695
        generate_exception_err(ctx, EXCP_CpU, 1);
3696
#endif
3697
        break;
3698

    
3699
    case OPC_CP1:
3700
#if defined(MIPS_USES_FPU)
3701
        save_cpu_state(ctx, 1);
3702
        gen_op_cp1_enabled();
3703
        op1 = MASK_CP1(ctx->opcode);
3704
        switch (op1) {
3705
        case OPC_MFC1:
3706
        case OPC_CFC1:
3707
        case OPC_MTC1:
3708
        case OPC_CTC1:
3709
            gen_cp1(ctx, op1, rt, rd);
3710
            break;
3711
        case OPC_BC1:
3712
            gen_compute_branch1(ctx, MASK_CP1_BCOND(ctx->opcode), imm << 2);
3713
            return;
3714
        case OPC_S_FMT:
3715
        case OPC_D_FMT:
3716
        case OPC_W_FMT:
3717
        case OPC_L_FMT:
3718
            gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa);
3719
            break;
3720
        default:
3721
            generate_exception_err(ctx, EXCP_RI, 1);
3722
            break;
3723
        }
3724
#else
3725
        generate_exception_err(ctx, EXCP_CpU, 1);
3726
#endif
3727
        break;
3728

    
3729
    /* COP2.  */
3730
    case OPC_LWC2:
3731
    case OPC_LDC2:
3732
    case OPC_SWC2:
3733
    case OPC_SDC2:
3734
    case OPC_CP2:
3735
        /* COP2: Not implemented. */
3736
        generate_exception_err(ctx, EXCP_CpU, 2);
3737
        break;
3738

    
3739
    case OPC_CP3:
3740
        gen_op_cp1_enabled();
3741
        op1 = MASK_CP3(ctx->opcode);
3742
        switch (op1) {
3743
        /* Not implemented */
3744
        default:
3745
            generate_exception_err(ctx, EXCP_RI, 1);
3746
            break;
3747
        }
3748
        break;
3749

    
3750
#ifdef MIPS_HAS_MIPS64
3751
    /* MIPS64 opcodes */
3752
    case OPC_LWU:
3753
    case OPC_LDL ... OPC_LDR:
3754
    case OPC_SDL ... OPC_SDR:
3755
    case OPC_LLD:
3756
    case OPC_LD:
3757
    case OPC_SCD:
3758
    case OPC_SD:
3759
        gen_ldst(ctx, op, rt, rs, imm);
3760
        break;
3761
    case OPC_DADDI ... OPC_DADDIU:
3762
        gen_arith_imm(ctx, op, rt, rs, imm);
3763
        break;
3764
#endif
3765
#ifdef MIPS_HAS_MIPS16
3766
    case OPC_JALX:
3767
        /* MIPS16: Not implemented. */
3768
#endif
3769
#ifdef MIPS_HAS_MDMX
3770
    case OPC_MDMX:
3771
        /* MDMX: Not implemented. */
3772
#endif
3773
    default:            /* Invalid */
3774
        MIPS_INVAL("");
3775
        generate_exception(ctx, EXCP_RI);
3776
        break;
3777
    }
3778
    if (ctx->hflags & MIPS_HFLAG_BMASK) {
3779
        int hflags = ctx->hflags;
3780
        /* Branches completion */
3781
        ctx->hflags &= ~MIPS_HFLAG_BMASK;
3782
        ctx->bstate = BS_BRANCH;
3783
        save_cpu_state(ctx, 0);
3784
        switch (hflags & MIPS_HFLAG_BMASK) {
3785
        case MIPS_HFLAG_B:
3786
            /* unconditional branch */
3787
            MIPS_DEBUG("unconditional branch");
3788
            gen_goto_tb(ctx, 0, ctx->btarget);
3789
            break;
3790
        case MIPS_HFLAG_BL:
3791
            /* blikely taken case */
3792
            MIPS_DEBUG("blikely branch taken");
3793
            gen_goto_tb(ctx, 0, ctx->btarget);
3794
            break;
3795
        case MIPS_HFLAG_BC:
3796
            /* Conditional branch */
3797
            MIPS_DEBUG("conditional branch");
3798
            {
3799
              int l1;
3800
              l1 = gen_new_label();
3801
              gen_op_jnz_T2(l1);
3802
              gen_goto_tb(ctx, 1, ctx->pc + 4);
3803
              gen_set_label(l1);
3804
              gen_goto_tb(ctx, 0, ctx->btarget);
3805
            }
3806
            break;
3807
        case MIPS_HFLAG_BR:
3808
            /* unconditional branch to register */
3809
            MIPS_DEBUG("branch to register");
3810
            gen_op_breg();
3811
            break;
3812
        default:
3813
            MIPS_DEBUG("unknown branch");
3814
            break;
3815
        }
3816
    }
3817
}
3818

    
3819
int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
3820
                                    int search_pc)
3821
{
3822
    DisasContext ctx, *ctxp = &ctx;
3823
    target_ulong pc_start;
3824
    uint16_t *gen_opc_end;
3825
    int j, lj = -1;
3826

    
3827
    if (search_pc && loglevel)
3828
        fprintf (logfile, "search pc %d\n", search_pc);
3829

    
3830
    pc_start = tb->pc;
3831
    gen_opc_ptr = gen_opc_buf;
3832
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3833
    gen_opparam_ptr = gen_opparam_buf;
3834
    nb_gen_labels = 0;
3835
    ctx.pc = pc_start;
3836
    ctx.saved_pc = -1;
3837
    ctx.tb = tb;
3838
    ctx.bstate = BS_NONE;
3839
    /* Restore delay slot state from the tb context.  */
3840
    ctx.hflags = tb->flags;
3841
    ctx.saved_hflags = ctx.hflags;
3842
    if (ctx.hflags & MIPS_HFLAG_BR) {
3843
        gen_op_restore_breg_target();
3844
    } else if (ctx.hflags & MIPS_HFLAG_B) {
3845
        ctx.btarget = env->btarget;
3846
    } else if (ctx.hflags & MIPS_HFLAG_BMASK) {
3847
        /* If we are in the delay slot of a conditional branch,
3848
         * restore the branch condition from env->bcond to T2
3849
         */
3850
        ctx.btarget = env->btarget;
3851
        gen_op_restore_bcond();
3852
    }
3853
#if defined(CONFIG_USER_ONLY)
3854
    ctx.mem_idx = 0;
3855
#else
3856
    ctx.mem_idx = !((ctx.hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM);
3857
#endif
3858
    ctx.CP0_Status = env->CP0_Status;
3859
#ifdef DEBUG_DISAS
3860
    if (loglevel & CPU_LOG_TB_CPU) {
3861
        fprintf(logfile, "------------------------------------------------\n");
3862
        /* FIXME: This may print out stale hflags from env... */
3863
        cpu_dump_state(env, logfile, fprintf, 0);
3864
    }
3865
#endif
3866
#if defined MIPS_DEBUG_DISAS
3867
    if (loglevel & CPU_LOG_TB_IN_ASM)
3868
        fprintf(logfile, "\ntb %p super %d cond %04x\n",
3869
                tb, ctx.mem_idx, ctx.hflags);
3870
#endif
3871
    while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
3872
        if (env->nb_breakpoints > 0) {
3873
            for(j = 0; j < env->nb_breakpoints; j++) {
3874
                if (env->breakpoints[j] == ctx.pc) {
3875
                    save_cpu_state(ctxp, 1);
3876
                    ctx.bstate = BS_BRANCH;
3877
                    gen_op_debug();
3878
                    goto done_generating;
3879
                }
3880
            }
3881
        }
3882

    
3883
        if (search_pc) {
3884
            j = gen_opc_ptr - gen_opc_buf;
3885
            if (lj < j) {
3886
                lj++;
3887
                while (lj < j)
3888
                    gen_opc_instr_start[lj++] = 0;
3889
            }
3890
            gen_opc_pc[lj] = ctx.pc;
3891
            gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
3892
            gen_opc_instr_start[lj] = 1;
3893
        }
3894
        ctx.opcode = ldl_code(ctx.pc);
3895
        decode_opc(&ctx);
3896
        ctx.pc += 4;
3897

    
3898
        if (env->singlestep_enabled)
3899
            break;
3900

    
3901
        if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
3902
            break;
3903

    
3904
#if defined (MIPS_SINGLE_STEP)
3905
        break;
3906
#endif
3907
    }
3908
    if (env->singlestep_enabled) {
3909
        save_cpu_state(ctxp, ctx.bstate == BS_NONE);
3910
        gen_op_debug();
3911
        goto done_generating;
3912
    }
3913
    else if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) {
3914
        save_cpu_state(ctxp, 0);
3915
        gen_goto_tb(&ctx, 0, ctx.pc);
3916
    }
3917
    gen_op_reset_T0();
3918
    /* Generate the return instruction */
3919
    gen_op_exit_tb();
3920
done_generating:
3921
    *gen_opc_ptr = INDEX_op_end;
3922
    if (search_pc) {
3923
        j = gen_opc_ptr - gen_opc_buf;
3924
        lj++;
3925
        while (lj <= j)
3926
            gen_opc_instr_start[lj++] = 0;
3927
        tb->size = 0;
3928
    } else {
3929
        tb->size = ctx.pc - pc_start;
3930
    }
3931
#ifdef DEBUG_DISAS
3932
#if defined MIPS_DEBUG_DISAS
3933
    if (loglevel & CPU_LOG_TB_IN_ASM)
3934
        fprintf(logfile, "\n");
3935
#endif
3936
    if (loglevel & CPU_LOG_TB_IN_ASM) {
3937
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
3938
    target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
3939
        fprintf(logfile, "\n");
3940
    }
3941
    if (loglevel & CPU_LOG_TB_OP) {
3942
        fprintf(logfile, "OP:\n");
3943
        dump_ops(gen_opc_buf, gen_opparam_buf);
3944
        fprintf(logfile, "\n");
3945
    }
3946
    if (loglevel & CPU_LOG_TB_CPU) {
3947
        fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
3948
    }
3949
#endif
3950
    
3951
    return 0;
3952
}
3953

    
3954
int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
3955
{
3956
    return gen_intermediate_code_internal(env, tb, 0);
3957
}
3958

    
3959
int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
3960
{
3961
    return gen_intermediate_code_internal(env, tb, 1);
3962
}
3963

    
3964
void fpu_dump_state(CPUState *env, FILE *f, 
3965
                    int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
3966
                    int flags)
3967
{
3968
    int i;
3969

    
3970
#   define printfpr(fp) do { \
3971
        fpu_fprintf(f, "w:%08x d:%08lx%08lx fd:%g fs:%g\n", \
3972
                (fp)->w[FP_ENDIAN_IDX], (fp)->w[0], (fp)->w[1], (fp)->fd, (fp)->fs[FP_ENDIAN_IDX]); \
3973
    } while(0)
3974

    
3975
    fpu_fprintf(f, "CP1 FCR0 0x%08x  FCR31 0x%08x  SR.FR %d\n",
3976
                env->fcr0, env->fcr31,
3977
                (env->CP0_Status & (1 << CP0St_FR)) != 0);
3978
    fpu_fprintf(f, "FT0: "); printfpr(&env->ft0);
3979
    fpu_fprintf(f, "FT1: "); printfpr(&env->ft1);
3980
    fpu_fprintf(f, "FT2: "); printfpr(&env->ft2);
3981
    for(i = 0; i < 32; i += 2) {
3982
        fpu_fprintf(f, "%s: ", fregnames[i]);
3983
        printfpr(FPR(env, i));
3984
    }
3985

    
3986
#undef printfpr
3987
}
3988

    
3989
void dump_fpu (CPUState *env)
3990
{
3991
    if (loglevel) { 
3992
       fprintf(logfile, "pc=0x%08x HI=0x%08x LO=0x%08x ds %04x %08x %d\n",
3993
               env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
3994
       fpu_dump_state(env, logfile, fprintf, 0);
3995
    }
3996
}
3997

    
3998
void cpu_dump_state (CPUState *env, FILE *f, 
3999
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
4000
                     int flags)
4001
{
4002
    uint32_t c0_status;
4003
    int i;
4004
    
4005
    cpu_fprintf(f, "pc=0x%08x HI=0x%08x LO=0x%08x ds %04x %08x %d\n",
4006
                env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
4007
    for (i = 0; i < 32; i++) {
4008
        if ((i & 3) == 0)
4009
            cpu_fprintf(f, "GPR%02d:", i);
4010
        cpu_fprintf(f, " %s %08x", regnames[i], env->gpr[i]);
4011
        if ((i & 3) == 3)
4012
            cpu_fprintf(f, "\n");
4013
    }
4014

    
4015
    c0_status = env->CP0_Status;
4016
    if (env->hflags & MIPS_HFLAG_UM)
4017
        c0_status |= (1 << CP0St_UM);
4018
    if (env->hflags & MIPS_HFLAG_ERL)
4019
        c0_status |= (1 << CP0St_ERL);
4020
    if (env->hflags & MIPS_HFLAG_EXL)
4021
        c0_status |= (1 << CP0St_EXL);
4022

    
4023
    cpu_fprintf(f, "CP0 Status  0x%08x Cause   0x%08x EPC    0x%08x\n",
4024
                c0_status, env->CP0_Cause, env->CP0_EPC);
4025
    cpu_fprintf(f, "    Config0 0x%08x Config1 0x%08x LLAddr 0x%08x\n",
4026
                env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
4027
    if (c0_status & (1 << CP0St_CU1))
4028
        fpu_dump_state(env, f, cpu_fprintf, flags);
4029
}
4030

    
4031
CPUMIPSState *cpu_mips_init (void)
4032
{
4033
    CPUMIPSState *env;
4034

    
4035
    env = qemu_mallocz(sizeof(CPUMIPSState));
4036
    if (!env)
4037
        return NULL;
4038
    cpu_exec_init(env);
4039
    cpu_reset(env);
4040
    return env;
4041
}
4042

    
4043
void cpu_reset (CPUMIPSState *env)
4044
{
4045
    memset(env, 0, offsetof(CPUMIPSState, breakpoints));
4046

    
4047
    tlb_flush(env, 1);
4048

    
4049
    /* Minimal init */
4050
    env->PC = 0xBFC00000;
4051
#if defined (MIPS_USES_R4K_TLB)
4052
    env->CP0_random = MIPS_TLB_NB - 1;
4053
    env->tlb_in_use = MIPS_TLB_NB;
4054
#endif
4055
    env->CP0_Wired = 0;
4056
    /* SMP not implemented */
4057
    env->CP0_EBase = 0x80000000;
4058
    env->CP0_Config0 = MIPS_CONFIG0;
4059
    env->CP0_Config1 = MIPS_CONFIG1;
4060
    env->CP0_Config2 = MIPS_CONFIG2;
4061
    env->CP0_Config3 = MIPS_CONFIG3;
4062
    env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV);
4063
    env->CP0_WatchLo = 0;
4064
    env->hflags = MIPS_HFLAG_ERL;
4065
    /* Count register increments in debug mode, EJTAG version 1 */
4066
    env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
4067
    env->CP0_PRid = MIPS_CPU;
4068
    env->exception_index = EXCP_NONE;
4069
#if defined(CONFIG_USER_ONLY)
4070
    env->hflags |= MIPS_HFLAG_UM;
4071
#endif
4072
#ifdef MIPS_USES_FPU
4073
    env->fcr0 = MIPS_FCR0;        
4074
#endif
4075
    /* XXX some guesswork here, values are CPU specific */
4076
    env->SYNCI_Step = 16;
4077
    env->CCRes = 2;
4078
}