Statistics
| Branch: | Revision:

root / target-mips / translate.c @ 60aa19ab

History | View | Annotate | Download (139 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 TARGET_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 TARGET_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(ctx, EXCP_RI);
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 TARGET_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 TARGET_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 TARGET_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 TARGET_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 TARGET_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 TARGET_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
        /* 4,5 are reserved */
1951
        /* 6,7 are implementation dependent */
1952
        case 6:
1953
            gen_op_mfc0_config6();
1954
            rn = "Config6";
1955
            break;
1956
        case 7:
1957
            gen_op_mfc0_config7();
1958
            rn = "Config7";
1959
            break;
1960
        default:
1961
            goto die;
1962
        }
1963
        break;
1964
    case 17:
1965
        switch (sel) {
1966
        case 0:
1967
           gen_op_mfc0_lladdr();
1968
           rn = "LLAddr";
1969
           break;
1970
        default:
1971
            goto die;
1972
        }
1973
        break;
1974
    case 18:
1975
        switch (sel) {
1976
        case 0:
1977
           gen_op_mfc0_watchlo0();
1978
           rn = "WatchLo";
1979
           break;
1980
        case 1:
1981
//         gen_op_mfc0_watchlo1();
1982
           rn = "WatchLo1";
1983
//         break;
1984
        case 2:
1985
//         gen_op_mfc0_watchlo2();
1986
           rn = "WatchLo2";
1987
//         break;
1988
        case 3:
1989
//         gen_op_mfc0_watchlo3();
1990
           rn = "WatchLo3";
1991
//         break;
1992
        case 4:
1993
//         gen_op_mfc0_watchlo4();
1994
           rn = "WatchLo4";
1995
//         break;
1996
        case 5:
1997
//         gen_op_mfc0_watchlo5();
1998
           rn = "WatchLo5";
1999
//         break;
2000
        case 6:
2001
//         gen_op_mfc0_watchlo6();
2002
           rn = "WatchLo6";
2003
//         break;
2004
        case 7:
2005
//         gen_op_mfc0_watchlo7();
2006
           rn = "WatchLo7";
2007
//         break;
2008
        default:
2009
            goto die;
2010
        }
2011
        break;
2012
    case 19:
2013
        switch (sel) {
2014
        case 0:
2015
           gen_op_mfc0_watchhi0();
2016
           rn = "WatchHi";
2017
           break;
2018
        case 1:
2019
//         gen_op_mfc0_watchhi1();
2020
           rn = "WatchHi1";
2021
//         break;
2022
        case 2:
2023
//         gen_op_mfc0_watchhi2();
2024
           rn = "WatchHi2";
2025
//         break;
2026
        case 3:
2027
//         gen_op_mfc0_watchhi3();
2028
           rn = "WatchHi3";
2029
//         break;
2030
        case 4:
2031
//         gen_op_mfc0_watchhi4();
2032
           rn = "WatchHi4";
2033
//         break;
2034
        case 5:
2035
//         gen_op_mfc0_watchhi5();
2036
           rn = "WatchHi5";
2037
//         break;
2038
        case 6:
2039
//         gen_op_mfc0_watchhi6();
2040
           rn = "WatchHi6";
2041
//         break;
2042
        case 7:
2043
//         gen_op_mfc0_watchhi7();
2044
           rn = "WatchHi7";
2045
//         break;
2046
        default:
2047
            goto die;
2048
        }
2049
        break;
2050
    case 20:
2051
        switch (sel) {
2052
        case 0:
2053
           /* 64 bit MMU only */
2054
           gen_op_mfc0_xcontext();
2055
           rn = "XContext";
2056
           break;
2057
        default:
2058
            goto die;
2059
        }
2060
        break;
2061
    case 21:
2062
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
2063
        switch (sel) {
2064
        case 0:
2065
           gen_op_mfc0_framemask();
2066
           rn = "Framemask";
2067
           break;
2068
        default:
2069
            goto die;
2070
        }
