Statistics
| Branch: | Revision:

root / target-mips / translate.c @ 3953d786

History | View | Annotate | Download (139.1 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 = -1;
1372
    int blink = 0;
1373
    int bcond = 0;
1374

    
1375
    if (ctx->hflags & MIPS_HFLAG_BMASK) {
1376
        if (loglevel & CPU_LOG_TB_IN_ASM) {
1377
            fprintf(logfile,
1378
                    "undefined branch in delay slot at pc 0x%08x\n", ctx->pc);
1379
        }
1380
        MIPS_INVAL("branch/jump in bdelay slot");
1381
        generate_exception(ctx, EXCP_RI);
1382
        return;
1383
    }
1384

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
4112
/* CP1 Branches (before delay slot) */
4113
static void gen_compute_branch1 (DisasContext *ctx, uint32_t op,
4114
                                 int32_t offset)
4115
{
4116
    target_ulong btarget;
4117

    
4118
    btarget = ctx->pc + 4 + offset;
4119

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

    
4148
    MIPS_DEBUG("enter ds: cond %02x target " TARGET_FMT_lx,
4149
               ctx->hflags, btarget);
4150
    ctx->btarget = btarget;
4151

    
4152
    return;
4153
}
4154

    
4155
/* Coprocessor 1 (FPU) */
4156
static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
4157
{
4158
    const char *opn = "unk";
4159

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

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

    
4227
#define FOP(func, fmt) (((fmt) << 21) | (func))
4228

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

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

    
4516
static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
4517
{
4518
    uint32_t ccbit;
4519

    
4520
    if (cc)
4521
        ccbit = 1 << (24 + cc);
4522
    else
4523
        ccbit = 1 << 23;
4524
    if (!tf)
4525
        gen_op_movf(ccbit, rd, rs);
4526
    else
4527
       gen_op_movt(ccbit, rd, rs);
4528
}
4529

    
4530
/* ISA extensions (ASEs) */
4531
/* MIPS16 extension to MIPS32 */
4532
/* SmartMIPS extension to MIPS32 */
4533

    
4534
#ifdef MIPS_HAS_MIPS64
4535
/* Coprocessor 3 (FPU) */
4536

    
4537
/* MDMX extension to MIPS64 */
4538
/* MIPS-3D extension to MIPS64 */
4539

    
4540
#endif
4541

    
4542
static void gen_blikely(DisasContext *ctx)
4543
{
4544
    int l1;
4545
    l1 = gen_new_label();
4546
    gen_op_jnz_T2(l1);
4547
    gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
4548
    gen_goto_tb(ctx, 1, ctx->pc + 4);
4549
    gen_set_label(l1);
4550
}
4551

    
4552
static void decode_opc (CPUState *env, DisasContext *ctx)
4553
{
4554
    int32_t offset;
4555
    int rs, rt, rd, sa;
4556
    uint32_t op, op1, op2;
4557
    int16_t imm;
4558

    
4559
    /* make sure instructions are on a word boundary */
4560
    if (ctx->pc & 0x3) {
4561
        generate_exception(ctx, EXCP_AdEL);
4562
        return;
4563
    }
4564

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

    
4628
        case OPC_MOVCI:
4629
            if (env->CP0_Config1 & (1 << CP0C1_FP)) {
4630
                gen_op_cp1_enabled();
4631
                gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
4632
                          (ctx->opcode >> 16) & 1);
4633
            } else {
4634
                generate_exception(ctx, EXCP_RI);
4635
            }
4636
            break;
4637

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

    
4868
    /* Floating point.  */
4869
    case OPC_LWC1:
4870
    case OPC_LDC1:
4871
    case OPC_SWC1:
4872
    case OPC_SDC1:
4873
        if (env->CP0_Config1 & (1 << CP0C1_FP)) {
4874
            save_cpu_state(ctx, 1);
4875
            gen_op_cp1_enabled();
4876
            gen_flt_ldst(ctx, op, rt, rs, imm);
4877
        } else {
4878
            generate_exception_err(ctx, EXCP_CpU, 1);
4879
        }
4880
        break;
4881

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

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

    
4926
    case OPC_CP3:
4927
        if (env->CP0_Config1 & (1 << CP0C1_FP)) {
4928
            gen_op_cp1_enabled();
4929
            op1 = MASK_CP3(ctx->opcode);
4930
            switch (op1) {
4931
            /* Not implemented */
4932
            default:
4933
                generate_exception_err(ctx, EXCP_RI, 1);
4934
                break;
4935
            }
4936
        } else {
4937
            generate_exception(ctx, EXCP_RI);
4938
        }
4939
        break;
4940

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

    
5010
static inline int
5011
gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
5012
                                int search_pc)
5013
{
5014
    DisasContext ctx, *ctxp = &ctx;
5015
    target_ulong pc_start;
5016
    uint16_t *gen_opc_end;
5017
    int j, lj = -1;
5018

    
5019
    if (search_pc && loglevel)
5020
        fprintf (logfile, "search pc %d\n", search_pc);
5021

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

    
5075
        if (search_pc) {
5076
            j = gen_opc_ptr - gen_opc_buf;
5077
            if (lj < j) {
5078
                lj++;
5079
                while (lj < j)
5080
                    gen_opc_instr_start[lj++] = 0;
5081
            }
5082
            gen_opc_pc[lj] = ctx.pc;
5083
            gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
5084
            gen_opc_instr_start[lj] = 1;
5085
        }
5086
        ctx.opcode = ldl_code(ctx.pc);
5087
        decode_opc(env, &ctx);
5088
        ctx.pc += 4;
5089

    
5090
        if (env->singlestep_enabled)
5091
            break;
5092

    
5093
        if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
5094
            break;
5095

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

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

    
5151
int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
5152
{
5153
    return gen_intermediate_code_internal(env, tb, 1);
5154
}
5155

    
5156
void fpu_dump_state(CPUState *env, FILE *f, 
5157
                    int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
5158
                    int flags)
5159
{
5160
    int i;
5161

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

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

    
5178
#undef printfpr
5179
}
5180

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

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

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

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

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

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

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

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

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

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

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

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

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

    
5275
    tlb_flush(env, 1);
5276

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

    
5311
#include "translate_init.c"