Statistics
| Branch: | Revision:

root / target-mips / translate.c @ 2423f660

History | View | Annotate | Download (143.9 kB)

1
/*
2
 *  MIPS32 emulation for qemu: main translation routines.
3
 * 
4
 *  Copyright (c) 2004-2005 Jocelyn Mayer
5
 *  Copyright (c) 2006 Marius Groeger (FPU operations)
6
 *  Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2 of the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with this library; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
 */
22

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

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

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

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

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

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

    
53
#include "gen-op.h"
54

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

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

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

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

    
199
    OPC_MOVCI    = 0x01 | OPC_SPECIAL,
200

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
362
enum {
363
    OPC_MFC2    = (0x00 << 21) | OPC_CP2,
364
    OPC_DMFC2   = (0x01 << 21) | OPC_CP2,
365
    OPC_CFC2    = (0x02 << 21) | OPC_CP2,
366
    OPC_MFHC2   = (0x03 << 21) | OPC_CP2,
367
    OPC_MTC2    = (0x04 << 21) | OPC_CP2,
368
    OPC_DMTC2   = (0x05 << 21) | OPC_CP2,
369
    OPC_CTC2    = (0x06 << 21) | OPC_CP2,
370
    OPC_MTHC2   = (0x07 << 21) | OPC_CP2,
371
    OPC_BC2     = (0x08 << 21) | OPC_CP2,
372
};
373

    
374
#define MASK_CP3(op)       MASK_OP_MAJOR(op) | (op & 0x3F)
375

    
376
enum {
377
    OPC_LWXC1   = 0x00 | OPC_CP3,
378
    OPC_LDXC1   = 0x01 | OPC_CP3,
379
    OPC_LUXC1   = 0x05 | OPC_CP3,
380
    OPC_SWXC1   = 0x08 | OPC_CP3,
381
    OPC_SDXC1   = 0x09 | OPC_CP3,
382
    OPC_SUXC1   = 0x0D | OPC_CP3,
383
    OPC_PREFX   = 0x0F | OPC_CP3,
384
    OPC_ALNV_PS = 0x1E | OPC_CP3,
385
    OPC_MADD_S  = 0x20 | OPC_CP3,
386
    OPC_MADD_D  = 0x21 | OPC_CP3,
387
    OPC_MADD_PS = 0x26 | OPC_CP3,
388
    OPC_MSUB_S  = 0x28 | OPC_CP3,
389
    OPC_MSUB_D  = 0x29 | OPC_CP3,
390
    OPC_MSUB_PS = 0x2E | OPC_CP3,
391
    OPC_NMADD_S = 0x30 | OPC_CP3,
392
    OPC_NMADD_D = 0x32 | OPC_CP3,
393
    OPC_NMADD_PS= 0x36 | OPC_CP3,
394
    OPC_NMSUB_S = 0x38 | OPC_CP3,
395
    OPC_NMSUB_D = 0x39 | OPC_CP3,
396
    OPC_NMSUB_PS= 0x3E | OPC_CP3,
397
};
398

    
399

    
400
const unsigned char *regnames[] =
401
    { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
402
      "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
403
      "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
404
      "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
405

    
406
/* Warning: no function for r0 register (hard wired to zero) */
407
#define GEN32(func, NAME) \
408
static GenOpFunc *NAME ## _table [32] = {                                     \
409
NULL,       NAME ## 1, NAME ## 2, NAME ## 3,                                  \
410
NAME ## 4,  NAME ## 5, NAME ## 6, NAME ## 7,                                  \
411
NAME ## 8,  NAME ## 9, NAME ## 10, NAME ## 11,                                \
412
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
413
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
414
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
415
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
416
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
417
};                                                                            \
418
static inline void func(int n)                                                \
419
{                                                                             \
420
    NAME ## _table[n]();                                                      \
421
}
422

    
423
/* General purpose registers moves */
424
GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
425
GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
426
GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr);
427

    
428
GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
429
GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
430

    
431
static const char *fregnames[] =
432
    { "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
433
      "f8",  "f9",  "f10", "f11", "f12", "f13", "f14", "f15",
434
      "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
435
      "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
436

    
437
# define SFGEN32(func, NAME) \
438
static GenOpFunc *NAME ## _table [32] = {                                     \
439
NAME ## 0,  NAME ## 1,  NAME ## 2,  NAME ## 3,                                \
440
NAME ## 4,  NAME ## 5,  NAME ## 6,  NAME ## 7,                                \
441
NAME ## 8,  NAME ## 9,  NAME ## 10, NAME ## 11,                               \
442
NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
443
NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
444
NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
445
NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
446
NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
447
};                                                                            \
448
static inline void func(int n)                                                \
449
{                                                                             \
450
    NAME ## _table[n]();                                                      \
451
}
452

    
453
# define DFGEN32(func, NAME) \
454
static GenOpFunc *NAME ## _table [32] = {                                     \
455
NAME ## 0,  0, NAME ## 2,  0,                                                 \
456
NAME ## 4,  0, NAME ## 6,  0,                                                 \
457
NAME ## 8,  0, NAME ## 10, 0,                                                 \
458
NAME ## 12, 0, NAME ## 14, 0,                                                 \
459
NAME ## 16, 0, NAME ## 18, 0,                                                 \
460
NAME ## 20, 0, NAME ## 22, 0,                                                 \
461
NAME ## 24, 0, NAME ## 26, 0,                                                 \
462
NAME ## 28, 0, NAME ## 30, 0,                                                 \
463
};                                                                            \
464
static inline void func(int n)                                                \
465
{                                                                             \
466
    NAME ## _table[n]();                                                      \
467
}
468

    
469
SFGEN32(gen_op_load_fpr_WT0,  gen_op_load_fpr_WT0_fpr);
470
SFGEN32(gen_op_store_fpr_WT0, gen_op_store_fpr_WT0_fpr);
471

    
472
SFGEN32(gen_op_load_fpr_WT1,  gen_op_load_fpr_WT1_fpr);
473
SFGEN32(gen_op_store_fpr_WT1, gen_op_store_fpr_WT1_fpr);
474

    
475
SFGEN32(gen_op_load_fpr_WT2,  gen_op_load_fpr_WT2_fpr);
476
SFGEN32(gen_op_store_fpr_WT2, gen_op_store_fpr_WT2_fpr);
477

    
478
DFGEN32(gen_op_load_fpr_DT0,  gen_op_load_fpr_DT0_fpr);
479
DFGEN32(gen_op_store_fpr_DT0, gen_op_store_fpr_DT0_fpr);
480

    
481
DFGEN32(gen_op_load_fpr_DT1,  gen_op_load_fpr_DT1_fpr);
482
DFGEN32(gen_op_store_fpr_DT1, gen_op_store_fpr_DT1_fpr);
483

    
484
DFGEN32(gen_op_load_fpr_DT2,  gen_op_load_fpr_DT2_fpr);
485
DFGEN32(gen_op_store_fpr_DT2, gen_op_store_fpr_DT2_fpr);
486

    
487
#define FOP_CONDS(fmt) \
488
static GenOpFunc * cond_ ## fmt ## _table[16] = {                       \
489
    gen_op_cmp_ ## fmt ## _f,                                           \
490
    gen_op_cmp_ ## fmt ## _un,                                          \
491
    gen_op_cmp_ ## fmt ## _eq,                                          \
492
    gen_op_cmp_ ## fmt ## _ueq,                                         \
493
    gen_op_cmp_ ## fmt ## _olt,                                         \
494
    gen_op_cmp_ ## fmt ## _ult,                                         \
495
    gen_op_cmp_ ## fmt ## _ole,                                         \
496
    gen_op_cmp_ ## fmt ## _ule,                                         \
497
    gen_op_cmp_ ## fmt ## _sf,                                          \
498
    gen_op_cmp_ ## fmt ## _ngle,                                        \
499
    gen_op_cmp_ ## fmt ## _seq,                                         \
500
    gen_op_cmp_ ## fmt ## _ngl,                                         \
501
    gen_op_cmp_ ## fmt ## _lt,                                          \
502
    gen_op_cmp_ ## fmt ## _nge,                                         \
503
    gen_op_cmp_ ## fmt ## _le,                                          \
504
    gen_op_cmp_ ## fmt ## _ngt,                                         \
505
};                                                                      \
506
static inline void gen_cmp_ ## fmt(int n)                               \
507
{                                                                       \
508
    cond_ ## fmt ## _table[n]();                                        \
509
}
510

    
511
FOP_CONDS(d)
512
FOP_CONDS(s)
513

    
514
typedef struct DisasContext {
515
    struct TranslationBlock *tb;
516
    target_ulong pc, saved_pc;
517
    uint32_t opcode;
518
    /* Routine used to access memory */
519
    int mem_idx;
520
    uint32_t hflags, saved_hflags;
521
    uint32_t CP0_Status;
522
    int bstate;
523
    target_ulong btarget;
524
} DisasContext;
525

    
526
enum {
527
    BS_NONE     = 0, /* We go out of the TB without reaching a branch or an
528
                      * exception condition
529
                      */
530
    BS_STOP     = 1, /* We want to stop translation for any reason */
531
    BS_BRANCH   = 2, /* We reached a branch condition     */
532
    BS_EXCP     = 3, /* We reached an exception condition */
533
};
534

    
535
#if defined MIPS_DEBUG_DISAS
536
#define MIPS_DEBUG(fmt, args...)                                              \
537
do {                                                                          \
538
    if (loglevel & CPU_LOG_TB_IN_ASM) {                                       \
539
        fprintf(logfile, TARGET_FMT_lx ": %08x " fmt "\n",                    \
540
                ctx->pc, ctx->opcode , ##args);                               \
541
    }                                                                         \
542
} while (0)
543
#else
544
#define MIPS_DEBUG(fmt, args...) do { } while(0)
545
#endif
546

    
547
#define MIPS_INVAL(op)                                                        \
548
do {                                                                          \
549
    MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26,            \
550
               ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F));             \
551
} while (0)
552

    
553
#define GEN_LOAD_REG_TN(Tn, Rn)                                               \
554
do {                                                                          \
555
    if (Rn == 0) {                                                            \
556
        glue(gen_op_reset_, Tn)();                                            \
557
    } else {                                                                  \
558
        glue(gen_op_load_gpr_, Tn)(Rn);                                       \
559
    }                                                                         \
560
} while (0)
561

    
562
#define GEN_LOAD_IMM_TN(Tn, Imm)                                              \
563
do {                                                                          \
564
    if (Imm == 0) {                                                           \
565
        glue(gen_op_reset_, Tn)();                                            \
566
    } else {                                                                  \
567
        glue(gen_op_set_, Tn)(Imm);                                           \
568
    }                                                                         \
569
} while (0)
570

    
571
#define GEN_STORE_TN_REG(Rn, Tn)                                              \
572
do {                                                                          \
573
    if (Rn != 0) {                                                            \
574
        glue(glue(gen_op_store_, Tn),_gpr)(Rn);                               \
575
    }                                                                         \
576
} while (0)
577

    
578
#define GEN_LOAD_FREG_FTN(FTn, Fn)                                            \
579
do {                                                                          \
580
    glue(gen_op_load_fpr_, FTn)(Fn);                                          \
581
} while (0)
582

    
583
#define GEN_STORE_FTN_FREG(Fn, FTn)                                           \
584
do {                                                                          \
585
    glue(gen_op_store_fpr_, FTn)(Fn);                                         \
586
} while (0)
587

    
588
static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
589
{
590
#if defined MIPS_DEBUG_DISAS
591
    if (loglevel & CPU_LOG_TB_IN_ASM) {
592
            fprintf(logfile, "hflags %08x saved %08x\n",
593
                    ctx->hflags, ctx->saved_hflags);
594
    }
595
#endif
596
    if (do_save_pc && ctx->pc != ctx->saved_pc) {
597
        gen_op_save_pc(ctx->pc);
598
        ctx->saved_pc = ctx->pc;
599
    }
600
    if (ctx->hflags != ctx->saved_hflags) {
601
        gen_op_save_state(ctx->hflags);
602
        ctx->saved_hflags = ctx->hflags;
603
        if (ctx->hflags & MIPS_HFLAG_BR) {
604
            gen_op_save_breg_target();
605
        } else if (ctx->hflags & MIPS_HFLAG_B) {
606
            gen_op_save_btarget(ctx->btarget);
607
        } else if (ctx->hflags & MIPS_HFLAG_BMASK) {
608
            gen_op_save_bcond();
609
            gen_op_save_btarget(ctx->btarget);
610
        }
611
    }
612
}
613

    
614
static inline void generate_exception_err (DisasContext *ctx, int excp, int err)
615
{
616
#if defined MIPS_DEBUG_DISAS
617
    if (loglevel & CPU_LOG_TB_IN_ASM)
618
            fprintf(logfile, "%s: raise exception %d\n", __func__, excp);
619
#endif
620
    save_cpu_state(ctx, 1);
621
    if (err == 0)
622
        gen_op_raise_exception(excp);
623
    else
624
        gen_op_raise_exception_err(excp, err);
625
    ctx->bstate = BS_EXCP;
626
}
627

    
628
static inline void generate_exception (DisasContext *ctx, int excp)
629
{
630
    generate_exception_err (ctx, excp, 0);
631
}
632

    
633
#if defined(CONFIG_USER_ONLY)
634
#define op_ldst(name)        gen_op_##name##_raw()
635
#define OP_LD_TABLE(width)
636
#define OP_ST_TABLE(width)
637
#else
638
#define op_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
639
#define OP_LD_TABLE(width)                                                    \
640
static GenOpFunc *gen_op_l##width[] = {                                       \
641
    &gen_op_l##width##_user,                                                  \
642
    &gen_op_l##width##_kernel,                                                \
643
}
644
#define OP_ST_TABLE(width)                                                    \
645
static GenOpFunc *gen_op_s##width[] = {                                       \
646
    &gen_op_s##width##_user,                                                  \
647
    &gen_op_s##width##_kernel,                                                \
648
}
649
#endif
650

    
651
#ifdef TARGET_MIPS64
652
OP_LD_TABLE(d);
653
OP_LD_TABLE(dl);
654
OP_LD_TABLE(dr);
655
OP_ST_TABLE(d);
656
OP_ST_TABLE(dl);
657
OP_ST_TABLE(dr);
658
OP_LD_TABLE(ld);
659
OP_ST_TABLE(cd);
660
#endif
661
OP_LD_TABLE(w);
662
OP_LD_TABLE(wu);
663
OP_LD_TABLE(wl);
664
OP_LD_TABLE(wr);
665
OP_ST_TABLE(w);
666
OP_ST_TABLE(wl);
667
OP_ST_TABLE(wr);
668
OP_LD_TABLE(h);
669
OP_LD_TABLE(hu);
670
OP_ST_TABLE(h);
671
OP_LD_TABLE(b);
672
OP_LD_TABLE(bu);
673
OP_ST_TABLE(b);
674
OP_LD_TABLE(l);
675
OP_ST_TABLE(c);
676
OP_LD_TABLE(wc1);
677
OP_ST_TABLE(wc1);
678
OP_LD_TABLE(dc1);
679
OP_ST_TABLE(dc1);
680

    
681
/* Load and store */
682
static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
683
                      int base, int16_t offset)
684
{
685
    const char *opn = "unk";
686

    
687
    if (base == 0) {
688
        GEN_LOAD_IMM_TN(T0, offset);
689
    } else if (offset == 0) {
690
        gen_op_load_gpr_T0(base);
691
    } else {
692
        gen_op_load_gpr_T0(base);
693
        gen_op_set_T1(offset);
694
        gen_op_add();
695
    }
696
    /* Don't do NOP if destination is zero: we must perform the actual
697
     * memory access
698
     */
699
    switch (opc) {
700
#ifdef TARGET_MIPS64
701
    case OPC_LD:
702
        op_ldst(ld);
703
        GEN_STORE_TN_REG(rt, T0);
704
        opn = "ld";
705
        break;
706
    case OPC_LLD:
707
        op_ldst(lld);
708
        GEN_STORE_TN_REG(rt, T0);
709
        opn = "lld";
710
        break;
711
    case OPC_SD:
712
        GEN_LOAD_REG_TN(T1, rt);
713
        op_ldst(sd);
714
        opn = "sd";
715
        break;
716
    case OPC_SCD:
717
        save_cpu_state(ctx, 1);
718
        GEN_LOAD_REG_TN(T1, rt);
719
        op_ldst(scd);
720
        opn = "scd";
721
        break;
722
    case OPC_LDL:
723
        op_ldst(ldl);
724
        GEN_STORE_TN_REG(rt, T0);
725
        opn = "ldl";
726
        break;
727
    case OPC_SDL:
728
        GEN_LOAD_REG_TN(T1, rt);
729
        op_ldst(sdl);
730
        opn = "sdl";
731
        break;
732
    case OPC_LDR:
733
        op_ldst(ldr);
734
        GEN_STORE_TN_REG(rt, T0);
735
        opn = "ldr";
736
        break;
737
    case OPC_SDR:
738
        GEN_LOAD_REG_TN(T1, rt);
739
        op_ldst(sdr);
740
        opn = "sdr";
741
        break;
742
#endif
743
    case OPC_LW:
744
        op_ldst(lw);
745
        GEN_STORE_TN_REG(rt, T0);
746
        opn = "lw";
747
        break;
748
    case OPC_LWU:
749
        op_ldst(lwu);
750
        GEN_STORE_TN_REG(rt, T0);
751
        opn = "lwu";
752
        break;
753
    case OPC_SW:
754
        GEN_LOAD_REG_TN(T1, rt);
755
        op_ldst(sw);
756
        opn = "sw";
757
        break;
758
    case OPC_LH:
759
        op_ldst(lh);
760
        GEN_STORE_TN_REG(rt, T0);
761
        opn = "lh";
762
        break;
763
    case OPC_SH:
764
        GEN_LOAD_REG_TN(T1, rt);
765
        op_ldst(sh);
766
        opn = "sh";
767
        break;
768
    case OPC_LHU:
769
        op_ldst(lhu);
770
        GEN_STORE_TN_REG(rt, T0);
771
        opn = "lhu";
772
        break;
773
    case OPC_LB:
774
        op_ldst(lb);
775
        GEN_STORE_TN_REG(rt, T0);
776
        opn = "lb";
777
        break;
778
    case OPC_SB:
779
        GEN_LOAD_REG_TN(T1, rt);
780
        op_ldst(sb);
781
        opn = "sb";
782
        break;
783
    case OPC_LBU:
784
        op_ldst(lbu);
785
        GEN_STORE_TN_REG(rt, T0);
786
        opn = "lbu";
787
        break;
788
    case OPC_LWL:
789
        GEN_LOAD_REG_TN(T1, rt);
790
        op_ldst(lwl);
791
        GEN_STORE_TN_REG(rt, T0);
792
        opn = "lwl";
793
        break;
794
    case OPC_SWL:
795
        GEN_LOAD_REG_TN(T1, rt);
796
        op_ldst(swl);
797
        opn = "swr";
798
        break;
799
    case OPC_LWR:
800
        GEN_LOAD_REG_TN(T1, rt);
801
        op_ldst(lwr);
802
        GEN_STORE_TN_REG(rt, T0);
803
        opn = "lwr";
804
        break;
805
    case OPC_SWR:
806
        GEN_LOAD_REG_TN(T1, rt);
807
        op_ldst(swr);
808
        opn = "swr";
809
        break;
810
    case OPC_LL:
811
        op_ldst(ll);
812
        GEN_STORE_TN_REG(rt, T0);
813
        opn = "ll";
814
        break;
815
    case OPC_SC:
816
        save_cpu_state(ctx, 1);
817
        GEN_LOAD_REG_TN(T1, rt);
818
        op_ldst(sc);
819
        GEN_STORE_TN_REG(rt, T0);
820
        opn = "sc";
821
        break;
822
    default:
823
        MIPS_INVAL("load/store");
824
        generate_exception(ctx, EXCP_RI);
825
        return;
826
    }
827
    MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
828
}
829

    
830
/* Load and store */
831
static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
832
                      int base, int16_t offset)