2071
        break;
2072
    case 22:
2073
       /* ignored */
2074
       rn = "'Diagnostic"; /* implementation dependent */
2075
       break;
2076
    case 23:
2077
        switch (sel) {
2078
        case 0:
2079
           gen_op_mfc0_debug(); /* EJTAG support */
2080
           rn = "Debug";
2081
           break;
2082
        case 1:
2083
//         gen_op_mfc0_tracecontrol(); /* PDtrace support */
2084
           rn = "TraceControl";
2085
//         break;
2086
        case 2:
2087
//         gen_op_mfc0_tracecontrol2(); /* PDtrace support */
2088
           rn = "TraceControl2";
2089
//         break;
2090
        case 3:
2091
//         gen_op_mfc0_usertracedata(); /* PDtrace support */
2092
           rn = "UserTraceData";
2093
//         break;
2094
        case 4:
2095
//         gen_op_mfc0_debug(); /* PDtrace support */
2096
           rn = "TraceBPC";
2097
//         break;
2098
        default:
2099
            goto die;
2100
        }
2101
        break;
2102
    case 24:
2103
        switch (sel) {
2104
        case 0:
2105
           gen_op_mfc0_depc(); /* EJTAG support */
2106
           rn = "DEPC";
2107
           break;
2108
        default:
2109
            goto die;
2110
        }
2111
        break;
2112
    case 25:
2113
        switch (sel) {
2114
        case 0:
2115
           gen_op_mfc0_performance0();
2116
           rn = "Performance0";
2117
            break;
2118
        case 1:
2119
//         gen_op_mfc0_performance1();
2120
           rn = "Performance1";
2121
//         break;
2122
        case 2:
2123
//         gen_op_mfc0_performance2();
2124
           rn = "Performance2";
2125
//         break;
2126
        case 3:
2127
//         gen_op_mfc0_performance3();
2128
           rn = "Performance3";
2129
//         break;
2130
        case 4:
2131
//         gen_op_mfc0_performance4();
2132
           rn = "Performance4";
2133
//         break;
2134
        case 5:
2135
//         gen_op_mfc0_performance5();
2136
           rn = "Performance5";
2137
//         break;
2138
        case 6:
2139
//         gen_op_mfc0_performance6();
2140
           rn = "Performance6";
2141
//         break;
2142
        case 7:
2143
//         gen_op_mfc0_performance7();
2144
           rn = "Performance7";
2145
//         break;
2146
        default:
2147
            goto die;
2148
        }
2149
        break;
2150
    case 26:
2151
       rn = "ECC";
2152
       break;
2153
    case 27:
2154
        switch (sel) {
2155
        /* ignored */
2156
        case 0 ... 3:
2157
           rn = "CacheErr";
2158
           break;
2159
        default:
2160
            goto die;
2161
        }
2162
        break;
2163
    case 28:
2164
        switch (sel) {
2165
        case 0:
2166
        case 2:
2167
        case 4:
2168
        case 6:
2169
            gen_op_mfc0_taglo();
2170
            rn = "TagLo";
2171
            break;
2172
        case 1:
2173
        case 3:
2174
        case 5:
2175
        case 7:
2176
            gen_op_mfc0_datalo();
2177
            rn = "DataLo";
2178
            break;
2179
        default:
2180
            goto die;
2181
        }
2182
        break;
2183
    case 29:
2184
        switch (sel) {
2185
        case 0:
2186
        case 2:
2187
        case 4:
2188
        case 6:
2189
            gen_op_mfc0_taghi();
2190
            rn = "TagHi";
2191
            break;
2192
        case 1:
2193
        case 3:
2194
        case 5:
2195
        case 7:
2196
            gen_op_mfc0_datahi();
2197
            rn = "DataHi";
2198
            break;
2199
        default:
2200
            goto die;
2201
        }
