Statistics
| Branch: | Revision:

root / target-mips / translate.c @ 00a709c7

History | View | Annotate | Download (138.6 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
 *  Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2 of the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with this library; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
 */
22

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

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

    
33
//#define MIPS_DEBUG_DISAS
34
//#define MIPS_DEBUG_SIGN_EXTENSIONS
35
//#define MIPS_SINGLE_STEP
36

    
37
#ifdef USE_DIRECT_JUMP
38
#define TBPARAM(x)
39
#else
40
#define TBPARAM(x) (long)(x)
41
#endif
42

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

    
50
static uint16_t *gen_opc_ptr;
51
static uint32_t *gen_opparam_ptr;
52

    
53
#include "gen-op.h"
54

    
55
/* MIPS major opcodes */
56
#define MASK_OP_MAJOR(op)  (op & (0x3F << 26))
57

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

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

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

    
199
    OPC_MOVCI    = 0x01 | OPC_SPECIAL,
200

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
357
#define MASK_CP1_BCOND(op)      MASK_CP1(op) | (op & (0x3 << 16))
358
#define MASK_CP1_FUNC(op)       MASK_CP1(op) | (op & 0x3F)
359

    
360
#define MASK_CP2(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
361
#define MASK_CP3(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
362

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

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

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

    
391
GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
392
GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
393

    
394
#ifdef MIPS_USES_FPU
395

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

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

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

    
434
SFGEN32(gen_op_load_fpr_WT0,  gen_op_load_fpr_WT0_fpr);
435
SFGEN32(gen_op_store_fpr_WT0, gen_op_store_fpr_WT0_fpr);
436

    
437
SFGEN32(gen_op_load_fpr_WT1,  gen_op_load_fpr_WT1_fpr);
438
SFGEN32(gen_op_store_fpr_WT1, gen_op_store_fpr_WT1_fpr);
439

    
440
SFGEN32(gen_op_load_fpr_WT2,  gen_op_load_fpr_WT2_fpr);
441
SFGEN32(gen_op_store_fpr_WT2, gen_op_store_fpr_WT2_fpr);
442

    
443
DFGEN32(gen_op_load_fpr_DT0,  gen_op_load_fpr_DT0_fpr);
444
DFGEN32(gen_op_store_fpr_DT0, gen_op_store_fpr_DT0_fpr);
445

    
446
DFGEN32(gen_op_load_fpr_DT1,  gen_op_load_fpr_DT1_fpr);
447
DFGEN32(gen_op_store_fpr_DT1, gen_op_store_fpr_DT1_fpr);
448

    
449
DFGEN32(gen_op_load_fpr_DT2,  gen_op_load_fpr_DT2_fpr);
450
DFGEN32(gen_op_store_fpr_DT2, gen_op_store_fpr_DT2_fpr);
451

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

    
476
FOP_CONDS(d)
477
FOP_CONDS(s)
478

    
479
#endif /* MIPS_USES_FPU */
480

    
481
typedef struct DisasContext {
482
    struct TranslationBlock *tb;
483
    target_ulong pc, saved_pc;
484
    uint32_t opcode;
485
    /* Routine used to access memory */
486
    int mem_idx;
487
    uint32_t hflags, saved_hflags;
488
    uint32_t CP0_Status;
489
    int bstate;
490
    target_ulong btarget;
491
} DisasContext;
492

    
493
enum {
494
    BS_NONE     = 0, /* We go out of the TB without reaching a branch or an
495
                      * exception condition
496
                      */
497
    BS_STOP     = 1, /* We want to stop translation for any reason */
498
    BS_BRANCH   = 2, /* We reached a branch condition     */
499
    BS_EXCP     = 3, /* We reached an exception condition */
500
};
501

    
502
#if defined MIPS_DEBUG_DISAS
503
#define MIPS_DEBUG(fmt, args...)                                              \
504
do {                                                                          \
505
    if (loglevel & CPU_LOG_TB_IN_ASM) {                                       \
506
        fprintf(logfile, TARGET_FMT_lx ": %08x " fmt "\n",                    \
507
                ctx->pc, ctx->opcode , ##args);                               \
508
    }                                                                         \
509
} while (0)
510
#else
511
#define MIPS_DEBUG(fmt, args...) do { } while(0)
512
#endif
513

    
514
#define MIPS_INVAL(op)                                                        \
515
do {                                                                          \
516
    MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26,            \
517
               ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F));             \
518
} while (0)
519

    
520
#define GEN_LOAD_REG_TN(Tn, Rn)                                               \
521
do {                                                                          \
522
    if (Rn == 0) {                                                            \
523
        glue(gen_op_reset_, Tn)();                                            \
524
    } else {                                                                  \
525
        glue(gen_op_load_gpr_, Tn)(Rn);                                       \
526
    }                                                                         \
527
} while (0)
528

    
529
#define GEN_LOAD_IMM_TN(Tn, Imm)                                              \
530
do {                                                                          \
531
    if (Imm == 0) {                                                           \
532
        glue(gen_op_reset_, Tn)();                                            \
533
    } else {                                                                  \
534
        glue(gen_op_set_, Tn)(Imm);                                           \
535
    }                                                                         \
536
} while (0)
537

    
538
#define GEN_STORE_TN_REG(Rn, Tn)                                              \
539
do {                                                                          \
540
    if (Rn != 0) {                                                            \
541
        glue(glue(gen_op_store_, Tn),_gpr)(Rn);                               \
542
    }                                                                         \
543
} while (0)
544

    
545
#define GEN_LOAD_FREG_FTN(FTn, Fn)                                            \
546
do {                                                                          \
547
    glue(gen_op_load_fpr_, FTn)(Fn);                                          \
548
} while (0)
549

    
550
#define GEN_STORE_FTN_FREG(Fn, FTn)                                           \
551
do {                                                                          \
552
    glue(gen_op_store_fpr_, FTn)(Fn);                                         \
553
} while (0)
554

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

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

    
595
static inline void generate_exception (DisasContext *ctx, int excp)
596
{
597
    generate_exception_err (ctx, excp, 0);
598
}
599

    
600
#if defined(CONFIG_USER_ONLY)
601
#define op_ldst(name)        gen_op_##name##_raw()
602
#define OP_LD_TABLE(width)
603
#define OP_ST_TABLE(width)
604
#else
605
#define op_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
606
#define OP_LD_TABLE(width)                                                    \
607
static GenOpFunc *gen_op_l##width[] = {                                       \
608
    &gen_op_l##width##_user,                                                  \
609
    &gen_op_l##width##_kernel,                                                \
610
}
611
#define OP_ST_TABLE(width)                                                    \
612
static GenOpFunc *gen_op_s##width[] = {                                       \
613
    &gen_op_s##width##_user,                                                  \
614
    &gen_op_s##width##_kernel,                                                \
615
}
616
#endif
617

    
618
#ifdef MIPS_HAS_MIPS64
619
OP_LD_TABLE(d);
620
OP_LD_TABLE(dl);
621
OP_LD_TABLE(dr);
622
OP_ST_TABLE(d);
623
OP_ST_TABLE(dl);
624
OP_ST_TABLE(dr);
625
OP_LD_TABLE(ld);
626
OP_ST_TABLE(cd);
627
#endif
628
OP_LD_TABLE(w);
629
OP_LD_TABLE(wu);
630
OP_LD_TABLE(wl);
631
OP_LD_TABLE(wr);
632
OP_ST_TABLE(w);
633
OP_ST_TABLE(wl);
634
OP_ST_TABLE(wr);
635
OP_LD_TABLE(h);
636
OP_LD_TABLE(hu);
637
OP_ST_TABLE(h);
638
OP_LD_TABLE(b);
639
OP_LD_TABLE(bu);
640
OP_ST_TABLE(b);
641
OP_LD_TABLE(l);
642
OP_ST_TABLE(c);
643
#ifdef MIPS_USES_FPU
644
OP_LD_TABLE(wc1);
645
OP_ST_TABLE(wc1);
646
OP_LD_TABLE(dc1);
647
OP_ST_TABLE(dc1);
648
#endif
649

    
650
/* Load and store */
651
static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
652
                      int base, int16_t offset)
653
{
654
    const char *opn = "unk";
655

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

    
797
#ifdef MIPS_USES_FPU
798

    
799
/* Load and store */
800
static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
801
                      int base, int16_t offset)
802
{
803
    const char *opn = "unk";
804

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

    
846
#endif /* MIPS_USES_FPU */
847

    
848
/* Arithmetic with immediate operand */
849
static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt,
850
                           int rs, int16_t imm)
851
{
852
    uint32_t uimm;
853
    const char *opn = "unk";
854

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

    
981
/* Arithmetic */
982
static void gen_arith (DisasContext *ctx, uint32_t opc,
983
                       int rd, int rs, int rt)
984
{
985
    const char *opn = "unk";
986

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

    
1118
/* Arithmetic on HI/LO registers */
1119
static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1120
{
1121
    const char *opn = "unk";
1122

    
1123
    if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1124
        /* Treat as a NOP */
1125
        MIPS_DEBUG("NOP");
1126
        return;
1127
    }
1128
    switch (opc) {
1129
    case OPC_MFHI:
1130
        gen_op_load_HI();
1131
        GEN_STORE_TN_REG(reg, T0);
1132
        opn = "mfhi";
1133
        break;
1134
    case OPC_MFLO:
1135
        gen_op_load_LO();
1136
        GEN_STORE_TN_REG(reg, T0);
1137
        opn = "mflo";
1138
        break;
1139
    case OPC_MTHI:
1140
        GEN_LOAD_REG_TN(T0, reg);
1141
        gen_op_store_HI();
1142
        opn = "mthi";
1143
        break;
1144
    case OPC_MTLO:
1145
        GEN_LOAD_REG_TN(T0, reg);
1146
        gen_op_store_LO();
1147
        opn = "mtlo";
1148
        break;
1149
    default:
1150
        MIPS_INVAL("HILO");
1151
        generate_exception(ctx, EXCP_RI);
1152
        return;
1153
    }
1154
    MIPS_DEBUG("%s %s", opn, regnames[reg]);
1155
}
1156

    
1157
static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1158
                        int rs, int rt)
1159
{
1160
    const char *opn = "unk";
1161

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

    
1223
static void gen_cl (DisasContext *ctx, uint32_t opc,
1224
                    int rd, int rs)
1225
{
1226
    const char *opn = "unk";
1227
    if (rd == 0) {
1228
        /* Treat as a NOP */
1229
        MIPS_DEBUG("NOP");
1230
        return;
1231
    }
1232
    GEN_LOAD_REG_TN(T0, rs);
1233
    switch (opc) {
1234
    case OPC_CLO:
1235
        gen_op_clo();
1236
        opn = "clo";
1237
        break;
1238
    case OPC_CLZ:
1239
        gen_op_clz();
1240
        opn = "clz";
1241
        break;
1242
#ifdef MIPS_HAS_MIPS64
1243
    case OPC_DCLO:
1244
        gen_op_dclo();
1245
        opn = "dclo";
1246
        break;
1247
    case OPC_DCLZ:
1248
        gen_op_dclz();
1249
        opn = "dclz";
1250
        break;
1251
#endif
1252
    default:
1253
        MIPS_INVAL("CLx");
1254
        generate_exception(ctx, EXCP_RI);
1255
        return;
1256
    }
1257
    gen_op_store_T0_gpr(rd);
1258
    MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
1259
}
1260

    
1261
/* Traps */
1262
static void gen_trap (DisasContext *ctx, uint32_t opc,
1263
                      int rs, int rt, int16_t imm)
1264
{
1265
    int cond;
1266

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

    
1358
static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
1359
{
1360
    TranslationBlock *tb;
1361
    tb = ctx->tb;
1362
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
1363
        if (n == 0)
1364
            gen_op_goto_tb0(TBPARAM(tb));
1365
        else
1366
            gen_op_goto_tb1(TBPARAM(tb));
1367
        gen_op_save_pc(dest);
1368
        gen_op_set_T0((long)tb + n);
1369
        gen_op_exit_tb();
1370
    } else {
1371
        gen_op_save_pc(dest);
1372
        gen_op_set_T0(0);
1373
        gen_op_exit_tb();
1374
    }
1375
}
1376

    
1377
/* Branches (before delay slot) */
1378
static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
1379
                                int rs, int rt, int32_t offset)
1380
{
1381
    target_ulong btarget;
1382
    int blink, bcond;
1383

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

    
1597
/* special3 bitfield operations */
1598
static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
1599
                       int rs, int lsb, int msb)