833
{
834
    const char *opn = "unk";
835

    
836
    if (base == 0) {
837
        GEN_LOAD_IMM_TN(T0, offset);
838
    } else if (offset == 0) {
839
        gen_op_load_gpr_T0(base);
840
    } else {
841
        gen_op_load_gpr_T0(base);
842
        gen_op_set_T1(offset);
843
        gen_op_add();
844
    }
845
    /* Don't do NOP if destination is zero: we must perform the actual
846
     * memory access
847
     */
848
    switch (opc) {
849
    case OPC_LWC1:
850
        op_ldst(lwc1);
851
        GEN_STORE_FTN_FREG(ft, WT0);
852
        opn = "lwc1";
853
        break;
854
    case OPC_SWC1:
855
        GEN_LOAD_FREG_FTN(WT0, ft);
856
        op_ldst(swc1);
857
        opn = "swc1";
858
        break;
859
    case OPC_LDC1:
860
        op_ldst(ldc1);
861
        GEN_STORE_FTN_FREG(ft, DT0);
862
        opn = "ldc1";
863
        break;
864
    case OPC_SDC1:
865
        GEN_LOAD_FREG_FTN(DT0, ft);
866
        op_ldst(sdc1);
867
        opn = "sdc1";
868
        break;
869
    default:
870
        MIPS_INVAL("float load/store");
871
        generate_exception(ctx, EXCP_RI);
872
        return;
873
    }
874
    MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
875
}
876

    
877
/* Arithmetic with immediate operand */
878
static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt,
879
                           int rs, int16_t imm)
880
{
881
    uint32_t uimm;
882
    const char *opn = "unk";
883

    
884
    if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
885
        /* if no destination, treat it as a NOP 
886
         * For addi, we must generate the overflow exception when needed.
887
         */
888
        MIPS_DEBUG("NOP");
889
        return;
890
    }
891
    uimm = (uint16_t)imm;
892
    switch (opc) {
893
    case OPC_ADDI:
894
    case OPC_ADDIU:
895
#ifdef TARGET_MIPS64
896
    case OPC_DADDI:
897
    case OPC_DADDIU:
898
#endif
899
    case OPC_SLTI:
900
    case OPC_SLTIU:
901
        uimm = (int32_t)imm; /* Sign extend to 32 bits */
902
        /* Fall through. */
903
    case OPC_ANDI:
904
    case OPC_ORI:
905
    case OPC_XORI:
906
        GEN_LOAD_REG_TN(T0, rs);
907
        GEN_LOAD_IMM_TN(T1, uimm);
908
        break;
909
    case OPC_LUI:
910
        uimm <<= 16;
911
        GEN_LOAD_IMM_TN(T0, uimm);
912
        break;
913
    case OPC_SLL:
914
    case OPC_SRA:
915
    case OPC_SRL:
916
#ifdef TARGET_MIPS64
917
    case OPC_DSLL:
918
    case OPC_DSRA:
919
    case OPC_DSRL:
920
    case OPC_DSLL32:
921
    case OPC_DSRA32:
922
    case OPC_DSRL32:
923
#endif
924
        uimm &= 0x1f;
925
        GEN_LOAD_REG_TN(T0, rs);
926
        GEN_LOAD_IMM_TN(T1, uimm);
927
        break;
928
    }
929
    switch (opc) {
930
    case OPC_ADDI:
931
        save_cpu_state(ctx, 1);
932
        gen_op_addo();
933
        opn = "addi";
934
        break;
935
    case OPC_ADDIU:
936
        gen_op_add();
937
        opn = "addiu";
938
        break;
939
#ifdef TARGET_MIPS64
940
    case OPC_DADDI:
941
        save_cpu_state(ctx, 1);
942
        gen_op_daddo();
943
        opn = "daddi";
944
        break;
945
    case OPC_DADDIU:
946
        gen_op_dadd();
947
        opn = "daddiu";
948
        break;
949
#endif
950
    case OPC_SLTI:
951
        gen_op_lt();
952
        opn = "slti";
953
        break;
954
    case OPC_SLTIU:
955
        gen_op_ltu();
956
        opn = "sltiu";
957
        break;
958
    case OPC_ANDI:
959
        gen_op_and();
960
        opn = "andi";
961
        break;
962
    case OPC_ORI:
963
        gen_op_or();
964
        opn = "ori";
965
        break;
966
    case OPC_XORI:
967
        gen_op_xor();
968
        opn = "xori";
969
        break;
970
    case OPC_LUI:
971
        opn = "lui";
972
        break;
973
    case OPC_SLL:
974
        gen_op_sll();
975
        opn = "sll";
976
        break;
977
    case OPC_SRA:
978
        gen_op_sra();
979
        opn = "sra";
980
        break;
981
    case OPC_SRL:
982
        switch ((ctx->opcode >> 21) & 0x1f) {
983
        case 0:
984
            gen_op_srl();
985
            opn = "srl";
986
            break;
987
        case 1:
988
            gen_op_rotr();
989
            opn = "rotr";
990
            break;
991
        default:
992
            MIPS_INVAL("invalid srl flag");
993
            generate_exception(ctx, EXCP_RI);
994
            break;
995
        }
996
        break;
997
#ifdef TARGET_MIPS64
998
    case OPC_DSLL:
999
        gen_op_dsll();
1000
        opn = "dsll";
1001
        break;
1002
    case OPC_DSRA:
1003
        gen_op_dsra();
1004
        opn = "dsra";
1005
        break;
1006
    case OPC_DSRL:
1007
        switch ((ctx->opcode >> 21) & 0x1f) {
1008
        case 0:
1009
            gen_op_dsrl();
1010
            opn = "dsrl";
1011
            break;
1012
        case 1:
1013
            gen_op_drotr();
1014
            opn = "drotr";
1015
            break;
1016
        default:
1017
            MIPS_INVAL("invalid dsrl flag");
1018
            generate_exception(ctx, EXCP_RI);
1019
            break;
1020
        }
1021
        break;
1022
    case OPC_DSLL32:
1023
        gen_op_dsll32();
1024
        opn = "dsll32";
1025
        break;
1026
    case OPC_DSRA32:
1027
        gen_op_dsra32();
1028
        opn = "dsra32";
1029
        break;
1030
    case OPC_DSRL32:
1031
        switch ((ctx->opcode >> 21) & 0x1f) {
1032
        case 0:
1033
            gen_op_dsrl32();
1034
            opn = "dsrl32";
1035
            break;
1036
        case 1:
1037
            gen_op_drotr32();
1038
            opn = "drotr32";
1039
            break;
1040
        default:
1041
            MIPS_INVAL("invalid dsrl32 flag");
1042
            generate_exception(ctx, EXCP_RI);
1043
            break;
1044
        }
1045
        break;
1046
#endif
1047
    default:
1048
        MIPS_INVAL("imm arith");
1049
        generate_exception(ctx, EXCP_RI);
1050
        return;
1051
    }
1052
    GEN_STORE_TN_REG(rt, T0);
1053
    MIPS_DEBUG("%s %s, %s, %x", opn, regnames[rt], regnames[rs], uimm);
1054
}
1055

    
1056
/* Arithmetic */
1057
static void gen_arith (DisasContext *ctx, uint32_t opc,
1058
                       int rd, int rs, int rt)
1059
{
1060
    const char *opn = "unk";
1061

    
1062
    if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1063
       && opc != OPC_DADD && opc != OPC_DSUB) {
1064
        /* if no destination, treat it as a NOP 
1065
         * For add & sub, we must generate the overflow exception when needed.
1066
         */
1067
        MIPS_DEBUG("NOP");
1068
        return;
1069
    }
1070
    GEN_LOAD_REG_TN(T0, rs);
1071
    GEN_LOAD_REG_TN(T1, rt);
1072
    switch (opc) {
1073
    case OPC_ADD:
1074
        save_cpu_state(ctx, 1);
1075
        gen_op_addo();
1076
        opn = "add";
1077
        break;
1078
    case OPC_ADDU:
1079
        gen_op_add();
1080
        opn = "addu";
1081
        break;
1082
    case OPC_SUB:
1083
        save_cpu_state(ctx, 1);
1084
        gen_op_subo();
1085
        opn = "sub";
1086
        break;
1087
    case OPC_SUBU:
1088
        gen_op_sub();
1089
        opn = "subu";
1090
        break;
1091
#ifdef TARGET_MIPS64
1092
    case OPC_DADD:
1093
        save_cpu_state(ctx, 1);
1094
        gen_op_daddo();
1095
        opn = "dadd";
1096
        break;
1097
    case OPC_DADDU:
1098
        gen_op_dadd();
1099
        opn = "daddu";
1100
        break;
1101
    case OPC_DSUB:
1102
        save_cpu_state(ctx, 1);
1103
        gen_op_dsubo();
1104
        opn = "dsub";
1105
        break;
1106
    case OPC_DSUBU:
1107
        gen_op_dsub();
1108
        opn = "dsubu";
1109
        break;
1110
#endif
1111
    case OPC_SLT:
1112
        gen_op_lt();
1113
        opn = "slt";
1114
        break;
1115
    case OPC_SLTU:
1116
        gen_op_ltu();
1117
        opn = "sltu";
1118
        break;
1119
    case OPC_AND:
1120
        gen_op_and();
1121
        opn = "and";
1122
        break;
1123
    case OPC_NOR:
1124
        gen_op_nor();
1125
        opn = "nor";
1126
        break;
1127
    case OPC_OR:
1128
        gen_op_or();
1129
        opn = "or";
1130
        break;
1131
    case OPC_XOR:
1132
        gen_op_xor();
1133
        opn = "xor";
1134
        break;
1135
    case OPC_MUL:
1136
        gen_op_mul();
1137
        opn = "mul";
1138
        break;
1139
    case OPC_MOVN:
1140
        gen_op_movn(rd);
1141
        opn = "movn";
1142
        goto print;
1143
    case OPC_MOVZ:
1144
        gen_op_movz(rd);
1145
        opn = "movz";
1146
        goto print;
1147
    case OPC_SLLV:
1148
        gen_op_sllv();
1149
        opn = "sllv";
1150
        break;
1151
    case OPC_SRAV:
1152
        gen_op_srav();
1153
        opn = "srav";
1154
        break;
1155
    case OPC_SRLV:
1156
        switch ((ctx->opcode >> 6) & 0x1f) {
1157
        case 0:
1158
            gen_op_srlv();
1159
            opn = "srlv";
1160
            break;
1161
        case 1:
1162
            gen_op_rotrv();
1163
            opn = "rotrv";
1164
            break;
1165
        default:
1166
            MIPS_INVAL("invalid srlv flag");
1167
            generate_exception(ctx, EXCP_RI);
1168
            break;
1169
        }
1170
        break;
1171
#ifdef TARGET_MIPS64
1172
    case OPC_DSLLV:
1173
        gen_op_dsllv();
1174
        opn = "dsllv";
1175
        break;
1176
    case OPC_DSRAV:
1177
        gen_op_dsrav();
1178
        opn = "dsrav";
1179
        break;
1180
    case OPC_DSRLV:
1181
        switch ((ctx->opcode >> 6) & 0x1f) {
1182
        case 0:
1183
            gen_op_dsrlv();
1184
            opn = "dsrlv";
1185
            break;
1186
        case 1:
1187
            gen_op_drotrv();
1188
            opn = "drotrv";
1189
            break;
1190
        default:
1191
            MIPS_INVAL("invalid dsrlv flag");
1192
            generate_exception(ctx, EXCP_RI);
1193
            break;
1194
        }
1195
        break;
1196
#endif
1197
    default:
1198
        MIPS_INVAL("arith");
1199
        generate_exception(ctx, EXCP_RI);
1200
        return;
1201
    }
1202
    GEN_STORE_TN_REG(rd, T0);
1203
 print:
1204
    MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1205
}
1206

    
1207
/* Arithmetic on HI/LO registers */
1208
static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1209
{
1210
    const char *opn = "unk";
1211

    
1212
    if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1213
        /* Treat as a NOP */
1214
        MIPS_DEBUG("NOP");
1215
        return;
1216
    }
1217
    switch (opc) {
1218
    case OPC_MFHI:
1219
        gen_op_load_HI();
1220
        GEN_STORE_TN_REG(reg, T0);
1221
        opn = "mfhi";
1222
        break;
1223
    case OPC_MFLO:
1224
        gen_op_load_LO();
1225
        GEN_STORE_TN_REG(reg, T0);
1226
        opn = "mflo";
1227
        break;
1228
    case OPC_MTHI:
1229
        GEN_LOAD_REG_TN(T0, reg);
1230
        gen_op_store_HI();
1231
        opn = "mthi";
1232
        break;
1233
    case OPC_MTLO:
1234
        GEN_LOAD_REG_TN(T0, reg);
1235
        gen_op_store_LO();
1236
        opn = "mtlo";
1237
        break;
1238
    default:
1239
        MIPS_INVAL("HILO");
1240
        generate_exception(ctx, EXCP_RI);
1241
        return;
1242
    }
1243
    MIPS_DEBUG("%s %s", opn, regnames[reg]);
1244
}
1245

    
1246
static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1247
                        int rs, int rt)
1248
{
1249
    const char *opn = "unk";
1250

    
1251
    GEN_LOAD_REG_TN(T0, rs);
1252
    GEN_LOAD_REG_TN(T1, rt);
1253
    switch (opc) {
1254
    case OPC_DIV:
1255
        gen_op_div();
1256
        opn = "div";
1257
        break;
1258
    case OPC_DIVU:
1259
        gen_op_divu();
1260
        opn = "divu";
1261
        break;
1262
    case OPC_MULT:
1263
        gen_op_mult();
1264
        opn = "mult";
1265
        break;
1266
    case OPC_MULTU:
1267
        gen_op_multu();
1268
        opn = "multu";
1269
        break;
1270
#ifdef TARGET_MIPS64
1271
    case OPC_DDIV:
1272
        gen_op_ddiv();
1273
        opn = "ddiv";
1274
        break;
1275
    case OPC_DDIVU:
1276
        gen_op_ddivu();
1277
        opn = "ddivu";
1278
        break;
1279
    case OPC_DMULT:
1280
        gen_op_dmult();
1281
        opn = "dmult";
1282
        break;
1283
    case OPC_DMULTU:
1284
        gen_op_dmultu();
1285
        opn = "dmultu";
1286
        break;
1287
#endif
1288
    case OPC_MADD:
1289
        gen_op_madd();
1290
        opn = "madd";
1291
        break;
1292
    case OPC_MADDU:
1293
        gen_op_maddu();
1294
        opn = "maddu";
1295
        break;
1296
    case OPC_MSUB:
1297
        gen_op_msub();
1298
        opn = "msub";
1299
        break;
1300
    case OPC_MSUBU:
1301
        gen_op_msubu();
1302
        opn = "msubu";
1303
        break;
1304
    default:
1305
        MIPS_INVAL("mul/div");
1306
        generate_exception(ctx, EXCP_RI);
1307
        return;
1308
    }
1309
    MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
1310
}
1311

    
1312
static void gen_cl (DisasContext *ctx, uint32_t opc,
1313
                    int rd, int rs)