2202
        break;
2203
    case 30:
2204
        switch (sel) {
2205
        case 0:
2206
           gen_op_mfc0_errorepc();
2207
           rn = "ErrorEPC";
2208
           break;
2209
        default:
2210
            goto die;
2211
        }
2212
        break;
2213
    case 31:
2214
        switch (sel) {
2215
        case 0:
2216
           gen_op_mfc0_desave(); /* EJTAG support */
2217
           rn = "DESAVE";
2218
           break;
2219
        default:
2220
            goto die;
2221
        }
2222
        break;
2223
    default:
2224
       goto die;
2225
    }
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
    return;
2233

    
2234
die:
2235
#if defined MIPS_DEBUG_DISAS
2236
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2237
        fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
2238
                rn, reg, sel);
2239
    }
2240
#endif
2241
    generate_exception(ctx, EXCP_RI);
2242
}
2243

    
2244
static void gen_mtc0 (DisasContext *ctx, int reg, int sel)
2245
{
2246
    const char *rn = "invalid";
2247

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

    
2836
die:
2837
#if defined MIPS_DEBUG_DISAS
2838
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2839
        fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
2840
                rn, reg, sel);
2841
    }
2842
#endif
2843
    generate_exception(ctx, EXCP_RI);
2844
}
2845

    
2846
static void gen_dmfc0 (DisasContext *ctx, int reg, int sel)
2847
{
2848
    const char *rn = "invalid";
2849

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

    
3418
die:
3419
#if defined MIPS_DEBUG_DISAS
3420
    if (loglevel & CPU_LOG_TB_IN_ASM) {
3421
        fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
3422
                rn, reg, sel);
3423
    }
3424
#endif
3425
    generate_exception(ctx, EXCP_RI);
3426
}
3427

    
3428
static void gen_dmtc0 (DisasContext *ctx, int reg, int sel)
3429
{
3430
    const char *rn = "invalid";
3431

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

    
4011
die:
4012
#if defined MIPS_DEBUG_DISAS
4013
    if (loglevel & CPU_LOG_TB_IN_ASM) {
4014
        fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
4015
                rn, reg, sel);
4016
    }
4017
#endif
4018
    generate_exception(ctx, EXCP_RI);
4019
}
4020

    
4021
static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd)
4022
{
4023
    const char *opn = "unk";
4024

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

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

    
4125
    btarget = ctx->pc + 4 + offset;
4126

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

    
4155
    MIPS_DEBUG("enter ds: cond %02x target " TARGET_FMT_lx,
4156
               ctx->hflags, btarget);
4157
    ctx->btarget = btarget;
4158

    
4159
    return;
4160
}
4161

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

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

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

    
4234
#define FOP(func, fmt) (((fmt) << 21) | (func))
4235

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

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

    
4523
static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
4524
{
4525
    uint32_t ccbit;
4526

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

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

    
4541
#ifdef TARGET_MIPS64
4542
/* Coprocessor 3 (FPU) */
4543

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

    
4547
#endif
4548

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

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

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

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

    
4635
        case OPC_MOVCI:
4636
            if (env->CP0_Config1 & (1 << CP0C1_FP)) {
4637
                save_cpu_state(ctx, 1);
4638
                gen_op_cp1_enabled();
4639
                gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
4640
                          (ctx->opcode >> 16) & 1);
4641
            } else {
4642
                generate_exception_err(ctx, EXCP_CpU, 1);
4643
            }
4644
            break;
4645

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

    
4877
    /* Floating point.  */
4878
    case OPC_LWC1:
4879
    case OPC_LDC1:
4880
    case OPC_SWC1:
4881
    case OPC_SDC1:
4882
        if (env->CP0_Config1 & (1 << CP0C1_FP)) {
4883
            save_cpu_state(ctx, 1);
4884
            gen_op_cp1_enabled();
4885
            gen_flt_ldst(ctx, op, rt, rs, imm);
4886
        } else {
4887
            generate_exception_err(ctx, EXCP_CpU, 1);
4888
        }