1600
{
1601
    GEN_LOAD_REG_TN(T1, rs);
1602
    switch (opc) {
1603
    case OPC_EXT:
1604
        if (lsb + msb > 31)
1605
            goto fail;
1606
        gen_op_ext(lsb, msb + 1);
1607
        break;
1608
    case OPC_DEXTM:
1609
        if (lsb + msb > 63)
1610
            goto fail;
1611
        gen_op_ext(lsb, msb + 1 + 32);
1612
        break;
1613
    case OPC_DEXTU:
1614
        if (lsb + msb > 63)
1615
            goto fail;
1616
        gen_op_ext(lsb + 32, msb + 1);
1617
        break;
1618
    case OPC_DEXT:
1619
        gen_op_ext(lsb, msb + 1);
1620
        break;
1621
    case OPC_INS:
1622
        if (lsb > msb)
1623
            goto fail;
1624
        GEN_LOAD_REG_TN(T2, rt);
1625
        gen_op_ins(lsb, msb - lsb + 1);
1626
        break;
1627
    case OPC_DINSM:
1628
        if (lsb > msb)
1629
            goto fail;
1630
        GEN_LOAD_REG_TN(T2, rt);
1631
        gen_op_ins(lsb, msb - lsb + 1 + 32);
1632
        break;
1633
    case OPC_DINSU:
1634
        if (lsb > msb)
1635
            goto fail;
1636
        GEN_LOAD_REG_TN(T2, rt);
1637
        gen_op_ins(lsb + 32, msb - lsb + 1);
1638
        break;
1639
    case OPC_DINS:
1640
        if (lsb > msb)
1641
            goto fail;
1642
        GEN_LOAD_REG_TN(T2, rt);
1643
        gen_op_ins(lsb, msb - lsb + 1);
1644
        break;
1645
    default:
1646
fail:
1647
        MIPS_INVAL("bitops");
1648
        generate_exception(ctx, EXCP_RI);
1649
        return;
1650
    }
1651
    GEN_STORE_TN_REG(rt, T0);
1652
}
1653

    
1654
/* CP0 (MMU and control) */
1655
static void gen_mfc0 (DisasContext *ctx, int reg, int sel)
1656
{
1657
    const char *rn = "invalid";
1658

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

    
2227
die:
2228
#if defined MIPS_DEBUG_DISAS
2229
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2230
        fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
2231
                rn, reg, sel);
2232
    }
2233
#endif
2234
    generate_exception(ctx, EXCP_RI);
2235
}
2236

    
2237
static void gen_mtc0 (DisasContext *ctx, int reg, int sel)
2238
{
2239
    const char *rn = "invalid";
2240

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

    
2820
die:
2821
#if defined MIPS_DEBUG_DISAS
2822
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2823
        fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
2824
                rn, reg, sel);
2825
    }
2826
#endif
2827
    generate_exception(ctx, EXCP_RI);
2828
}
2829

    
2830
static void gen_dmfc0 (DisasContext *ctx, int reg, int sel)
2831
{
2832
    const char *rn = "invalid";
2833

    
2834
    switch (reg) {
2835
    case 0:
2836
        switch (sel) {
2837
        case 0:
2838
           gen_op_mfc0_index();
2839
            rn = "Index";
2840
            break;
2841
        case 1:
2842
//         gen_op_dmfc0_mvpcontrol(); /* MT ASE */
2843
            rn = "MVPControl";
2844
//         break;
2845
        case 2:
2846
//         gen_op_dmfc0_mvpconf0(); /* MT ASE */
2847
            rn = "MVPConf0";
2848
//         break;
2849
        case 3:
2850
//         gen_op_dmfc0_mvpconf1(); /* MT ASE */
2851
            rn = "MVPConf1";
2852
//         break;
2853
        default:
2854
            goto die;
2855
        }
2856
        break;
2857
    case 1:
2858
        switch (sel) {
2859
        case 0:
2860
            gen_op_mfc0_random();
2861
            rn = "Random";
2862
           break;
2863
        case 1:
2864
//         gen_op_dmfc0_vpecontrol(); /* MT ASE */
2865
            rn = "VPEControl";
2866
//         break;
2867
        case 2:
2868
//         gen_op_dmfc0_vpeconf0(); /* MT ASE */
2869
            rn = "VPEConf0";
2870
//         break;
2871
        case 3:
2872
//         gen_op_dmfc0_vpeconf1(); /* MT ASE */
2873
            rn = "VPEConf1";
2874
//         break;
2875
        case 4:
2876
//         gen_op_dmfc0_YQMask(); /* MT ASE */
2877
            rn = "YQMask";
2878
//         break;
2879
        case 5:
2880
//         gen_op_dmfc0_vpeschedule(); /* MT ASE */
2881
            rn = "VPESchedule";
2882
//         break;
2883
        case 6:
2884
//         gen_op_dmfc0_vpeschefback(); /* MT ASE */
2885
            rn = "VPEScheFBack";
2886
//         break;
2887
        case 7:
2888
//         gen_op_dmfc0_vpeopt(); /* MT ASE */
2889
            rn = "VPEOpt";
2890
//         break;
2891
        default:
2892
            goto die;
2893
        }
2894
        break;
2895
    case 2:
2896
        switch (sel) {
2897
        case 0:
2898
           gen_op_dmfc0_entrylo0();
2899
           rn = "EntryLo0";
2900
           break;
2901
        case 1:
2902
//         gen_op_dmfc0_tcstatus(); /* MT ASE */
2903
           rn = "TCStatus";
2904
//         break;
2905
        case 2:
2906
//         gen_op_dmfc0_tcbind(); /* MT ASE */
2907
           rn = "TCBind";
2908
//         break;
2909
        case 3:
2910
//         gen_op_dmfc0_tcrestart(); /* MT ASE */
2911
           rn = "TCRestart";
2912
//         break;
2913
        case 4:
2914
//         gen_op_dmfc0_tchalt(); /* MT ASE */
2915
           rn = "TCHalt";
2916
//         break;
2917
        case 5:
2918
//         gen_op_dmfc0_tccontext(); /* MT ASE */
2919
           rn = "TCContext";
2920
//         break;
2921
        case 6:
2922
//         gen_op_dmfc0_tcschedule(); /* MT ASE */
2923
           rn = "TCSchedule";
2924
//         break;
2925
        case 7:
2926
//         gen_op_dmfc0_tcschefback(); /* MT ASE */
2927
           rn = "TCScheFBack";
2928
//         break;
2929
        default:
2930
            goto die;
2931
        }
2932
        break;
2933
    case 3:
2934
        switch (sel) {
2935
        case 0:
2936
           gen_op_dmfc0_entrylo1();
2937
           rn = "EntryLo1";
2938
           break;
2939
        default:
2940
            goto die;
2941
       }
2942
        break;
2943
    case 4:
2944
        switch (sel) {
2945
        case 0:
2946
           gen_op_dmfc0_context();
2947
           rn = "Context";
2948
           break;
2949
        case 1:
2950
//         gen_op_dmfc0_contextconfig(); /* SmartMIPS ASE */
2951
           rn = "ContextConfig";
2952
//         break;
2953
        default:
2954
            goto die;
2955
       }
2956
        break;
2957
    case 5:
2958
        switch (sel) {
2959
        case 0:
2960
           gen_op_mfc0_pagemask();
2961
           rn = "PageMask";
2962
           break;
2963
        case 1:
2964
           gen_op_mfc0_pagegrain();
2965
           rn = "PageGrain";
2966
           break;
2967
        default:
2968
            goto die;
2969
       }
2970
        break;
2971
    case 6:
2972
        switch (sel) {
2973
        case 0:
2974
           gen_op_mfc0_wired();
2975
           rn = "Wired";
2976
           break;
2977
        case 1:
2978
//         gen_op_dmfc0_srsconf0(); /* shadow registers */
2979
           rn = "SRSConf0";
2980
//         break;
2981
        case 2:
2982
//         gen_op_dmfc0_srsconf1(); /* shadow registers */
2983
           rn = "SRSConf1";
2984
//         break;
2985
        case 3:
2986
//         gen_op_dmfc0_srsconf2(); /* shadow registers */
2987
           rn = "SRSConf2";
2988
//         break;
2989
        case 4:
2990
//         gen_op_dmfc0_srsconf3(); /* shadow registers */
2991
           rn = "SRSConf3";
2992
//         break;
2993
        case 5:
2994
//         gen_op_dmfc0_srsconf4(); /* shadow registers */
2995
           rn = "SRSConf4";
2996
//         break;
2997
        default:
2998
            goto die;
2999
       }
3000
        break;
3001
    case 7:
3002
        switch (sel) {
3003
        case 0:
3004
           gen_op_mfc0_hwrena();
3005
           rn = "HWREna";
3006
           break;
3007
        default:
3008
            goto die;
3009
       }
3010
        break;
3011
    case 8:
3012
        switch (sel) {
3013
        case 0:
3014
           gen_op_dmfc0_badvaddr();
3015
           rn = "BadVaddr";
3016
           break;
3017
        default:
3018
            goto die;
3019
       }
3020
        break;
3021
    case 9:
3022
        switch (sel) {
3023
        case 0:
3024
           gen_op_mfc0_count();
3025
           rn = "Count";
3026
           break;
3027
       /* 6,7 are implementation dependent */
3028
        default:
3029
            goto die;
3030
       }
3031
        break;
3032
    case 10:
3033
        switch (sel) {
3034
        case 0:
3035
           gen_op_dmfc0_entryhi();
3036
           rn = "EntryHi";
3037
           break;
3038
        default:
3039
            goto die;
3040
       }
3041
        break;
3042
    case 11:
3043
        switch (sel) {
3044
        case 0:
3045
           gen_op_mfc0_compare();
3046
           rn = "Compare";
3047
           break;
3048
       /* 6,7 are implementation dependent */
3049
        default:
3050
            goto die;
3051
       }
3052
        break;
3053
    case 12:
3054
        switch (sel) {
3055
        case 0:
3056
           gen_op_mfc0_status();
3057
           rn = "Status";
3058
           break;
3059
        case 1:
3060
           gen_op_mfc0_intctl();
3061
           rn = "IntCtl";
3062
           break;
3063
        case 2:
3064
           gen_op_mfc0_srsctl();
3065
           rn = "SRSCtl";
3066
           break;
3067
        case 3:
3068
           gen_op_mfc0_srsmap(); /* shadow registers */
3069
           rn = "SRSMap";
3070
           break;
3071
        default:
3072
            goto die;
3073
       }
3074
        break;
3075
    case 13:
3076
        switch (sel) {
3077
        case 0:
3078
           gen_op_mfc0_cause();
3079
           rn = "Cause";
3080
           break;
3081
        default:
3082
            goto die;
3083
       }
3084
        break;
3085
    case 14:
3086
        switch (sel) {
3087
        case 0:
3088
           gen_op_dmfc0_epc();
3089
           rn = "EPC";
3090
           break;
3091
        default:
3092
            goto die;
3093
       }
3094
        break;
3095
    case 15:
3096
        switch (sel) {
3097
        case 0:
3098
           gen_op_mfc0_prid();
3099
           rn = "PRid";
3100
           break;
3101
        case 1:
3102
           gen_op_mfc0_ebase();
3103
           rn = "EBase";
3104
           break;
3105
        default:
3106
            goto die;
3107
       }
3108
        break;
3109
    case 16:
3110
        switch (sel) {
3111
        case 0:
3112
           gen_op_mfc0_config0();
3113
            rn = "Config";
3114
            break;
3115
        case 1:
3116
           gen_op_mfc0_config1();
3117
            rn = "Config1";
3118
            break;
3119
        case 2:
3120
           gen_op_mfc0_config2();
3121
            rn = "Config2";
3122
            break;
3123
        case 3:
3124
           gen_op_mfc0_config3();
3125
            rn = "Config3";
3126
            break;
3127
       /* 6,7 are implementation dependent */
3128
        default:
3129
            goto die;
3130
        }
3131
        break;
3132
    case 17:
3133
        switch (sel) {
3134
        case 0:
3135
           gen_op_dmfc0_lladdr();
3136
           rn = "LLAddr";
3137
           break;
3138
        default:
3139
            goto die;
3140
        }
3141
        break;
3142
    case 18:
3143
        switch (sel) {
3144
        case 0:
3145
           gen_op_dmfc0_watchlo0();
3146
           rn = "WatchLo";
3147
           break;
3148
        case 1:
3149
//         gen_op_dmfc0_watchlo1();
3150
           rn = "WatchLo1";
3151
//         break;
3152
        case 2:
3153
//         gen_op_dmfc0_watchlo2();
3154
           rn = "WatchLo2";
3155
//         break;
3156
        case 3:
3157
//         gen_op_dmfc0_watchlo3();
3158
           rn = "WatchLo3";
3159
//         break;
3160
        case 4:
3161
//         gen_op_dmfc0_watchlo4();
3162
           rn = "WatchLo4";
3163
//         break;
3164
        case 5:
3165
//         gen_op_dmfc0_watchlo5();
3166
           rn = "WatchLo5";
3167
//         break;
3168
        case 6:
3169
//         gen_op_dmfc0_watchlo6();
3170
           rn = "WatchLo6";
3171
//         break;
3172
        case 7:
3173
//         gen_op_dmfc0_watchlo7();
3174
           rn = "WatchLo7";
3175
//         break;
3176
        default:
3177
            goto die;
3178
        }
3179
        break;
3180
    case 19:
3181
        switch (sel) {
3182
        case 0:
3183
           gen_op_mfc0_watchhi0();
3184
           rn = "WatchHi";
3185
           break;
3186
        case 1:
3187
//         gen_op_mfc0_watchhi1();
3188
           rn = "WatchHi1";
3189
//         break;
3190
        case 2:
3191
//         gen_op_mfc0_watchhi2();
3192
           rn = "WatchHi2";
3193
//         break;
3194
        case 3:
3195
//         gen_op_mfc0_watchhi3();
3196
           rn = "WatchHi3";
3197
//         break;
3198
        case 4:
3199
//         gen_op_mfc0_watchhi4();
3200
           rn = "WatchHi4";
3201
//         break;
3202
        case 5:
3203
//         gen_op_mfc0_watchhi5();
3204
           rn = "WatchHi5";
3205
//         break;
3206
        case 6:
3207
//         gen_op_mfc0_watchhi6();
3208
           rn = "WatchHi6";
3209
//         break;
3210
        case 7:
3211
//         gen_op_mfc0_watchhi7();
3212
           rn = "WatchHi7";
3213
//         break;
3214
        default:
3215
            goto die;
3216
        }
3217
        break;
3218
    case 20:
3219
        switch (sel) {
3220
        case 0:
3221
           /* 64 bit MMU only */
3222
           gen_op_dmfc0_xcontext();
3223
           rn = "XContext";
3224
           break;
3225
        default:
3226
            goto die;
3227
        }
3228
        break;
3229
    case 21:
3230
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
3231
        switch (sel) {
3232
        case 0:
3233
           gen_op_mfc0_framemask();
3234
           rn = "Framemask";
3235
           break;
3236
        default:
3237
            goto die;
3238
        }
3239
        break;
3240
    case 22:
3241
       /* ignored */
3242
       rn = "'Diagnostic"; /* implementation dependent */
3243
       break;
3244
    case 23:
3245
        switch (sel) {
3246
        case 0:
3247
           gen_op_mfc0_debug(); /* EJTAG support */
3248
           rn = "Debug";
3249
           break;
3250
        case 1:
3251
//         gen_op_dmfc0_tracecontrol(); /* PDtrace support */
3252
           rn = "TraceControl";
3253
//         break;
3254
        case 2:
3255
//         gen_op_dmfc0_tracecontrol2(); /* PDtrace support */
3256
           rn = "TraceControl2";
3257
//         break;
3258
        case 3:
3259
//         gen_op_dmfc0_usertracedata(); /* PDtrace support */
3260
           rn = "UserTraceData";
3261
//         break;
3262
        case 4:
3263
//         gen_op_dmfc0_debug(); /* PDtrace support */
3264
           rn = "TraceBPC";
3265
//         break;
3266
        default:
3267
            goto die;
3268
        }
3269
        break;
3270
    case 24:
3271
        switch (sel) {
3272
        case 0:
3273
           gen_op_dmfc0_depc(); /* EJTAG support */
3274
           rn = "DEPC";
3275
           break;
3276
        default:
3277
            goto die;
3278
        }
3279
        break;
3280
    case 25:
3281
        switch (sel) {
3282
        case 0:
3283
           gen_op_mfc0_performance0();
3284
           rn = "Performance0";
3285
            break;
3286
        case 1:
3287
//         gen_op_dmfc0_performance1();
3288
           rn = "Performance1";
3289
//         break;
3290
        case 2:
3291
//         gen_op_dmfc0_performance2();
3292
           rn = "Performance2";
3293
//         break;
3294
        case 3:
3295
//         gen_op_dmfc0_performance3();
3296
           rn = "Performance3";
3297
//         break;
3298
        case 4:
3299
//         gen_op_dmfc0_performance4();
3300
           rn = "Performance4";
3301
//         break;
3302
        case 5:
3303
//         gen_op_dmfc0_performance5();
3304
           rn = "Performance5";
3305
//         break;
3306
        case 6:
3307
//         gen_op_dmfc0_performance6();
3308
           rn = "Performance6";
3309
//         break;
3310
        case 7:
3311
//         gen_op_dmfc0_performance7();
3312
           rn = "Performance7";
3313
//         break;
3314
        default:
3315
            goto die;
3316
        }
3317
        break;
3318
    case 26:
3319
       rn = "ECC";
3320
       break;
3321
    case 27:
3322
        switch (sel) {
3323
        /* ignored */
3324
        case 0 ... 3:
3325
           rn = "CacheErr";
3326
           break;
3327
        default:
3328
            goto die;
3329
        }
3330
        break;
3331
    case 28:
3332
        switch (sel) {
3333
        case 0:
3334
        case 2:
3335
        case 4:
3336
        case 6:
3337
            gen_op_mfc0_taglo();
3338
            rn = "TagLo";
3339
            break;
3340
        case 1:
3341
        case 3:
3342
        case 5:
3343
        case 7:
3344
            gen_op_mfc0_datalo();
3345
            rn = "DataLo";
3346
            break;
3347
        default:
3348
            goto die;
3349
        }
3350
        break;
3351
    case 29:
3352
        switch (sel) {
3353
        case 0:
3354
        case 2:
3355
        case 4:
3356
        case 6:
3357
            gen_op_mfc0_taghi();
3358
            rn = "TagHi";
3359
            break;
3360
        case 1:
3361
        case 3:
3362
        case 5:
3363
        case 7:
3364
            gen_op_mfc0_datahi();
3365
            rn = "DataHi";
3366
            break;
3367
        default:
3368
            goto die;
3369
        }
3370
        break;
3371
    case 30:
3372
        switch (sel) {
3373
        case 0:
3374
           gen_op_dmfc0_errorepc();
3375
           rn = "ErrorEPC";
3376
           break;
3377
        default:
3378
            goto die;
3379
        }
3380
        break;
3381
    case 31:
3382
        switch (sel) {
3383
        case 0:
3384
           gen_op_mfc0_desave(); /* EJTAG support */
3385
           rn = "DESAVE";
3386
           break;
3387
        default:
3388
            goto die;
3389
        }
3390
        break;
3391
    default:
3392
       goto die;
3393
    }
3394
#if defined MIPS_DEBUG_DISAS
3395
    if (loglevel & CPU_LOG_TB_IN_ASM) {
3396
        fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
3397
                rn, reg, sel);
3398
    }