1314
{
1315
    const char *opn = "unk";
1316
    if (rd == 0) {
1317
        /* Treat as a NOP */
1318
        MIPS_DEBUG("NOP");
1319
        return;
1320
    }
1321
    GEN_LOAD_REG_TN(T0, rs);
1322
    switch (opc) {
1323
    case OPC_CLO:
1324
        gen_op_clo();
1325
        opn = "clo";
1326
        break;
1327
    case OPC_CLZ:
1328
        gen_op_clz();
1329
        opn = "clz";
1330
        break;
1331
#ifdef TARGET_MIPS64
1332
    case OPC_DCLO:
1333
        gen_op_dclo();
1334
        opn = "dclo";
1335
        break;
1336
    case OPC_DCLZ:
1337
        gen_op_dclz();
1338
        opn = "dclz";
1339
        break;
1340
#endif
1341
    default:
1342
        MIPS_INVAL("CLx");
1343
        generate_exception(ctx, EXCP_RI);
1344
        return;
1345
    }
1346
    gen_op_store_T0_gpr(rd);
1347
    MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
1348
}
1349

    
1350
/* Traps */
1351
static void gen_trap (DisasContext *ctx, uint32_t opc,
1352
                      int rs, int rt, int16_t imm)
1353
{
1354
    int cond;
1355

    
1356
    cond = 0;
1357
    /* Load needed operands */
1358
    switch (opc) {
1359
    case OPC_TEQ:
1360
    case OPC_TGE:
1361
    case OPC_TGEU:
1362
    case OPC_TLT:
1363
    case OPC_TLTU:
1364
    case OPC_TNE:
1365
        /* Compare two registers */
1366
        if (rs != rt) {
1367
            GEN_LOAD_REG_TN(T0, rs);
1368
            GEN_LOAD_REG_TN(T1, rt);
1369
            cond = 1;
1370
        }
1371
        break;
1372
    case OPC_TEQI:
1373
    case OPC_TGEI:
1374
    case OPC_TGEIU:
1375
    case OPC_TLTI:
1376
    case OPC_TLTIU:
1377
    case OPC_TNEI:
1378
        /* Compare register to immediate */
1379
        if (rs != 0 || imm != 0) {
1380
            GEN_LOAD_REG_TN(T0, rs);
1381
            GEN_LOAD_IMM_TN(T1, (int32_t)imm);
1382
            cond = 1;
1383
        }
1384
        break;
1385
    }
1386
    if (cond == 0) {
1387
        switch (opc) {
1388
        case OPC_TEQ:   /* rs == rs */
1389
        case OPC_TEQI:  /* r0 == 0  */
1390
        case OPC_TGE:   /* rs >= rs */
1391
        case OPC_TGEI:  /* r0 >= 0  */
1392
        case OPC_TGEU:  /* rs >= rs unsigned */
1393
        case OPC_TGEIU: /* r0 >= 0  unsigned */
1394
            /* Always trap */
1395
            gen_op_set_T0(1);
1396
            break;
1397
        case OPC_TLT:   /* rs < rs           */
1398
        case OPC_TLTI:  /* r0 < 0            */
1399
        case OPC_TLTU:  /* rs < rs unsigned  */
1400
        case OPC_TLTIU: /* r0 < 0  unsigned  */
1401
        case OPC_TNE:   /* rs != rs          */
1402
        case OPC_TNEI:  /* r0 != 0           */
1403
            /* Never trap: treat as NOP */
1404
            return;
1405
        default:
1406
            MIPS_INVAL("TRAP");
1407
            generate_exception(ctx, EXCP_RI);
1408
            return;
1409
        }
1410
    } else {
1411
        switch (opc) {
1412
        case OPC_TEQ:
1413
        case OPC_TEQI:
1414
            gen_op_eq();
1415
            break;
1416
        case OPC_TGE:
1417
        case OPC_TGEI:
1418
            gen_op_ge();
1419
            break;
1420
        case OPC_TGEU:
1421
        case OPC_TGEIU:
1422
            gen_op_geu();
1423
            break;
1424
        case OPC_TLT:
1425
        case OPC_TLTI:
1426
            gen_op_lt();
1427
            break;
1428
        case OPC_TLTU:
1429
        case OPC_TLTIU:
1430
            gen_op_ltu();
1431
            break;
1432
        case OPC_TNE:
1433
        case OPC_TNEI:
1434
            gen_op_ne();
1435
            break;
1436
        default:
1437
            MIPS_INVAL("TRAP");
1438
            generate_exception(ctx, EXCP_RI);
1439
            return;
1440
        }
1441
    }
1442
    save_cpu_state(ctx, 1);
1443
    gen_op_trap();
1444
    ctx->bstate = BS_STOP;
1445
}
1446

    
1447
static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
1448
{
1449
    TranslationBlock *tb;
1450
    tb = ctx->tb;
1451
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
1452
        if (n == 0)
1453
            gen_op_goto_tb0(TBPARAM(tb));
1454
        else
1455
            gen_op_goto_tb1(TBPARAM(tb));
1456
        gen_op_save_pc(dest);
1457
        gen_op_set_T0((long)tb + n);
1458
        gen_op_exit_tb();
1459
    } else {
1460
        gen_op_save_pc(dest);
1461
        gen_op_set_T0(0);
1462
        gen_op_exit_tb();
1463
    }
1464
}
1465

    
1466
/* Branches (before delay slot) */
1467
static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
1468
                                int rs, int rt, int32_t offset)
1469
{
1470
    target_ulong btarget = -1;
1471
    int blink = 0;
1472
    int bcond = 0;
1473

    
1474
    if (ctx->hflags & MIPS_HFLAG_BMASK) {
1475
        if (loglevel & CPU_LOG_TB_IN_ASM) {
1476
            fprintf(logfile,
1477
                    "undefined branch in delay slot at PC " TARGET_FMT_lx "\n",
1478
                    ctx->pc);
1479
        }
1480
        MIPS_INVAL("branch/jump in bdelay slot");
1481
        generate_exception(ctx, EXCP_RI);
1482
        return;
1483
    }
1484

    
1485
    /* Load needed operands */
1486
    switch (opc) {
1487
    case OPC_BEQ:
1488
    case OPC_BEQL:
1489
    case OPC_BNE:
1490
    case OPC_BNEL:
1491
        /* Compare two registers */
1492
        if (rs != rt) {
1493
            GEN_LOAD_REG_TN(T0, rs);
1494
            GEN_LOAD_REG_TN(T1, rt);
1495
            bcond = 1;
1496
        }
1497
        btarget = ctx->pc + 4 + offset;
1498
        break;
1499
    case OPC_BGEZ:
1500
    case OPC_BGEZAL:
1501
    case OPC_BGEZALL:
1502
    case OPC_BGEZL:
1503
    case OPC_BGTZ:
1504
    case OPC_BGTZL:
1505
    case OPC_BLEZ:
1506
    case OPC_BLEZL:
1507
    case OPC_BLTZ:
1508
    case OPC_BLTZAL:
1509
    case OPC_BLTZALL:
1510
    case OPC_BLTZL:
1511
        /* Compare to zero */
1512
        if (rs != 0) {
1513
            gen_op_load_gpr_T0(rs);
1514
            bcond = 1;
1515
        }
1516
        btarget = ctx->pc + 4 + offset;
1517
        break;
1518
    case OPC_J:
1519
    case OPC_JAL:
1520
        /* Jump to immediate */
1521
        btarget = ((ctx->pc + 4) & (int32_t)0xF0000000) | offset;
1522
        break;
1523
    case OPC_JR:
1524
    case OPC_JALR:
1525
        /* Jump to register */
1526
        if (offset != 0 && offset != 16) {
1527
            /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
1528
               others are reserved. */
1529
            generate_exception(ctx, EXCP_RI);
1530
            return;
1531
        }
1532
        GEN_LOAD_REG_TN(T2, rs);
1533
        break;
1534
    default:
1535
        MIPS_INVAL("branch/jump");
1536
        generate_exception(ctx, EXCP_RI);
1537
        return;
1538
    }
1539
    if (bcond == 0) {
1540
        /* No condition to be computed */
1541
        switch (opc) {
1542
        case OPC_BEQ:     /* rx == rx        */
1543
        case OPC_BEQL:    /* rx == rx likely */
1544
        case OPC_BGEZ:    /* 0 >= 0          */
1545
        case OPC_BGEZL:   /* 0 >= 0 likely   */
1546
        case OPC_BLEZ:    /* 0 <= 0          */
1547
        case OPC_BLEZL:   /* 0 <= 0 likely   */
1548
            /* Always take */
1549
            ctx->hflags |= MIPS_HFLAG_B;
1550
            MIPS_DEBUG("balways");
1551
            break;
1552
        case OPC_BGEZAL:  /* 0 >= 0          */
1553
        case OPC_BGEZALL: /* 0 >= 0 likely   */
1554
            /* Always take and link */
1555
            blink = 31;
1556
            ctx->hflags |= MIPS_HFLAG_B;
1557
            MIPS_DEBUG("balways and link");
1558
            break;
1559
        case OPC_BNE:     /* rx != rx        */
1560
        case OPC_BGTZ:    /* 0 > 0           */
1561
        case OPC_BLTZ:    /* 0 < 0           */
1562
            /* Treated as NOP */
1563
            MIPS_DEBUG("bnever (NOP)");
1564
            return;
1565
        case OPC_BLTZAL:  /* 0 < 0           */
1566
            gen_op_set_T0(ctx->pc + 8);
1567
            gen_op_store_T0_gpr(31);
1568
            return;
1569
        case OPC_BLTZALL: /* 0 < 0 likely */
1570
            gen_op_set_T0(ctx->pc + 8);
1571
            gen_op_store_T0_gpr(31);
1572
            gen_goto_tb(ctx, 0, ctx->pc + 8);
1573
            return;
1574
        case OPC_BNEL:    /* rx != rx likely */
1575
        case OPC_BGTZL:   /* 0 > 0 likely */
1576
        case OPC_BLTZL:   /* 0 < 0 likely */
1577
            /* Skip the instruction in the delay slot */
1578
            MIPS_DEBUG("bnever and skip");
1579
            gen_goto_tb(ctx, 0, ctx->pc + 8);
1580
            return;
1581
        case OPC_J:
1582
            ctx->hflags |= MIPS_HFLAG_B;
1583
            MIPS_DEBUG("j %08x", btarget);
1584
            break;
1585
        case OPC_JAL:
1586
            blink = 31;
1587
            ctx->hflags |= MIPS_HFLAG_B;
1588
            MIPS_DEBUG("jal %08x", btarget);
1589
            break;
1590
        case OPC_JR:
1591
            ctx->hflags |= MIPS_HFLAG_BR;
1592
            MIPS_DEBUG("jr %s", regnames[rs]);
1593
            break;
1594
        case OPC_JALR:
1595
            blink = rt;
1596
            ctx->hflags |= MIPS_HFLAG_BR;
1597
            MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
1598
            break;
1599
        default:
1600
            MIPS_INVAL("branch/jump");
1601
            generate_exception(ctx, EXCP_RI);
1602
            return;
1603
        }
1604
    } else {
1605
        switch (opc) {
1606
        case OPC_BEQ:
1607
            gen_op_eq();
1608
            MIPS_DEBUG("beq %s, %s, %08x",
1609
                       regnames[rs], regnames[rt], btarget);
1610
            goto not_likely;
1611
        case OPC_BEQL:
1612
            gen_op_eq();
1613
            MIPS_DEBUG("beql %s, %s, %08x",
1614
                       regnames[rs], regnames[rt], btarget);
1615
            goto likely;
1616
        case OPC_BNE:
1617
            gen_op_ne();
1618
            MIPS_DEBUG("bne %s, %s, %08x",
1619
                       regnames[rs], regnames[rt], btarget);
1620
            goto not_likely;
1621
        case OPC_BNEL:
1622
            gen_op_ne();
1623
            MIPS_DEBUG("bnel %s, %s, %08x",
1624
                       regnames[rs], regnames[rt], btarget);
1625
            goto likely;
1626
        case OPC_BGEZ:
1627
            gen_op_gez();
1628
            MIPS_DEBUG("bgez %s, %08x", regnames[rs], btarget);
1629
            goto not_likely;
1630
        case OPC_BGEZL:
1631
            gen_op_gez();
1632
            MIPS_DEBUG("bgezl %s, %08x", regnames[rs], btarget);
1633
            goto likely;
1634
        case OPC_BGEZAL:
1635
            gen_op_gez();
1636
            MIPS_DEBUG("bgezal %s, %08x", regnames[rs], btarget);
1637
            blink = 31;
1638
            goto not_likely;
1639
        case OPC_BGEZALL:
1640
            gen_op_gez();
1641
            blink = 31;
1642
            MIPS_DEBUG("bgezall %s, %08x", regnames[rs], btarget);
1643
            goto likely;
1644
        case OPC_BGTZ:
1645
            gen_op_gtz();
1646
            MIPS_DEBUG("bgtz %s, %08x", regnames[rs], btarget);
1647
            goto not_likely;
1648
        case OPC_BGTZL:
1649
            gen_op_gtz();
1650
            MIPS_DEBUG("bgtzl %s, %08x", regnames[rs], btarget);
1651
            goto likely;
1652
        case OPC_BLEZ:
1653
            gen_op_lez();
1654
            MIPS_DEBUG("blez %s, %08x", regnames[rs], btarget);
1655
            goto not_likely;
1656
        case OPC_BLEZL:
1657
            gen_op_lez();
1658
            MIPS_DEBUG("blezl %s, %08x", regnames[rs], btarget);
1659
            goto likely;
1660
        case OPC_BLTZ:
1661
            gen_op_ltz();
1662
            MIPS_DEBUG("bltz %s, %08x", regnames[rs], btarget);
1663
            goto not_likely;
1664
        case OPC_BLTZL:
1665
            gen_op_ltz();
1666
            MIPS_DEBUG("bltzl %s, %08x", regnames[rs], btarget);
1667
            goto likely;
1668
        case OPC_BLTZAL:
1669
            gen_op_ltz();
1670
            blink = 31;
1671
            MIPS_DEBUG("bltzal %s, %08x", regnames[rs], btarget);
1672
        not_likely:
1673
            ctx->hflags |= MIPS_HFLAG_BC;
1674
            break;
1675
        case OPC_BLTZALL:
1676
            gen_op_ltz();
1677
            blink = 31;
1678
            MIPS_DEBUG("bltzall %s, %08x", regnames[rs], btarget);
1679
        likely:
1680
            ctx->hflags |= MIPS_HFLAG_BL;
1681
            break;
1682
        default:
1683
            MIPS_INVAL("conditional branch/jump");
1684
            generate_exception(ctx, EXCP_RI);
1685
            return;
1686
        }
1687
        gen_op_set_bcond();
1688
    }
1689
    MIPS_DEBUG("enter ds: link %d cond %02x target %08x",
1690
               blink, ctx->hflags, btarget);
1691
    ctx->btarget = btarget;
1692
    if (blink > 0) {
1693
        gen_op_set_T0(ctx->pc + 8);
1694
        gen_op_store_T0_gpr(blink);
1695
    }
1696
}
1697

    
1698
/* special3 bitfield operations */
1699
static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
1700
                       int rs, int lsb, int msb)
