Statistics
| Branch: | Revision:

root / target-mips / translate.c @ 36d23958

History | View | Annotate | Download (138.9 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
static const char *fregnames[] =
395
    { "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
396
      "f8",  "f9",  "f10", "f11", "f12", "f13", "f14", "f15",
397
      "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
398
      "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
399

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

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

    
432
SFGEN32(gen_op_load_fpr_WT0,  gen_op_load_fpr_WT0_fpr);
433
SFGEN32(gen_op_store_fpr_WT0, gen_op_store_fpr_WT0_fpr);
434

    
435
SFGEN32(gen_op_load_fpr_WT1,  gen_op_load_fpr_WT1_fpr);
436
SFGEN32(gen_op_store_fpr_WT1, gen_op_store_fpr_WT1_fpr);
437

    
438
SFGEN32(gen_op_load_fpr_WT2,  gen_op_load_fpr_WT2_fpr);
439
SFGEN32(gen_op_store_fpr_WT2, gen_op_store_fpr_WT2_fpr);
440

    
441
DFGEN32(gen_op_load_fpr_DT0,  gen_op_load_fpr_DT0_fpr);
442
DFGEN32(gen_op_store_fpr_DT0, gen_op_store_fpr_DT0_fpr);
443

    
444
DFGEN32(gen_op_load_fpr_DT1,  gen_op_load_fpr_DT1_fpr);
445
DFGEN32(gen_op_store_fpr_DT1, gen_op_store_fpr_DT1_fpr);
446

    
447
DFGEN32(gen_op_load_fpr_DT2,  gen_op_load_fpr_DT2_fpr);
448
DFGEN32(gen_op_store_fpr_DT2, gen_op_store_fpr_DT2_fpr);
449

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

    
474
FOP_CONDS(d)
475
FOP_CONDS(s)
476

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
644
/* Load and store */
645
static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
646
                      int base, int16_t offset)
647
{
648
    const char *opn = "unk";
649

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

    
791
/* Load and store */
792
static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
793
                      int base, int16_t offset)
794
{
795
    const char *opn = "unk";
796

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

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

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

    
971
/* Arithmetic */
972
static void gen_arith (DisasContext *ctx, uint32_t opc,
973
                       int rd, int rs, int rt)
974
{
975
    const char *opn = "unk";
976

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

    
1108
/* Arithmetic on HI/LO registers */
1109
static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1110
{
1111
    const char *opn = "unk";
1112

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

    
1147
static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1148
                        int rs, int rt)
1149
{
1150
    const char *opn = "unk";
1151

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

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

    
1251
/* Traps */
1252
static void gen_trap (DisasContext *ctx, uint32_t opc,
1253
                      int rs, int rt, int16_t imm)
1254
{
1255
    int cond;
1256

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

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

    
1367
/* Branches (before delay slot) */
1368
static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
1369
                                int rs, int rt, int32_t offset)
1370
{
1371
    target_ulong btarget;
1372
    int blink, bcond;
1373

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

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

    
1644
/* CP0 (MMU and control) */
1645
static void gen_mfc0 (DisasContext *ctx, int reg, int sel)
1646
{
1647
    const char *rn = "invalid";
1648

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

    
2217
die:
2218
#if defined MIPS_DEBUG_DISAS
2219
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2220
        fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
2221
                rn, reg, sel);
2222
    }
2223
#endif
2224
    generate_exception(ctx, EXCP_RI);
2225
}
2226

    
2227
static void gen_mtc0 (DisasContext *ctx, int reg, int sel)
2228
{
2229
    const char *rn = "invalid";
2230

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

    
2810
die:
2811
#if defined MIPS_DEBUG_DISAS
2812
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2813
        fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
2814
                rn, reg, sel);
2815
    }
2816
#endif
2817
    generate_exception(ctx, EXCP_RI);
2818
}
2819

    
2820
static void gen_dmfc0 (DisasContext *ctx, int reg, int sel)
2821
{
2822
    const char *rn = "invalid";
2823

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

    
3392
die:
3393
#if defined MIPS_DEBUG_DISAS
3394
    if (loglevel & CPU_LOG_TB_IN_ASM) {
3395
        fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
3396
                rn, reg, sel);
3397
    }
3398
#endif
3399
    generate_exception(ctx, EXCP_RI);
3400
}
3401

    
3402
static void gen_dmtc0 (DisasContext *ctx, int reg, int sel)
3403
{
3404
    const char *rn = "invalid";
3405

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

    
3985
die:
3986
#if defined MIPS_DEBUG_DISAS
3987
    if (loglevel & CPU_LOG_TB_IN_ASM) {
3988
        fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
3989
                rn, reg, sel);
3990
    }