3399
#endif
3400
    return;
3401

    
3402
die:
3403
#if defined MIPS_DEBUG_DISAS
3404
    if (loglevel & CPU_LOG_TB_IN_ASM) {
3405
        fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
3406
                rn, reg, sel);
3407
    }
3408
#endif
3409
    generate_exception(ctx, EXCP_RI);
3410
}
3411

    
3412
static void gen_dmtc0 (DisasContext *ctx, int reg, int sel)
3413
{
3414
    const char *rn = "invalid";
3415

    
3416
    switch (reg) {
3417
    case 0:
3418
        switch (sel) {
3419
        case 0:
3420
            gen_op_mtc0_index();
3421
            rn = "Index";
3422
            break;
3423
        case 1:
3424
//         gen_op_dmtc0_mvpcontrol(); /* MT ASE */
3425
            rn = "MVPControl";
3426
//         break;
3427
        case 2:
3428
//         gen_op_dmtc0_mvpconf0(); /* MT ASE */
3429
            rn = "MVPConf0";
3430
//         break;
3431
        case 3:
3432
//         gen_op_dmtc0_mvpconf1(); /* MT ASE */
3433
            rn = "MVPConf1";
3434
//         break;
3435
        default:
3436
            goto die;
3437
        }
3438
        break;
3439
    case 1:
3440
        switch (sel) {
3441
        case 0:
3442
           /* ignored */
3443
            rn = "Random";
3444
           break;
3445
        case 1:
3446
//         gen_op_dmtc0_vpecontrol(); /* MT ASE */
3447
            rn = "VPEControl";
3448
//         break;
3449
        case 2:
3450
//         gen_op_dmtc0_vpeconf0(); /* MT ASE */
3451
            rn = "VPEConf0";
3452
//         break;
3453
        case 3:
3454
//         gen_op_dmtc0_vpeconf1(); /* MT ASE */
3455
            rn = "VPEConf1";
3456
//         break;
3457
        case 4:
3458
//         gen_op_dmtc0_YQMask(); /* MT ASE */
3459
            rn = "YQMask";
3460
//         break;
3461
        case 5:
3462
//         gen_op_dmtc0_vpeschedule(); /* MT ASE */
3463
            rn = "VPESchedule";
3464
//         break;
3465
        case 6:
3466
//         gen_op_dmtc0_vpeschefback(); /* MT ASE */
3467
            rn = "VPEScheFBack";
3468
//         break;
3469
        case 7:
3470
//         gen_op_dmtc0_vpeopt(); /* MT ASE */
3471
            rn = "VPEOpt";
3472
//         break;
3473
        default:
3474
            goto die;
3475
        }
3476
        break;
3477
    case 2:
3478
        switch (sel) {
3479
        case 0:
3480
           gen_op_dmtc0_entrylo0();
3481
           rn = "EntryLo0";
3482
           break;
3483
        case 1:
3484
//         gen_op_dmtc0_tcstatus(); /* MT ASE */
3485
           rn = "TCStatus";
3486
//         break;
3487
        case 2:
3488
//         gen_op_dmtc0_tcbind(); /* MT ASE */
3489
           rn = "TCBind";
3490
//         break;
3491
        case 3:
3492
//         gen_op_dmtc0_tcrestart(); /* MT ASE */
3493
           rn = "TCRestart";
3494
//         break;
3495
        case 4:
3496
//         gen_op_dmtc0_tchalt(); /* MT ASE */
3497
           rn = "TCHalt";
3498
//         break;
3499
        case 5:
3500
//         gen_op_dmtc0_tccontext(); /* MT ASE */
3501
           rn = "TCContext";
3502
//         break;
3503
        case 6:
3504
//         gen_op_dmtc0_tcschedule(); /* MT ASE */
3505
           rn = "TCSchedule";
3506
//         break;
3507
        case 7:
3508
//         gen_op_dmtc0_tcschefback(); /* MT ASE */
3509
           rn = "TCScheFBack";
3510
//         break;
3511
        default:
3512
            goto die;
3513
        }
3514
        break;
3515
    case 3:
3516
        switch (sel) {
3517
        case 0:
3518
           gen_op_dmtc0_entrylo1();
3519
           rn = "EntryLo1";
3520
           break;
3521
        default:
3522
            goto die;
3523
       }
3524
        break;
3525
    case 4:
3526
        switch (sel) {
3527
        case 0:
3528
           gen_op_dmtc0_context();
3529
           rn = "Context";
3530
           break;
3531
        case 1:
3532
//         gen_op_dmtc0_contextconfig(); /* SmartMIPS ASE */
3533
           rn = "ContextConfig";
3534
//         break;
3535
        default:
3536
            goto die;
3537
       }
3538
        break;
3539
    case 5:
3540
        switch (sel) {
3541
        case 0:
3542
           gen_op_mtc0_pagemask();
3543
           rn = "PageMask";
3544
           break;
3545
        case 1:
3546
           gen_op_mtc0_pagegrain();
3547
           rn = "PageGrain";
3548
           break;
3549
        default:
3550
            goto die;
3551
       }
3552
        break;
3553
    case 6:
3554
        switch (sel) {
3555
        case 0:
3556
           gen_op_mtc0_wired();
3557
           rn = "Wired";
3558
           break;
3559
        case 1:
3560
//         gen_op_dmtc0_srsconf0(); /* shadow registers */
3561
           rn = "SRSConf0";
3562
//         break;
3563
        case 2:
3564
//         gen_op_dmtc0_srsconf1(); /* shadow registers */
3565
           rn = "SRSConf1";
3566
//         break;
3567
        case 3:
3568
//         gen_op_dmtc0_srsconf2(); /* shadow registers */
3569
           rn = "SRSConf2";
3570
//         break;
3571
        case 4:
3572
//         gen_op_dmtc0_srsconf3(); /* shadow registers */
3573
           rn = "SRSConf3";
3574
//         break;
3575
        case 5:
3576
//         gen_op_dmtc0_srsconf4(); /* shadow registers */
3577
           rn = "SRSConf4";
3578
//         break;
3579
        default:
3580
            goto die;
3581
       }
3582
        break;
3583
    case 7:
3584
        switch (sel) {
3585
        case 0:
3586
           gen_op_mtc0_hwrena();
3587
           rn = "HWREna";
3588
           break;
3589
        default:
3590
            goto die;
3591
       }
3592
        break;
3593
    case 8:
3594
        /* ignored */
3595
        rn = "BadVaddr";
3596
        break;
3597
    case 9:
3598
        switch (sel) {
3599
        case 0:
3600
           gen_op_mtc0_count();
3601
           rn = "Count";
3602
           break;
3603
       /* 6,7 are implementation dependent */
3604
        default:
3605
            goto die;
3606
       }
3607
       /* Stop translation as we may have switched the execution mode */
3608
       ctx->bstate = BS_STOP;
3609
        break;
3610
    case 10:
3611
        switch (sel) {
3612
        case 0:
3613
           gen_op_mtc0_entryhi();
3614
           rn = "EntryHi";
3615
           break;
3616
        default:
3617
            goto die;
3618
       }
3619
        break;
3620
    case 11:
3621
        switch (sel) {
3622
        case 0:
3623
           gen_op_mtc0_compare();
3624
           rn = "Compare";
3625
           break;
3626
       /* 6,7 are implementation dependent */
3627
        default:
3628
            goto die;
3629
       }
3630
       /* Stop translation as we may have switched the execution mode */
3631
       ctx->bstate = BS_STOP;
3632
        break;
3633
    case 12:
3634
        switch (sel) {
3635
        case 0:
3636
           gen_op_mtc0_status();
3637
           rn = "Status";
3638
           break;
3639
        case 1:
3640
           gen_op_mtc0_intctl();
3641
           rn = "IntCtl";
3642
           break;
3643
        case 2:
3644
           gen_op_mtc0_srsctl();
3645
           rn = "SRSCtl";
3646
           break;
3647
        case 3:
3648
         gen_op_mtc0_srsmap(); /* shadow registers */
3649
           rn = "SRSMap";
3650
         break;
3651
        default:
3652
            goto die;
3653
       }
3654
       /* Stop translation as we may have switched the execution mode */
3655
       ctx->bstate = BS_STOP;
3656
        break;
3657
    case 13:
3658
        switch (sel) {
3659
        case 0:
3660
           gen_op_mtc0_cause();
3661
           rn = "Cause";
3662
           break;
3663
        default:
3664
            goto die;
3665
       }
3666
       /* Stop translation as we may have switched the execution mode */
3667
       ctx->bstate = BS_STOP;
3668
        break;
3669
    case 14:
3670
        switch (sel) {
3671
        case 0:
3672
           gen_op_dmtc0_epc();
3673
           rn = "EPC";
3674
           break;
3675
        default:
3676
            goto die;
3677
       }
3678
        break;
3679
    case 15:
3680
        switch (sel) {
3681
        case 0:
3682
           /* ignored */
3683
           rn = "PRid";
3684
           break;
3685
        case 1:
3686
           gen_op_mtc0_ebase();
3687
           rn = "EBase";
3688
           break;
3689
        default:
3690
            goto die;
3691
       }
3692
        break;
3693
    case 16:
3694
        switch (sel) {
3695
        case 0:
3696
            gen_op_mtc0_config0();
3697
            rn = "Config";
3698
            break;
3699
        case 1:
3700
           /* ignored */
3701
            rn = "Config1";
3702
            break;
3703
        case 2:
3704
            gen_op_mtc0_config2();
3705
            rn = "Config2";
3706
            break;
3707
        case 3:
3708
           /* ignored */
3709
            rn = "Config3";
3710
            break;
3711
        /* 6,7 are implementation dependent */
3712
        default:
3713
            rn = "Invalid config selector";
3714
            goto die;
3715
        }
3716
        /* Stop translation as we may have switched the execution mode */
3717
        ctx->bstate = BS_STOP;
3718
        break;
3719
    case 17:
3720
        switch (sel) {
3721
        case 0:
3722
           /* ignored */
3723
           rn = "LLAddr";
3724
           break;
3725
        default:
3726
            goto die;
3727
        }
3728
        break;
3729
    case 18:
3730
        switch (sel) {
3731
        case 0:
3732
           gen_op_dmtc0_watchlo0();
3733
           rn = "WatchLo";
3734
           break;
3735
        case 1:
3736
//         gen_op_dmtc0_watchlo1();
3737
           rn = "WatchLo1";
3738
//         break;
3739
        case 2:
3740
//         gen_op_dmtc0_watchlo2();
3741
           rn = "WatchLo2";
3742
//         break;
3743
        case 3:
3744
//         gen_op_dmtc0_watchlo3();
3745
           rn = "WatchLo3";
3746
//         break;
3747
        case 4:
3748
//         gen_op_dmtc0_watchlo4();
3749
           rn = "WatchLo4";
3750
//         break;
3751
        case 5:
3752
//         gen_op_dmtc0_watchlo5();
3753
           rn = "WatchLo5";
3754
//         break;
3755
        case 6:
3756
//         gen_op_dmtc0_watchlo6();
3757
           rn = "WatchLo6";
3758
//         break;
3759
        case 7:
3760
//         gen_op_dmtc0_watchlo7();
3761
           rn = "WatchLo7";
3762
//         break;
3763
        default:
3764
            goto die;
3765
        }
3766
        break;
3767
    case 19:
3768
        switch (sel) {
3769
        case 0:
3770
           gen_op_mtc0_watchhi0();
3771
           rn = "WatchHi";
3772
           break;
3773
        case 1:
3774
//         gen_op_dmtc0_watchhi1();
3775
           rn = "WatchHi1";
3776
//         break;
3777
        case 2:
3778
//         gen_op_dmtc0_watchhi2();
3779
           rn = "WatchHi2";
3780
//         break;
3781
        case 3:
3782
//         gen_op_dmtc0_watchhi3();
3783
           rn = "WatchHi3";
3784
//         break;
3785
        case 4:
3786
//         gen_op_dmtc0_watchhi4();
3787
           rn = "WatchHi4";
3788
//         break;
3789
        case 5:
3790
//         gen_op_dmtc0_watchhi5();
3791
           rn = "WatchHi5";
3792
//         break;
3793
        case 6:
3794
//         gen_op_dmtc0_watchhi6();
3795
           rn = "WatchHi6";
3796
//         break;
3797
        case 7:
3798
//         gen_op_dmtc0_watchhi7();
3799
           rn = "WatchHi7";
3800
//         break;
3801
        default:
3802
            goto die;
3803
        }
3804
        break;
3805
    case 20:
3806
        switch (sel) {
3807
        case 0:
3808
           /* 64 bit MMU only */
3809
           gen_op_dmtc0_xcontext();
3810
           rn = "XContext";
3811
           break;
3812
        default:
3813
            goto die;
3814
        }
3815
        break;
3816
    case 21:
3817
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
3818
        switch (sel) {
3819
        case 0:
3820
           gen_op_mtc0_framemask();
3821
           rn = "Framemask";
3822
           break;
3823
        default:
3824
            goto die;
3825
        }
3826
        break;
3827
    case 22:
3828
        /* ignored */
3829
        rn = "Diagnostic"; /* implementation dependent */
3830
       break;
3831
    case 23:
3832
        switch (sel) {
3833
        case 0:
3834
           gen_op_mtc0_debug(); /* EJTAG support */
3835
           rn = "Debug";
3836
           break;
3837
        case 1:
3838
//         gen_op_dmtc0_tracecontrol(); /* PDtrace support */
3839
           rn = "TraceControl";
3840
//         break;
3841
        case 2:
3842
//         gen_op_dmtc0_tracecontrol2(); /* PDtrace support */
3843
           rn = "TraceControl2";
3844
//         break;
3845
        case 3:
3846
//         gen_op_dmtc0_usertracedata(); /* PDtrace support */
3847
           rn = "UserTraceData";
3848
//         break;
3849
        case 4:
3850
//         gen_op_dmtc0_debug(); /* PDtrace support */
3851
           rn = "TraceBPC";
3852
//         break;
3853
        default:
3854
            goto die;
3855
        }
3856
       /* Stop translation as we may have switched the execution mode */
3857
       ctx->bstate = BS_STOP;
3858
        break;
3859
    case 24:
3860
        switch (sel) {
3861
        case 0:
3862
           gen_op_dmtc0_depc(); /* EJTAG support */
3863
           rn = "DEPC";
3864
           break;
3865
        default:
3866
            goto die;
3867
        }
3868
        break;
3869
    case 25:
3870
        switch (sel) {
3871
        case 0:
3872
           gen_op_mtc0_performance0();
3873
           rn = "Performance0";
3874
           break;
3875
        case 1:
3876
//         gen_op_dmtc0_performance1();
3877
           rn = "Performance1";
3878
//         break;
3879
        case 2:
3880
//         gen_op_dmtc0_performance2();
3881
           rn = "Performance2";
3882
//         break;
3883
        case 3:
3884
//         gen_op_dmtc0_performance3();
3885
           rn = "Performance3";
3886
//         break;
3887
        case 4:
3888
//         gen_op_dmtc0_performance4();
3889
           rn = "Performance4";
3890
//         break;
3891
        case 5:
3892
//         gen_op_dmtc0_performance5();
3893
           rn = "Performance5";
3894
//         break;
3895
        case 6:
3896
//         gen_op_dmtc0_performance6();
3897
           rn = "Performance6";
3898
//         break;
3899
        case 7:
3900
//         gen_op_dmtc0_performance7();
3901
           rn = "Performance7";
3902
//         break;
3903
        default:
3904
            goto die;
3905
        }
3906
       break;
3907
    case 26:
3908
       /* ignored */
3909
        rn = "ECC";
3910
       break;
3911
    case 27:
3912
        switch (sel) {
3913
        case 0 ... 3:
3914
           /* ignored */
3915
           rn = "CacheErr";
3916
           break;
3917
        default:
3918
            goto die;
3919
        }
3920
       break;
3921
    case 28:
3922
        switch (sel) {
3923
        case 0:
3924
        case 2:
3925
        case 4:
3926
        case 6:
3927
            gen_op_mtc0_taglo();
3928
            rn = "TagLo";
3929
            break;
3930
        case 1:
3931
        case 3:
3932
        case 5:
3933
        case 7:
3934
           gen_op_mtc0_datalo();
3935
            rn = "DataLo";
3936
            break;
3937
        default:
3938
            goto die;
3939
        }
3940
        break;
3941
    case 29:
3942
        switch (sel) {
3943
        case 0:
3944
        case 2:
3945
        case 4:
3946
        case 6:
3947
            gen_op_mtc0_taghi();
3948
            rn = "TagHi";
3949
            break;
3950
        case 1:
3951
        case 3:
3952
        case 5:
3953
        case 7:
3954
           gen_op_mtc0_datahi();
3955
            rn = "DataHi";
3956
            break;
3957
        default:
3958
            rn = "invalid sel";
3959
            goto die;
3960
        }
3961
       break;
3962
    case 30:
3963
        switch (sel) {
3964
        case 0:
3965
           gen_op_dmtc0_errorepc();
3966
           rn = "ErrorEPC";
3967
           break;
3968
        default:
3969
            goto die;
3970
        }
3971
        break;
3972
    case 31:
3973
        switch (sel) {
3974
        case 0:
3975
           gen_op_mtc0_desave(); /* EJTAG support */
3976
           rn = "DESAVE";
3977
           break;
3978
        default:
3979
            goto die;
3980
        }
3981
       /* Stop translation as we may have switched the execution mode */
3982
       ctx->bstate = BS_STOP;
3983
        break;
3984
    default:
3985
       goto die;
3986
    }
3987
#if defined MIPS_DEBUG_DISAS
3988
    if (loglevel & CPU_LOG_TB_IN_ASM) {
3989
        fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
3990
                rn, reg, sel);
3991
    }