1701
{
1702
    GEN_LOAD_REG_TN(T1, rs);
1703
    switch (opc) {
1704
    case OPC_EXT:
1705
        if (lsb + msb > 31)
1706
            goto fail;
1707
        gen_op_ext(lsb, msb + 1);
1708
        break;
1709
    case OPC_DEXTM:
1710
        if (lsb + msb > 63)
1711
            goto fail;
1712
        gen_op_ext(lsb, msb + 1 + 32);
1713
        break;
1714
    case OPC_DEXTU:
1715
        if (lsb + msb > 63)
1716
            goto fail;
1717
        gen_op_ext(lsb + 32, msb + 1);
1718
        break;
1719
    case OPC_DEXT:
1720
        gen_op_ext(lsb, msb + 1);
1721
        break;
1722
    case OPC_INS:
1723
        if (lsb > msb)
1724
            goto fail;
1725
        GEN_LOAD_REG_TN(T2, rt);
1726
        gen_op_ins(lsb, msb - lsb + 1);
1727
        break;
1728
    case OPC_DINSM:
1729
        if (lsb > msb)
1730
            goto fail;
1731
        GEN_LOAD_REG_TN(T2, rt);
1732
        gen_op_ins(lsb, msb - lsb + 1 + 32);
1733
        break;
1734
    case OPC_DINSU:
1735
        if (lsb > msb)
1736
            goto fail;
1737
        GEN_LOAD_REG_TN(T2, rt);
1738
        gen_op_ins(lsb + 32, msb - lsb + 1);
1739
        break;
1740
    case OPC_DINS:
1741
        if (lsb > msb)
1742
            goto fail;
1743
        GEN_LOAD_REG_TN(T2, rt);
1744
        gen_op_ins(lsb, msb - lsb + 1);
1745
        break;
1746
    default:
1747
fail:
1748
        MIPS_INVAL("bitops");
1749
        generate_exception(ctx, EXCP_RI);
1750
        return;
1751
    }
1752
    GEN_STORE_TN_REG(rt, T0);
1753
}
1754

    
1755
/* CP0 (MMU and control) */
1756
static void gen_mfc0 (DisasContext *ctx, int reg, int sel)
1757
{
1758
    const char *rn = "invalid";
1759

    
1760
    switch (reg) {
1761
    case 0:
1762
        switch (sel) {
1763
        case 0:
1764
            gen_op_mfc0_index();
1765
            rn = "Index";
1766
            break;
1767
        case 1:
1768
//            gen_op_mfc0_mvpcontrol(); /* MT ASE */
1769
            rn = "MVPControl";
1770
//            break;
1771
        case 2:
1772
//            gen_op_mfc0_mvpconf0(); /* MT ASE */
1773
            rn = "MVPConf0";
1774
//            break;
1775
        case 3:
1776
//            gen_op_mfc0_mvpconf1(); /* MT ASE */
1777
            rn = "MVPConf1";
1778
//            break;
1779
        default:
1780
            goto die;
1781
        }
1782
        break;
1783
    case 1:
1784
        switch (sel) {
1785
        case 0:
1786
            gen_op_mfc0_random();
1787
            rn = "Random";
1788
            break;
1789
        case 1:
1790
//            gen_op_mfc0_vpecontrol(); /* MT ASE */
1791
            rn = "VPEControl";
1792
//            break;
1793
        case 2:
1794
//            gen_op_mfc0_vpeconf0(); /* MT ASE */
1795
            rn = "VPEConf0";
1796
//            break;
1797
        case 3:
1798
//            gen_op_mfc0_vpeconf1(); /* MT ASE */
1799
            rn = "VPEConf1";
1800
//            break;
1801
        case 4:
1802
//            gen_op_mfc0_YQMask(); /* MT ASE */
1803
            rn = "YQMask";
1804
//            break;
1805
        case 5:
1806
//            gen_op_mfc0_vpeschedule(); /* MT ASE */
1807
            rn = "VPESchedule";
1808
//            break;
1809
        case 6:
1810
//            gen_op_mfc0_vpeschefback(); /* MT ASE */
1811
            rn = "VPEScheFBack";
1812
//            break;
1813
        case 7:
1814
//            gen_op_mfc0_vpeopt(); /* MT ASE */
1815
            rn = "VPEOpt";
1816
//            break;
1817
        default:
1818
            goto die;
1819
        }
1820
        break;
1821
    case 2:
1822
        switch (sel) {
1823
        case 0:
1824
            gen_op_mfc0_entrylo0();
1825
            rn = "EntryLo0";
1826
            break;
1827
        case 1:
1828
//            gen_op_mfc0_tcstatus(); /* MT ASE */
1829
            rn = "TCStatus";
1830
//            break;
1831
        case 2:
1832
//            gen_op_mfc0_tcbind(); /* MT ASE */
1833
            rn = "TCBind";
1834
//            break;
1835
        case 3:
1836
//            gen_op_mfc0_tcrestart(); /* MT ASE */
1837
            rn = "TCRestart";
1838
//            break;
1839
        case 4:
1840
//            gen_op_mfc0_tchalt(); /* MT ASE */
1841
            rn = "TCHalt";
1842
//            break;
1843
        case 5:
1844
//            gen_op_mfc0_tccontext(); /* MT ASE */
1845
            rn = "TCContext";
1846
//            break;
1847
        case 6:
1848
//            gen_op_mfc0_tcschedule(); /* MT ASE */
1849
            rn = "TCSchedule";
1850
//            break;
1851
        case 7:
1852
//            gen_op_mfc0_tcschefback(); /* MT ASE */
1853
            rn = "TCScheFBack";
1854
//            break;
1855
        default:
1856
            goto die;
1857
        }
1858
        break;
1859
    case 3:
1860
        switch (sel) {
1861
        case 0:
1862
            gen_op_mfc0_entrylo1();
1863
            rn = "EntryLo1";
1864
            break;
1865
        default:
1866
            goto die;
1867
        }
1868
        break;
1869
    case 4:
1870
        switch (sel) {
1871
        case 0:
1872
            gen_op_mfc0_context();
1873
            rn = "Context";
1874
            break;
1875
        case 1:
1876
//            gen_op_mfc0_contextconfig(); /* SmartMIPS ASE */
1877
            rn = "ContextConfig";
1878
//            break;
1879
        default:
1880
            goto die;
1881
        }
1882
        break;
1883
    case 5:
1884
        switch (sel) {
1885
        case 0:
1886
            gen_op_mfc0_pagemask();
1887
            rn = "PageMask";
1888
            break;
1889
        case 1:
1890
            gen_op_mfc0_pagegrain();
1891
            rn = "PageGrain";
1892
            break;
1893
        default:
1894
            goto die;
1895
        }
1896
        break;
1897
    case 6:
1898
        switch (sel) {
1899
        case 0:
1900
            gen_op_mfc0_wired();
1901
            rn = "Wired";
1902
            break;
1903
        case 1:
1904
//            gen_op_mfc0_srsconf0(); /* shadow registers */
1905
            rn = "SRSConf0";
1906
//            break;
1907
        case 2:
1908
//            gen_op_mfc0_srsconf1(); /* shadow registers */
1909
            rn = "SRSConf1";
1910
//            break;
1911
        case 3:
1912
//            gen_op_mfc0_srsconf2(); /* shadow registers */
1913
            rn = "SRSConf2";
1914
//            break;
1915
        case 4:
1916
//            gen_op_mfc0_srsconf3(); /* shadow registers */
1917
            rn = "SRSConf3";
1918
//            break;
1919
        case 5:
1920
//            gen_op_mfc0_srsconf4(); /* shadow registers */
1921
            rn = "SRSConf4";
1922
//            break;
1923
        default:
1924
            goto die;
1925
        }
1926
        break;
1927
    case 7:
1928
        switch (sel) {
1929
        case 0:
1930
            gen_op_mfc0_hwrena();
1931
            rn = "HWREna";
1932
            break;
1933
        default:
1934
            goto die;
1935
        }
1936
        break;
1937
    case 8:
1938
        switch (sel) {
1939
        case 0:
1940
            gen_op_mfc0_badvaddr();
1941
            rn = "BadVaddr";
1942
            break;
1943
        default:
1944
            goto die;
1945
       }
1946
        break;
1947
    case 9:
1948
        switch (sel) {
1949
        case 0:
1950
            gen_op_mfc0_count();
1951
            rn = "Count";
1952
            break;
1953
        /* 6,7 are implementation dependent */
1954
        default:
1955
            goto die;
1956
        }
1957
        break;
1958
    case 10:
1959
        switch (sel) {
1960
        case 0:
1961
            gen_op_mfc0_entryhi();
1962
            rn = "EntryHi";
1963
            break;
1964
        default:
1965
            goto die;
1966
        }
1967
        break;
1968
    case 11:
1969
        switch (sel) {
1970
        case 0:
1971
            gen_op_mfc0_compare();
1972
            rn = "Compare";
1973
            break;
1974
        /* 6,7 are implementation dependent */
1975
        default:
1976
            goto die;
1977
        }
1978
        break;
1979
    case 12:
1980
        switch (sel) {
1981
        case 0:
1982
            gen_op_mfc0_status();
1983
            rn = "Status";
1984
            break;
1985
        case 1:
1986
            gen_op_mfc0_intctl();
1987
            rn = "IntCtl";
1988
            break;
1989
        case 2:
1990
            gen_op_mfc0_srsctl();
1991
            rn = "SRSCtl";
1992
            break;
1993
        case 3:
1994
//            gen_op_mfc0_srsmap(); /* shadow registers */
1995
            rn = "SRSMap";
1996
//            break;
1997
        default:
1998
            goto die;
1999
       }
2000
        break;
2001
    case 13:
2002
        switch (sel) {
2003
        case 0:
2004
            gen_op_mfc0_cause();
2005
            rn = "Cause";
2006
            break;
2007
        default:
2008
            goto die;
2009
       }
2010
        break;
2011
    case 14:
2012
        switch (sel) {
2013
        case 0:
2014
            gen_op_mfc0_epc();
2015
            rn = "EPC";
2016
            break;
2017
        default:
2018
            goto die;
2019
        }
2020
        break;
2021
    case 15:
2022
        switch (sel) {
2023
        case 0:
2024
            gen_op_mfc0_prid();
2025
            rn = "PRid";
2026
            break;
2027
        case 1:
2028
            gen_op_mfc0_ebase();
2029
            rn = "EBase";
2030
            break;
2031
        default:
2032
            goto die;
2033
       }
2034
        break;
2035
    case 16:
2036
        switch (sel) {
2037
        case 0:
2038
            gen_op_mfc0_config0();
2039
            rn = "Config";
2040
            break;
2041
        case 1:
2042
            gen_op_mfc0_config1();
2043
            rn = "Config1";
2044
            break;
2045
        case 2:
2046
            gen_op_mfc0_config2();
2047
            rn = "Config2";
2048
            break;
2049
        case 3:
2050
            gen_op_mfc0_config3();
2051
            rn = "Config3";
2052
            break;
2053
        /* 4,5 are reserved */
2054
        /* 6,7 are implementation dependent */
2055
        case 6:
2056
            gen_op_mfc0_config6();
2057
            rn = "Config6";
2058
            break;
2059
        case 7:
2060
            gen_op_mfc0_config7();
2061
            rn = "Config7";
2062
            break;
2063
        default:
2064
            goto die;
2065
        }
2066
        break;
2067
    case 17:
2068
        switch (sel) {
2069
        case 0:
2070
            gen_op_mfc0_lladdr();
2071
            rn = "LLAddr";
2072
            break;
2073
        default:
2074
            goto die;
2075
        }
2076
        break;
2077
    case 18:
2078
        switch (sel) {
2079
        case 0:
2080
            gen_op_mfc0_watchlo0();
2081
            rn = "WatchLo";
2082
            break;
2083
        case 1:
2084
//            gen_op_mfc0_watchlo1();
2085
            rn = "WatchLo1";
2086
//            break;
2087
        case 2:
2088
//            gen_op_mfc0_watchlo2();
2089
            rn = "WatchLo2";
2090
//            break;
2091
        case 3:
2092
//            gen_op_mfc0_watchlo3();
2093
            rn = "WatchLo3";
2094
//            break;
2095
        case 4:
2096
//            gen_op_mfc0_watchlo4();
2097
            rn = "WatchLo4";
2098
//            break;
2099
        case 5:
2100
//            gen_op_mfc0_watchlo5();
2101
            rn = "WatchLo5";
2102
//            break;
2103
        case 6:
2104
//            gen_op_mfc0_watchlo6();
2105
            rn = "WatchLo6";
2106
//            break;
2107
        case 7:
2108
//            gen_op_mfc0_watchlo7();
2109
            rn = "WatchLo7";
2110
//            break;
2111
        default:
2112
            goto die;
2113
        }
2114
        break;
2115
    case 19:
2116
        switch (sel) {
2117
        case 0:
2118
            gen_op_mfc0_watchhi0();
2119
            rn = "WatchHi";
2120
            break;
2121
        case 1:
2122
//            gen_op_mfc0_watchhi1();
2123
            rn = "WatchHi1";
2124
//            break;
2125
        case 2:
2126
//            gen_op_mfc0_watchhi2();
2127
            rn = "WatchHi2";
2128
//            break;
2129
        case 3:
2130
//            gen_op_mfc0_watchhi3();
2131
            rn = "WatchHi3";
2132
//            break;
2133
        case 4:
2134
//            gen_op_mfc0_watchhi4();
2135
            rn = "WatchHi4";
2136
//            break;
2137
        case 5:
2138
//            gen_op_mfc0_watchhi5();
2139
            rn = "WatchHi5";
2140
//            break;
2141
        case 6:
2142
//            gen_op_mfc0_watchhi6();
2143
            rn = "WatchHi6";
2144
//            break;
2145
        case 7:
2146
//            gen_op_mfc0_watchhi7();
2147
            rn = "WatchHi7";
2148
//            break;
2149
        default:
2150
            goto die;
2151
        }
2152
        break;
2153
    case 20:
2154
        switch (sel) {
2155
        case 0:
2156
            /* 64 bit MMU only */
2157
            gen_op_mfc0_xcontext();
2158
            rn = "XContext";
2159
            break;
2160
        default:
2161
            goto die;
2162
        }
2163
        break;
2164
    case 21:
2165
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
2166
        switch (sel) {
2167
        case 0:
2168
            gen_op_mfc0_framemask();
2169
            rn = "Framemask";
2170
            break;
2171
        default:
2172
            goto die;
2173
        }
2174
        break;
2175
    case 22:
2176
        /* ignored */
2177
        rn = "'Diagnostic"; /* implementation dependent */
2178
        break;
2179
    case 23:
2180
        switch (sel) {
2181
        case 0:
2182
            gen_op_mfc0_debug(); /* EJTAG support */
2183
            rn = "Debug";
2184
            break;
2185
        case 1:
2186
//            gen_op_mfc0_tracecontrol(); /* PDtrace support */
2187
            rn = "TraceControl";
2188
//            break;
2189
        case 2:
2190
//            gen_op_mfc0_tracecontrol2(); /* PDtrace support */
2191
            rn = "TraceControl2";
2192
//            break;
2193
        case 3:
2194
//            gen_op_mfc0_usertracedata(); /* PDtrace support */
2195
            rn = "UserTraceData";
2196
//            break;
2197
        case 4:
2198
//            gen_op_mfc0_debug(); /* PDtrace support */
2199
            rn = "TraceBPC";
2200
//            break;
2201
        default:
2202
            goto die;
2203
        }
2204
        break;
2205
    case 24:
2206
        switch (sel) {
2207
        case 0:
2208
            gen_op_mfc0_depc(); /* EJTAG support */
2209
            rn = "DEPC";
2210
            break;
2211
        default:
2212
            goto die;
2213
        }
2214
        break;
2215
    case 25:
2216
        switch (sel) {
2217
        case 0:
2218
            gen_op_mfc0_performance0();
2219
            rn = "Performance0";
2220
            break;
2221
        case 1:
2222
//            gen_op_mfc0_performance1();
2223
            rn = "Performance1";
2224
//            break;
2225
        case 2:
2226
//            gen_op_mfc0_performance2();
2227
            rn = "Performance2";
2228
//            break;
2229
        case 3:
2230
//            gen_op_mfc0_performance3();
2231
            rn = "Performance3";
2232
//            break;
2233
        case 4:
2234
//            gen_op_mfc0_performance4();
2235
            rn = "Performance4";
2236
//            break;
2237
        case 5:
2238
//            gen_op_mfc0_performance5();
2239
            rn = "Performance5";
2240
//            break;
2241
        case 6:
2242
//            gen_op_mfc0_performance6();
2243
            rn = "Performance6";
2244
//            break;
2245
        case 7:
2246
//            gen_op_mfc0_performance7();
2247
            rn = "Performance7";
2248
//            break;
2249
        default:
2250
            goto die;
2251
        }
2252
        break;
2253
    case 26:
2254
       rn = "ECC";
2255
       break;
2256
    case 27:
2257
        switch (sel) {
2258
        /* ignored */
2259
        case 0 ... 3:
2260
            rn = "CacheErr";
2261
            break;
2262
        default:
2263
            goto die;
2264
        }
2265
        break;
2266
    case 28:
2267
        switch (sel) {
2268
        case 0:
2269
        case 2:
2270
        case 4:
2271
        case 6:
2272
            gen_op_mfc0_taglo();
2273
            rn = "TagLo";
2274
            break;
2275
        case 1:
2276
        case 3:
2277
        case 5:
2278
        case 7:
2279
            gen_op_mfc0_datalo();
2280
            rn = "DataLo";
2281
            break;
2282
        default:
2283
            goto die;
2284
        }
2285
        break;
2286
    case 29:
2287
        switch (sel) {
2288
        case 0:
2289
        case 2:
2290
        case 4:
2291
        case 6:
2292
            gen_op_mfc0_taghi();
2293
            rn = "TagHi";
2294
            break;
2295
        case 1:
2296
        case 3:
2297
        case 5:
2298
        case 7:
2299
            gen_op_mfc0_datahi();
2300
            rn = "DataHi";
2301
            break;
2302
        default:
2303
            goto die;
2304
        }
2305
        break;
2306
    case 30:
2307
        switch (sel) {
2308
        case 0:
2309
            gen_op_mfc0_errorepc();
2310
            rn = "ErrorEPC";
2311
            break;
2312
        default:
2313
            goto die;
2314
        }
2315
        break;
2316
    case 31:
2317
        switch (sel) {
2318
        case 0:
2319
            gen_op_mfc0_desave(); /* EJTAG support */
2320
            rn = "DESAVE";
2321
            break;
2322
        default:
2323
            goto die;
2324
        }
2325
        break;
2326
    default:
2327
       goto die;
2328
    }
2329
#if defined MIPS_DEBUG_DISAS
2330
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2331
        fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
2332
                rn, reg, sel);
2333
    }
2334
#endif
2335
    return;
2336

    
2337
die:
2338
#if defined MIPS_DEBUG_DISAS
2339
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2340
        fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
2341
                rn, reg, sel);
2342
    }
2343
#endif
2344
    generate_exception(ctx, EXCP_RI);