3991
#endif
3992
    generate_exception(ctx, EXCP_RI);
3993
}
3994

    
3995
static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd)
3996
{
3997
    const char *opn = "unk";
3998

    
3999
    if ((!ctx->CP0_Status & (1 << CP0St_CU0) &&
4000
          (ctx->hflags & MIPS_HFLAG_UM)) &&
4001
        !(ctx->hflags & MIPS_HFLAG_ERL) &&
4002
        !(ctx->hflags & MIPS_HFLAG_EXL)) {
4003
        if (loglevel & CPU_LOG_TB_IN_ASM) {
4004
            fprintf(logfile, "CP0 is not usable\n");
4005
        }
4006
        generate_exception (ctx, EXCP_CpU);
4007
        return;
4008
    }
4009

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

    
4104
/* CP1 Branches (before delay slot) */
4105
static void gen_compute_branch1 (DisasContext *ctx, uint32_t op,
4106
                                 int32_t offset)
4107
{
4108
    target_ulong btarget;
4109

    
4110
    btarget = ctx->pc + 4 + offset;
4111

    
4112
    switch (op) {
4113
    case OPC_BC1F:
4114
        gen_op_bc1f();
4115
        MIPS_DEBUG("bc1f " TARGET_FMT_lx, btarget);
4116
        goto not_likely;
4117
    case OPC_BC1FL:
4118
        gen_op_bc1f();
4119
        MIPS_DEBUG("bc1fl " TARGET_FMT_lx, btarget);
4120
        goto likely;
4121
    case OPC_BC1T:
4122
        gen_op_bc1t();
4123
        MIPS_DEBUG("bc1t " TARGET_FMT_lx, btarget);
4124
    not_likely:
4125
        ctx->hflags |= MIPS_HFLAG_BC;
4126
        break;
4127
    case OPC_BC1TL:
4128
        gen_op_bc1t();
4129
        MIPS_DEBUG("bc1tl " TARGET_FMT_lx, btarget);
4130
    likely:
4131
        ctx->hflags |= MIPS_HFLAG_BL;
4132
        break;
4133
    default:    
4134
        MIPS_INVAL("cp1 branch/jump");
4135
        generate_exception_err (ctx, EXCP_RI, 1);
4136
        return;
4137
    }
4138
    gen_op_set_bcond();
4139

    
4140
    MIPS_DEBUG("enter ds: cond %02x target " TARGET_FMT_lx,
4141
               ctx->hflags, btarget);
4142
    ctx->btarget = btarget;
4143

    
4144
    return;
4145
}
4146

    
4147
/* Coprocessor 1 (FPU) */
4148
static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
4149
{
4150
    const char *opn = "unk";
4151

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

    
4202
/* verify if floating point register is valid; an operation is not defined
4203
 * if bit 0 of any register specification is set and the FR bit in the
4204
 * Status register equals zero, since the register numbers specify an
4205
 * even-odd pair of adjacent coprocessor general registers. When the FR bit
4206
 * in the Status register equals one, both even and odd register numbers
4207
 * are valid. This limitation exists only for 64 bit wide (d,l) registers.
4208
 * 
4209
 * Multiple 64 bit wide registers can be checked by calling
4210
 * CHECK_FR(ctx, freg1 | freg2 | ... | fregN);
4211
 */
4212
#define CHECK_FR(ctx, freg) do { \
4213
        if (!((ctx)->CP0_Status & (1<<CP0St_FR)) && ((freg) & 1)) { \
4214
            generate_exception_err (ctx, EXCP_RI, 1); \
4215
            return; \
4216
        } \
4217
    } while(0)
4218

    
4219
#define FOP(func, fmt) (((fmt) << 21) | (func))
4220

    
4221
static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, int fs, int fd)
4222
{
4223
    const char *opn = "unk";
4224
    const char *condnames[] = {
4225
            "c.f",
4226
            "c.un",
4227
            "c.eq",
4228
            "c.ueq",
4229
            "c.olt",
4230
            "c.ult",
4231
            "c.ole",
4232
            "c.ule",
4233
            "c.sf",
4234
            "c.ngle",
4235
            "c.seq",
4236
            "c.ngl",
4237
            "c.lt",
4238
            "c.nge",
4239
            "c.le",
4240
            "c.ngt",
4241
    };
4242
    int binary = 0;
4243
    uint32_t func = ctx->opcode & 0x3f;
4244

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

    
4508
static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
4509
{
4510
    uint32_t ccbit;
4511

    
4512
    if (cc)
4513
        ccbit = 1 << (24 + cc);
4514
    else
4515
        ccbit = 1 << 23;
4516
    if (!tf)
4517
        gen_op_movf(ccbit, rd, rs);
4518
    else
4519
       gen_op_movt(ccbit, rd, rs);
4520
}
4521

    
4522
/* ISA extensions (ASEs) */
4523
/* MIPS16 extension to MIPS32 */
4524
/* SmartMIPS extension to MIPS32 */
4525

    
4526
#ifdef MIPS_HAS_MIPS64
4527
/* Coprocessor 3 (FPU) */
4528

    
4529
/* MDMX extension to MIPS64 */
4530
/* MIPS-3D extension to MIPS64 */
4531

    
4532
#endif
4533

    
4534
static void gen_blikely(DisasContext *ctx)
4535
{
4536
    int l1;
4537
    l1 = gen_new_label();
4538
    gen_op_jnz_T2(l1);
4539
    gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
4540
    gen_goto_tb(ctx, 1, ctx->pc + 4);
4541
    gen_set_label(l1);
4542
}
4543

    
4544
static void decode_opc (CPUState *env, DisasContext *ctx)
4545
{
4546
    int32_t offset;
4547
    int rs, rt, rd, sa;
4548
    uint32_t op, op1, op2;
4549
    int16_t imm;
4550

    
4551
    /* make sure instructions are on a word boundary */
4552
    if (ctx->pc & 0x3) {
4553
        generate_exception(ctx, EXCP_AdEL);
4554
        return;
4555
    }
4556

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

    
4620
        case OPC_MOVCI:
4621
            if (env->CP0_Config1 & (1 << CP0C1_FP)) {
4622
                gen_op_cp1_enabled();
4623
                gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
4624
                          (ctx->opcode >> 16) & 1);
4625
            } else {
4626
                generate_exception(ctx, EXCP_RI);
4627
            }
4628
            break;
4629

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

    
4854
    /* Floating point.  */
4855
    case OPC_LWC1:
4856
    case OPC_LDC1:
4857
    case OPC_SWC1:
4858
    case OPC_SDC1:
4859
        if (env->CP0_Config1 & (1 << CP0C1_FP)) {
4860
            save_cpu_state(ctx, 1);
4861
            gen_op_cp1_enabled();
4862
            gen_flt_ldst(ctx, op, rt, rs, imm);
4863
        } else {
4864
            generate_exception_err(ctx, EXCP_CpU, 1);
4865
        }
4866
        break;
4867

    
4868
    case OPC_CP1:
4869
        if (env->CP0_Config1 & (1 << CP0C1_FP)) {
4870
            save_cpu_state(ctx, 1);
4871
            gen_op_cp1_enabled();
4872
            op1 = MASK_CP1(ctx->opcode);
4873
            switch (op1) {
4874
            case OPC_MFC1:
4875
            case OPC_CFC1:
4876
            case OPC_MTC1:
4877
            case OPC_CTC1:
4878
#ifdef MIPS_HAS_MIPS64
4879
            case OPC_DMFC1:
4880
            case OPC_DMTC1:
4881
#endif
4882
                gen_cp1(ctx, op1, rt, rd);
4883
                break;
4884
            case OPC_BC1:
4885
                gen_compute_branch1(ctx, MASK_CP1_BCOND(ctx->opcode), imm << 2);
4886
                return;
4887
            case OPC_S_FMT:
4888
            case OPC_D_FMT:
4889
            case OPC_W_FMT:
4890
            case OPC_L_FMT:
4891
                gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa);
4892
                break;
4893
            default:
4894
                generate_exception_err(ctx, EXCP_RI, 1);
4895
                break;
4896
            }
4897
        } else {
4898
            generate_exception_err(ctx, EXCP_CpU, 1);
4899
        }