3992
#endif
3993
    return;
3994

    
3995
die:
3996
#if defined MIPS_DEBUG_DISAS
3997
    if (loglevel & CPU_LOG_TB_IN_ASM) {
3998
        fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
3999
                rn, reg, sel);
4000
    }
4001
#endif
4002
    generate_exception(ctx, EXCP_RI);
4003
}
4004

    
4005
static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd)
4006
{
4007
    const char *opn = "unk";
4008

    
4009
    if ((!ctx->CP0_Status & (1 << CP0St_CU0) &&
4010
          (ctx->hflags & MIPS_HFLAG_UM)) &&
4011
        !(ctx->hflags & MIPS_HFLAG_ERL) &&
4012
        !(ctx->hflags & MIPS_HFLAG_EXL)) {
4013
        if (loglevel & CPU_LOG_TB_IN_ASM) {
4014
            fprintf(logfile, "CP0 is not usable\n");
4015
        }
4016
        generate_exception (ctx, EXCP_CpU);
4017
        return;
4018
    }
4019

    
4020
    switch (opc) {
4021
    case OPC_MFC0:
4022
        if (rt == 0) {
4023
            /* Treat as NOP */
4024
            return;
4025
        }
4026
        gen_mfc0(ctx, rd, ctx->opcode & 0x7);
4027
        gen_op_store_T0_gpr(rt);
4028
        opn = "mfc0";
4029
        break;
4030
    case OPC_MTC0:
4031
        /* If we get an exception, we want to restart at next instruction */
4032
        /* XXX: breaks for mtc in delay slot */
4033
        ctx->pc += 4;
4034
        save_cpu_state(ctx, 1);
4035
        ctx->pc -= 4;
4036
        GEN_LOAD_REG_TN(T0, rt);
4037
        gen_mtc0(ctx, rd, ctx->opcode & 0x7);
4038
        opn = "mtc0";
4039
        break;
4040
    case OPC_DMFC0:
4041
        if (rt == 0) {
4042
            /* Treat as NOP */
4043
            return;
4044
        }
4045
        gen_dmfc0(ctx, rd, ctx->opcode & 0x7);
4046
        gen_op_store_T0_gpr(rt);
4047
        opn = "dmfc0";
4048
        break;
4049
    case OPC_DMTC0:
4050
        /* If we get an exception, we want to restart at next instruction */
4051
        /* XXX: breaks for dmtc in delay slot */
4052
        ctx->pc += 4;
4053
        save_cpu_state(ctx, 1);
4054
        ctx->pc -= 4;
4055
        GEN_LOAD_REG_TN(T0, rt);
4056
        gen_dmtc0(ctx, rd, ctx->opcode & 0x7);
4057
        opn = "dmtc0";
4058
        break;
4059
#if defined(MIPS_USES_R4K_TLB)
4060
    case OPC_TLBWI:
4061
        gen_op_tlbwi();
4062
        opn = "tlbwi";
4063
        break;
4064
    case OPC_TLBWR:
4065
        gen_op_tlbwr();
4066
        opn = "tlbwr";
4067
        break;
4068
    case OPC_TLBP:
4069
        gen_op_tlbp();
4070
        opn = "tlbp";
4071
        break;
4072
    case OPC_TLBR:
4073
        gen_op_tlbr();
4074
        opn = "tlbr";
4075
        break;
4076
#endif
4077
    case OPC_ERET:
4078
        opn = "eret";
4079
        save_cpu_state(ctx, 0);
4080
        gen_op_eret();
4081
        ctx->bstate = BS_EXCP;
4082
        break;
4083
    case OPC_DERET:
4084
        opn = "deret";
4085
        if (!(ctx->hflags & MIPS_HFLAG_DM)) {
4086
            generate_exception(ctx, EXCP_RI);
4087
        } else {
4088
            save_cpu_state(ctx, 0);
4089
            gen_op_deret();
4090
            ctx->bstate = BS_EXCP;
4091
        }
4092
        break;
4093
    case OPC_WAIT:
4094
        opn = "wait";
4095
        /* If we get an exception, we want to restart at next instruction */
4096
        ctx->pc += 4;
4097
        save_cpu_state(ctx, 1);
4098
        ctx->pc -= 4;
4099
        gen_op_wait();
4100
        ctx->bstate = BS_EXCP;
4101
        break;
4102
    default:
4103
        if (loglevel & CPU_LOG_TB_IN_ASM) {
4104
            fprintf(logfile, "Invalid CP0 opcode: %08x %03x %03x %03x\n",
4105
                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
4106
                    ((ctx->opcode >> 16) & 0x1F));
4107
        }
4108
        generate_exception(ctx, EXCP_RI);
4109
        return;
4110
    }
4111
    MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
4112
}
4113

    
4114
#ifdef MIPS_USES_FPU
4115

    
4116
/* CP1 Branches (before delay slot) */
4117
static void gen_compute_branch1 (DisasContext *ctx, uint32_t op,
4118
                                 int32_t offset)