2345
}
2346

    
2347
static void gen_mtc0 (DisasContext *ctx, int reg, int sel)
2348
{
2349
    const char *rn = "invalid";
2350

    
2351
    switch (reg) {
2352
    case 0:
2353
        switch (sel) {
2354
        case 0:
2355
           gen_op_mtc0_index();
2356
            rn = "Index";
2357
            break;
2358
        case 1:
2359
//            gen_op_mtc0_mvpcontrol(); /* MT ASE */
2360
            rn = "MVPControl";
2361
//            break;
2362
        case 2:
2363
//            gen_op_mtc0_mvpconf0(); /* MT ASE */
2364
            rn = "MVPConf0";
2365
//            break;
2366
        case 3:
2367
//            gen_op_mtc0_mvpconf1(); /* MT ASE */
2368
            rn = "MVPConf1";
2369
//            break;
2370
        default:
2371
            goto die;
2372
        }
2373
        break;
2374
    case 1:
2375
        switch (sel) {
2376
        case 0:
2377
            /* ignored */
2378
            rn = "Random";
2379
            break;
2380
        case 1:
2381
//            gen_op_mtc0_vpecontrol(); /* MT ASE */
2382
            rn = "VPEControl";
2383
//            break;
2384
        case 2:
2385
//            gen_op_mtc0_vpeconf0(); /* MT ASE */
2386
            rn = "VPEConf0";
2387
//            break;
2388
        case 3:
2389
//            gen_op_mtc0_vpeconf1(); /* MT ASE */
2390
            rn = "VPEConf1";
2391
//            break;
2392
        case 4:
2393
//            gen_op_mtc0_YQMask(); /* MT ASE */
2394
            rn = "YQMask";
2395
//            break;
2396
        case 5:
2397
//            gen_op_mtc0_vpeschedule(); /* MT ASE */
2398
            rn = "VPESchedule";
2399
//            break;
2400
        case 6:
2401
//            gen_op_mtc0_vpeschefback(); /* MT ASE */
2402
            rn = "VPEScheFBack";
2403
//            break;
2404
        case 7:
2405
//            gen_op_mtc0_vpeopt(); /* MT ASE */
2406
            rn = "VPEOpt";
2407
//            break;
2408
        default:
2409
            goto die;
2410
        }
2411
        break;
2412
    case 2:
2413
        switch (sel) {
2414
        case 0:
2415
            gen_op_mtc0_entrylo0();
2416
            rn = "EntryLo0";
2417
            break;
2418
        case 1:
2419
//            gen_op_mtc0_tcstatus(); /* MT ASE */
2420
            rn = "TCStatus";
2421
//            break;
2422
        case 2:
2423
//            gen_op_mtc0_tcbind(); /* MT ASE */
2424
            rn = "TCBind";
2425
//            break;
2426
        case 3:
2427
//            gen_op_mtc0_tcrestart(); /* MT ASE */
2428
            rn = "TCRestart";
2429
//            break;
2430
        case 4:
2431
//            gen_op_mtc0_tchalt(); /* MT ASE */
2432
            rn = "TCHalt";
2433
//            break;
2434
        case 5:
2435
//            gen_op_mtc0_tccontext(); /* MT ASE */
2436
            rn = "TCContext";
2437
//            break;
2438
        case 6:
2439
//            gen_op_mtc0_tcschedule(); /* MT ASE */
2440
            rn = "TCSchedule";
2441
//            break;
2442
        case 7:
2443
//            gen_op_mtc0_tcschefback(); /* MT ASE */
2444
            rn = "TCScheFBack";
2445
//            break;
2446
        default:
2447
            goto die;
2448
        }
2449
        break;
2450
    case 3:
2451
        switch (sel) {
2452
        case 0:
2453
            gen_op_mtc0_entrylo1();
2454
            rn = "EntryLo1";
2455
            break;
2456
        default:
2457
            goto die;
2458
        }
2459
        break;
2460
    case 4:
2461
        switch (sel) {
2462
        case 0:
2463
            gen_op_mtc0_context();
2464
            rn = "Context";
2465
            break;
2466
        case 1:
2467
//            gen_op_mtc0_contextconfig(); /* SmartMIPS ASE */
2468
            rn = "ContextConfig";
2469
//            break;
2470
        default:
2471
            goto die;
2472
        }
2473
        break;
2474
    case 5:
2475
        switch (sel) {
2476
        case 0:
2477
            gen_op_mtc0_pagemask();
2478
            rn = "PageMask";
2479
            break;
2480
        case 1:
2481
            gen_op_mtc0_pagegrain();
2482
            rn = "PageGrain";
2483
            break;
2484
        default:
2485
            goto die;
2486
        }
2487
        break;
2488
    case 6:
2489
        switch (sel) {
2490
        case 0:
2491
            gen_op_mtc0_wired();
2492
            rn = "Wired";
2493
            break;
2494
        case 1:
2495
//            gen_op_mtc0_srsconf0(); /* shadow registers */
2496
            rn = "SRSConf0";
2497
//            break;
2498
        case 2:
2499
//            gen_op_mtc0_srsconf1(); /* shadow registers */
2500
            rn = "SRSConf1";
2501
//            break;
2502
        case 3:
2503
//            gen_op_mtc0_srsconf2(); /* shadow registers */
2504
            rn = "SRSConf2";
2505
//            break;
2506
        case 4:
2507
//            gen_op_mtc0_srsconf3(); /* shadow registers */
2508
            rn = "SRSConf3";
2509
//            break;
2510
        case 5:
2511
//            gen_op_mtc0_srsconf4(); /* shadow registers */
2512
            rn = "SRSConf4";
2513
//            break;
2514
        default:
2515
            goto die;
2516
        }
2517
        break;
2518
    case 7:
2519
        switch (sel) {
2520
        case 0:
2521
            gen_op_mtc0_hwrena();
2522
            rn = "HWREna";
2523
            break;
2524
        default:
2525
            goto die;
2526
        }
2527
        break;
2528
    case 8:
2529
        /* ignored */
2530
        rn = "BadVaddr";
2531
        break;
2532
    case 9:
2533
        switch (sel) {
2534
        case 0:
2535
            gen_op_mtc0_count();
2536
            rn = "Count";
2537
            break;
2538
        /* 6,7 are implementation dependent */
2539
        default:
2540
            goto die;
2541
        }
2542
        /* Stop translation as we may have switched the execution mode */
2543
        ctx->bstate = BS_STOP;
2544
        break;
2545
    case 10:
2546
        switch (sel) {
2547
        case 0:
2548
            gen_op_mtc0_entryhi();
2549
            rn = "EntryHi";
2550
            break;
2551
        default:
2552
            goto die;
2553
        }
2554
        break;
2555
    case 11:
2556
        switch (sel) {
2557
        case 0:
2558
            gen_op_mtc0_compare();
2559
            rn = "Compare";
2560
            break;
2561
        /* 6,7 are implementation dependent */
2562
        default:
2563
            goto die;
2564
        }
2565
        /* Stop translation as we may have switched the execution mode */
2566
        ctx->bstate = BS_STOP;
2567
        break;
2568
    case 12:
2569
        switch (sel) {
2570
        case 0:
2571
            gen_op_mtc0_status();
2572
            rn = "Status";
2573
            break;
2574
        case 1:
2575
            gen_op_mtc0_intctl();
2576
            rn = "IntCtl";
2577
            break;
2578
        case 2:
2579
            gen_op_mtc0_srsctl();
2580
            rn = "SRSCtl";
2581
            break;
2582
        case 3:
2583
//            gen_op_mtc0_srsmap(); /* shadow registers */
2584
            rn = "SRSMap";
2585
//            break;
2586
        default:
2587
            goto die;
2588
        }
2589
        /* Stop translation as we may have switched the execution mode */
2590
        ctx->bstate = BS_STOP;
2591
        break;
2592
    case 13:
2593
        switch (sel) {
2594
        case 0:
2595
            gen_op_mtc0_cause();
2596
            rn = "Cause";
2597
            break;
2598
        default:
2599
            goto die;
2600
        }
2601
        /* Stop translation as we may have switched the execution mode */
2602
        ctx->bstate = BS_STOP;
2603
        break;
2604
    case 14:
2605
        switch (sel) {
2606
        case 0:
2607
            gen_op_mtc0_epc();
2608
            rn = "EPC";
2609
            break;
2610
        default:
2611
            goto die;
2612
        }
2613
        break;
2614
    case 15:
2615
        switch (sel) {
2616
        case 0:
2617
            /* ignored */
2618
            rn = "PRid";
2619
            break;
2620
        case 1:
2621
            gen_op_mtc0_ebase();
2622
            rn = "EBase";
2623
            break;
2624
        default:
2625
            goto die;
2626
        }
2627
        break;
2628
    case 16:
2629
        switch (sel) {
2630
        case 0:
2631
            gen_op_mtc0_config0();
2632
            rn = "Config";
2633
            /* Stop translation as we may have switched the execution mode */
2634
            ctx->bstate = BS_STOP;
2635
            break;
2636
        case 1:
2637
            /* ignored, read only */
2638
            rn = "Config1";
2639
            break;
2640
        case 2:
2641
            gen_op_mtc0_config2();
2642
            rn = "Config2";
2643
            /* Stop translation as we may have switched the execution mode */
2644
            ctx->bstate = BS_STOP;
2645
            break;
2646
        case 3:
2647
            /* ignored, read only */
2648
            rn = "Config3";
2649
            break;
2650
        /* 4,5 are reserved */
2651
        /* 6,7 are implementation dependent */
2652
        case 6:
2653
            /* ignored */
2654
            rn = "Config6";
2655
            break;
2656
        case 7:
2657
            /* ignored */
2658
            rn = "Config7";
2659
            break;
2660
        default:
2661
            rn = "Invalid config selector";
2662
            goto die;
2663
        }
2664
        break;
2665
    case 17:
2666
        switch (sel) {
2667
        case 0:
2668
            /* ignored */
2669
            rn = "LLAddr";
2670
            break;
2671
        default:
2672
            goto die;
2673
        }
2674
        break;
2675
    case 18:
2676
        switch (sel) {
2677
        case 0:
2678
            gen_op_mtc0_watchlo0();
2679
            rn = "WatchLo";
2680
            break;
2681
        case 1:
2682
//            gen_op_mtc0_watchlo1();
2683
            rn = "WatchLo1";
2684
//            break;
2685
        case 2:
2686
//            gen_op_mtc0_watchlo2();
2687
            rn = "WatchLo2";
2688
//            break;
2689
        case 3:
2690
//            gen_op_mtc0_watchlo3();
2691
            rn = "WatchLo3";
2692
//            break;
2693
        case 4:
2694
//            gen_op_mtc0_watchlo4();
2695
            rn = "WatchLo4";
2696
//            break;
2697
        case 5:
2698
//            gen_op_mtc0_watchlo5();
2699
            rn = "WatchLo5";
2700
//            break;
2701
        case 6:
2702
//            gen_op_mtc0_watchlo6();
2703
            rn = "WatchLo6";
2704
//            break;
2705
        case 7:
2706
//            gen_op_mtc0_watchlo7();
2707
            rn = "WatchLo7";
2708
//            break;
2709
        default:
2710
            goto die;
2711
        }
2712
        break;
2713
    case 19:
2714
        switch (sel) {
2715
        case 0:
2716
            gen_op_mtc0_watchhi0();
2717
            rn = "WatchHi";
2718
            break;
2719
        case 1:
2720
//            gen_op_mtc0_watchhi1();
2721
            rn = "WatchHi1";
2722
//            break;
2723
        case 2:
2724
//            gen_op_mtc0_watchhi2();
2725
            rn = "WatchHi2";
2726
//            break;
2727
        case 3:
2728
//            gen_op_mtc0_watchhi3();
2729
            rn = "WatchHi3";
2730
//            break;
2731
        case 4:
2732
//            gen_op_mtc0_watchhi4();
2733
            rn = "WatchHi4";
2734
//            break;
2735
        case 5:
2736
//            gen_op_mtc0_watchhi5();
2737
            rn = "WatchHi5";
2738
//            break;
2739
        case 6:
2740
//            gen_op_mtc0_watchhi6();
2741
            rn = "WatchHi6";
2742
//            break;
2743
        case 7:
2744
//            gen_op_mtc0_watchhi7();
2745
            rn = "WatchHi7";
2746
//            break;
2747
        default:
2748
            goto die;
2749
        }
2750
        break;
2751
    case 20:
2752
        switch (sel) {
2753
        case 0:
2754
            /* 64 bit MMU only */
2755
            /* Nothing writable in lower 32 bits */
2756
            rn = "XContext";
2757
            break;
2758
        default:
2759
            goto die;
2760
        }
2761
        break;
2762
    case 21:
2763
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
2764
        switch (sel) {
2765
        case 0:
2766
            gen_op_mtc0_framemask();
2767
            rn = "Framemask";
2768
            break;
2769
        default:
2770
            goto die;
2771
        }
2772
        break;
2773
    case 22:
2774
        /* ignored */
2775
        rn = "Diagnostic"; /* implementation dependent */
2776
        break;
2777
    case 23:
2778
        switch (sel) {
2779
        case 0:
2780
            gen_op_mtc0_debug(); /* EJTAG support */
2781
            rn = "Debug";
2782
            break;
2783
        case 1:
2784
//            gen_op_mtc0_tracecontrol(); /* PDtrace support */
2785
            rn = "TraceControl";
2786
//            break;
2787
        case 2:
2788
//            gen_op_mtc0_tracecontrol2(); /* PDtrace support */
2789
            rn = "TraceControl2";
2790
//            break;
2791
        case 3:
2792
//            gen_op_mtc0_usertracedata(); /* PDtrace support */
2793
            rn = "UserTraceData";
2794
//            break;
2795
        case 4:
2796
//            gen_op_mtc0_debug(); /* PDtrace support */
2797
            rn = "TraceBPC";
2798
//            break;
2799
        default:
2800
            goto die;
2801
        }
2802
        /* Stop translation as we may have switched the execution mode */
2803
        ctx->bstate = BS_STOP;
2804
        break;
2805
    case 24:
2806
        switch (sel) {
2807
        case 0:
2808
            gen_op_mtc0_depc(); /* EJTAG support */
2809
            rn = "DEPC";
2810
            break;
2811
        default:
2812
            goto die;
2813
        }
2814
        break;
2815
    case 25:
2816
        switch (sel) {
2817
        case 0:
2818
            gen_op_mtc0_performance0();
2819
            rn = "Performance0";
2820
            break;
2821
        case 1:
2822
//            gen_op_mtc0_performance1();
2823
            rn = "Performance1";
2824
//            break;
2825
        case 2:
2826
//            gen_op_mtc0_performance2();
2827
            rn = "Performance2";
2828
//            break;
2829
        case 3:
2830
//            gen_op_mtc0_performance3();
2831
            rn = "Performance3";
2832
//            break;
2833
        case 4:
2834
//            gen_op_mtc0_performance4();
2835
            rn = "Performance4";
2836
//            break;
2837
        case 5:
2838
//            gen_op_mtc0_performance5();
2839
            rn = "Performance5";
2840
//            break;
2841
        case 6:
2842
//            gen_op_mtc0_performance6();
2843
            rn = "Performance6";
2844
//            break;
2845
        case 7:
2846
//            gen_op_mtc0_performance7();
2847
            rn = "Performance7";
2848
//            break;
2849
        default:
2850
            goto die;
2851
        }
2852
       break;
2853
    case 26:
2854
        /* ignored */
2855
        rn = "ECC";
2856
        break;
2857
    case 27:
2858
        switch (sel) {
2859
        case 0 ... 3:
2860
            /* ignored */
2861
            rn = "CacheErr";
2862
            break;
2863
        default:
2864
            goto die;
2865
        }
2866
       break;
2867
    case 28:
2868
        switch (sel) {
2869
        case 0:
2870
        case 2:
2871
        case 4:
2872
        case 6:
2873
            gen_op_mtc0_taglo();
2874
            rn = "TagLo";
2875
            break;
2876
        case 1:
2877
        case 3:
2878
        case 5:
2879
        case 7:
2880
            gen_op_mtc0_datalo();
2881
            rn = "DataLo";
2882
            break;
2883
        default:
2884
            goto die;
2885
        }
2886
        break;
2887
    case 29:
2888
        switch (sel) {
2889
        case 0:
2890
        case 2:
2891
        case 4:
2892
        case 6:
2893
            gen_op_mtc0_taghi();
2894
            rn = "TagHi";
2895
            break;
2896
        case 1:
2897
        case 3:
2898
        case 5:
2899
        case 7:
2900
            gen_op_mtc0_datahi();
2901
            rn = "DataHi";
2902
            break;
2903
        default:
2904
            rn = "invalid sel";
2905
            goto die;
2906
        }
2907
       break;
2908
    case 30:
2909
        switch (sel) {
2910
        case 0:
2911
            gen_op_mtc0_errorepc();
2912
            rn = "ErrorEPC";
2913
            break;
2914
        default:
2915
            goto die;
2916
        }
2917
        break;
2918
    case 31:
2919
        switch (sel) {
2920
        case 0:
2921
            gen_op_mtc0_desave(); /* EJTAG support */
2922
            rn = "DESAVE";
2923
            break;
2924
        default:
2925
            goto die;
2926
        }
2927
        /* Stop translation as we may have switched the execution mode */
2928
        ctx->bstate = BS_STOP;
2929
        break;
2930
    default:
2931
       goto die;
2932
    }
2933
#if defined MIPS_DEBUG_DISAS
2934
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2935
        fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
2936
                rn, reg, sel);
2937
    }
2938
#endif
2939
    return;
2940

    
2941
die:
2942
#if defined MIPS_DEBUG_DISAS
2943
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2944
        fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
2945
                rn, reg, sel);
2946
    }
2947
#endif
2948
    generate_exception(ctx, EXCP_RI);