4900
        break;
4901

    
4902
    /* COP2.  */
4903
    case OPC_LWC2:
4904
    case OPC_LDC2:
4905
    case OPC_SWC2:
4906
    case OPC_SDC2:
4907
    case OPC_CP2:
4908
        /* COP2: Not implemented. */
4909
        generate_exception_err(ctx, EXCP_CpU, 2);
4910
        break;
4911

    
4912
    case OPC_CP3:
4913
        if (env->CP0_Config1 & (1 << CP0C1_FP)) {
4914
            gen_op_cp1_enabled();
4915
            op1 = MASK_CP3(ctx->opcode);
4916
            switch (op1) {
4917
            /* Not implemented */
4918
            default:
4919
                generate_exception_err(ctx, EXCP_RI, 1);
4920
                break;
4921
            }
4922
        } else {
4923
            generate_exception(ctx, EXCP_RI);
4924
        }
4925
        break;
4926

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

    
4996
int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
4997
                                    int search_pc)
4998
{
4999
    DisasContext ctx, *ctxp = &ctx;
5000
    target_ulong pc_start;
5001
    uint16_t *gen_opc_end;
5002
    int j, lj = -1;
5003

    
5004
    if (search_pc && loglevel)
5005
        fprintf (logfile, "search pc %d\n", search_pc);
5006

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

    
5060
        if (search_pc) {
5061
            j = gen_opc_ptr - gen_opc_buf;
5062
            if (lj < j) {
5063
                lj++;
5064
                while (lj < j)
5065
                    gen_opc_instr_start[lj++] = 0;
5066
            }
5067
            gen_opc_pc[lj] = ctx.pc;
5068
            gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
5069
            gen_opc_instr_start[lj] = 1;
5070
        }
5071
        ctx.opcode = ldl_code(ctx.pc);
5072
        decode_opc(env, &ctx);
5073
        ctx.pc += 4;
5074

    
5075
        if (env->singlestep_enabled)
5076
            break;
5077

    
5078
        if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
5079
            break;
5080

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

    
5131
int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
5132
{
5133
    return gen_intermediate_code_internal(env, tb, 0);
5134
}
5135

    
5136
int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
5137
{
5138
    return gen_intermediate_code_internal(env, tb, 1);
5139
}
5140

    
5141
void fpu_dump_state(CPUState *env, FILE *f, 
5142
                    int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
5143
                    int flags)
5144
{
5145
    int i;
5146

    
5147
#   define printfpr(fp) do { \
5148
        fpu_fprintf(f, "w:%08x d:%08lx%08lx fd:%g fs:%g\n", \
5149
                (fp)->w[FP_ENDIAN_IDX], (fp)->w[0], (fp)->w[1], (fp)->fd, (fp)->fs[FP_ENDIAN_IDX]); \
5150
    } while(0)
5151

    
5152
    fpu_fprintf(f, "CP1 FCR0 0x%08x  FCR31 0x%08x  SR.FR %d\n",
5153
                env->fcr0, env->fcr31,
5154
                (env->CP0_Status & (1 << CP0St_FR)) != 0);
5155
    fpu_fprintf(f, "FT0: "); printfpr(&env->ft0);
5156
    fpu_fprintf(f, "FT1: "); printfpr(&env->ft1);
5157
    fpu_fprintf(f, "FT2: "); printfpr(&env->ft2);
5158
    for(i = 0; i < 32; i += 2) {
5159
        fpu_fprintf(f, "%s: ", fregnames[i]);
5160
        printfpr(FPR(env, i));
5161
    }
5162

    
5163
#undef printfpr
5164
}
5165

    
5166
void dump_fpu (CPUState *env)
5167
{
5168
    if (loglevel) { 
5169
       fprintf(logfile, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx " %d\n",
5170
               env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
5171
       fpu_dump_state(env, logfile, fprintf, 0);
5172
    }
5173
}
5174

    
5175
#if defined(MIPS_HAS_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
5176
/* Debug help: The architecture requires 32bit code to maintain proper
5177
   sign-extened values on 64bit machines.  */
5178

    
5179
#define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
5180

    
5181
void cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
5182
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
5183
                     int flags)