4119
{
4120
    target_ulong btarget;
4121

    
4122
    btarget = ctx->pc + 4 + offset;
4123

    
4124
    switch (op) {
4125
    case OPC_BC1F:
4126
        gen_op_bc1f();
4127
        MIPS_DEBUG("bc1f " TARGET_FMT_lx, btarget);
4128
        goto not_likely;
4129
    case OPC_BC1FL:
4130
        gen_op_bc1f();
4131
        MIPS_DEBUG("bc1fl " TARGET_FMT_lx, btarget);
4132
        goto likely;
4133
    case OPC_BC1T:
4134
        gen_op_bc1t();
4135
        MIPS_DEBUG("bc1t " TARGET_FMT_lx, btarget);
4136
    not_likely:
4137
        ctx->hflags |= MIPS_HFLAG_BC;
4138
        break;
4139
    case OPC_BC1TL:
4140
        gen_op_bc1t();
4141
        MIPS_DEBUG("bc1tl " TARGET_FMT_lx, btarget);
4142
    likely:
4143
        ctx->hflags |= MIPS_HFLAG_BL;
4144
        break;
4145
    default:    
4146
        MIPS_INVAL("cp1 branch/jump");
4147
        generate_exception_err (ctx, EXCP_RI, 1);
4148
        return;
4149
    }
4150
    gen_op_set_bcond();
4151

    
4152
    MIPS_DEBUG("enter ds: cond %02x target " TARGET_FMT_lx,
4153
               ctx->hflags, btarget);
4154
    ctx->btarget = btarget;
4155

    
4156
    return;
4157
}
4158

    
4159
/* Coprocessor 1 (FPU) */
4160
static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
4161
{
4162
    const char *opn = "unk";
4163

    
4164
    switch (opc) {
4165
    case OPC_MFC1:
4166
        GEN_LOAD_FREG_FTN(WT0, fs);
4167
        gen_op_mfc1();
4168
        GEN_STORE_TN_REG(rt, T0);
4169
        opn = "mfc1";
4170
        break;
4171
    case OPC_MTC1:
4172
        GEN_LOAD_REG_TN(T0, rt);
4173
        gen_op_mtc1();
4174
        GEN_STORE_FTN_FREG(fs, WT0);
4175
        opn = "mtc1";
4176
        break;
4177
    case OPC_CFC1:
4178
        if (fs != 0 && fs != 31) {
4179
            MIPS_INVAL("cfc1 freg");
4180
            generate_exception_err (ctx, EXCP_RI, 1);
4181
            return;
4182
        }
4183
        GEN_LOAD_IMM_TN(T1, fs);
4184
        gen_op_cfc1();
4185
        GEN_STORE_TN_REG(rt, T0);
4186
        opn = "cfc1";
4187
        break;
4188
    case OPC_CTC1:
4189
         if (fs != 0 && fs != 31) {
4190
            MIPS_INVAL("ctc1 freg");
4191
            generate_exception_err (ctx, EXCP_RI, 1);
4192
            return;
4193
        }
4194
        GEN_LOAD_IMM_TN(T1, fs);
4195
        GEN_LOAD_REG_TN(T0, rt);
4196
        gen_op_ctc1();
4197
        opn = "ctc1";
4198
        break;
4199
    case OPC_DMFC1:
4200
    case OPC_DMTC1:
4201
        /* Not implemented, fallthrough. */
4202
    default:
4203
        if (loglevel & CPU_LOG_TB_IN_ASM) {
4204
            fprintf(logfile, "Invalid CP1 opcode: %08x %03x %03x %03x\n",
4205
                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
4206
                    ((ctx->opcode >> 16) & 0x1F));
4207
        }
4208
        generate_exception_err (ctx, EXCP_RI, 1);
4209
        return;
4210
    }
4211
    MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
4212
}
4213

    
4214
/* verify if floating point register is valid; an operation is not defined
4215
 * if bit 0 of any register specification is set and the FR bit in the
4216
 * Status register equals zero, since the register numbers specify an
4217
 * even-odd pair of adjacent coprocessor general registers. When the FR bit
4218
 * in the Status register equals one, both even and odd register numbers
4219
 * are valid. This limitation exists only for 64 bit wide (d,l) registers.
4220
 * 
4221
 * Multiple 64 bit wide registers can be checked by calling
4222
 * CHECK_FR(ctx, freg1 | freg2 | ... | fregN);
4223
 */
4224
#define CHECK_FR(ctx, freg) do { \
4225
        if (!((ctx)->CP0_Status & (1<<CP0St_FR)) && ((freg) & 1)) { \
4226
            generate_exception_err (ctx, EXCP_RI, 1); \
4227
            return; \
4228
        } \
4229
    } while(0)