2949
}
2950

    
2951
#ifdef TARGET_MIPS64
2952
static void gen_dmfc0 (DisasContext *ctx, int reg, int sel)
2953
{
2954
    const char *rn = "invalid";
2955

    
2956
    switch (reg) {
2957
    case 0:
2958
        switch (sel) {
2959
        case 0:
2960
            gen_op_mfc0_index();
2961
            rn = "Index";
2962
            break;
2963
        case 1:
2964
//            gen_op_dmfc0_mvpcontrol(); /* MT ASE */
2965
            rn = "MVPControl";
2966
//            break;
2967
        case 2:
2968
//            gen_op_dmfc0_mvpconf0(); /* MT ASE */
2969
            rn = "MVPConf0";
2970
//            break;
2971
        case 3:
2972
//            gen_op_dmfc0_mvpconf1(); /* MT ASE */
2973
            rn = "MVPConf1";
2974
//            break;
2975
        default:
2976
            goto die;
2977
        }
2978
        break;
2979
    case 1:
2980
        switch (sel) {
2981
        case 0:
2982
            gen_op_mfc0_random();
2983
            rn = "Random";
2984
            break;
2985
        case 1:
2986
//            gen_op_dmfc0_vpecontrol(); /* MT ASE */
2987
            rn = "VPEControl";
2988
//            break;
2989
        case 2:
2990
//            gen_op_dmfc0_vpeconf0(); /* MT ASE */
2991
            rn = "VPEConf0";
2992
//            break;
2993
        case 3:
2994
//            gen_op_dmfc0_vpeconf1(); /* MT ASE */
2995
            rn = "VPEConf1";
2996
//            break;
2997
        case 4:
2998
//            gen_op_dmfc0_YQMask(); /* MT ASE */
2999
            rn = "YQMask";
3000
//            break;
3001
        case 5:
3002
//            gen_op_dmfc0_vpeschedule(); /* MT ASE */
3003
            rn = "VPESchedule";
3004
//            break;
3005
        case 6:
3006
//            gen_op_dmfc0_vpeschefback(); /* MT ASE */
3007
            rn = "VPEScheFBack";
3008
//            break;
3009
        case 7:
3010
//            gen_op_dmfc0_vpeopt(); /* MT ASE */
3011
            rn = "VPEOpt";
3012
//            break;
3013
        default:
3014
            goto die;
3015
        }
3016
        break;
3017
    case 2:
3018
        switch (sel) {
3019
        case 0:
3020
            gen_op_dmfc0_entrylo0();
3021
            rn = "EntryLo0";
3022
            break;
3023
        case 1:
3024
//            gen_op_dmfc0_tcstatus(); /* MT ASE */
3025
            rn = "TCStatus";
3026
//            break;
3027
        case 2:
3028
//            gen_op_dmfc0_tcbind(); /* MT ASE */
3029
            rn = "TCBind";
3030
//            break;
3031
        case 3:
3032
//            gen_op_dmfc0_tcrestart(); /* MT ASE */
3033
            rn = "TCRestart";
3034
//            break;
3035
        case 4:
3036
//            gen_op_dmfc0_tchalt(); /* MT ASE */
3037
            rn = "TCHalt";
3038
//            break;
3039
        case 5:
3040
//            gen_op_dmfc0_tccontext(); /* MT ASE */
3041
            rn = "TCContext";
3042
//            break;
3043
        case 6:
3044
//            gen_op_dmfc0_tcschedule(); /* MT ASE */
3045
            rn = "TCSchedule";
3046
//            break;
3047
        case 7:
3048
//            gen_op_dmfc0_tcschefback(); /* MT ASE */
3049
            rn = "TCScheFBack";
3050
//            break;
3051
        default:
3052
            goto die;
3053
        }
3054
        break;
3055
    case 3:
3056
        switch (sel) {
3057
        case 0:
3058
            gen_op_dmfc0_entrylo1();
3059
            rn = "EntryLo1";
3060
            break;
3061
        default:
3062
            goto die;
3063
        }
3064
        break;
3065
    case 4:
3066
        switch (sel) {
3067
        case 0:
3068
            gen_op_dmfc0_context();
3069
            rn = "Context";
3070
            break;
3071
        case 1:
3072
//            gen_op_dmfc0_contextconfig(); /* SmartMIPS ASE */
3073
            rn = "ContextConfig";
3074
//            break;
3075
        default:
3076
            goto die;
3077
        }
3078
        break;
3079
    case 5:
3080
        switch (sel) {
3081
        case 0:
3082
            gen_op_mfc0_pagemask();
3083
            rn = "PageMask";
3084
            break;
3085
        case 1:
3086
            gen_op_mfc0_pagegrain();
3087
            rn = "PageGrain";
3088
            break;
3089
        default:
3090
            goto die;
3091
        }
3092
        break;
3093
    case 6:
3094
        switch (sel) {
3095
        case 0:
3096
            gen_op_mfc0_wired();
3097
            rn = "Wired";
3098
            break;
3099
        case 1:
3100
//            gen_op_dmfc0_srsconf0(); /* shadow registers */
3101
            rn = "SRSConf0";
3102
//            break;
3103
        case 2:
3104
//            gen_op_dmfc0_srsconf1(); /* shadow registers */
3105
            rn = "SRSConf1";
3106
//            break;
3107
        case 3:
3108
//            gen_op_dmfc0_srsconf2(); /* shadow registers */
3109
            rn = "SRSConf2";
3110
//            break;
3111
        case 4:
3112
//            gen_op_dmfc0_srsconf3(); /* shadow registers */
3113
            rn = "SRSConf3";
3114
//            break;
3115
        case 5:
3116
//            gen_op_dmfc0_srsconf4(); /* shadow registers */
3117
            rn = "SRSConf4";
3118
//            break;
3119
        default:
3120
            goto die;
3121
        }
3122
        break;
3123
    case 7:
3124
        switch (sel) {
3125
        case 0:
3126
            gen_op_mfc0_hwrena();
3127
            rn = "HWREna";
3128
            break;
3129
        default:
3130
            goto die;
3131
        }
3132
        break;
3133
    case 8:
3134
        switch (sel) {
3135
        case 0:
3136
            gen_op_dmfc0_badvaddr();
3137
            rn = "BadVaddr";
3138
            break;
3139
        default:
3140
            goto die;
3141
        }
3142
        break;
3143
    case 9:
3144
        switch (sel) {
3145
        case 0:
3146
            gen_op_mfc0_count();
3147
            rn = "Count";
3148
            break;
3149
        /* 6,7 are implementation dependent */
3150
        default:
3151
            goto die;
3152
        }
3153
        break;
3154
    case 10:
3155
        switch (sel) {
3156
        case 0:
3157
            gen_op_dmfc0_entryhi();
3158
            rn = "EntryHi";
3159
            break;
3160
        default:
3161
            goto die;
3162
        }
3163
        break;
3164
    case 11:
3165
        switch (sel) {
3166
        case 0:
3167
            gen_op_mfc0_compare();
3168
            rn = "Compare";
3169
            break;
3170
        /* 6,7 are implementation dependent */
3171
        default:
3172
            goto die;
3173
        }
3174
        break;
3175
    case 12:
3176
        switch (sel) {
3177
        case 0:
3178
            gen_op_mfc0_status();
3179
            rn = "Status";
3180
            break;
3181
        case 1:
3182
            gen_op_mfc0_intctl();
3183
            rn = "IntCtl";
3184
            break;
3185
        case 2:
3186
            gen_op_mfc0_srsctl();
3187
            rn = "SRSCtl";
3188
            break;
3189
        case 3:
3190
            gen_op_mfc0_srsmap(); /* shadow registers */
3191
            rn = "SRSMap";
3192
            break;
3193
        default:
3194
            goto die;
3195
        }
3196
        break;
3197
    case 13:
3198
        switch (sel) {
3199
        case 0:
3200
            gen_op_mfc0_cause();
3201
            rn = "Cause";
3202
            break;
3203
        default:
3204
            goto die;
3205
        }
3206
        break;
3207
    case 14:
3208
        switch (sel) {
3209
        case 0:
3210
            gen_op_dmfc0_epc();
3211
            rn = "EPC";
3212
            break;
3213
        default:
3214
            goto die;
3215
        }
3216
        break;
3217
    case 15:
3218
        switch (sel) {
3219
        case 0:
3220
            gen_op_mfc0_prid();
3221
            rn = "PRid";
3222
            break;
3223
        case 1:
3224
            gen_op_mfc0_ebase();
3225
            rn = "EBase";
3226
            break;
3227
        default:
3228
            goto die;
3229
        }
3230
        break;
3231
    case 16:
3232
        switch (sel) {
3233
        case 0:
3234
            gen_op_mfc0_config0();
3235
            rn = "Config";
3236
            break;
3237
        case 1:
3238
            gen_op_mfc0_config1();
3239
            rn = "Config1";
3240
            break;
3241
        case 2:
3242
            gen_op_mfc0_config2();
3243
            rn = "Config2";
3244
            break;
3245
        case 3:
3246
            gen_op_mfc0_config3();
3247
            rn = "Config3";
3248
            break;
3249
       /* 6,7 are implementation dependent */
3250
        default:
3251
            goto die;
3252
        }
3253
        break;
3254
    case 17:
3255
        switch (sel) {
3256
        case 0:
3257
            gen_op_dmfc0_lladdr();
3258
            rn = "LLAddr";
3259
            break;
3260
        default:
3261
            goto die;
3262
        }
3263
        break;
3264
    case 18:
3265
        switch (sel) {
3266
        case 0:
3267
            gen_op_dmfc0_watchlo0();
3268
            rn = "WatchLo";
3269
            break;
3270
        case 1:
3271
//            gen_op_dmfc0_watchlo1();
3272
            rn = "WatchLo1";
3273
//            break;
3274
        case 2:
3275
//            gen_op_dmfc0_watchlo2();
3276
            rn = "WatchLo2";
3277
//            break;
3278
        case 3:
3279
//            gen_op_dmfc0_watchlo3();
3280
            rn = "WatchLo3";
3281
//            break;
3282
        case 4:
3283
//            gen_op_dmfc0_watchlo4();
3284
            rn = "WatchLo4";
3285
//            break;
3286
        case 5:
3287
//            gen_op_dmfc0_watchlo5();
3288
            rn = "WatchLo5";
3289
//            break;
3290
        case 6:
3291
//            gen_op_dmfc0_watchlo6();
3292
            rn = "WatchLo6";
3293
//            break;
3294
        case 7:
3295
//            gen_op_dmfc0_watchlo7();
3296
            rn = "WatchLo7";
3297
//            break;
3298
        default:
3299
            goto die;
3300
        }
3301
        break;
3302
    case 19:
3303
        switch (sel) {
3304
        case 0:
3305
            gen_op_mfc0_watchhi0();
3306
            rn = "WatchHi";
3307
            break;
3308
        case 1:
3309
//            gen_op_mfc0_watchhi1();
3310
            rn = "WatchHi1";
3311
//            break;
3312
        case 2:
3313
//            gen_op_mfc0_watchhi2();
3314
            rn = "WatchHi2";
3315
//            break;
3316
        case 3:
3317
//            gen_op_mfc0_watchhi3();
3318
            rn = "WatchHi3";
3319
//            break;
3320
        case 4:
3321
//            gen_op_mfc0_watchhi4();
3322
            rn = "WatchHi4";
3323
//            break;
3324
        case 5:
3325
//            gen_op_mfc0_watchhi5();
3326
            rn = "WatchHi5";
3327
//            break;
3328
        case 6:
3329
//            gen_op_mfc0_watchhi6();
3330
            rn = "WatchHi6";
3331
//            break;
3332
        case 7:
3333
//            gen_op_mfc0_watchhi7();
3334
            rn = "WatchHi7";
3335
//            break;
3336
        default:
3337
            goto die;
3338
        }
3339
        break;
3340
    case 20:
3341
        switch (sel) {
3342
        case 0:
3343
            /* 64 bit MMU only */
3344
            gen_op_dmfc0_xcontext();
3345
            rn = "XContext";
3346
            break;
3347
        default:
3348
            goto die;
3349
        }
3350
        break;
3351
    case 21:
3352
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
3353
        switch (sel) {
3354
        case 0:
3355
            gen_op_mfc0_framemask();
3356
            rn = "Framemask";
3357
            break;
3358
        default:
3359
            goto die;
3360
        }
3361
        break;
3362
    case 22:
3363
        /* ignored */
3364
        rn = "'Diagnostic"; /* implementation dependent */
3365
        break;
3366
    case 23:
3367
        switch (sel) {
3368
        case 0:
3369
            gen_op_mfc0_debug(); /* EJTAG support */
3370
            rn = "Debug";
3371
            break;
3372
        case 1:
3373
//            gen_op_dmfc0_tracecontrol(); /* PDtrace support */
3374
            rn = "TraceControl";
3375
//            break;
3376
        case 2:
3377
//            gen_op_dmfc0_tracecontrol2(); /* PDtrace support */
3378
            rn = "TraceControl2";
3379
//            break;
3380
        case 3:
3381
//            gen_op_dmfc0_usertracedata(); /* PDtrace support */
3382
            rn = "UserTraceData";
3383
//            break;
3384
        case 4:
3385
//            gen_op_dmfc0_debug(); /* PDtrace support */
3386
            rn = "TraceBPC";
3387
//            break;
3388
        default:
3389
            goto die;
3390
        }
3391
        break;
3392
    case 24:
3393
        switch (sel) {
3394
        case 0:
3395
            gen_op_dmfc0_depc(); /* EJTAG support */
3396
            rn = "DEPC";
3397
            break;
3398
        default:
3399
            goto die;
3400
        }
3401
        break;
3402
    case 25:
3403
        switch (sel) {
3404
        case 0:
3405
            gen_op_mfc0_performance0();
3406
            rn = "Performance0";
3407
            break;
3408
        case 1:
3409
//            gen_op_dmfc0_performance1();
3410
            rn = "Performance1";
3411
//            break;
3412
        case 2:
3413
//            gen_op_dmfc0_performance2();
3414
            rn = "Performance2";
3415
//            break;
3416
        case 3:
3417
//            gen_op_dmfc0_performance3();
3418
            rn = "Performance3";
3419
//            break;
3420
        case 4:
3421
//            gen_op_dmfc0_performance4();
3422
            rn = "Performance4";
3423
//            break;
3424
        case 5:
3425
//            gen_op_dmfc0_performance5();
3426
            rn = "Performance5";
3427
//            break;
3428
        case 6:
3429
//            gen_op_dmfc0_performance6();
3430
            rn = "Performance6";
3431
//            break;
3432
        case 7:
3433
//            gen_op_dmfc0_performance7();
3434
            rn = "Performance7";
3435
//            break;
3436
        default:
3437
            goto die;
3438
        }
3439
        break;
3440
    case 26:
3441
       rn = "ECC";
3442
       break;
3443
    case 27:
3444
        switch (sel) {
3445
        /* ignored */
3446
        case 0 ... 3:
3447
            rn = "CacheErr";
3448
            break;
3449
        default:
3450
            goto die;
3451
        }
3452
        break;
3453
    case 28:
3454
        switch (sel) {
3455
        case 0:
3456
        case 2:
3457
        case 4:
3458
        case 6:
3459
            gen_op_mfc0_taglo();
3460
            rn = "TagLo";
3461
            break;
3462
        case 1:
3463
        case 3:
3464
        case 5:
3465
        case 7:
3466
            gen_op_mfc0_datalo();
3467
            rn = "DataLo";
3468
            break;
3469
        default:
3470
            goto die;
3471
        }
3472
        break;
3473
    case 29:
3474
        switch (sel) {
3475
        case 0:
3476
        case 2:
3477
        case 4:
3478
        case 6:
3479
            gen_op_mfc0_taghi();
3480
            rn = "TagHi";
3481
            break;
3482
        case 1:
3483
        case 3:
3484
        case 5:
3485
        case 7:
3486
            gen_op_mfc0_datahi();
3487
            rn = "DataHi";
3488
            break;
3489
        default:
3490
            goto die;
3491
        }
3492
        break;
3493
    case 30:
3494
        switch (sel) {
3495
        case 0:
3496
            gen_op_dmfc0_errorepc();
3497
            rn = "ErrorEPC";
3498
            break;
3499
        default:
3500
            goto die;
3501
        }
3502
        break;
3503
    case 31:
3504
        switch (sel) {
3505
        case 0:
3506
            gen_op_mfc0_desave(); /* EJTAG support */
3507
            rn = "DESAVE";
3508
            break;
3509
        default:
3510
            goto die;
3511
        }
3512
        break;
3513
    default:
3514
        goto die;
3515
    }
3516
#if defined MIPS_DEBUG_DISAS
3517
    if (loglevel & CPU_LOG_TB_IN_ASM) {
3518
        fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
3519
                rn, reg, sel);
3520
    }
3521
#endif
3522
    return;
3523

    
3524
die:
3525
#if defined MIPS_DEBUG_DISAS
3526
    if (loglevel & CPU_LOG_TB_IN_ASM) {
3527
        fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
3528
                rn, reg, sel);
3529
    }
3530
#endif
3531
    generate_exception(ctx, EXCP_RI);