5184
{
5185
    int i;
5186

    
5187
    if (!SIGN_EXT_P(env->PC))
5188
        cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->PC);
5189
    if (!SIGN_EXT_P(env->HI))
5190
        cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->HI);
5191
    if (!SIGN_EXT_P(env->LO))
5192
        cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->LO);
5193
    if (!SIGN_EXT_P(env->btarget))
5194
        cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
5195

    
5196
    for (i = 0; i < 32; i++) {
5197
        if (!SIGN_EXT_P(env->gpr[i]))
5198
            cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->gpr[i]);
5199
    }
5200

    
5201
    if (!SIGN_EXT_P(env->CP0_EPC))
5202
        cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
5203
    if (!SIGN_EXT_P(env->CP0_LLAddr))
5204
        cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
5205
}
5206
#endif
5207

    
5208
void cpu_dump_state (CPUState *env, FILE *f, 
5209
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
5210
                     int flags)
5211
{
5212
    uint32_t c0_status;
5213
    int i;
5214
    
5215
    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",
5216
                env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
5217
    for (i = 0; i < 32; i++) {
5218
        if ((i & 3) == 0)
5219
            cpu_fprintf(f, "GPR%02d:", i);
5220
        cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->gpr[i]);
5221
        if ((i & 3) == 3)
5222
            cpu_fprintf(f, "\n");
5223
    }