4230

    
4231
#define FOP(func, fmt) (((fmt) << 21) | (func))
4232

    
4233
static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, int fs, int fd)
4234
{
4235
    const char *opn = "unk";
4236
    const char *condnames[] = {
4237
            "c.f",
4238
            "c.un",
4239
            "c.eq",
4240
            "c.ueq",
4241
            "c.olt",
4242
            "c.ult",
4243
            "c.ole",
4244
            "c.ule",
4245
            "c.sf",
4246
            "c.ngle",
4247
            "c.seq",
4248
            "c.ngl",
4249
            "c.lt",
4250
            "c.nge",
4251
            "c.le",
4252
            "c.ngt",
4253
    };
4254
    int binary = 0;
4255
    uint32_t func = ctx->opcode & 0x3f;
4256

    
4257
    switch (ctx->opcode & FOP(0x3f, 0x1f)) {
4258
    case FOP(0, 17):
4259
        CHECK_FR(ctx, fs | ft | fd);
4260
        GEN_LOAD_FREG_FTN(DT0, fs);
4261
        GEN_LOAD_FREG_FTN(DT1, ft);
4262
        gen_op_float_add_d();
4263
        GEN_STORE_FTN_FREG(fd, DT2);
4264
        opn = "add.d";
4265
        binary = 1;
4266
        break;
4267
    case FOP(1, 17):
4268
        CHECK_FR(ctx, fs | ft | fd);
4269
        GEN_LOAD_FREG_FTN(DT0, fs);
4270
        GEN_LOAD_FREG_FTN(DT1, ft);
4271
        gen_op_float_sub_d();
4272
        GEN_STORE_FTN_FREG(fd, DT2);
4273
        opn = "sub.d";
4274
        binary = 1;
4275
        break;
4276
    case FOP(2, 17):
4277
        CHECK_FR(ctx, fs | ft | fd);
4278
        GEN_LOAD_FREG_FTN(DT0, fs);
4279
        GEN_LOAD_FREG_FTN(DT1, ft);
4280
        gen_op_float_mul_d();
4281
        GEN_STORE_FTN_FREG(fd, DT2);
4282
        opn = "mul.d";
4283
        binary = 1;
4284
        break;
4285
    case FOP(3, 17):
4286
        CHECK_FR(ctx, fs | ft | fd);
4287
        GEN_LOAD_FREG_FTN(DT0, fs);
4288
        GEN_LOAD_FREG_FTN(DT1, ft);
4289
        gen_op_float_div_d();
4290
        GEN_STORE_FTN_FREG(fd, DT2);
4291
        opn = "div.d";
4292
        binary = 1;
4293
        break;
4294
    case FOP(4, 17):
4295
        CHECK_FR(ctx, fs | fd);
4296
        GEN_LOAD_FREG_FTN(DT0, fs);
4297
        gen_op_float_sqrt_d();
4298
        GEN_STORE_FTN_FREG(fd, DT2);
4299
        opn = "sqrt.d";
4300
        break;
4301
    case FOP(5, 17):
4302
        CHECK_FR(ctx, fs | fd);
4303
        GEN_LOAD_FREG_FTN(DT0, fs);
4304
        gen_op_float_abs_d();
4305
        GEN_STORE_FTN_FREG(fd, DT2);
4306
        opn = "abs.d";
4307
        break;
4308
    case FOP(6, 17):
4309
        CHECK_FR(ctx, fs | fd);
4310
        GEN_LOAD_FREG_FTN(DT0, fs);
4311
        gen_op_float_mov_d();
4312
        GEN_STORE_FTN_FREG(fd, DT2);
4313
        opn = "mov.d";
4314
        break;
4315
    case FOP(7, 17):
4316
        CHECK_FR(ctx, fs | fd);
4317
        GEN_LOAD_FREG_FTN(DT0, fs);
4318
        gen_op_float_chs_d();
4319
        GEN_STORE_FTN_FREG(fd, DT2);
4320
        opn = "neg.d";
4321
        break;
4322
    /*  8 - round.l */
4323
    /*  9 - trunc.l */
4324
    /* 10 - ceil.l  */
4325
    /* 11 - floor.l */
4326
    case FOP(12, 17):
4327
        CHECK_FR(ctx, fs);
4328
        GEN_LOAD_FREG_FTN(DT0, fs);
4329
        gen_op_float_roundw_d();
4330
        GEN_STORE_FTN_FREG(fd, WT2);
4331
        opn = "round.w.d";
4332
        break;
4333
    case FOP(13, 17):
4334
        CHECK_FR(ctx, fs);
4335
        GEN_LOAD_FREG_FTN(DT0, fs);
4336
        gen_op_float_truncw_d();
4337
        GEN_STORE_FTN_FREG(fd, WT2);
4338
        opn = "trunc.w.d";
4339
        break;
4340
    case FOP(14, 17):
4341
        CHECK_FR(ctx, fs);
4342
        GEN_LOAD_FREG_FTN(DT0, fs);
4343
        gen_op_float_ceilw_d();
4344
        GEN_STORE_FTN_FREG(fd, WT2);
4345
        opn = "ceil.w.d";
4346
        break;
4347
    case FOP(15, 17):
4348
        CHECK_FR(ctx, fs);
4349
        GEN_LOAD_FREG_FTN(DT0, fs);
4350
        gen_op_float_floorw_d();
4351
        GEN_STORE_FTN_FREG(fd, WT2);
4352
        opn = "floor.w.d";
4353
        break;
4354
    case FOP(33, 16):
4355
        CHECK_FR(ctx, fd);
4356
        GEN_LOAD_FREG_FTN(WT0, fs);
4357
        gen_op_float_cvtd_s();
4358
        GEN_STORE_FTN_FREG(fd, DT2);
4359
        opn = "cvt.d.s";
4360
        break;
4361
    case FOP(33, 20):
4362
        CHECK_FR(ctx, fd);
4363
        GEN_LOAD_FREG_FTN(WT0, fs);
4364
        gen_op_float_cvtd_w();
4365
        GEN_STORE_FTN_FREG(fd, DT2);
4366
        opn = "cvt.d.w";
4367
        break;
4368
    case FOP(48, 17):
4369
    case FOP(49, 17):
4370
    case FOP(50, 17):
4371
    case FOP(51, 17):
4372
    case FOP(52, 17):
4373
    case FOP(53, 17):
4374
    case FOP(54, 17):
4375
    case FOP(55, 17):
4376
    case FOP(56, 17):
4377
    case FOP(57, 17):
4378
    case FOP(58, 17):
4379
    case FOP(59, 17):
4380
    case FOP(60, 17):
4381
    case FOP(61, 17):
4382
    case FOP(62, 17):
4383
    case FOP(63, 17):
4384
        CHECK_FR(ctx, fs | ft);
4385
        GEN_LOAD_FREG_FTN(DT0, fs);
4386
        GEN_LOAD_FREG_FTN(DT1, ft);
4387
        gen_cmp_d(func-48);
4388
        opn = condnames[func-48];
4389
        break;
4390
    case FOP(0, 16):
4391
        GEN_LOAD_FREG_FTN(WT0, fs);
4392
        GEN_LOAD_FREG_FTN(WT1, ft);
4393
        gen_op_float_add_s();
4394
        GEN_STORE_FTN_FREG(fd, WT2);
4395
        opn = "add.s";
4396
        binary = 1;
4397
        break;
4398
    case FOP(1, 16):
4399
        GEN_LOAD_FREG_FTN(WT0, fs);
4400
        GEN_LOAD_FREG_FTN(WT1, ft);
4401
        gen_op_float_sub_s();
4402
        GEN_STORE_FTN_FREG(fd, WT2);
4403
        opn = "sub.s";
4404
        binary = 1;
4405
        break;
4406
    case FOP(2, 16):
4407
        GEN_LOAD_FREG_FTN(WT0, fs);
4408
        GEN_LOAD_FREG_FTN(WT1, ft);
4409
        gen_op_float_mul_s();
4410
        GEN_STORE_FTN_FREG(fd, WT2);
4411
        opn = "mul.s";
4412
        binary = 1;
4413
        break;
4414
    case FOP(3, 16):
4415
        GEN_LOAD_FREG_FTN(WT0, fs);
4416
        GEN_LOAD_FREG_FTN(WT1, ft);
4417
        gen_op_float_div_s();
4418
        GEN_STORE_FTN_FREG(fd, WT2);
4419
        opn = "div.s";
4420
        binary = 1;
4421
        break;
4422
    case FOP(4, 16):
4423
        GEN_LOAD_FREG_FTN(WT0, fs);
4424
        gen_op_float_sqrt_s();
4425
        GEN_STORE_FTN_FREG(fd, WT2);
4426
        opn = "sqrt.s";
4427
        break;
4428
    case FOP(5, 16):
4429
        GEN_LOAD_FREG_FTN(WT0, fs);
4430
        gen_op_float_abs_s();
4431
        GEN_STORE_FTN_FREG(fd, WT2);
4432
        opn = "abs.s";
4433
        break;
4434
    case FOP(6, 16):
4435
        GEN_LOAD_FREG_FTN(WT0, fs);
4436
        gen_op_float_mov_s();
4437
        GEN_STORE_FTN_FREG(fd, WT2);
4438
        opn = "mov.s";
4439
        break;
4440
    case FOP(7, 16):
4441
        GEN_LOAD_FREG_FTN(WT0, fs);
4442
        gen_op_float_chs_s();
4443
        GEN_STORE_FTN_FREG(fd, WT2);
4444
        opn = "neg.s";
4445
        break;
4446
    case FOP(12, 16):
4447
        GEN_LOAD_FREG_FTN(WT0, fs);
4448
        gen_op_float_roundw_s();
4449
        GEN_STORE_FTN_FREG(fd, WT2);
4450
        opn = "round.w.s";
4451
        break;
4452
    case FOP(13, 16):
4453
        GEN_LOAD_FREG_FTN(WT0, fs);
4454
        gen_op_float_truncw_s();
4455
        GEN_STORE_FTN_FREG(fd, WT2);
4456
        opn = "trunc.w.s";
4457
        break;
4458
    case FOP(32, 17):
4459
        CHECK_FR(ctx, fs);
4460
        GEN_LOAD_FREG_FTN(DT0, fs);
4461
        gen_op_float_cvts_d();
4462
        GEN_STORE_FTN_FREG(fd, WT2);
4463
        opn = "cvt.s.d";
4464
        break;
4465
    case FOP(32, 20):
4466
        GEN_LOAD_FREG_FTN(WT0, fs);
4467
        gen_op_float_cvts_w();
4468
        GEN_STORE_FTN_FREG(fd, WT2);
4469
        opn = "cvt.s.w";
4470
        break;
4471
    case FOP(36, 16):
4472
        GEN_LOAD_FREG_FTN(WT0, fs);
4473
        gen_op_float_cvtw_s();
4474
        GEN_STORE_FTN_FREG(fd, WT2);
4475
        opn = "cvt.w.s";
4476
        break;
4477
    case FOP(36, 17):
4478
        CHECK_FR(ctx, fs);
4479
        GEN_LOAD_FREG_FTN(DT0, fs);
4480
        gen_op_float_cvtw_d();
4481
        GEN_STORE_FTN_FREG(fd, WT2);
4482
        opn = "cvt.w.d";
4483
        break;
4484
    case FOP(48, 16):
4485
    case FOP(49, 16):
4486
    case FOP(50, 16):
4487
    case FOP(51, 16):
4488
    case FOP(52, 16):
4489
    case FOP(53, 16):
4490
    case FOP(54, 16):
4491
    case FOP(55, 16):
4492
    case FOP(56, 16):
4493
    case FOP(57, 16):
4494
    case FOP(58, 16):
4495
    case FOP(59, 16):
4496
    case FOP(60, 16):
4497
    case FOP(61, 16):
4498
    case FOP(62, 16):
4499
    case FOP(63, 16):
4500
        GEN_LOAD_FREG_FTN(WT0, fs);
4501
        GEN_LOAD_FREG_FTN(WT1, ft);
4502
        gen_cmp_s(func-48);
4503
        opn = condnames[func-48];
4504
        break;
4505
    default:    
4506
        if (loglevel & CPU_LOG_TB_IN_ASM) {
4507
            fprintf(logfile, "Invalid FP arith function: %08x %03x %03x %03x\n",
4508
                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
4509
                    ((ctx->opcode >> 16) & 0x1F));
4510
        }
4511
        generate_exception_err (ctx, EXCP_RI, 1);
4512
        return;
4513
    }
4514
    if (binary)
4515
        MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
4516
    else
4517
        MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
4518
}
4519

    
4520
static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
4521
{
4522
    uint32_t ccbit;
4523

    
4524
    if (cc)
4525
        ccbit = 1 << (24 + cc);
4526
    else
4527
        ccbit = 1 << 23;
4528
    if (!tf)
4529
        gen_op_movf(ccbit, rd, rs);
4530
    else
4531
       gen_op_movt(ccbit, rd, rs);
4532
}
4533

    
4534
#endif /* MIPS_USES_FPU */
4535

    
4536
/* ISA extensions (ASEs) */
4537
/* MIPS16 extension to MIPS32 */
4538
/* SmartMIPS extension to MIPS32 */
4539

    
4540
#ifdef MIPS_HAS_MIPS64
4541
/* Coprocessor 3 (FPU) */
4542

    
4543
/* MDMX extension to MIPS64 */
4544
/* MIPS-3D extension to MIPS64 */
4545

    
4546
#endif
4547

    
4548
static void gen_blikely(DisasContext *ctx)
4549
{
4550
    int l1;
4551
    l1 = gen_new_label();
4552
    gen_op_jnz_T2(l1);
4553
    gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
4554
    gen_goto_tb(ctx, 1, ctx->pc + 4);
4555
    gen_set_label(l1);
4556
}
4557

    
4558
static void decode_opc (DisasContext *ctx)
4559
{
4560
    int32_t offset;
4561
    int rs, rt, rd, sa;
4562
    uint32_t op, op1, op2;
4563
    int16_t imm;
4564

    
4565
    /* make sure instructions are on a word boundary */
4566
    if (ctx->pc & 0x3) {
4567
        generate_exception(ctx, EXCP_AdEL);
4568
        return;
4569
    }
4570

    
4571
    if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
4572
        /* Handle blikely not taken case */
4573
        MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
4574
        gen_blikely(ctx);
4575
    }
4576
    op = MASK_OP_MAJOR(ctx->opcode);
4577
    rs = (ctx->opcode >> 21) & 0x1f;
4578
    rt = (ctx->opcode >> 16) & 0x1f;
4579
    rd = (ctx->opcode >> 11) & 0x1f;
4580
    sa = (ctx->opcode >> 6) & 0x1f;
4581
    imm = (int16_t)ctx->opcode;
4582
    switch (op) {
4583
    case OPC_SPECIAL:
4584
        op1 = MASK_SPECIAL(ctx->opcode);
4585
        switch (op1) {
4586
        case OPC_SLL:          /* Arithmetic with immediate */
4587
        case OPC_SRL ... OPC_SRA:
4588
            gen_arith_imm(ctx, op1, rd, rt, sa);
4589
            break;
4590
        case OPC_SLLV:         /* Arithmetic */
4591
        case OPC_SRLV ... OPC_SRAV:
4592
        case OPC_MOVZ ... OPC_MOVN:
4593
        case OPC_ADD ... OPC_NOR:
4594
        case OPC_SLT ... OPC_SLTU:
4595
            gen_arith(ctx, op1, rd, rs, rt);
4596
            break;
4597
        case OPC_MULT ... OPC_DIVU:
4598
            gen_muldiv(ctx, op1, rs, rt);
4599
            break;
4600
        case OPC_JR ... OPC_JALR:
4601
            gen_compute_branch(ctx, op1, rs, rd, sa);
4602
            return;
4603
        case OPC_TGE ... OPC_TEQ: /* Traps */
4604
        case OPC_TNE:
4605
            gen_trap(ctx, op1, rs, rt, -1);
4606
            break;
4607
        case OPC_MFHI:          /* Move from HI/LO */
4608
        case OPC_MFLO:
4609
            gen_HILO(ctx, op1, rd);
4610
            break;
4611
        case OPC_MTHI:
4612
        case OPC_MTLO:          /* Move to HI/LO */
4613
            gen_HILO(ctx, op1, rs);
4614
            break;
4615
        case OPC_PMON:          /* Pmon entry point */
4616
            gen_op_pmon(sa);
4617
            break;
4618
        case OPC_SYSCALL:
4619
            generate_exception(ctx, EXCP_SYSCALL);
4620
            ctx->bstate = BS_EXCP;
4621
            break;
4622
        case OPC_BREAK:
4623
            generate_exception(ctx, EXCP_BREAK);
4624
            break;
4625
        case OPC_SPIM:        /* SPIM ? */
4626
           /* Implemented as RI exception for now. */
4627
            MIPS_INVAL("spim (unofficial)");
4628
            generate_exception(ctx, EXCP_RI);
4629
            break;
4630
        case OPC_SYNC:
4631
            /* Treat as a noop. */
4632
            break;
4633

    
4634
#ifdef MIPS_USES_FPU
4635
        case OPC_MOVCI:
4636
            gen_op_cp1_enabled();
4637
            gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
4638
                      (ctx->opcode >> 16) & 1);
4639
            break;
4640
#endif
4641

    
4642
#ifdef MIPS_HAS_MIPS64
4643
       /* MIPS64 specific opcodes */
4644
        case OPC_DSLL:
4645
        case OPC_DSRL ... OPC_DSRA:
4646
        case OPC_DSLL32:
4647
        case OPC_DSRL32 ... OPC_DSRA32:
4648
            gen_arith_imm(ctx, op1, rd, rt, sa);
4649
            break;
4650
        case OPC_DSLLV:
4651
        case OPC_DSRLV ... OPC_DSRAV:
4652
        case OPC_DADD ... OPC_DSUBU:
4653
            gen_arith(ctx, op1, rd, rs, rt);
4654
            break;
4655
        case OPC_DMULT ... OPC_DDIVU:
4656
            gen_muldiv(ctx, op1, rs, rt);
4657
            break;
4658
#endif
4659
        default:            /* Invalid */
4660
            MIPS_INVAL("special");
4661
            generate_exception(ctx, EXCP_RI);
4662
            break;
4663
        }