3532
}
3533

    
3534
static void gen_dmtc0 (DisasContext *ctx, int reg, int sel)
3535
{
3536
    const char *rn = "invalid";
3537

    
3538
    switch (reg) {
3539
    case 0:
3540
        switch (sel) {
3541
        case 0:
3542
            gen_op_mtc0_index();
3543
            rn = "Index";
3544
            break;
3545
        case 1:
3546
//            gen_op_dmtc0_mvpcontrol(); /* MT ASE */
3547
            rn = "MVPControl";
3548
//            break;
3549
        case 2:
3550
//            gen_op_dmtc0_mvpconf0(); /* MT ASE */
3551
            rn = "MVPConf0";
3552
//            break;
3553
        case 3:
3554
//            gen_op_dmtc0_mvpconf1(); /* MT ASE */
3555
            rn = "MVPConf1";
3556
//            break;
3557
        default:
3558
            goto die;
3559
        }
3560
        break;
3561
    case 1:
3562
        switch (sel) {
3563
        case 0:
3564
            /* ignored */
3565
            rn = "Random";
3566
            break;
3567
        case 1:
3568
//            gen_op_dmtc0_vpecontrol(); /* MT ASE */
3569
            rn = "VPEControl";
3570
//            break;
3571
        case 2:
3572
//            gen_op_dmtc0_vpeconf0(); /* MT ASE */
3573
            rn = "VPEConf0";
3574
//            break;
3575
        case 3:
3576
//            gen_op_dmtc0_vpeconf1(); /* MT ASE */
3577
            rn = "VPEConf1";
3578
//            break;
3579
        case 4:
3580
//            gen_op_dmtc0_YQMask(); /* MT ASE */
3581
            rn = "YQMask";
3582
//            break;
3583
        case 5:
3584
//            gen_op_dmtc0_vpeschedule(); /* MT ASE */
3585
            rn = "VPESchedule";
3586
//            break;
3587
        case 6:
3588
//            gen_op_dmtc0_vpeschefback(); /* MT ASE */
3589
            rn = "VPEScheFBack";
3590
//            break;
3591
        case 7:
3592
//            gen_op_dmtc0_vpeopt(); /* MT ASE */
3593
            rn = "VPEOpt";
3594
//            break;
3595
        default:
3596
            goto die;
3597
        }
3598
        break;
3599
    case 2:
3600
        switch (sel) {
3601
        case 0:
3602
            gen_op_dmtc0_entrylo0();
3603
            rn = "EntryLo0";
3604
            break;
3605
        case 1:
3606
//            gen_op_dmtc0_tcstatus(); /* MT ASE */
3607
            rn = "TCStatus";
3608
//            break;
3609
        case 2:
3610
//            gen_op_dmtc0_tcbind(); /* MT ASE */
3611
            rn = "TCBind";
3612
//            break;
3613
        case 3:
3614
//            gen_op_dmtc0_tcrestart(); /* MT ASE */
3615
            rn = "TCRestart";
3616
//            break;
3617
        case 4:
3618
//            gen_op_dmtc0_tchalt(); /* MT ASE */
3619
            rn = "TCHalt";
3620
//            break;
3621
        case 5:
3622
//            gen_op_dmtc0_tccontext(); /* MT ASE */
3623
            rn = "TCContext";
3624
//            break;
3625
        case 6:
3626
//            gen_op_dmtc0_tcschedule(); /* MT ASE */
3627
            rn = "TCSchedule";
3628
//            break;
3629
        case 7:
3630
//            gen_op_dmtc0_tcschefback(); /* MT ASE */
3631
            rn = "TCScheFBack";
3632
//            break;
3633
        default:
3634
            goto die;
3635
        }
3636
        break;
3637
    case 3:
3638
        switch (sel) {
3639
        case 0:
3640
            gen_op_dmtc0_entrylo1();
3641
            rn = "EntryLo1";
3642
            break;
3643
        default:
3644
            goto die;
3645
        }
3646
        break;
3647
    case 4:
3648
        switch (sel) {
3649
        case 0:
3650
            gen_op_dmtc0_context();
3651
            rn = "Context";
3652
            break;
3653
        case 1:
3654
//           gen_op_dmtc0_contextconfig(); /* SmartMIPS ASE */
3655
            rn = "ContextConfig";
3656
//           break;
3657
        default:
3658
            goto die;
3659
        }
3660
        break;
3661
    case 5:
3662
        switch (sel) {
3663
        case 0:
3664
            gen_op_mtc0_pagemask();
3665
            rn = "PageMask";
3666
            break;
3667
        case 1:
3668
            gen_op_mtc0_pagegrain();
3669
            rn = "PageGrain";
3670
            break;
3671
        default:
3672
            goto die;
3673
        }
3674
        break;
3675
    case 6:
3676
        switch (sel) {
3677
        case 0:
3678
            gen_op_mtc0_wired();
3679
            rn = "Wired";
3680
            break;
3681
        case 1:
3682
//            gen_op_dmtc0_srsconf0(); /* shadow registers */
3683
            rn = "SRSConf0";
3684
//            break;
3685
        case 2:
3686
//            gen_op_dmtc0_srsconf1(); /* shadow registers */
3687
            rn = "SRSConf1";
3688
//            break;
3689
        case 3:
3690
//            gen_op_dmtc0_srsconf2(); /* shadow registers */
3691
            rn = "SRSConf2";
3692
//            break;
3693
        case 4:
3694
//            gen_op_dmtc0_srsconf3(); /* shadow registers */
3695
            rn = "SRSConf3";
3696
//            break;
3697
        case 5:
3698
//            gen_op_dmtc0_srsconf4(); /* shadow registers */
3699
            rn = "SRSConf4";
3700
//            break;
3701
        default:
3702
            goto die;
3703
        }
3704
        break;
3705
    case 7:
3706
        switch (sel) {
3707
        case 0:
3708
            gen_op_mtc0_hwrena();
3709
            rn = "HWREna";
3710
            break;
3711
        default:
3712
            goto die;
3713
        }
3714
        break;
3715
    case 8:
3716
        /* ignored */
3717
        rn = "BadVaddr";
3718
        break;
3719
    case 9:
3720
        switch (sel) {
3721
        case 0:
3722
            gen_op_mtc0_count();
3723
            rn = "Count";
3724
            break;
3725
        /* 6,7 are implementation dependent */
3726
        default:
3727
            goto die;
3728
        }
3729
        /* Stop translation as we may have switched the execution mode */
3730
        ctx->bstate = BS_STOP;
3731
        break;
3732
    case 10:
3733
        switch (sel) {
3734
        case 0:
3735
            gen_op_mtc0_entryhi();
3736
            rn = "EntryHi";
3737
            break;
3738
        default:
3739
            goto die;
3740
        }
3741
        break;
3742
    case 11:
3743
        switch (sel) {
3744
        case 0:
3745
            gen_op_mtc0_compare();
3746
            rn = "Compare";
3747
            break;
3748
        /* 6,7 are implementation dependent */
3749
        default:
3750
            goto die;
3751
        }
3752
        /* Stop translation as we may have switched the execution mode */
3753
        ctx->bstate = BS_STOP;
3754
        break;
3755
    case 12:
3756
        switch (sel) {
3757
        case 0:
3758
            gen_op_mtc0_status();
3759
            rn = "Status";
3760
            break;
3761
        case 1:
3762
            gen_op_mtc0_intctl();
3763
            rn = "IntCtl";
3764
            break;
3765
        case 2:
3766
            gen_op_mtc0_srsctl();
3767
            rn = "SRSCtl";
3768
            break;
3769
        case 3:
3770
            gen_op_mtc0_srsmap(); /* shadow registers */
3771
            rn = "SRSMap";
3772
            break;
3773
        default:
3774
            goto die;
3775
        }
3776
        /* Stop translation as we may have switched the execution mode */
3777
        ctx->bstate = BS_STOP;
3778
        break;
3779
    case 13:
3780
        switch (sel) {
3781
        case 0:
3782
            gen_op_mtc0_cause();
3783
            rn = "Cause";
3784
            break;
3785
        default:
3786
            goto die;
3787
        }
3788
        /* Stop translation as we may have switched the execution mode */
3789
        ctx->bstate = BS_STOP;
3790
        break;
3791
    case 14:
3792
        switch (sel) {
3793
        case 0:
3794
            gen_op_dmtc0_epc();
3795
            rn = "EPC";
3796
            break;
3797
        default:
3798
            goto die;
3799
        }
3800
        break;
3801
    case 15:
3802
        switch (sel) {
3803
        case 0:
3804
            /* ignored */
3805
            rn = "PRid";
3806
            break;
3807
        case 1:
3808
            gen_op_mtc0_ebase();
3809
            rn = "EBase";
3810
            break;
3811
        default:
3812
            goto die;
3813
        }
3814
        break;
3815
    case 16:
3816
        switch (sel) {
3817
        case 0:
3818
            gen_op_mtc0_config0();
3819
            rn = "Config";
3820
            /* Stop translation as we may have switched the execution mode */
3821
            ctx->bstate = BS_STOP;
3822
            break;
3823
        case 1:
3824
            /* ignored */
3825
            rn = "Config1";
3826
            break;
3827
        case 2:
3828
            gen_op_mtc0_config2();
3829
            rn = "Config2";
3830
            /* Stop translation as we may have switched the execution mode */
3831
            ctx->bstate = BS_STOP;
3832
            break;
3833
        case 3:
3834
            /* ignored */
3835
            rn = "Config3";
3836
            break;
3837
        /* 6,7 are implementation dependent */
3838
        default:
3839
            rn = "Invalid config selector";
3840
            goto die;
3841
        }
3842
        break;
3843
    case 17:
3844
        switch (sel) {
3845
        case 0:
3846
            /* ignored */
3847
            rn = "LLAddr";
3848
            break;
3849
        default:
3850
            goto die;
3851
        }
3852
        break;
3853
    case 18:
3854
        switch (sel) {
3855
        case 0:
3856
            gen_op_dmtc0_watchlo0();
3857
            rn = "WatchLo";
3858
            break;
3859
        case 1:
3860
//            gen_op_dmtc0_watchlo1();
3861
            rn = "WatchLo1";
3862
//            break;
3863
        case 2:
3864
//            gen_op_dmtc0_watchlo2();
3865
            rn = "WatchLo2";
3866
//            break;
3867
        case 3:
3868
//            gen_op_dmtc0_watchlo3();
3869
            rn = "WatchLo3";
3870
//            break;
3871
        case 4:
3872
//            gen_op_dmtc0_watchlo4();
3873
            rn = "WatchLo4";
3874
//            break;
3875
        case 5:
3876
//            gen_op_dmtc0_watchlo5();
3877
            rn = "WatchLo5";
3878
//            break;
3879
        case 6:
3880
//            gen_op_dmtc0_watchlo6();
3881
            rn = "WatchLo6";
3882
//            break;
3883
        case 7:
3884
//            gen_op_dmtc0_watchlo7();
3885
            rn = "WatchLo7";
3886
//            break;
3887
        default:
3888
            goto die;
3889
        }
3890
        break;
3891
    case 19:
3892
        switch (sel) {
3893
        case 0:
3894
            gen_op_mtc0_watchhi0();
3895
            rn = "WatchHi";
3896
            break;
3897
        case 1:
3898
//            gen_op_dmtc0_watchhi1();
3899
            rn = "WatchHi1";
3900
//            break;
3901
        case 2:
3902
//            gen_op_dmtc0_watchhi2();
3903
            rn = "WatchHi2";
3904
//            break;
3905
        case 3:
3906
//            gen_op_dmtc0_watchhi3();
3907
            rn = "WatchHi3";
3908
//            break;
3909
        case 4:
3910
//            gen_op_dmtc0_watchhi4();
3911
            rn = "WatchHi4";
3912
//            break;
3913
        case 5:
3914
//            gen_op_dmtc0_watchhi5();
3915
            rn = "WatchHi5";
3916
//            break;
3917
        case 6:
3918
//            gen_op_dmtc0_watchhi6();
3919
            rn = "WatchHi6";
3920
//            break;
3921
        case 7:
3922
//            gen_op_dmtc0_watchhi7();
3923
            rn = "WatchHi7";
3924
//            break;
3925
        default:
3926
            goto die;
3927
        }
3928
        break;
3929
    case 20:
3930
        switch (sel) {
3931
        case 0:
3932
            /* 64 bit MMU only */
3933
            gen_op_dmtc0_xcontext();
3934
            rn = "XContext";
3935
            break;
3936
        default:
3937
            goto die;
3938
        }
3939
        break;
3940
    case 21:
3941
       /* Officially reserved, but sel 0 is used for R1x000 framemask */
3942
        switch (sel) {
3943
        case 0:
3944
            gen_op_mtc0_framemask();
3945
            rn = "Framemask";
3946
            break;
3947
        default:
3948
            goto die;
3949
        }
3950
        break;
3951
    case 22:
3952
        /* ignored */
3953
        rn = "Diagnostic"; /* implementation dependent */
3954
        break;
3955
    case 23:
3956
        switch (sel) {
3957
        case 0:
3958
            gen_op_mtc0_debug(); /* EJTAG support */
3959
            rn = "Debug";
3960
            break;
3961
        case 1:
3962
//            gen_op_dmtc0_tracecontrol(); /* PDtrace support */
3963
            rn = "TraceControl";
3964
//            break;
3965
        case 2:
3966
//            gen_op_dmtc0_tracecontrol2(); /* PDtrace support */
3967
            rn = "TraceControl2";
3968
//            break;
3969
        case 3:
3970
//            gen_op_dmtc0_usertracedata(); /* PDtrace support */
3971
            rn = "UserTraceData";
3972
//            break;
3973
        case 4:
3974
//            gen_op_dmtc0_debug(); /* PDtrace support */
3975
            rn = "TraceBPC";
3976
//            break;
3977
        default:
3978
            goto die;
3979
        }
3980
        /* Stop translation as we may have switched the execution mode */
3981
        ctx->bstate = BS_STOP;
3982
        break;
3983
    case 24:
3984
        switch (sel) {
3985
        case 0:
3986
            gen_op_dmtc0_depc(); /* EJTAG support */
3987
            rn = "DEPC";
3988
            break;
3989
        default:
3990
            goto die;
3991
        }
3992
        break;
3993
    case 25:
3994
        switch (sel) {
3995
        case 0:
3996
            gen_op_mtc0_performance0();
3997
            rn = "Performance0";
3998
            break;
3999
        case 1:
4000
//            gen_op_dmtc0_performance1();
4001
            rn = "Performance1";
4002
//            break;
4003
        case 2:
4004
//            gen_op_dmtc0_performance2();
4005
            rn = "Performance2";
4006
//            break;
4007
        case 3:
4008
//            gen_op_dmtc0_performance3();
4009
            rn = "Performance3";
4010
//            break;
4011
        case 4:
4012
//            gen_op_dmtc0_performance4();
4013
            rn = "Performance4";
4014
//            break;
4015
        case 5:
4016
//            gen_op_dmtc0_performance5();
4017
            rn = "Performance5";
4018
//            break;
4019
        case 6:
4020
//            gen_op_dmtc0_performance6();
4021
            rn = "Performance6";
4022
//            break;
4023
        case 7:
4024
//            gen_op_dmtc0_performance7();
4025
            rn = "Performance7";
4026
//            break;
4027
        default:
4028
            goto die;
4029
        }
4030
        break;
4031
    case 26:
4032
        /* ignored */
4033
        rn = "ECC";
4034
        break;
4035
    case 27:
4036
        switch (sel) {
4037
        case 0 ... 3:
4038
            /* ignored */
4039
            rn = "CacheErr";
4040
            break;
4041
        default:
4042
            goto die;
4043
        }
4044
        break;
4045
    case 28:
4046
        switch (sel) {
4047
        case 0:
4048
        case 2:
4049
        case 4:
4050
        case 6:
4051
            gen_op_mtc0_taglo();
4052
            rn = "TagLo";
4053
            break;
4054
        case 1:
4055
        case 3:
4056
        case 5:
4057
        case 7:
4058
            gen_op_mtc0_datalo();
4059
            rn = "DataLo";
4060
            break;
4061
        default:
4062
            goto die;
4063
        }
4064
        break;
4065
    case 29:
4066
        switch (sel) {
4067
        case 0:
4068
        case 2:
4069
        case 4:
4070
        case 6:
4071
            gen_op_mtc0_taghi();
4072
            rn = "TagHi";
4073
            break;
4074
        case 1:
4075
        case 3:
4076
        case 5:
4077
        case 7:
4078
            gen_op_mtc0_datahi();
4079
            rn = "DataHi";
4080
            break;
4081
        default:
4082
            rn = "invalid sel";
4083
            goto die;
4084
        }
4085
        break;
4086
    case 30:
4087
        switch (sel) {
4088
        case 0:
4089
            gen_op_dmtc0_errorepc();
4090
            rn = "ErrorEPC";
4091
            break;
4092
        default:
4093
            goto die;
4094
        }
4095
        break;
4096
    case 31:
4097
        switch (sel) {
4098
        case 0:
4099
            gen_op_mtc0_desave(); /* EJTAG support */
4100
            rn = "DESAVE";
4101
            break;
4102
        default:
4103
            goto die;
4104
        }
4105
        /* Stop translation as we may have switched the execution mode */
4106
        ctx->bstate = BS_STOP;
4107
        break;
4108
    default:
4109
        goto die;
4110
    }
4111
#if defined MIPS_DEBUG_DISAS
4112
    if (loglevel & CPU_LOG_TB_IN_ASM) {
4113
        fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
4114
                rn, reg, sel);
4115
    }
4116
#endif
4117
    return;
4118

    
4119
die:
4120
#if defined MIPS_DEBUG_DISAS
4121
    if (loglevel & CPU_LOG_TB_IN_ASM) {
4122
        fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
4123
                rn, reg, sel);
4124
    }
4125
#endif
4126
    generate_exception(ctx, EXCP_RI);
4127
}
4128
#endif /* TARGET_MIPS64 */
4129

    
4130
static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd)
4131
{
4132
    const char *opn = "unk";
4133

    
4134
    switch (opc) {
4135
    case OPC_MFC0:
4136
        if (rt == 0) {
4137
            /* Treat as NOP */
4138
            return;
4139
        }
4140
        gen_mfc0(ctx, rd, ctx->opcode & 0x7);
4141
        gen_op_store_T0_gpr(rt);
4142
        opn = "mfc0";
4143
        break;
4144
    case OPC_MTC0:
4145
        GEN_LOAD_REG_TN(T0, rt);
4146
        gen_mtc0(ctx, rd, ctx->opcode & 0x7);
4147
        opn = "mtc0";
4148
        break;
4149
#ifdef TARGET_MIPS64
4150
    case OPC_DMFC0:
4151
        if (rt == 0) {
4152
            /* Treat as NOP */
4153
            return;
4154
        }
4155
        gen_dmfc0(ctx, rd, ctx->opcode & 0x7);
4156
        gen_op_store_T0_gpr(rt);
4157
        opn = "dmfc0";
4158
        break;
4159
    case OPC_DMTC0:
4160
        GEN_LOAD_REG_TN(T0, rt);
4161
        gen_dmtc0(ctx, rd, ctx->opcode & 0x7);
4162
        opn = "dmtc0";
4163
        break;
4164
#endif
4165
#if defined(MIPS_USES_R4K_TLB)
4166
    case OPC_TLBWI:
4167
        gen_op_tlbwi();
4168
        opn = "tlbwi";
4169
        break;
4170
    case OPC_TLBWR:
4171
        gen_op_tlbwr();
4172
        opn = "tlbwr";
4173
        break;
4174
    case OPC_TLBP:
4175
        gen_op_tlbp();
4176
        opn = "tlbp";
4177
        break;
4178
    case OPC_TLBR:
4179
        gen_op_tlbr();
4180
        opn = "tlbr";
4181
        break;
4182
#endif
4183
    case OPC_ERET:
4184
        opn = "eret";
4185
        save_cpu_state(ctx, 0);
4186
        gen_op_eret();
4187
        ctx->bstate = BS_EXCP;
4188
        break;
4189
    case OPC_DERET:
4190
        opn = "deret";
4191
        if (!(ctx->hflags & MIPS_HFLAG_DM)) {
4192
            generate_exception(ctx, EXCP_RI);
4193
        } else {
4194
            save_cpu_state(ctx, 0);
4195
            gen_op_deret();
4196
            ctx->bstate = BS_EXCP;
4197
        }
4198
        break;
4199
    case OPC_WAIT:
4200
        opn = "wait";
4201
        /* If we get an exception, we want to restart at next instruction */
4202
        ctx->pc += 4;
4203
        save_cpu_state(ctx, 1);
4204
        ctx->pc -= 4;
4205
        gen_op_wait();
4206
        ctx->bstate = BS_EXCP;
4207
        break;
4208
    default:
4209
        if (loglevel & CPU_LOG_TB_IN_ASM) {
4210
            fprintf(logfile, "Invalid CP0 opcode: %08x %03x %03x %03x\n",
4211
                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
4212
                    ((ctx->opcode >> 16) & 0x1F));
4213
        }
4214
        generate_exception(ctx, EXCP_RI);
4215
        return;
4216
    }
4217
    MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
4218
}
4219

    
4220
/* CP1 Branches (before delay slot) */
4221
static void gen_compute_branch1 (DisasContext *ctx, uint32_t op,
4222
                                 int32_t offset)