5224

    
5225
    c0_status = env->CP0_Status;
5226
    if (env->hflags & MIPS_HFLAG_UM)
5227
        c0_status |= (1 << CP0St_UM);
5228
    if (env->hflags & MIPS_HFLAG_ERL)
5229
        c0_status |= (1 << CP0St_ERL);
5230
    if (env->hflags & MIPS_HFLAG_EXL)
5231
        c0_status |= (1 << CP0St_EXL);
5232

    
5233
    cpu_fprintf(f, "CP0 Status  0x%08x Cause   0x%08x EPC    0x" TARGET_FMT_lx "\n",
5234
                c0_status, env->CP0_Cause, env->CP0_EPC);
5235
    cpu_fprintf(f, "    Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
5236
                env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
5237
    if (c0_status & (1 << CP0St_CU1))
5238
        fpu_dump_state(env, f, cpu_fprintf, flags);
5239
#if defined(MIPS_HAS_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
5240
    cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
5241
#endif
5242
}
5243

    
5244
CPUMIPSState *cpu_mips_init (void)
5245
{
5246
    CPUMIPSState *env;
5247

    
5248
    env = qemu_mallocz(sizeof(CPUMIPSState));
5249
    if (!env)
5250
        return NULL;
5251
    cpu_exec_init(env);
5252
    cpu_reset(env);
5253
    return env;
5254
}
5255

    
5256
void cpu_reset (CPUMIPSState *env)
5257
{
5258
    memset(env, 0, offsetof(CPUMIPSState, breakpoints));
5259

    
5260
    tlb_flush(env, 1);
5261

    
5262
    /* Minimal init */
5263
#if !defined(CONFIG_USER_ONLY)
5264
    if (env->hflags & MIPS_HFLAG_BMASK) {
5265
        /* If the exception was raised from a delay slot,
5266
         * come back to the jump.  */
5267
        env->CP0_ErrorEPC = env->PC - 4;
5268
        env->hflags &= ~MIPS_HFLAG_BMASK;
5269
    } else {
5270
        env->CP0_ErrorEPC = env->PC;
5271
    }
5272
    env->PC = (int32_t)0xBFC00000;
5273
#if defined (MIPS_USES_R4K_TLB)
5274
    env->CP0_Random = MIPS_TLB_NB - 1;
5275
    env->tlb_in_use = MIPS_TLB_NB;
5276
#endif
5277
    env->CP0_Wired = 0;
5278
    /* SMP not implemented */
5279
    env->CP0_EBase = 0x80000000;
5280
    env->CP0_Config0 = MIPS_CONFIG0;
5281
    env->CP0_Config1 = MIPS_CONFIG1;
5282
#ifdef MIPS_USES_FPU
5283
    /* basic FPU register support */
5284
    env->CP0_Config1 |= (1 << CP0C1_FP);
5285
#endif
5286
    env->CP0_Config2 = MIPS_CONFIG2;
5287
    env->CP0_Config3 = MIPS_CONFIG3;
5288
    env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
5289
    env->CP0_WatchLo = 0;
5290
    env->hflags = MIPS_HFLAG_ERL;
5291
    /* Count register increments in debug mode, EJTAG version 1 */
5292
    env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
5293
    env->CP0_PRid = MIPS_CPU;
5294
#endif
5295
    env->exception_index = EXCP_NONE;
5296
#if defined(CONFIG_USER_ONLY)
5297
    env->hflags |= MIPS_HFLAG_UM;
5298
    env->user_mode_only = 1;
5299
#endif
5300
    env->fcr0 = MIPS_FCR0;
5301
    /* XXX some guesswork here, values are CPU specific */
5302
    env->SYNCI_Step = 16;
5303
    env->CCRes = 2;
5304
}