4664
        break;
4665
    case OPC_SPECIAL2:
4666
        op1 = MASK_SPECIAL2(ctx->opcode);
4667
        switch (op1) {
4668
        case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
4669
        case OPC_MSUB ... OPC_MSUBU:
4670
            gen_muldiv(ctx, op1, rs, rt);
4671
            break;
4672
        case OPC_MUL:
4673
            gen_arith(ctx, op1, rd, rs, rt);
4674
            break;
4675
        case OPC_CLZ ... OPC_CLO:
4676
            gen_cl(ctx, op1, rd, rs);
4677
            break;
4678
        case OPC_SDBBP:
4679
            /* XXX: not clear which exception should be raised
4680
             *      when in debug mode...
4681
             */
4682
            if (!(ctx->hflags & MIPS_HFLAG_DM)) {
4683
                generate_exception(ctx, EXCP_DBp);
4684
            } else {
4685
                generate_exception(ctx, EXCP_DBp);
4686
            }
4687
            /* Treat as a noop */
4688
            break;
4689
#ifdef MIPS_HAS_MIPS64
4690
        case OPC_DCLZ ... OPC_DCLO:
4691
            gen_cl(ctx, op1, rd, rs);
4692
            break;
4693
#endif
4694
        default:            /* Invalid */
4695
            MIPS_INVAL("special2");
4696
            generate_exception(ctx, EXCP_RI);
4697
            break;
4698
        }
4699
        break;
4700
    case OPC_SPECIAL3:
4701
        op1 = MASK_SPECIAL3(ctx->opcode);
4702
        switch (op1) {
4703
        case OPC_EXT:
4704
        case OPC_INS:
4705
            gen_bitops(ctx, op1, rt, rs, sa, rd);
4706
            break;
4707
        case OPC_BSHFL:
4708
            op2 = MASK_BSHFL(ctx->opcode);
4709
            switch (op2) {
4710
            case OPC_WSBH:
4711
                GEN_LOAD_REG_TN(T1, rt);
4712
                gen_op_wsbh();
4713
                break;
4714
            case OPC_SEB:
4715
                GEN_LOAD_REG_TN(T1, rt);
4716
                gen_op_seb();
4717
                break;
4718
            case OPC_SEH:
4719
                GEN_LOAD_REG_TN(T1, rt);
4720
                gen_op_seh();
4721
                break;
4722
             default:            /* Invalid */
4723
                MIPS_INVAL("bshfl");
4724
                generate_exception(ctx, EXCP_RI);
4725
                break;
4726
           }
4727
           GEN_STORE_TN_REG(rd, T0);
4728
           break;
4729
       case OPC_RDHWR:
4730
           switch (rd) {
4731
           case 0:
4732
               gen_op_rdhwr_cpunum();
4733
               break;
4734
           case 1:
4735
               gen_op_rdhwr_synci_step();
4736
               break;
4737
           case 2:
4738
               gen_op_rdhwr_cc();
4739
               break;
4740
           case 3:
4741
               gen_op_rdhwr_ccres();
4742
               break;
4743
           default:            /* Invalid */
4744
               MIPS_INVAL("rdhwr");
4745
               generate_exception(ctx, EXCP_RI);
4746
               break;
4747
           }
4748
           GEN_STORE_TN_REG(rt, T0);
4749
           break;
4750
#ifdef MIPS_HAS_MIPS64
4751
       case OPC_DEXTM ... OPC_DEXT:
4752
       case OPC_DINSM ... OPC_DINS:
4753
           gen_bitops(ctx, op1, rt, rs, sa, rd);
4754
            break;
4755
       case OPC_DBSHFL:
4756
           op2 = MASK_DBSHFL(ctx->opcode);
4757
           switch (op2) {
4758
           case OPC_DSBH:
4759
               GEN_LOAD_REG_TN(T1, rt);
4760
               gen_op_dsbh();
4761
               break;
4762
           case OPC_DSHD:
4763
               GEN_LOAD_REG_TN(T1, rt);
4764
               gen_op_dshd();
4765
               break;
4766
            default:            /* Invalid */
4767
                MIPS_INVAL("dbshfl");
4768
                generate_exception(ctx, EXCP_RI);
4769
                break;
4770
           }
4771
           GEN_STORE_TN_REG(rd, T0);
4772
#endif
4773
        default:            /* Invalid */
4774
            MIPS_INVAL("special3");
4775
            generate_exception(ctx, EXCP_RI);
4776
            break;
4777
        }
4778
        break;
4779
    case OPC_REGIMM:
4780
        op1 = MASK_REGIMM(ctx->opcode);
4781
        switch (op1) {
4782
        case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
4783
        case OPC_BLTZAL ... OPC_BGEZALL:
4784
            gen_compute_branch(ctx, op1, rs, -1, imm << 2);
4785
            return;
4786
        case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
4787
        case OPC_TNEI:
4788
            gen_trap(ctx, op1, rs, -1, imm);
4789
            break;
4790
        case OPC_SYNCI:
4791
           /* treat as noop */
4792
            break;
4793
        default:            /* Invalid */
4794
            MIPS_INVAL("REGIMM");
4795
            generate_exception(ctx, EXCP_RI);
4796
            break;
4797
        }
4798
        break;
4799
    case OPC_CP0:
4800
        op1 = MASK_CP0(ctx->opcode);
4801
        switch (op1) {
4802
        case OPC_MFC0:
4803
        case OPC_MTC0:
4804
#ifdef MIPS_HAS_MIPS64
4805
        case OPC_DMFC0:
4806
        case OPC_DMTC0:
4807
#endif
4808
            gen_cp0(ctx, op1, rt, rd);
4809
            break;
4810
        case OPC_C0_FIRST ... OPC_C0_LAST:
4811
            gen_cp0(ctx, MASK_C0(ctx->opcode), rt, rd);
4812
            break;
4813
        case OPC_MFMC0:
4814
            op2 = MASK_MFMC0(ctx->opcode);
4815
            switch (op2) {
4816
            case OPC_DI:
4817
                gen_op_di();
4818
                /* Stop translation as we may have switched the execution mode */
4819
                ctx->bstate = BS_STOP;
4820
                break;
4821
            case OPC_EI:
4822
                gen_op_ei();
4823
                /* Stop translation as we may have switched the execution mode */
4824
                ctx->bstate = BS_STOP;
4825
                break;
4826
            default:            /* Invalid */
4827
                MIPS_INVAL("MFMC0");
4828
                generate_exception(ctx, EXCP_RI);
4829
                break;
4830
            }
4831
            GEN_STORE_TN_REG(rt, T0);
4832
            break;
4833
        /* Shadow registers (not implemented). */
4834
        case OPC_RDPGPR:
4835
        case OPC_WRPGPR:
4836
        default:
4837
            generate_exception(ctx, EXCP_RI);
4838
            break;
4839
        }
4840
        break;
4841
    case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
4842
         gen_arith_imm(ctx, op, rt, rs, imm);
4843
         break;
4844
    case OPC_J ... OPC_JAL: /* Jump */
4845
         offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
4846
         gen_compute_branch(ctx, op, rs, rt, offset);
4847
         return;
4848
    case OPC_BEQ ... OPC_BGTZ: /* Branch */
4849
    case OPC_BEQL ... OPC_BGTZL:
4850
         gen_compute_branch(ctx, op, rs, rt, imm << 2);
4851
         return;
4852
    case OPC_LB ... OPC_LWR: /* Load and stores */
4853
    case OPC_SB ... OPC_SW:
4854
    case OPC_SWR:
4855
    case OPC_LL:
4856
    case OPC_SC:
4857
         gen_ldst(ctx, op, rt, rs, imm);
4858
         break;
4859
    case OPC_CACHE:
4860
         /* Treat as a noop */
4861
         break;
4862
    case OPC_PREF:
4863
        /* Treat as a noop */
4864
        break;
4865

    
4866
    /* Floating point.  */
4867
    case OPC_LWC1:
4868
    case OPC_LDC1:
4869
    case OPC_SWC1:
4870
    case OPC_SDC1:
4871
#if defined(MIPS_USES_FPU)
4872
        save_cpu_state(ctx, 1);
4873
        gen_op_cp1_enabled();
4874
        gen_flt_ldst(ctx, op, rt, rs, imm);
4875
#else
4876
        generate_exception_err(ctx, EXCP_CpU, 1);
4877
#endif
4878
        break;
4879

    
4880
    case OPC_CP1:
4881
#if defined(MIPS_USES_FPU)
4882
        save_cpu_state(ctx, 1);
4883
        gen_op_cp1_enabled();
4884
        op1 = MASK_CP1(ctx->opcode);
4885
        switch (op1) {
4886
        case OPC_MFC1:
4887
        case OPC_CFC1:
4888
        case OPC_MTC1:
4889
        case OPC_CTC1:
4890
#ifdef MIPS_HAS_MIPS64
4891
        case OPC_DMFC1:
4892
        case OPC_DMTC1:
4893
#endif
4894
            gen_cp1(ctx, op1, rt, rd);
4895
            break;
4896
        case OPC_BC1:
4897
            gen_compute_branch1(ctx, MASK_CP1_BCOND(ctx->opcode), imm << 2);
4898
            return;
4899
        case OPC_S_FMT:
4900
        case OPC_D_FMT:
4901
        case OPC_W_FMT:
4902
        case OPC_L_FMT:
4903
            gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa);
4904
            break;
4905
        default:
4906
            generate_exception_err(ctx, EXCP_RI, 1);
4907
            break;
4908
        }
4909
#else
4910
        generate_exception_err(ctx, EXCP_CpU, 1);
4911
#endif
4912
        break;
4913

    
4914
    /* COP2.  */
4915
    case OPC_LWC2:
4916
    case OPC_LDC2:
4917
    case OPC_SWC2:
4918
    case OPC_SDC2:
4919
    case OPC_CP2:
4920
        /* COP2: Not implemented. */
4921
        generate_exception_err(ctx, EXCP_CpU, 2);
4922
        break;
4923

    
4924
#ifdef MIPS_USES_FPU
4925
    case OPC_CP3:
4926
        gen_op_cp1_enabled();
4927
        op1 = MASK_CP3(ctx->opcode);
4928
        switch (op1) {
4929
        /* Not implemented */
4930
        default:
4931
            generate_exception_err(ctx, EXCP_RI, 1);
4932
            break;
4933
        }
4934
        break;
4935
#endif
4936

    
4937
#ifdef MIPS_HAS_MIPS64
4938
    /* MIPS64 opcodes */
4939
    case OPC_LWU:
4940
    case OPC_LDL ... OPC_LDR:
4941
    case OPC_SDL ... OPC_SDR:
4942
    case OPC_LLD:
4943
    case OPC_LD:
4944
    case OPC_SCD:
4945
    case OPC_SD:
4946
        gen_ldst(ctx, op, rt, rs, imm);
4947
        break;
4948
    case OPC_DADDI ... OPC_DADDIU:
4949
        gen_arith_imm(ctx, op, rt, rs, imm);
4950
        break;
4951
#endif
4952
#ifdef MIPS_HAS_MIPS16
4953
    case OPC_JALX:
4954
        /* MIPS16: Not implemented. */
4955
#endif
4956
#ifdef MIPS_HAS_MDMX
4957
    case OPC_MDMX:
4958
        /* MDMX: Not implemented. */
4959
#endif
4960
    default:            /* Invalid */
4961
        MIPS_INVAL("");
4962
        generate_exception(ctx, EXCP_RI);
4963
        break;
4964
    }
4965
    if (ctx->hflags & MIPS_HFLAG_BMASK) {
4966
        int hflags = ctx->hflags;
4967
        /* Branches completion */
4968
        ctx->hflags &= ~MIPS_HFLAG_BMASK;
4969
        ctx->bstate = BS_BRANCH;
4970
        save_cpu_state(ctx, 0);
4971
        switch (hflags & MIPS_HFLAG_BMASK) {
4972
        case MIPS_HFLAG_B:
4973
            /* unconditional branch */
4974
            MIPS_DEBUG("unconditional branch");
4975
            gen_goto_tb(ctx, 0, ctx->btarget);
4976
            break;
4977
        case MIPS_HFLAG_BL:
4978
            /* blikely taken case */
4979
            MIPS_DEBUG("blikely branch taken");
4980
            gen_goto_tb(ctx, 0, ctx->btarget);
4981
            break;
4982
        case MIPS_HFLAG_BC:
4983
            /* Conditional branch */
4984
            MIPS_DEBUG("conditional branch");
4985
            {
4986
              int l1;
4987
              l1 = gen_new_label();
4988
              gen_op_jnz_T2(l1);
4989
              gen_goto_tb(ctx, 1, ctx->pc + 4);
4990
              gen_set_label(l1);
4991
              gen_goto_tb(ctx, 0, ctx->btarget);
4992
            }
4993
            break;
4994
        case MIPS_HFLAG_BR:
4995
            /* unconditional branch to register */
4996
            MIPS_DEBUG("branch to register");
4997
            gen_op_breg();
4998
            break;
4999
        default:
5000
            MIPS_DEBUG("unknown branch");
5001
            break;
5002
        }
5003
    }