4223
{
4224
    target_ulong btarget;
4225

    
4226
    btarget = ctx->pc + 4 + offset;
4227

    
4228
    switch (op) {
4229
    case OPC_BC1F:
4230
        gen_op_bc1f();
4231
        MIPS_DEBUG("bc1f " TARGET_FMT_lx, btarget);
4232
        goto not_likely;
4233
    case OPC_BC1FL:
4234
        gen_op_bc1f();
4235
        MIPS_DEBUG("bc1fl " TARGET_FMT_lx, btarget);
4236
        goto likely;
4237
    case OPC_BC1T:
4238
        gen_op_bc1t();
4239
        MIPS_DEBUG("bc1t " TARGET_FMT_lx, btarget);
4240
    not_likely:
4241
        ctx->hflags |= MIPS_HFLAG_BC;
4242
        break;
4243
    case OPC_BC1TL:
4244
        gen_op_bc1t();
4245
        MIPS_DEBUG("bc1tl " TARGET_FMT_lx, btarget);
4246
    likely:
4247
        ctx->hflags |= MIPS_HFLAG_BL;
4248
        break;
4249
    default:    
4250
        MIPS_INVAL("cp1 branch/jump");
4251
        generate_exception (ctx, EXCP_RI);
4252
        return;
4253
    }
4254
    gen_op_set_bcond();
4255

    
4256
    MIPS_DEBUG("enter ds: cond %02x target " TARGET_FMT_lx,
4257
               ctx->hflags, btarget);
4258
    ctx->btarget = btarget;
4259

    
4260
    return;
4261
}
4262

    
4263
/* Coprocessor 1 (FPU) */
4264
static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
4265
{
4266
    const char *opn = "unk";
4267

    
4268
    switch (opc) {
4269
    case OPC_MFC1:
4270
        GEN_LOAD_FREG_FTN(WT0, fs);
4271
        gen_op_mfc1();
4272
        GEN_STORE_TN_REG(rt, T0);
4273
        opn = "mfc1";
4274
        break;
4275
    case OPC_MTC1:
4276
        GEN_LOAD_REG_TN(T0, rt);
4277
        gen_op_mtc1();
4278
        GEN_STORE_FTN_FREG(fs, WT0);
4279
        opn = "mtc1";
4280
        break;
4281
    case OPC_CFC1:
4282
        if (fs != 0 && fs != 31) {
4283
            MIPS_INVAL("cfc1 freg");
4284
            generate_exception (ctx, EXCP_RI);
4285
            return;
4286
        }
4287
        GEN_LOAD_IMM_TN(T1, fs);
4288
        gen_op_cfc1();
4289
        GEN_STORE_TN_REG(rt, T0);
4290
        opn = "cfc1";
4291
        break;
4292
    case OPC_CTC1:
4293
         if (fs != 0 && fs != 31) {
4294
            MIPS_INVAL("ctc1 freg");
4295
            generate_exception (ctx, EXCP_RI);
4296
            return;
4297
        }
4298
        GEN_LOAD_IMM_TN(T1, fs);
4299
        GEN_LOAD_REG_TN(T0, rt);
4300
        gen_op_ctc1();
4301
        opn = "ctc1";
4302
        break;
4303
    case OPC_DMFC1:
4304
    case OPC_DMTC1:
4305
        /* Not implemented, fallthrough. */
4306
    default:
4307
        if (loglevel & CPU_LOG_TB_IN_ASM) {
4308
            fprintf(logfile, "Invalid CP1 opcode: %08x %03x %03x %03x\n",
4309
                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
4310
                    ((ctx->opcode >> 16) & 0x1F));
4311
        }
4312
        generate_exception (ctx, EXCP_RI);
4313
        return;
4314
    }
4315
    MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
4316
}
4317

    
4318
/* verify if floating point register is valid; an operation is not defined
4319
 * if bit 0 of any register specification is set and the FR bit in the
4320
 * Status register equals zero, since the register numbers specify an
4321
 * even-odd pair of adjacent coprocessor general registers. When the FR bit
4322
 * in the Status register equals one, both even and odd register numbers
4323
 * are valid. This limitation exists only for 64 bit wide (d,l) registers.
4324
 * 
4325
 * Multiple 64 bit wide registers can be checked by calling
4326
 * CHECK_FR(ctx, freg1 | freg2 | ... | fregN);
4327
 */
4328
#define CHECK_FR(ctx, freg) do { \
4329
        if (!((ctx)->CP0_Status & (1<<CP0St_FR)) && ((freg) & 1)) { \
4330
            generate_exception (ctx, EXCP_RI); \
4331
            return; \
4332
        } \
4333
    } while(0)
4334

    
4335
#define FOP(func, fmt) (((fmt) << 21) | (func))
4336

    
4337
static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, int fs, int fd)
4338
{
4339
    const char *opn = "unk";
4340
    const char *condnames[] = {
4341
            "c.f",
4342
            "c.un",
4343
            "c.eq",
4344
            "c.ueq",
4345
            "c.olt",
4346
            "c.ult",
4347
            "c.ole",
4348
            "c.ule",
4349
            "c.sf",
4350
            "c.ngle",
4351
            "c.seq",
4352
            "c.ngl",
4353
            "c.lt",
4354
            "c.nge",
4355
            "c.le",
4356
            "c.ngt",
4357
    };
4358
    int binary = 0;
4359
    uint32_t func = ctx->opcode & 0x3f;
4360

    
4361
    switch (ctx->opcode & FOP(0x3f, 0x1f)) {
4362
    case FOP(0, 17):
4363
        CHECK_FR(ctx, fs | ft | fd);
4364
        GEN_LOAD_FREG_FTN(DT0, fs);
4365
        GEN_LOAD_FREG_FTN(DT1, ft);
4366
        gen_op_float_add_d();
4367
        GEN_STORE_FTN_FREG(fd, DT2);
4368
        opn = "add.d";
4369
        binary = 1;
4370
        break;
4371
    case FOP(1, 17):
4372
        CHECK_FR(ctx, fs | ft | fd);
4373
        GEN_LOAD_FREG_FTN(DT0, fs);
4374
        GEN_LOAD_FREG_FTN(DT1, ft);
4375
        gen_op_float_sub_d();
4376
        GEN_STORE_FTN_FREG(fd, DT2);
4377
        opn = "sub.d";
4378
        binary = 1;
4379
        break;
4380
    case FOP(2, 17):
4381
        CHECK_FR(ctx, fs | ft | fd);
4382
        GEN_LOAD_FREG_FTN(DT0, fs);
4383
        GEN_LOAD_FREG_FTN(DT1, ft);
4384
        gen_op_float_mul_d();
4385
        GEN_STORE_FTN_FREG(fd, DT2);
4386
        opn = "mul.d";
4387
        binary = 1;
4388
        break;
4389
    case FOP(3, 17):
4390
        CHECK_FR(ctx, fs | ft | fd);
4391
        GEN_LOAD_FREG_FTN(DT0, fs);
4392
        GEN_LOAD_FREG_FTN(DT1, ft);
4393
        gen_op_float_div_d();
4394
        GEN_STORE_FTN_FREG(fd, DT2);
4395
        opn = "div.d";
4396
        binary = 1;
4397
        break;
4398
    case FOP(4, 17):
4399
        CHECK_FR(ctx, fs | fd);
4400
        GEN_LOAD_FREG_FTN(DT0, fs);
4401
        gen_op_float_sqrt_d();
4402
        GEN_STORE_FTN_FREG(fd, DT2);
4403
        opn = "sqrt.d";
4404
        break;
4405
    case FOP(5, 17):
4406
        CHECK_FR(ctx, fs | fd);
4407
        GEN_LOAD_FREG_FTN(DT0, fs);
4408
        gen_op_float_abs_d();
4409
        GEN_STORE_FTN_FREG(fd, DT2);
4410
        opn = "abs.d";
4411
        break;
4412
    case FOP(6, 17):
4413
        CHECK_FR(ctx, fs | fd);
4414
        GEN_LOAD_FREG_FTN(DT0, fs);
4415
        gen_op_float_mov_d();
4416
        GEN_STORE_FTN_FREG(fd, DT2);
4417
        opn = "mov.d";
4418
        break;
4419
    case FOP(7, 17):
4420
        CHECK_FR(ctx, fs | fd);
4421
        GEN_LOAD_FREG_FTN(DT0, fs);
4422
        gen_op_float_chs_d();
4423
        GEN_STORE_FTN_FREG(fd, DT2);
4424
        opn = "neg.d";
4425
        break;
4426
    /*  8 - round.l */
4427
    /*  9 - trunc.l */
4428
    /* 10 - ceil.l  */
4429
    /* 11 - floor.l */
4430
    case FOP(12, 17):
4431
        CHECK_FR(ctx, fs);
4432
        GEN_LOAD_FREG_FTN(DT0, fs);
4433
        gen_op_float_roundw_d();
4434
        GEN_STORE_FTN_FREG(fd, WT2);
4435
        opn = "round.w.d";
4436
        break;
4437
    case FOP(13, 17):
4438
        CHECK_FR(ctx, fs);
4439
        GEN_LOAD_FREG_FTN(DT0, fs);
4440
        gen_op_float_truncw_d();
4441
        GEN_STORE_FTN_FREG(fd, WT2);
4442
        opn = "trunc.w.d";
4443
        break;
4444
    case FOP(14, 17):
4445
        CHECK_FR(ctx, fs);
4446
        GEN_LOAD_FREG_FTN(DT0, fs);
4447
        gen_op_float_ceilw_d();
4448
        GEN_STORE_FTN_FREG(fd, WT2);
4449
        opn = "ceil.w.d";
4450
        break;
4451
    case FOP(15, 17):
4452
        CHECK_FR(ctx, fs);
4453
        GEN_LOAD_FREG_FTN(DT0, fs);
4454
        gen_op_float_floorw_d();
4455
        GEN_STORE_FTN_FREG(fd, WT2);
4456
        opn = "floor.w.d";
4457
        break;
4458
    case FOP(33, 16):
4459
        CHECK_FR(ctx, fd);
4460
        GEN_LOAD_FREG_FTN(WT0, fs);
4461
        gen_op_float_cvtd_s();
4462
        GEN_STORE_FTN_FREG(fd, DT2);
4463
        opn = "cvt.d.s";
4464
        break;
4465
    case FOP(33, 20):
4466
        CHECK_FR(ctx, fd);
4467
        GEN_LOAD_FREG_FTN(WT0, fs);
4468
        gen_op_float_cvtd_w();
4469
        GEN_STORE_FTN_FREG(fd, DT2);
4470
        opn = "cvt.d.w";
4471
        break;
4472
    case FOP(48, 17):
4473
    case FOP(49, 17):
4474
    case FOP(50, 17):
4475
    case FOP(51, 17):
4476
    case FOP(52, 17):
4477
    case FOP(53, 17):
4478
    case FOP(54, 17):
4479
    case FOP(55, 17):
4480
    case FOP(56, 17):
4481
    case FOP(57, 17):
4482
    case FOP(58, 17):
4483
    case FOP(59, 17):
4484
    case FOP(60, 17):
4485
    case FOP(61, 17):
4486
    case FOP(62, 17):
4487
    case FOP(63, 17):
4488
        CHECK_FR(ctx, fs | ft);
4489
        GEN_LOAD_FREG_FTN(DT0, fs);
4490
        GEN_LOAD_FREG_FTN(DT1, ft);
4491
        gen_cmp_d(func-48);
4492
        opn = condnames[func-48];
4493
        break;
4494
    case FOP(0, 16):
4495
        GEN_LOAD_FREG_FTN(WT0, fs);
4496
        GEN_LOAD_FREG_FTN(WT1, ft);
4497
        gen_op_float_add_s();
4498
        GEN_STORE_FTN_FREG(fd, WT2);
4499
        opn = "add.s";
4500
        binary = 1;
4501
        break;
4502
    case FOP(1, 16):
4503
        GEN_LOAD_FREG_FTN(WT0, fs);
4504
        GEN_LOAD_FREG_FTN(WT1, ft);
4505
        gen_op_float_sub_s();
4506
        GEN_STORE_FTN_FREG(fd, WT2);
4507
        opn = "sub.s";
4508
        binary = 1;
4509
        break;
4510
    case FOP(2, 16):
4511
        GEN_LOAD_FREG_FTN(WT0, fs);
4512
        GEN_LOAD_FREG_FTN(WT1, ft);
4513
        gen_op_float_mul_s();
4514
        GEN_STORE_FTN_FREG(fd, WT2);
4515
        opn = "mul.s";
4516
        binary = 1;
4517
        break;
4518
    case FOP(3, 16):
4519
        GEN_LOAD_FREG_FTN(WT0, fs);
4520
        GEN_LOAD_FREG_FTN(WT1, ft);
4521
        gen_op_float_div_s();
4522
        GEN_STORE_FTN_FREG(fd, WT2);
4523
        opn = "div.s";
4524
        binary = 1;
4525
        break;
4526
    case FOP(4, 16):
4527
        GEN_LOAD_FREG_FTN(WT0, fs);
4528
        gen_op_float_sqrt_s();
4529
        GEN_STORE_FTN_FREG(fd, WT2);
4530
        opn = "sqrt.s";
4531
        break;
4532
    case FOP(5, 16):
4533
        GEN_LOAD_FREG_FTN(WT0, fs);
4534
        gen_op_float_abs_s();
4535
        GEN_STORE_FTN_FREG(fd, WT2);
4536
        opn = "abs.s";
4537
        break;
4538
    case FOP(6, 16):
4539
        GEN_LOAD_FREG_FTN(WT0, fs);
4540
        gen_op_float_mov_s();
4541
        GEN_STORE_FTN_FREG(fd, WT2);
4542
        opn = "mov.s";
4543
        break;
4544
    case FOP(7, 16):
4545
        GEN_LOAD_FREG_FTN(WT0, fs);
4546
        gen_op_float_chs_s();
4547
        GEN_STORE_FTN_FREG(fd, WT2);
4548
        opn = "neg.s";
4549
        break;
4550
    case FOP(12, 16):
4551
        GEN_LOAD_FREG_FTN(WT0, fs);
4552
        gen_op_float_roundw_s();
4553
        GEN_STORE_FTN_FREG(fd, WT2);
4554
        opn = "round.w.s";
4555
        break;
4556
    case FOP(13, 16):
4557
        GEN_LOAD_FREG_FTN(WT0, fs);
4558
        gen_op_float_truncw_s();
4559
        GEN_STORE_FTN_FREG(fd, WT2);
4560
        opn = "trunc.w.s";
4561
        break;
4562
    case FOP(32, 17):
4563
        CHECK_FR(ctx, fs);
4564
        GEN_LOAD_FREG_FTN(DT0, fs);
4565
        gen_op_float_cvts_d();
4566
        GEN_STORE_FTN_FREG(fd, WT2);
4567
        opn = "cvt.s.d";
4568
        break;
4569
    case FOP(32, 20):
4570
        GEN_LOAD_FREG_FTN(WT0, fs);
4571
        gen_op_float_cvts_w();
4572
        GEN_STORE_FTN_FREG(fd, WT2);
4573
        opn = "cvt.s.w";
4574
        break;
4575
    case FOP(36, 16):
4576
        GEN_LOAD_FREG_FTN(WT0, fs);
4577
        gen_op_float_cvtw_s();
4578
        GEN_STORE_FTN_FREG(fd, WT2);
4579
        opn = "cvt.w.s";
4580
        break;
4581
    case FOP(36, 17):
4582
        CHECK_FR(ctx, fs);
4583
        GEN_LOAD_FREG_FTN(DT0, fs);
4584
        gen_op_float_cvtw_d();
4585
        GEN_STORE_FTN_FREG(fd, WT2);
4586
        opn = "cvt.w.d";
4587
        break;
4588
    case FOP(48, 16):
4589
    case FOP(49, 16):
4590
    case FOP(50, 16):
4591
    case FOP(51, 16):
4592
    case FOP(52, 16):
4593
    case FOP(53, 16):
4594
    case FOP(54, 16):
4595
    case FOP(55, 16):
4596
    case FOP(56, 16):
4597
    case FOP(57, 16):
4598
    case FOP(58, 16):
4599
    case FOP(59, 16):
4600
    case FOP(60, 16):
4601
    case FOP(61, 16):
4602
    case FOP(62, 16):
4603
    case FOP(63, 16):
4604
        GEN_LOAD_FREG_FTN(WT0, fs);
4605
        GEN_LOAD_FREG_FTN(WT1, ft);
4606
        gen_cmp_s(func-48);
4607
        opn = condnames[func-48];
4608
        break;
4609
    default:    
4610
        if (loglevel & CPU_LOG_TB_IN_ASM) {
4611
            fprintf(logfile, "Invalid FP arith function: %08x %03x %03x %03x\n",
4612
                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
4613
                    ((ctx->opcode >> 16) & 0x1F));
4614
        }
4615
        generate_exception (ctx, EXCP_RI);
4616
        return;
4617
    }
4618
    if (binary)
4619
        MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
4620
    else
4621
        MIPS_DEBUG("%s %s,%s", opn, f