4889
        break;
4890

    
4891
    case OPC_CP1:
4892
        if (env->CP0_Config1 & (1 << CP0C1_FP)) {
4893
            save_cpu_state(ctx, 1);
4894
            gen_op_cp1_enabled();
4895
            op1 = MASK_CP1(ctx->opcode);
4896
            switch (op1) {
4897
            case OPC_MFC1:
4898
            case OPC_CFC1:
4899
            case OPC_MTC1:
4900
            case OPC_CTC1:
4901
#ifdef TARGET_MIPS64
4902
            case OPC_DMFC1:
4903
            case OPC_DMTC1:
4904
#endif
4905
                gen_cp1(ctx, op1, rt, rd);
4906
                break;
4907
            case OPC_BC1:
4908
                gen_compute_branch1(ctx, MASK_CP1_BCOND(ctx->opcode), imm << 2);
4909
                return;
4910
            case OPC_S_FMT:
4911
            case OPC_D_FMT:
4912
            case OPC_W_FMT:
4913
            case OPC_L_FMT:
4914
                gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa);
4915
                break;
4916
            default:
4917
                generate_exception (ctx, EXCP_RI);
4918
                break;
4919
            }
4920
        } else {
4921
            generate_exception_err(ctx, EXCP_CpU, 1);
4922
        }
4923
        break;
4924

    
4925
    /* COP2.  */
4926
    case OPC_LWC2:
4927
    case OPC_LDC2:
4928
    case OPC_SWC2:
4929
    case OPC_SDC2:
4930
    case OPC_CP2:
4931
        /* COP2: Not implemented. */
4932
        generate_exception_err(ctx, EXCP_CpU, 2);
4933
        break;
4934

    
4935
    case OPC_CP3:
4936
        if (env->CP0_Config1 & (1 << CP0C1_FP)) {
4937
            save_cpu_state(ctx, 1);
4938
            gen_op_cp1_enabled();
4939
            op1 = MASK_CP3(ctx->opcode);
4940
            switch (op1) {
4941
            /* Not implemented */
4942
            default:
4943
                generate_exception (ctx, EXCP_RI);
4944
                break;
4945
            }
4946
        } else {
4947
            generate_exception_err(ctx, EXCP_CpU, 1);
4948
        }
4949
        break;
4950

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

    
5020
static inline int
5021
gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
5022
                                int search_pc)