5004
}
5005

    
5006
int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
5007
                                    int search_pc)
5008
{
5009
    DisasContext ctx, *ctxp = &ctx;
5010
    target_ulong pc_start;
5011
    uint16_t *gen_opc_end;
5012
    int j, lj = -1;
5013

    
5014
    if (search_pc && loglevel)
5015
        fprintf (logfile, "search pc %d\n", search_pc);
5016

    
5017
    pc_start = tb->pc;
5018
    gen_opc_ptr = gen_opc_buf;
5019
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
5020
    gen_opparam_ptr = gen_opparam_buf;
5021
    nb_gen_labels = 0;
5022
    ctx.pc = pc_start;
5023
    ctx.saved_pc = -1;
5024
    ctx.tb = tb;
5025
    ctx.bstate = BS_NONE;
5026
    /* Restore delay slot state from the tb context.  */
5027
    ctx.hflags = tb->flags;
5028
    ctx.saved_hflags = ctx.hflags;
5029
    if (ctx.hflags & MIPS_HFLAG_BR) {
5030
        gen_op_restore_breg_target();
5031
    } else if (ctx.hflags & MIPS_HFLAG_B) {
5032
        ctx.btarget = env->btarget;
5033
    } else if (ctx.hflags & MIPS_HFLAG_BMASK) {
5034
        /* If we are in the delay slot of a conditional branch,
5035
         * restore the branch condition from env->bcond to T2
5036
         */
5037
        ctx.btarget = env->btarget;
5038
        gen_op_restore_bcond();
5039
    }
5040
#if defined(CONFIG_USER_ONLY)
5041
    ctx.mem_idx = 0;
5042
#else
5043
    ctx.mem_idx = !((ctx.hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM);
5044
#endif
5045
    ctx.CP0_Status = env->CP0_Status;
5046
#ifdef DEBUG_DISAS
5047
    if (loglevel & CPU_LOG_TB_CPU) {
5048
        fprintf(logfile, "------------------------------------------------\n");
5049
        /* FIXME: This may print out stale hflags from env... */
5050
        cpu_dump_state(env, logfile, fprintf, 0);
5051
    }
5052
#endif
5053
#if defined MIPS_DEBUG_DISAS
5054
    if (loglevel & CPU_LOG_TB_IN_ASM)
5055
        fprintf(logfile, "\ntb %p super %d cond %04x\n",
5056
                tb, ctx.mem_idx, ctx.hflags);
5057
#endif
5058
    while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
5059
        if (env->nb_breakpoints > 0) {
5060
            for(j = 0; j < env->nb_breakpoints; j++) {
5061
                if (env->breakpoints[j] == ctx.pc) {
5062
                    save_cpu_state(ctxp, 1);
5063
                    ctx.bstate = BS_BRANCH;
5064
                    gen_op_debug();
5065
                    goto done_generating;
5066
                }
5067
            }
5068
        }
5069

    
5070
        if (search_pc) {
5071
            j = gen_opc_ptr - gen_opc_buf;
5072
            if (lj < j) {
5073
                lj++;
5074
                while (lj < j)
5075
                    gen_opc_instr_start[lj++] = 0;
5076
            }
5077
            gen_opc_pc[lj] = ctx.pc;
5078
            gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
5079
            gen_opc_instr_start[lj] = 1;
5080
        }
5081
        ctx.opcode = ldl_code(ctx.pc);
5082
        decode_opc(&ctx);
5083
        ctx.pc += 4;
5084

    
5085
        if (env->singlestep_enabled)
5086
            break;
5087

    
5088
        if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
5089
            break;
5090

    
5091
#if defined (MIPS_SINGLE_STEP)
5092
        break;
5093
#endif
5094
    }
5095
    if (env->singlestep_enabled) {
5096
        save_cpu_state(ctxp, ctx.bstate == BS_NONE);
5097
        gen_op_debug();
5098
        goto done_generating;
5099
    }
5100
    else if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) {
5101
        save_cpu_state(ctxp, 0);
5102
        gen_goto_tb(&ctx, 0, ctx.pc);
5103
    }
5104
    gen_op_reset_T0();
5105
    /* Generate the return instruction */
5106
    gen_op_exit_tb();
5107
done_generating:
5108
    *gen_opc_ptr = INDEX_op_end;
5109
    if (search_pc) {
5110
        j = gen_opc_ptr - gen_opc_buf;
5111
        lj++;
5112
        while (lj <= j)
5113
            gen_opc_instr_start[lj++] = 0;
5114
        tb->size = 0;
5115
    } else {
5116
        tb->size = ctx.pc - pc_start;
5117
    }
5118
#ifdef DEBUG_DISAS
5119
#if defined MIPS_DEBUG_DISAS
5120
    if (loglevel & CPU_LOG_TB_IN_ASM)
5121
        fprintf(logfile, "\n");
5122
#endif
5123
    if (loglevel & CPU_LOG_TB_IN_ASM) {
5124
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
5125
    target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
5126
        fprintf(logfile, "\n");
5127
    }
5128
    if (loglevel & CPU_LOG_TB_OP) {
5129
        fprintf(logfile, "OP:\n");
5130
        dump_ops(gen_opc_buf, gen_opparam_buf);
5131
        fprintf(logfile, "\n");
5132
    }
5133
    if (loglevel & CPU_LOG_TB_CPU) {
5134
        fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
5135
    }
5136
#endif
5137
    
5138
    return 0;
5139
}
5140

    
5141
int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
5142
{
5143
    return gen_intermediate_code_internal(env, tb, 0);
5144
}
5145

    
5146
int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
5147
{
5148
    return gen_intermediate_code_internal(env, tb, 1);
5149
}
5150

    
5151
#ifdef MIPS_USES_FPU
5152

    
5153
void fpu_dump_state(CPUState *env, FILE *f, 
5154
                    int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
5155
                    int flags)
5156
{
5157
    int i;
5158

    
5159
#   define printfpr(fp) do { \
5160
        fpu_fprintf(f, "w:%08x d:%08lx%08lx fd:%g fs:%g\n", \
5161
                (fp)->w[FP_ENDIAN_IDX], (fp)->w[0], (fp)->w[1], (fp)->fd, (fp)->fs[FP_ENDIAN_IDX]); \
5162
    } while(0)
5163

    
5164
    fpu_fprintf(f, "CP1 FCR0 0x%08x  FCR31 0x%08x  SR.FR %d\n",
5165
                env->fcr0, env->fcr31,
5166
                (env->CP0_Status & (1 << CP0St_FR)) != 0);
5167
    fpu_fprintf(f, "FT0: "); printfpr(&env->ft0);
5168
    fpu_fprintf(f, "FT1: "); printfpr(&env->ft1);
5169
    fpu_fprintf(f, "FT2: "); printfpr(&env->ft2);
5170
    for(i = 0; i < 32; i += 2) {
5171
        fpu_fprintf(f, "%s: ", fregnames[i]);
5172
        printfpr(FPR(env, i));
5173
    }
5174

    
5175
#undef printfpr
5176
}
5177

    
5178
void dump_fpu (CPUState *env)
5179
{
5180
    if (loglevel) { 
5181
       fprintf(logfile, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx " %d\n",
5182
               env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
5183
       fpu_dump_state(env, logfile, fprintf, 0);
5184
    }
5185
}
5186

    
5187
#endif /* MIPS_USES_FPU */
5188

    
5189
#if defined(MIPS_HAS_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
5190
/* Debug help: The architecture requires 32bit code to maintain proper
5191
   sign-extened values on 64bit machines.  */
5192

    
5193
#define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
5194

    
5195
void cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
5196
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
5197
                     int flags)
5198
{
5199
    int i;
5200

    
5201
    if (!SIGN_EXT_P(env->PC))
5202
        cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->PC);
5203
    if (!SIGN_EXT_P(env->HI))
5204
        cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->HI);
5205
    if (!SIGN_EXT_P(env->LO))
5206
        cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->LO);
5207
    if (!SIGN_EXT_P(env->btarget))
5208
        cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
5209

    
5210
    for (i = 0; i < 32; i++) {
5211
        if (!SIGN_EXT_P(env->gpr[i]))
5212
            cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->gpr[i]);
5213
    }
5214

    
5215
    if (!SIGN_EXT_P(env->CP0_EPC))
5216
        cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
5217
    if (!SIGN_EXT_P(env->CP0_LLAddr))
5218
        cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
5219
}
5220
#endif
5221

    
5222
void cpu_dump_state (CPUState *env, FILE *f, 
5223
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
5224
                     int flags)
5225
{
5226
    uint32_t c0_status;
5227
    int i;
5228
    
5229
    cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx " %d\n",
5230
                env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
5231
    for (i = 0; i < 32; i++) {
5232
        if ((i & 3) == 0)
5233
            cpu_fprintf(f, "GPR%02d:", i);
5234
        cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->gpr[i]);
5235
        if ((i & 3) == 3)
5236
            cpu_fprintf(f, "\n");
5237
    }
5238

    
5239
    c0_status = env->CP0_Status;
5240
    if (env->hflags & MIPS_HFLAG_UM)
5241
        c0_status |= (1 << CP0St_UM);
5242
    if (env->hflags & MIPS_HFLAG_ERL)
5243
        c0_status |= (1 << CP0St_ERL);
5244
    if (env->hflags & MIPS_HFLAG_EXL)
5245
        c0_status |= (1 << CP0St_EXL);
5246

    
5247
    cpu_fprintf(f, "CP0 Status  0x%08x Cause   0x%08x EPC    0x" TARGET_FMT_lx "\n",
5248
                c0_status, env->CP0_Cause, env->CP0_EPC);
5249
    cpu_fprintf(f, "    Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
5250
                env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
5251
#ifdef MIPS_USES_FPU
5252
    if (c0_status & (1 << CP0St_CU1))
5253
        fpu_dump_state(env, f, cpu_fprintf, flags);
5254
#endif
5255
#if defined(MIPS_HAS_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
5256
    cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
5257
#endif
5258
}
5259

    
5260
CPUMIPSState *cpu_mips_init (void)
5261
{
5262
    CPUMIPSState *env;
5263

    
5264
    env = qemu_mallocz(sizeof(CPUMIPSState));
5265
    if (!env)
5266
        return NULL;
5267
    cpu_exec_init(env);
5268
    cpu_reset(env);
5269
    return env;
5270
}
5271

    
5272
void cpu_reset (CPUMIPSState *env)
5273
{
5274
    memset(env, 0, offsetof(CPUMIPSState, breakpoints));
5275

    
5276
    tlb_flush(env, 1);
5277

    
5278
    /* Minimal init */
5279
#if !defined(CONFIG_USER_ONLY)
5280
    if (env->hflags & MIPS_HFLAG_BMASK) {
5281
        /* If the exception was raised from a delay slot,
5282
         * come back to the jump.  */
5283
        env->CP0_ErrorEPC = env->PC - 4;
5284
        env->hflags &= ~MIPS_HFLAG_BMASK;
5285
    } else {
5286
        env->CP0_ErrorEPC = env->PC;
5287
    }
5288
    env->PC = (int32_t)0xBFC00000;
5289
#if defined (MIPS_USES_R4K_TLB)
5290
    env->CP0_Random = MIPS_TLB_NB - 1;
5291
    env->tlb_in_use = MIPS_TLB_NB;
5292
#endif
5293
    env->CP0_Wired = 0;
5294
    /* SMP not implemented */
5295
    env->CP0_EBase = 0x80000000;
5296
    env->CP0_Config0 = MIPS_CONFIG0;
5297
    env->CP0_Config1 = MIPS_CONFIG1;
5298
    env->CP0_Config2 = MIPS_CONFIG2;
5299
    env->CP0_Config3 = MIPS_CONFIG3;
5300
    env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
5301
    env->CP0_WatchLo = 0;
5302
    env->hflags = MIPS_HFLAG_ERL;
5303
    /* Count register increments in debug mode, EJTAG version 1 */
5304
    env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
5305
    env->CP0_PRid = MIPS_CPU;
5306
#endif
5307
    env->exception_index = EXCP_NONE;
5308
#if defined(CONFIG_USER_ONLY)
5309
    env->hflags |= MIPS_HFLAG_UM;
5310
    env->user_mode_only = 1;
5311
#endif
5312
#ifdef MIPS_USES_FPU
5313
    env->fcr0 = MIPS_FCR0;        
5314
#endif
5315
    /* XXX some guesswork here, values are CPU specific */
5316
    env->SYNCI_Step = 16;
5317
    env->CCRes = 2;
5318
}