5023
{
5024
    DisasContext ctx, *ctxp = &ctx;
5025
    target_ulong pc_start;
5026
    uint16_t *gen_opc_end;
5027
    int j, lj = -1;
5028

    
5029
    if (search_pc && loglevel)
5030
        fprintf (logfile, "search pc %d\n", search_pc);
5031

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

    
5085
        if (search_pc) {
5086
            j = gen_opc_ptr - gen_opc_buf;
5087
            if (lj < j) {
5088
                lj++;
5089
                while (lj < j)
5090
                    gen_opc_instr_start[lj++] = 0;
5091
            }
5092
            gen_opc_pc[lj] = ctx.pc;
5093
            gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
5094
            gen_opc_instr_start[lj] = 1;
5095
        }
5096
        ctx.opcode = ldl_code(ctx.pc);
5097
        decode_opc(env, &ctx);
5098
        ctx.pc += 4;
5099

    
5100
        if (env->singlestep_enabled)
5101
            break;
5102

    
5103
        if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
5104
            break;
5105

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

    
5156
int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
5157
{
5158
    return gen_intermediate_code_internal(env, tb, 0);
5159
}
5160

    
5161
int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
5162
{
5163
    return gen_intermediate_code_internal(env, tb, 1);
5164
}
5165

    
5166
void fpu_dump_state(CPUState *env, FILE *f, 
5167
                    int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
5168
                    int flags)
5169
{
5170
    int i;
5171

    
5172
#   define printfpr(fp) do { \
5173
        fpu_fprintf(f, "w:%08x d:%08lx%08lx fd:%g fs:%g\n", \
5174
                (fp)->w[FP_ENDIAN_IDX], (fp)->w[0], (fp)->w[1], (fp)->fd, (fp)->fs[FP_ENDIAN_IDX]); \
5175
    } while(0)
5176

    
5177
    fpu_fprintf(f, "CP1 FCR0 0x%08x  FCR31 0x%08x  SR.FR %d\n",
5178
                env->fcr0, env->fcr31,
5179
                (env->CP0_Status & (1 << CP0St_FR)) != 0);
5180
    fpu_fprintf(f, "FT0: "); printfpr(&env->ft0);
5181
    fpu_fprintf(f, "FT1: "); printfpr(&env->ft1);
5182
    fpu_fprintf(f, "FT2: "); printfpr(&env->ft2);
5183
    for(i = 0; i < 32; i += 2) {
5184
        fpu_fprintf(f, "%s: ", fregnames[i]);
5185
        printfpr(FPR(env, i));
5186
    }
5187

    
5188
#undef printfpr
5189
}
5190

    
5191
void dump_fpu (CPUState *env)
5192
{
5193
    if (loglevel) { 
5194
       fprintf(logfile, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx " %d\n",
5195
               env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
5196
       fpu_dump_state(env, logfile, fprintf, 0);
5197
    }
5198
}
5199

    
5200
#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
5201
/* Debug help: The architecture requires 32bit code to maintain proper
5202
   sign-extened values on 64bit machines.  */
5203

    
5204
#define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
5205

    
5206
void cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
5207
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
5208
                     int flags)
5209
{
5210
    int i;
5211

    
5212
    if (!SIGN_EXT_P(env->PC))
5213
        cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->PC);
5214
    if (!SIGN_EXT_P(env->HI))
5215
        cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->HI);
5216
    if (!SIGN_EXT_P(env->LO))
5217
        cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->LO);
5218
    if (!SIGN_EXT_P(env->btarget))
5219
        cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
5220

    
5221
    for (i = 0; i < 32; i++) {
5222
        if (!SIGN_EXT_P(env->gpr[i]))
5223
            cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->gpr[i]);
5224
    }
5225

    
5226
    if (!SIGN_EXT_P(env->CP0_EPC))
5227
        cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
5228
    if (!SIGN_EXT_P(env->CP0_LLAddr))
5229
        cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
5230
}
5231
#endif
5232

    
5233
void cpu_dump_state (CPUState *env, FILE *f, 
5234
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
5235
                     int flags)
5236
{
5237
    uint32_t c0_status;
5238
    int i;
5239
    
5240
    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",
5241
                env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
5242
    for (i = 0; i < 32; i++) {
5243
        if ((i & 3) == 0)
5244
            cpu_fprintf(f, "GPR%02d:", i);
5245
        cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->gpr[i]);
5246
        if ((i & 3) == 3)
5247
            cpu_fprintf(f, "\n");
5248
    }
5249

    
5250
    c0_status = env->CP0_Status;
5251

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

    
5263
CPUMIPSState *cpu_mips_init (void)
5264
{
5265
    CPUMIPSState *env;
5266

    
5267
    env = qemu_mallocz(sizeof(CPUMIPSState));
5268
    if (!env)
5269
        return NULL;
5270
    cpu_exec_init(env);
5271
    cpu_reset(env);
5272
    return env;
5273
}
5274

    
5275
void cpu_reset (CPUMIPSState *env)
5276
{
5277
    memset(env, 0, offsetof(CPUMIPSState, breakpoints));
5278

    
5279
    tlb_flush(env, 1);
5280

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

    
5315
#include "translate_init.c"