Statistics
| Branch: | Revision:

root / target-mips / translate.c @ 5dc4b744

History | View | Annotate | Download (111.7 kB)

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

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

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

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

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

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

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

    
53
#include "gen-op.h"
54

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

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

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

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

    
199
    OPC_MOVCI    = 0x01 | OPC_SPECIAL,
200

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
394
#ifdef MIPS_USES_FPU
395

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

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

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

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

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

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

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

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

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

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

    
476
FOP_CONDS(d)
477
FOP_CONDS(s)
478

    
479
#endif /* MIPS_USES_FPU */
480

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
797
#ifdef MIPS_USES_FPU
798

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

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

    
846
#endif /* MIPS_USES_FPU */
847

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2830
static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd)
2831
{
2832
    const char *opn = "unk";
2833

    
2834
    if ((!ctx->CP0_Status & (1 << CP0St_CU0) &&
2835
          (ctx->hflags & MIPS_HFLAG_UM)) &&
2836
        !(ctx->hflags & MIPS_HFLAG_ERL) &&
2837
        !(ctx->hflags & MIPS_HFLAG_EXL)) {
2838
        if (loglevel & CPU_LOG_TB_IN_ASM) {
2839
            fprintf(logfile, "CP0 is not usable\n");
2840
        }
2841
        generate_exception (ctx, EXCP_CpU);
2842
        return;
2843
    }
2844

    
2845
    switch (opc) {
2846
    case OPC_MFC0:
2847
        if (rt == 0) {
2848
            /* Treat as NOP */
2849
            return;
2850
        }
2851
        gen_mfc0(ctx, rd, ctx->opcode & 0x7);
2852
        gen_op_store_T0_gpr(rt);
2853
        opn = "mfc0";
2854
        break;
2855
    case OPC_MTC0:
2856
        /* If we get an exception, we want to restart at next instruction */
2857
       /* XXX: breaks for mtc in delay slot */
2858
        ctx->pc += 4;
2859
        save_cpu_state(ctx, 1);
2860
        ctx->pc -= 4;
2861
        GEN_LOAD_REG_TN(T0, rt);
2862
        gen_mtc0(ctx, rd, ctx->opcode & 0x7);
2863
        opn = "mtc0";
2864
        break;
2865
#if defined(MIPS_USES_R4K_TLB)
2866
    case OPC_TLBWI:
2867
        gen_op_tlbwi();
2868
        opn = "tlbwi";
2869
        break;
2870
    case OPC_TLBWR:
2871
        gen_op_tlbwr();
2872
        opn = "tlbwr";
2873
        break;
2874
    case OPC_TLBP:
2875
        gen_op_tlbp();
2876
        opn = "tlbp";
2877
        break;
2878
    case OPC_TLBR:
2879
        gen_op_tlbr();
2880
        opn = "tlbr";
2881
        break;
2882
#endif
2883
    case OPC_ERET:
2884
        opn = "eret";
2885
        save_cpu_state(ctx, 0);
2886
        gen_op_eret();
2887
        ctx->bstate = BS_EXCP;
2888
        break;
2889
    case OPC_DERET:
2890
        opn = "deret";
2891
        if (!(ctx->hflags & MIPS_HFLAG_DM)) {
2892
            generate_exception(ctx, EXCP_RI);
2893
        } else {
2894
            save_cpu_state(ctx, 0);
2895
            gen_op_deret();
2896
            ctx->bstate = BS_EXCP;
2897
        }
2898
        break;
2899
    case OPC_WAIT:
2900
        opn = "wait";
2901
        /* If we get an exception, we want to restart at next instruction */
2902
        ctx->pc += 4;
2903
        save_cpu_state(ctx, 1);
2904
        ctx->pc -= 4;
2905
        gen_op_wait();
2906
        ctx->bstate = BS_EXCP;
2907
        break;
2908
    default:
2909
        if (loglevel & CPU_LOG_TB_IN_ASM) {
2910
            fprintf(logfile, "Invalid CP0 opcode: %08x %03x %03x %03x\n",
2911
                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
2912
                    ((ctx->opcode >> 16) & 0x1F));
2913
        }
2914
        generate_exception(ctx, EXCP_RI);
2915
        return;
2916
    }
2917
    MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
2918
}
2919

    
2920
#ifdef MIPS_USES_FPU
2921

    
2922
/* CP1 Branches (before delay slot) */
2923
static void gen_compute_branch1 (DisasContext *ctx, uint32_t op,
2924
                                 int32_t offset)
2925
{
2926
    target_ulong btarget;
2927

    
2928
    btarget = ctx->pc + 4 + offset;
2929

    
2930
    switch (op) {
2931
    case OPC_BC1F:
2932
        gen_op_bc1f();
2933
        MIPS_DEBUG("bc1f " TLSZ, btarget);
2934
        goto not_likely;
2935
    case OPC_BC1FL:
2936
        gen_op_bc1f();
2937
        MIPS_DEBUG("bc1fl " TLSZ, btarget);
2938
        goto likely;
2939
    case OPC_BC1T:
2940
        gen_op_bc1t();
2941
        MIPS_DEBUG("bc1t " TLSZ, btarget);
2942
    not_likely:
2943
        ctx->hflags |= MIPS_HFLAG_BC;
2944
        break;
2945
    case OPC_BC1TL:
2946
        gen_op_bc1t();
2947
        MIPS_DEBUG("bc1tl " TLSZ, btarget);
2948
    likely:
2949
        ctx->hflags |= MIPS_HFLAG_BL;
2950
        break;
2951
    default:    
2952
        MIPS_INVAL("cp1 branch/jump");
2953
        generate_exception_err (ctx, EXCP_RI, 1);
2954
        return;
2955
    }
2956
    gen_op_set_bcond();
2957

    
2958
    MIPS_DEBUG("enter ds: cond %02x target " TLSZ,
2959
               ctx->hflags, btarget);
2960
    ctx->btarget = btarget;
2961

    
2962
    return;
2963
}
2964

    
2965
/* Coprocessor 1 (FPU) */
2966
static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
2967
{
2968
    const char *opn = "unk";
2969

    
2970
    switch (opc) {
2971
    case OPC_MFC1:
2972
        GEN_LOAD_FREG_FTN(WT0, fs);
2973
        gen_op_mfc1();
2974
        GEN_STORE_TN_REG(rt, T0);
2975
        opn = "mfc1";
2976
        break;
2977
    case OPC_MTC1:
2978
        GEN_LOAD_REG_TN(T0, rt);
2979
        gen_op_mtc1();
2980
        GEN_STORE_FTN_FREG(fs, WT0);
2981
        opn = "mtc1";
2982
        break;
2983
    case OPC_CFC1:
2984
        if (fs != 0 && fs != 31) {
2985
            MIPS_INVAL("cfc1 freg");
2986
            generate_exception_err (ctx, EXCP_RI, 1);
2987
            return;
2988
        }
2989
        GEN_LOAD_IMM_TN(T1, fs);
2990
        gen_op_cfc1();
2991
        GEN_STORE_TN_REG(rt, T0);
2992
        opn = "cfc1";
2993
        break;
2994
    case OPC_CTC1:
2995
         if (fs != 0 && fs != 31) {
2996
            MIPS_INVAL("ctc1 freg");
2997
            generate_exception_err (ctx, EXCP_RI, 1);
2998
            return;
2999
        }
3000
        GEN_LOAD_IMM_TN(T1, fs);
3001
        GEN_LOAD_REG_TN(T0, rt);
3002
        gen_op_ctc1();
3003
        opn = "ctc1";
3004
        break;
3005
    default:
3006
        if (loglevel & CPU_LOG_TB_IN_ASM) {
3007
            fprintf(logfile, "Invalid CP1 opcode: %08x %03x %03x %03x\n",
3008
                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
3009
                    ((ctx->opcode >> 16) & 0x1F));
3010
        }
3011
        generate_exception_err (ctx, EXCP_RI, 1);
3012
        return;
3013
    }
3014
    MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
3015
}
3016

    
3017
/* verify if floating point register is valid; an operation is not defined
3018
 * if bit 0 of any register specification is set and the FR bit in the
3019
 * Status register equals zero, since the register numbers specify an
3020
 * even-odd pair of adjacent coprocessor general registers. When the FR bit
3021
 * in the Status register equals one, both even and odd register numbers
3022
 * are valid.
3023
 * 
3024
 * Multiple float registers can be checked by calling
3025
 * CHECK_FR(ctx, freg1 | freg2 | ... | fregN);
3026
 */
3027
#define CHECK_FR(ctx, freg) do { \
3028
        if (!((ctx)->CP0_Status & (1<<CP0St_FR)) && ((freg) & 1)) { \
3029
            generate_exception_err (ctx, EXCP_RI, 1); \
3030
            return; \
3031
        } \
3032
    } while(0)
3033

    
3034
#define FOP(func, fmt) (((fmt) << 21) | (func))
3035

    
3036
static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, int fs, int fd)
3037
{
3038
    const char *opn = "unk";
3039
    const char *condnames[] = {
3040
            "c.f",
3041
            "c.un",
3042
            "c.eq",
3043
            "c.ueq",
3044
            "c.olt",
3045
            "c.ult",
3046
            "c.ole",
3047
            "c.ule",
3048
            "c.sf",
3049
            "c.ngle",
3050
            "c.seq",
3051
            "c.ngl",
3052
            "c.lt",
3053
            "c.nge",
3054
            "c.le",
3055
            "c.ngt",
3056
    };
3057
    int binary = 0;
3058
    uint32_t func = ctx->opcode & 0x3f;
3059

    
3060
    switch (ctx->opcode & FOP(0x3f, 0x1f)) {
3061
    case FOP(0, 17):
3062
        CHECK_FR(ctx, fs | ft | fd);
3063
        GEN_LOAD_FREG_FTN(DT0, fs);
3064
        GEN_LOAD_FREG_FTN(DT1, ft);
3065
        gen_op_float_add_d();
3066
        GEN_STORE_FTN_FREG(fd, DT2);
3067
        opn = "add.d";
3068
        binary = 1;
3069
        break;
3070
    case FOP(1, 17):
3071
        CHECK_FR(ctx, fs | ft | fd);
3072
        GEN_LOAD_FREG_FTN(DT0, fs);
3073
        GEN_LOAD_FREG_FTN(DT1, ft);
3074
        gen_op_float_sub_d();
3075
        GEN_STORE_FTN_FREG(fd, DT2);
3076
        opn = "sub.d";
3077
        binary = 1;
3078
        break;
3079
    case FOP(2, 17):
3080
        CHECK_FR(ctx, fs | ft | fd);
3081
        GEN_LOAD_FREG_FTN(DT0, fs);
3082
        GEN_LOAD_FREG_FTN(DT1, ft);
3083
        gen_op_float_mul_d();
3084
        GEN_STORE_FTN_FREG(fd, DT2);
3085
        opn = "mul.d";
3086
        binary = 1;
3087
        break;
3088
    case FOP(3, 17):
3089
        CHECK_FR(ctx, fs | ft | fd);
3090
        GEN_LOAD_FREG_FTN(DT0, fs);
3091
        GEN_LOAD_FREG_FTN(DT1, ft);
3092
        gen_op_float_div_d();
3093
        GEN_STORE_FTN_FREG(fd, DT2);
3094
        opn = "div.d";
3095
        binary = 1;
3096
        break;
3097
    case FOP(4, 17):
3098
        CHECK_FR(ctx, fs | fd);
3099
        GEN_LOAD_FREG_FTN(DT0, fs);
3100
        gen_op_float_sqrt_d();
3101
        GEN_STORE_FTN_FREG(fd, DT2);
3102
        opn = "sqrt.d";
3103
        break;
3104
    case FOP(5, 17):
3105
        CHECK_FR(ctx, fs | fd);
3106
        GEN_LOAD_FREG_FTN(DT0, fs);
3107
        gen_op_float_abs_d();
3108
        GEN_STORE_FTN_FREG(fd, DT2);
3109
        opn = "abs.d";
3110
        break;
3111
    case FOP(6, 17):
3112
        CHECK_FR(ctx, fs | fd);
3113
        GEN_LOAD_FREG_FTN(DT0, fs);
3114
        gen_op_float_mov_d();
3115
        GEN_STORE_FTN_FREG(fd, DT2);
3116
        opn = "mov.d";
3117
        break;
3118
    case FOP(7, 17):
3119
        CHECK_FR(ctx, fs | fd);
3120
        GEN_LOAD_FREG_FTN(DT0, fs);
3121
        gen_op_float_chs_d();
3122
        GEN_STORE_FTN_FREG(fd, DT2);
3123
        opn = "neg.d";
3124
        break;
3125
    /*  8 - round.l */
3126
    /*  9 - trunc.l */
3127
    /* 10 - ceil.l  */
3128
    /* 11 - floor.l */
3129
    case FOP(12, 17):
3130
        CHECK_FR(ctx, fs | fd);
3131
        GEN_LOAD_FREG_FTN(DT0, fs);
3132
        gen_op_float_roundw_d();
3133
        GEN_STORE_FTN_FREG(fd, WT2);
3134
        opn = "round.w.d";
3135
        break;
3136
    case FOP(13, 17):
3137
        CHECK_FR(ctx, fs | fd);
3138
        GEN_LOAD_FREG_FTN(DT0, fs);
3139
        gen_op_float_truncw_d();
3140
        GEN_STORE_FTN_FREG(fd, WT2);
3141
        opn = "trunc.w.d";
3142
        break;
3143
    case FOP(14, 17):
3144
        CHECK_FR(ctx, fs | fd);
3145
        GEN_LOAD_FREG_FTN(DT0, fs);
3146
        gen_op_float_ceilw_d();
3147
        GEN_STORE_FTN_FREG(fd, WT2);
3148
        opn = "ceil.w.d";
3149
        break;
3150
    case FOP(15, 17):
3151
        CHECK_FR(ctx, fs | fd);
3152
        GEN_LOAD_FREG_FTN(DT0, fs);
3153
        gen_op_float_floorw_d();
3154
        GEN_STORE_FTN_FREG(fd, WT2);
3155
        opn = "floor.w.d";
3156
        break;
3157
    case FOP(33, 16): /* cvt.d.s */
3158
        CHECK_FR(ctx, fs | fd);
3159
        GEN_LOAD_FREG_FTN(WT0, fs);
3160
        gen_op_float_cvtd_s();
3161
        GEN_STORE_FTN_FREG(fd, DT2);
3162
        opn = "cvt.d.s";
3163
        break;
3164
    case FOP(33, 20): /* cvt.d.w */
3165
        CHECK_FR(ctx, fs | fd);
3166
        GEN_LOAD_FREG_FTN(WT0, fs);
3167
        gen_op_float_cvtd_w();
3168
        GEN_STORE_FTN_FREG(fd, DT2);
3169
        opn = "cvt.d.w";
3170
        break;
3171
    case FOP(48, 17):
3172
    case FOP(49, 17):
3173
    case FOP(50, 17):
3174
    case FOP(51, 17):
3175
    case FOP(52, 17):
3176
    case FOP(53, 17):
3177
    case FOP(54, 17):
3178
    case FOP(55, 17):
3179
    case FOP(56, 17):
3180
    case FOP(57, 17):
3181
    case FOP(58, 17):
3182
    case FOP(59, 17):
3183
    case FOP(60, 17):
3184
    case FOP(61, 17):
3185
    case FOP(62, 17):
3186
    case FOP(63, 17):
3187
        CHECK_FR(ctx, fs | ft);
3188
        GEN_LOAD_FREG_FTN(DT0, fs);
3189
        GEN_LOAD_FREG_FTN(DT1, ft);
3190
        gen_cmp_d(func-48);
3191
        opn = condnames[func-48];
3192
        break;
3193
    case FOP(0, 16):
3194
        CHECK_FR(ctx, fs | ft | fd);
3195
        GEN_LOAD_FREG_FTN(WT0, fs);
3196
        GEN_LOAD_FREG_FTN(WT1, ft);
3197
        gen_op_float_add_s();
3198
        GEN_STORE_FTN_FREG(fd, WT2);
3199
        opn = "add.s";
3200
        binary = 1;
3201
        break;
3202
    case FOP(1, 16):
3203
        CHECK_FR(ctx, fs | ft | fd);
3204
        GEN_LOAD_FREG_FTN(WT0, fs);
3205
        GEN_LOAD_FREG_FTN(WT1, ft);
3206
        gen_op_float_sub_s();
3207
        GEN_STORE_FTN_FREG(fd, WT2);
3208
        opn = "sub.s";
3209
        binary = 1;
3210
        break;
3211
    case FOP(2, 16):
3212
        CHECK_FR(ctx, fs | ft | fd);
3213
        GEN_LOAD_FREG_FTN(WT0, fs);
3214
        GEN_LOAD_FREG_FTN(WT1, ft);
3215
        gen_op_float_mul_s();
3216
        GEN_STORE_FTN_FREG(fd, WT2);
3217
        opn = "mul.s";
3218
        binary = 1;
3219
        break;
3220
    case FOP(3, 16):
3221
        CHECK_FR(ctx, fs | ft | fd);
3222
        GEN_LOAD_FREG_FTN(WT0, fs);
3223
        GEN_LOAD_FREG_FTN(WT1, ft);
3224
        gen_op_float_div_s();
3225
        GEN_STORE_FTN_FREG(fd, WT2);
3226
        opn = "div.s";
3227
        binary = 1;
3228
        break;
3229
    case FOP(4, 16):
3230
        CHECK_FR(ctx, fs | fd);
3231
        GEN_LOAD_FREG_FTN(WT0, fs);
3232
        gen_op_float_sqrt_s();
3233
        GEN_STORE_FTN_FREG(fd, WT2);
3234
        opn = "sqrt.s";
3235
        break;
3236
    case FOP(5, 16):
3237
        CHECK_FR(ctx, fs | fd);
3238
        GEN_LOAD_FREG_FTN(WT0, fs);
3239
        gen_op_float_abs_s();
3240
        GEN_STORE_FTN_FREG(fd, WT2);
3241
        opn = "abs.s";
3242
        break;
3243
    case FOP(6, 16):
3244
        CHECK_FR(ctx, fs | fd);
3245
        GEN_LOAD_FREG_FTN(WT0, fs);
3246
        gen_op_float_mov_s();
3247
        GEN_STORE_FTN_FREG(fd, WT2);
3248
        opn = "mov.s";
3249
        break;
3250
    case FOP(7, 16):
3251
        CHECK_FR(ctx, fs | fd);
3252
        GEN_LOAD_FREG_FTN(WT0, fs);
3253
        gen_op_float_chs_s();
3254
        GEN_STORE_FTN_FREG(fd, WT2);
3255
        opn = "neg.s";
3256
        break;
3257
    case FOP(12, 16):
3258
        CHECK_FR(ctx, fs | fd);
3259
        GEN_LOAD_FREG_FTN(WT0, fs);
3260
        gen_op_float_roundw_s();
3261
        GEN_STORE_FTN_FREG(fd, WT2);
3262
        opn = "round.w.s";
3263
        break;
3264
    case FOP(13, 16):
3265
        CHECK_FR(ctx, fs | fd);
3266
        GEN_LOAD_FREG_FTN(WT0, fs);
3267
        gen_op_float_truncw_s();
3268
        GEN_STORE_FTN_FREG(fd, WT2);
3269
        opn = "trunc.w.s";
3270
        break;
3271
    case FOP(32, 17): /* cvt.s.d */
3272
        CHECK_FR(ctx, fs | fd);
3273
        GEN_LOAD_FREG_FTN(DT0, fs);
3274
        gen_op_float_cvts_d();
3275
        GEN_STORE_FTN_FREG(fd, WT2);
3276
        opn = "cvt.s.d";
3277
        break;
3278
    case FOP(32, 20): /* cvt.s.w */
3279
        CHECK_FR(ctx, fs | fd);
3280
        GEN_LOAD_FREG_FTN(WT0, fs);
3281
        gen_op_float_cvts_w();
3282
        GEN_STORE_FTN_FREG(fd, WT2);
3283
        opn = "cvt.s.w";
3284
        break;
3285
    case FOP(36, 16): /* cvt.w.s */
3286
        CHECK_FR(ctx, fs | fd);
3287
        GEN_LOAD_FREG_FTN(WT0, fs);
3288
        gen_op_float_cvtw_s();
3289
        GEN_STORE_FTN_FREG(fd, WT2);
3290
        opn = "cvt.w.s";
3291
        break;
3292
    case FOP(36, 17): /* cvt.w.d */
3293
        CHECK_FR(ctx, fs | fd);
3294
        GEN_LOAD_FREG_FTN(DT0, fs);
3295
        gen_op_float_cvtw_d();
3296
        GEN_STORE_FTN_FREG(fd, WT2);
3297
        opn = "cvt.w.d";
3298
        break;
3299
    case FOP(48, 16):
3300
    case FOP(49, 16):
3301
    case FOP(50, 16):
3302
    case FOP(51, 16):
3303
    case FOP(52, 16):
3304
    case FOP(53, 16):
3305
    case FOP(54, 16):
3306
    case FOP(55, 16):
3307
    case FOP(56, 16):
3308
    case FOP(57, 16):
3309
    case FOP(58, 16):
3310
    case FOP(59, 16):
3311
    case FOP(60, 16):
3312
    case FOP(61, 16):
3313
    case FOP(62, 16):
3314
    case FOP(63, 16):
3315
        CHECK_FR(ctx, fs | ft);
3316
        GEN_LOAD_FREG_FTN(WT0, fs);
3317
        GEN_LOAD_FREG_FTN(WT1, ft);
3318
        gen_cmp_s(func-48);
3319
        opn = condnames[func-48];
3320
        break;
3321
    default:    
3322
        if (loglevel & CPU_LOG_TB_IN_ASM) {
3323
            fprintf(logfile, "Invalid FP arith function: %08x %03x %03x %03x\n",
3324
                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
3325
                    ((ctx->opcode >> 16) & 0x1F));
3326
        }
3327
        generate_exception_err (ctx, EXCP_RI, 1);
3328
        return;
3329
    }
3330
    if (binary)
3331
        MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
3332
    else
3333
        MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
3334
}
3335

    
3336
static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
3337
{
3338
    uint32_t ccbit;
3339

    
3340
    if (cc)
3341
        ccbit = 1 << (24 + cc);
3342
    else
3343
        ccbit = 1 << 23;
3344
    if (!tf)
3345
        gen_op_movf(ccbit, rd, rs);
3346
    else
3347
       gen_op_movt(ccbit, rd, rs);
3348
}
3349

    
3350
#endif /* MIPS_USES_FPU */
3351

    
3352
/* ISA extensions (ASEs) */
3353
/* MIPS16 extension to MIPS32 */
3354
/* SmartMIPS extension to MIPS32 */
3355

    
3356
#ifdef MIPS_HAS_MIPS64
3357
/* Coprocessor 3 (FPU) */
3358

    
3359
/* MDMX extension to MIPS64 */
3360
/* MIPS-3D extension to MIPS64 */
3361

    
3362
#endif
3363

    
3364
static void gen_blikely(DisasContext *ctx)
3365
{
3366
    int l1;
3367
    l1 = gen_new_label();
3368
    gen_op_jnz_T2(l1);
3369
    gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
3370
    gen_goto_tb(ctx, 1, ctx->pc + 4);
3371
    gen_set_label(l1);
3372
}
3373

    
3374
static void decode_opc (DisasContext *ctx)
3375
{
3376
    int32_t offset;
3377
    int rs, rt, rd, sa;
3378
    uint32_t op, op1, op2;
3379
    int16_t imm;
3380

    
3381
    /* make sure instructions are on a word boundary */
3382
    if (ctx->pc & 0x3) {
3383
        generate_exception(ctx, EXCP_AdEL);
3384
        return;
3385
    }
3386

    
3387
    if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
3388
        /* Handle blikely not taken case */
3389
        MIPS_DEBUG("blikely condition (" TLSZ ")", ctx->pc + 4);
3390
        gen_blikely(ctx);
3391
    }
3392
    op = MASK_OP_MAJOR(ctx->opcode);
3393
    rs = (ctx->opcode >> 21) & 0x1f;
3394
    rt = (ctx->opcode >> 16) & 0x1f;
3395
    rd = (ctx->opcode >> 11) & 0x1f;
3396
    sa = (ctx->opcode >> 6) & 0x1f;
3397
    imm = (int16_t)ctx->opcode;
3398
    switch (op) {
3399
    case OPC_SPECIAL:
3400
        op1 = MASK_SPECIAL(ctx->opcode);
3401
        switch (op1) {
3402
        case OPC_SLL:          /* Arithmetic with immediate */
3403
        case OPC_SRL ... OPC_SRA:
3404
            gen_arith_imm(ctx, op1, rd, rt, sa);
3405
            break;
3406
        case OPC_SLLV:         /* Arithmetic */
3407
        case OPC_SRLV ... OPC_SRAV:
3408
        case OPC_MOVZ ... OPC_MOVN:
3409
        case OPC_ADD ... OPC_NOR:
3410
        case OPC_SLT ... OPC_SLTU:
3411
            gen_arith(ctx, op1, rd, rs, rt);
3412
            break;
3413
        case OPC_MULT ... OPC_DIVU:
3414
            gen_muldiv(ctx, op1, rs, rt);
3415
            break;
3416
        case OPC_JR ... OPC_JALR:
3417
            gen_compute_branch(ctx, op1, rs, rd, sa);
3418
            return;
3419
        case OPC_TGE ... OPC_TEQ: /* Traps */
3420
        case OPC_TNE:
3421
            gen_trap(ctx, op1, rs, rt, -1);
3422
            break;
3423
        case OPC_MFHI:          /* Move from HI/LO */
3424
        case OPC_MFLO:
3425
            gen_HILO(ctx, op1, rd);
3426
            break;
3427
        case OPC_MTHI:
3428
        case OPC_MTLO:          /* Move to HI/LO */
3429
            gen_HILO(ctx, op1, rs);
3430
            break;
3431
        case OPC_PMON:          /* Pmon entry point */
3432
            gen_op_pmon(sa);
3433
            break;
3434
        case OPC_SYSCALL:
3435
            generate_exception(ctx, EXCP_SYSCALL);
3436
            ctx->bstate = BS_EXCP;
3437
            break;
3438
        case OPC_BREAK:
3439
            generate_exception(ctx, EXCP_BREAK);
3440
            break;
3441
        case OPC_SPIM:        /* SPIM ? */
3442
           /* Implemented as RI exception for now. */
3443
            MIPS_INVAL("spim (unofficial)");
3444
            generate_exception(ctx, EXCP_RI);
3445
            break;
3446
        case OPC_SYNC:
3447
            /* Treat as a noop. */
3448
            break;
3449

    
3450
#ifdef MIPS_USES_FPU
3451
        case OPC_MOVCI:
3452
            gen_op_cp1_enabled();
3453
            gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
3454
                      (ctx->opcode >> 16) & 1);
3455
            break;
3456
#endif
3457

    
3458
#ifdef MIPS_HAS_MIPS64
3459
       /* MIPS64 specific opcodes */
3460
        case OPC_DSLL:
3461
        case OPC_DSRL ... OPC_DSRA:
3462
        case OPC_DSLL32:
3463
        case OPC_DSRL32 ... OPC_DSRA32:
3464
            gen_arith_imm(ctx, op1, rd, rt, sa);
3465
            break;
3466
        case OPC_DSLLV:
3467
        case OPC_DSRLV ... OPC_DSRAV:
3468
        case OPC_DADD ... OPC_DSUBU:
3469
            gen_arith(ctx, op1, rd, rs, rt);
3470
            break;
3471
        case OPC_DMULT ... OPC_DDIVU:
3472
            gen_muldiv(ctx, op1, rs, rt);
3473
            break;
3474
#endif
3475
        default:            /* Invalid */
3476
            MIPS_INVAL("special");
3477
            generate_exception(ctx, EXCP_RI);
3478
            break;
3479
        }
3480
        break;
3481
    case OPC_SPECIAL2:
3482
        op1 = MASK_SPECIAL2(ctx->opcode);
3483
        switch (op1) {
3484
        case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
3485
        case OPC_MSUB ... OPC_MSUBU:
3486
            gen_muldiv(ctx, op1, rs, rt);
3487
            break;
3488
        case OPC_MUL:
3489
            gen_arith(ctx, op1, rd, rs, rt);
3490
            break;
3491
        case OPC_CLZ ... OPC_CLO:
3492
            gen_cl(ctx, op1, rd, rs);
3493
            break;
3494
        case OPC_SDBBP:
3495
            /* XXX: not clear which exception should be raised
3496
             *      when in debug mode...
3497
             */
3498
            if (!(ctx->hflags & MIPS_HFLAG_DM)) {
3499
                generate_exception(ctx, EXCP_DBp);
3500
            } else {
3501
                generate_exception(ctx, EXCP_DBp);
3502
            }
3503
            /* Treat as a noop */
3504
            break;
3505
#ifdef MIPS_HAS_MIPS64
3506
        case OPC_DCLZ ... OPC_DCLO:
3507
            gen_cl(ctx, op1, rd, rs);
3508
            break;
3509
#endif
3510
        default:            /* Invalid */
3511
            MIPS_INVAL("special2");
3512
            generate_exception(ctx, EXCP_RI);
3513
            break;
3514
        }
3515
        break;
3516
    case OPC_SPECIAL3:
3517
        op1 = MASK_SPECIAL3(ctx->opcode);
3518
        switch (op1) {
3519
        case OPC_EXT:
3520
        case OPC_INS:
3521
            gen_bitops(ctx, op1, rt, rs, sa, rd);
3522
            break;
3523
        case OPC_BSHFL:
3524
            op2 = MASK_BSHFL(ctx->opcode);
3525
            switch (op2) {
3526
            case OPC_WSBH:
3527
                GEN_LOAD_REG_TN(T1, rt);
3528
                gen_op_wsbh();
3529
                break;
3530
            case OPC_SEB:
3531
                GEN_LOAD_REG_TN(T1, rt);
3532
                gen_op_seb();
3533
                break;
3534
            case OPC_SEH:
3535
                GEN_LOAD_REG_TN(T1, rt);
3536
                gen_op_seh();
3537
                break;
3538
             default:            /* Invalid */
3539
                MIPS_INVAL("bshfl");
3540
                generate_exception(ctx, EXCP_RI);
3541
                break;
3542
           }
3543
           GEN_STORE_TN_REG(rd, T0);
3544
           break;
3545
       case OPC_RDHWR:
3546
           switch (rd) {
3547
           case 0:
3548
               gen_op_rdhwr_cpunum();
3549
               break;
3550
           case 1:
3551
               gen_op_rdhwr_synci_step();
3552
               break;
3553
           case 2:
3554
               gen_op_rdhwr_cc();
3555
               break;
3556
           case 3:
3557
               gen_op_rdhwr_ccres();
3558
               break;
3559
           default:            /* Invalid */
3560
               MIPS_INVAL("rdhwr");
3561
               generate_exception(ctx, EXCP_RI);
3562
               break;
3563
           }
3564
           GEN_STORE_TN_REG(rt, T0);
3565
           break;
3566
#ifdef MIPS_HAS_MIPS64
3567
       case OPC_DEXTM ... OPC_DEXT:
3568
       case OPC_DINSM ... OPC_DINS:
3569
           gen_bitops(ctx, op1, rt, rs, sa, rd);
3570
            break;
3571
       case OPC_DBSHFL:
3572
           op2 = MASK_DBSHFL(ctx->opcode);
3573
           switch (op2) {
3574
           case OPC_DSBH:
3575
               GEN_LOAD_REG_TN(T1, rt);
3576
               gen_op_dsbh();
3577
               break;
3578
           case OPC_DSHD:
3579
               GEN_LOAD_REG_TN(T1, rt);
3580
               gen_op_dshd();
3581
               break;
3582
            default:            /* Invalid */
3583
                MIPS_INVAL("dbshfl");
3584
                generate_exception(ctx, EXCP_RI);
3585
                break;
3586
           }
3587
           GEN_STORE_TN_REG(rd, T0);
3588
#endif
3589
        default:            /* Invalid */
3590
            MIPS_INVAL("special3");
3591
            generate_exception(ctx, EXCP_RI);
3592
            break;
3593
        }
3594
        break;
3595
    case OPC_REGIMM:
3596
        op1 = MASK_REGIMM(ctx->opcode);
3597
        switch (op1) {
3598
        case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
3599
        case OPC_BLTZAL ... OPC_BGEZALL:
3600
            gen_compute_branch(ctx, op1, rs, -1, imm << 2);
3601
            return;
3602
        case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
3603
        case OPC_TNEI:
3604
            gen_trap(ctx, op1, rs, -1, imm);
3605
            break;
3606
        case OPC_SYNCI:
3607
           /* treat as noop */
3608
            break;
3609
        default:            /* Invalid */
3610
            MIPS_INVAL("REGIMM");
3611
            generate_exception(ctx, EXCP_RI);
3612
            break;
3613
        }
3614
        break;
3615
    case OPC_CP0:
3616
        op1 = MASK_CP0(ctx->opcode);
3617
        switch (op1) {
3618
        case OPC_MFC0:
3619
        case OPC_MTC0:
3620
#ifdef MIPS_HAS_MIPS64
3621
        case OPC_DMFC0:
3622
        case OPC_DMTC0:
3623
#endif
3624
            gen_cp0(ctx, op1, rt, rd);
3625
            break;
3626
        case OPC_C0_FIRST ... OPC_C0_LAST:
3627
            gen_cp0(ctx, MASK_C0(ctx->opcode), rt, rd);
3628
            break;
3629
        case OPC_MFMC0:
3630
            op2 = MASK_MFMC0(ctx->opcode);
3631
            switch (op2) {
3632
            case OPC_DI:
3633
                gen_op_di();
3634
                /* Stop translation as we may have switched the execution mode */
3635
                ctx->bstate = BS_STOP;
3636
                break;
3637
            case OPC_EI:
3638
                gen_op_ei();
3639
                /* Stop translation as we may have switched the execution mode */
3640
                ctx->bstate = BS_STOP;
3641
                break;
3642
            default:            /* Invalid */
3643
                MIPS_INVAL("MFMC0");
3644
                generate_exception(ctx, EXCP_RI);
3645
                break;
3646
            }
3647
            GEN_STORE_TN_REG(rt, T0);
3648
            break;
3649
        /* Shadow registers (not implemented). */
3650
        case OPC_RDPGPR:
3651
        case OPC_WRPGPR:
3652
        default:
3653
            generate_exception(ctx, EXCP_RI);
3654
            break;
3655
        }
3656
        break;
3657
    case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
3658
         gen_arith_imm(ctx, op, rt, rs, imm);
3659
         break;
3660
    case OPC_J ... OPC_JAL: /* Jump */
3661
         offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
3662
         gen_compute_branch(ctx, op, rs, rt, offset);
3663
         return;
3664
    case OPC_BEQ ... OPC_BGTZ: /* Branch */
3665
    case OPC_BEQL ... OPC_BGTZL:
3666
         gen_compute_branch(ctx, op, rs, rt, imm << 2);
3667
         return;
3668
    case OPC_LB ... OPC_LWR: /* Load and stores */
3669
    case OPC_SB ... OPC_SW:
3670
    case OPC_SWR:
3671
    case OPC_LL:
3672
    case OPC_SC:
3673
         gen_ldst(ctx, op, rt, rs, imm);
3674
         break;
3675
    case OPC_CACHE:
3676
         /* Treat as a noop */
3677
         break;
3678
    case OPC_PREF:
3679
        /* Treat as a noop */
3680
        break;
3681

    
3682
    /* Floating point.  */
3683
    case OPC_LWC1:
3684
    case OPC_LDC1:
3685
    case OPC_SWC1:
3686
    case OPC_SDC1:
3687
#if defined(MIPS_USES_FPU)
3688
        save_cpu_state(ctx, 1);
3689
        gen_op_cp1_enabled();
3690
        gen_flt_ldst(ctx, op, rt, rs, imm);
3691
#else
3692
        generate_exception_err(ctx, EXCP_CpU, 1);
3693
#endif
3694
        break;
3695

    
3696
    case OPC_CP1:
3697
#if defined(MIPS_USES_FPU)
3698
        save_cpu_state(ctx, 1);
3699
        gen_op_cp1_enabled();
3700
        op1 = MASK_CP1(ctx->opcode);
3701
        switch (op1) {
3702
        case OPC_MFC1:
3703
        case OPC_CFC1:
3704
        case OPC_MTC1:
3705
        case OPC_CTC1:
3706
            gen_cp1(ctx, op1, rt, rd);
3707
            break;
3708
        case OPC_BC1:
3709
            gen_compute_branch1(ctx, MASK_CP1_BCOND(ctx->opcode), imm << 2);
3710
            return;
3711
        case OPC_S_FMT:
3712
        case OPC_D_FMT:
3713
        case OPC_W_FMT:
3714
        case OPC_L_FMT:
3715
            gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa);
3716
            break;
3717
        default:
3718
            generate_exception_err(ctx, EXCP_RI, 1);
3719
            break;
3720
        }
3721
#else
3722
        generate_exception_err(ctx, EXCP_CpU, 1);
3723
#endif
3724
        break;
3725

    
3726
    /* COP2.  */
3727
    case OPC_LWC2:
3728
    case OPC_LDC2:
3729
    case OPC_SWC2:
3730
    case OPC_SDC2:
3731
    case OPC_CP2:
3732
        /* COP2: Not implemented. */
3733
        generate_exception_err(ctx, EXCP_CpU, 2);
3734
        break;
3735

    
3736
#ifdef MIPS_USES_FPU
3737
    case OPC_CP3:
3738
        gen_op_cp1_enabled();
3739
        op1 = MASK_CP3(ctx->opcode);
3740
        switch (op1) {
3741
        /* Not implemented */
3742
        default:
3743
            generate_exception_err(ctx, EXCP_RI, 1);
3744
            break;
3745
        }
3746
        break;
3747
#endif
3748

    
3749
#ifdef MIPS_HAS_MIPS64
3750
    /* MIPS64 opcodes */
3751
    case OPC_LWU:
3752
    case OPC_LDL ... OPC_LDR:
3753
    case OPC_SDL ... OPC_SDR:
3754
    case OPC_LLD:
3755
    case OPC_LD:
3756
    case OPC_SCD:
3757
    case OPC_SD:
3758
        gen_ldst(ctx, op, rt, rs, imm);
3759
        break;
3760
    case OPC_DADDI ... OPC_DADDIU:
3761
        gen_arith_imm(ctx, op, rt, rs, imm);
3762
        break;
3763
#endif
3764
#ifdef MIPS_HAS_MIPS16
3765
    case OPC_JALX:
3766
        /* MIPS16: Not implemented. */
3767
#endif
3768
#ifdef MIPS_HAS_MDMX
3769
    case OPC_MDMX:
3770
        /* MDMX: Not implemented. */
3771
#endif
3772
    default:            /* Invalid */
3773
        MIPS_INVAL("");
3774
        generate_exception(ctx, EXCP_RI);
3775
        break;
3776
    }
3777
    if (ctx->hflags & MIPS_HFLAG_BMASK) {
3778
        int hflags = ctx->hflags;
3779
        /* Branches completion */
3780
        ctx->hflags &= ~MIPS_HFLAG_BMASK;
3781
        ctx->bstate = BS_BRANCH;
3782
        save_cpu_state(ctx, 0);
3783
        switch (hflags & MIPS_HFLAG_BMASK) {
3784
        case MIPS_HFLAG_B:
3785
            /* unconditional branch */
3786
            MIPS_DEBUG("unconditional branch");
3787
            gen_goto_tb(ctx, 0, ctx->btarget);
3788
            break;
3789
        case MIPS_HFLAG_BL:
3790
            /* blikely taken case */
3791
            MIPS_DEBUG("blikely branch taken");
3792
            gen_goto_tb(ctx, 0, ctx->btarget);
3793
            break;
3794
        case MIPS_HFLAG_BC:
3795
            /* Conditional branch */
3796
            MIPS_DEBUG("conditional branch");
3797
            {
3798
              int l1;
3799
              l1 = gen_new_label();
3800
              gen_op_jnz_T2(l1);
3801
              gen_goto_tb(ctx, 1, ctx->pc + 4);
3802
              gen_set_label(l1);
3803
              gen_goto_tb(ctx, 0, ctx->btarget);
3804
            }
3805
            break;
3806
        case MIPS_HFLAG_BR:
3807
            /* unconditional branch to register */
3808
            MIPS_DEBUG("branch to register");
3809
            gen_op_breg();
3810
            break;
3811
        default:
3812
            MIPS_DEBUG("unknown branch");
3813
            break;
3814
        }
3815
    }
3816
}
3817

    
3818
int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
3819
                                    int search_pc)
3820
{
3821
    DisasContext ctx, *ctxp = &ctx;
3822
    target_ulong pc_start;
3823
    uint16_t *gen_opc_end;
3824
    int j, lj = -1;
3825

    
3826
    if (search_pc && loglevel)
3827
        fprintf (logfile, "search pc %d\n", search_pc);
3828

    
3829
    pc_start = tb->pc;
3830
    gen_opc_ptr = gen_opc_buf;
3831
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3832
    gen_opparam_ptr = gen_opparam_buf;
3833
    nb_gen_labels = 0;
3834
    ctx.pc = pc_start;
3835
    ctx.saved_pc = -1;
3836
    ctx.tb = tb;
3837
    ctx.bstate = BS_NONE;
3838
    /* Restore delay slot state from the tb context.  */
3839
    ctx.hflags = tb->flags;
3840
    ctx.saved_hflags = ctx.hflags;
3841
    if (ctx.hflags & MIPS_HFLAG_BR) {
3842
        gen_op_restore_breg_target();
3843
    } else if (ctx.hflags & MIPS_HFLAG_B) {
3844
        ctx.btarget = env->btarget;
3845
    } else if (ctx.hflags & MIPS_HFLAG_BMASK) {
3846
        /* If we are in the delay slot of a conditional branch,
3847
         * restore the branch condition from env->bcond to T2
3848
         */
3849
        ctx.btarget = env->btarget;
3850
        gen_op_restore_bcond();
3851
    }
3852
#if defined(CONFIG_USER_ONLY)
3853
    ctx.mem_idx = 0;
3854
#else
3855
    ctx.mem_idx = !((ctx.hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM);
3856
#endif
3857
    ctx.CP0_Status = env->CP0_Status;
3858
#ifdef DEBUG_DISAS
3859
    if (loglevel & CPU_LOG_TB_CPU) {
3860
        fprintf(logfile, "------------------------------------------------\n");
3861
        /* FIXME: This may print out stale hflags from env... */
3862
        cpu_dump_state(env, logfile, fprintf, 0);
3863
    }
3864
#endif
3865
#if defined MIPS_DEBUG_DISAS
3866
    if (loglevel & CPU_LOG_TB_IN_ASM)
3867
        fprintf(logfile, "\ntb %p super %d cond %04x\n",
3868
                tb, ctx.mem_idx, ctx.hflags);
3869
#endif
3870
    while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
3871
        if (env->nb_breakpoints > 0) {
3872
            for(j = 0; j < env->nb_breakpoints; j++) {
3873
                if (env->breakpoints[j] == ctx.pc) {
3874
                    save_cpu_state(ctxp, 1);
3875
                    ctx.bstate = BS_BRANCH;
3876
                    gen_op_debug();
3877
                    goto done_generating;
3878
                }
3879
            }
3880
        }
3881

    
3882
        if (search_pc) {
3883
            j = gen_opc_ptr - gen_opc_buf;
3884
            if (lj < j) {
3885
                lj++;
3886
                while (lj < j)
3887
                    gen_opc_instr_start[lj++] = 0;
3888
            }
3889
            gen_opc_pc[lj] = ctx.pc;
3890
            gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
3891
            gen_opc_instr_start[lj] = 1;
3892
        }
3893
        ctx.opcode = ldl_code(ctx.pc);
3894
        decode_opc(&ctx);
3895
        ctx.pc += 4;
3896

    
3897
        if (env->singlestep_enabled)
3898
            break;
3899

    
3900
        if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
3901
            break;
3902

    
3903
#if defined (MIPS_SINGLE_STEP)
3904
        break;
3905
#endif
3906
    }
3907
    if (env->singlestep_enabled) {
3908
        save_cpu_state(ctxp, ctx.bstate == BS_NONE);
3909
        gen_op_debug();
3910
        goto done_generating;
3911
    }
3912
    else if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) {
3913
        save_cpu_state(ctxp, 0);
3914
        gen_goto_tb(&ctx, 0, ctx.pc);
3915
    }
3916
    gen_op_reset_T0();
3917
    /* Generate the return instruction */
3918
    gen_op_exit_tb();
3919
done_generating:
3920
    *gen_opc_ptr = INDEX_op_end;
3921
    if (search_pc) {
3922
        j = gen_opc_ptr - gen_opc_buf;
3923
        lj++;
3924
        while (lj <= j)
3925
            gen_opc_instr_start[lj++] = 0;
3926
        tb->size = 0;
3927
    } else {
3928
        tb->size = ctx.pc - pc_start;
3929
    }
3930
#ifdef DEBUG_DISAS
3931
#if defined MIPS_DEBUG_DISAS
3932
    if (loglevel & CPU_LOG_TB_IN_ASM)
3933
        fprintf(logfile, "\n");
3934
#endif
3935
    if (loglevel & CPU_LOG_TB_IN_ASM) {
3936
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
3937
    target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
3938
        fprintf(logfile, "\n");
3939
    }
3940
    if (loglevel & CPU_LOG_TB_OP) {
3941
        fprintf(logfile, "OP:\n");
3942
        dump_ops(gen_opc_buf, gen_opparam_buf);
3943
        fprintf(logfile, "\n");
3944
    }
3945
    if (loglevel & CPU_LOG_TB_CPU) {
3946
        fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
3947
    }
3948
#endif
3949
    
3950
    return 0;
3951
}
3952

    
3953
int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
3954
{
3955
    return gen_intermediate_code_internal(env, tb, 0);
3956
}
3957

    
3958
int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
3959
{
3960
    return gen_intermediate_code_internal(env, tb, 1);
3961
}
3962

    
3963
#ifdef MIPS_USES_FPU
3964

    
3965
void fpu_dump_state(CPUState *env, FILE *f, 
3966
                    int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
3967
                    int flags)
3968
{
3969
    int i;
3970

    
3971
#   define printfpr(fp) do { \
3972
        fpu_fprintf(f, "w:%08x d:%08lx%08lx fd:%g fs:%g\n", \
3973
                (fp)->w[FP_ENDIAN_IDX], (fp)->w[0], (fp)->w[1], (fp)->fd, (fp)->fs[FP_ENDIAN_IDX]); \
3974
    } while(0)
3975

    
3976
    fpu_fprintf(f, "CP1 FCR0 0x%08x  FCR31 0x%08x  SR.FR %d\n",
3977
                env->fcr0, env->fcr31,
3978
                (env->CP0_Status & (1 << CP0St_FR)) != 0);
3979
    fpu_fprintf(f, "FT0: "); printfpr(&env->ft0);
3980
    fpu_fprintf(f, "FT1: "); printfpr(&env->ft1);
3981
    fpu_fprintf(f, "FT2: "); printfpr(&env->ft2);
3982
    for(i = 0; i < 32; i += 2) {
3983
        fpu_fprintf(f, "%s: ", fregnames[i]);
3984
        printfpr(FPR(env, i));
3985
    }
3986

    
3987
#undef printfpr
3988
}
3989

    
3990
void dump_fpu (CPUState *env)
3991
{
3992
    if (loglevel) { 
3993
       fprintf(logfile, "pc=0x" TLSZ " HI=0x" TLSZ " LO=0x" TLSZ " ds %04x " TLSZ " %d\n",
3994
               env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
3995
       fpu_dump_state(env, logfile, fprintf, 0);
3996
    }
3997
}
3998

    
3999
#endif /* MIPS_USES_FPU */
4000

    
4001
#if defined(MIPS_HAS_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
4002
/* Debug help: The architecture requires 32bit code to maintain proper
4003
   sign-extened values on 64bit machines.  */
4004

    
4005
#define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
4006

    
4007
void cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
4008
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
4009
                     int flags)
4010
{
4011
    int i;
4012

    
4013
    if (!SIGN_EXT_P(env->PC))
4014
        cpu_fprintf(f, "BROKEN: pc=0x" TLSZ "\n", env->PC);
4015
    if (!SIGN_EXT_P(env->HI))
4016
        cpu_fprintf(f, "BROKEN: HI=0x" TLSZ "\n", env->HI);
4017
    if (!SIGN_EXT_P(env->LO))
4018
        cpu_fprintf(f, "BROKEN: LO=0x" TLSZ "\n", env->LO);
4019
    if (!SIGN_EXT_P(env->btarget))
4020
        cpu_fprintf(f, "BROKEN: btarget=0x" TLSZ "\n", env->btarget);
4021

    
4022
    for (i = 0; i < 32; i++) {
4023
        if (!SIGN_EXT_P(env->gpr[i]))
4024
            cpu_fprintf(f, "BROKEN: %s=0x" TLSZ "\n", regnames[i], env->gpr[i]);
4025
    }
4026

    
4027
    if (!SIGN_EXT_P(env->CP0_EPC))
4028
        cpu_fprintf(f, "BROKEN: EPC=0x" TLSZ "\n", env->CP0_EPC);
4029
    if (!SIGN_EXT_P(env->CP0_LLAddr))
4030
        cpu_fprintf(f, "BROKEN: LLAddr=0x" TLSZ "\n", env->CP0_LLAddr);
4031
}
4032
#endif
4033

    
4034
void cpu_dump_state (CPUState *env, FILE *f, 
4035
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
4036
                     int flags)
4037
{
4038
    uint32_t c0_status;
4039
    int i;
4040
    
4041
    cpu_fprintf(f, "pc=0x" TLSZ " HI=0x" TLSZ " LO=0x" TLSZ " ds %04x " TLSZ " %d\n",
4042
                env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
4043
    for (i = 0; i < 32; i++) {
4044
        if ((i & 3) == 0)
4045
            cpu_fprintf(f, "GPR%02d:", i);
4046
        cpu_fprintf(f, " %s " TLSZ, regnames[i], env->gpr[i]);
4047
        if ((i & 3) == 3)
4048
            cpu_fprintf(f, "\n");
4049
    }
4050

    
4051
    c0_status = env->CP0_Status;
4052
    if (env->hflags & MIPS_HFLAG_UM)
4053
        c0_status |= (1 << CP0St_UM);
4054
    if (env->hflags & MIPS_HFLAG_ERL)
4055
        c0_status |= (1 << CP0St_ERL);
4056
    if (env->hflags & MIPS_HFLAG_EXL)
4057
        c0_status |= (1 << CP0St_EXL);
4058

    
4059
    cpu_fprintf(f, "CP0 Status  0x%08x Cause   0x%08x EPC    0x" TLSZ "\n",
4060
                c0_status, env->CP0_Cause, env->CP0_EPC);
4061
    cpu_fprintf(f, "    Config0 0x%08x Config1 0x%08x LLAddr 0x" TLSZ "\n",
4062
                env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
4063
#ifdef MIPS_USES_FPU
4064
    if (c0_status & (1 << CP0St_CU1))
4065
        fpu_dump_state(env, f, cpu_fprintf, flags);
4066
#endif
4067
#if defined(MIPS_HAS_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
4068
    cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
4069
#endif
4070
}
4071

    
4072
CPUMIPSState *cpu_mips_init (void)
4073
{
4074
    CPUMIPSState *env;
4075

    
4076
    env = qemu_mallocz(sizeof(CPUMIPSState));
4077
    if (!env)
4078
        return NULL;
4079
    cpu_exec_init(env);
4080
    cpu_reset(env);
4081
    return env;
4082
}
4083

    
4084
void cpu_reset (CPUMIPSState *env)
4085
{
4086
    memset(env, 0, offsetof(CPUMIPSState, breakpoints));
4087

    
4088
    tlb_flush(env, 1);
4089

    
4090
    /* Minimal init */
4091
#if !defined(CONFIG_USER_ONLY)
4092
    if (env->hflags & MIPS_HFLAG_BMASK) {
4093
        /* If the exception was raised from a delay slot,
4094
         * come back to the jump.  */
4095
        env->CP0_ErrorEPC = env->PC - 4;
4096
        env->hflags &= ~MIPS_HFLAG_BMASK;
4097
    } else {
4098
        env->CP0_ErrorEPC = env->PC;
4099
    }
4100
    env->PC = (int32_t)0xBFC00000;
4101
#if defined (MIPS_USES_R4K_TLB)
4102
    env->CP0_random = MIPS_TLB_NB - 1;
4103
    env->tlb_in_use = MIPS_TLB_NB;
4104
#endif
4105
    env->CP0_Wired = 0;
4106
    /* SMP not implemented */
4107
    env->CP0_EBase = (int32_t)0x80000000;
4108
    env->CP0_Config0 = MIPS_CONFIG0;
4109
    env->CP0_Config1 = MIPS_CONFIG1;
4110
    env->CP0_Config2 = MIPS_CONFIG2;
4111
    env->CP0_Config3 = MIPS_CONFIG3;
4112
    env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
4113
    env->CP0_WatchLo = 0;
4114
    env->hflags = MIPS_HFLAG_ERL;
4115
    /* Count register increments in debug mode, EJTAG version 1 */
4116
    env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
4117
    env->CP0_PRid = MIPS_CPU;
4118
#endif
4119
    env->exception_index = EXCP_NONE;
4120
#if defined(CONFIG_USER_ONLY)
4121
    env->hflags |= MIPS_HFLAG_UM;
4122
    env->user_mode_only = 1;
4123
#endif
4124
#ifdef MIPS_USES_FPU
4125
    env->fcr0 = MIPS_FCR0;        
4126
#endif
4127
    /* XXX some guesswork here, values are CPU specific */
4128
    env->SYNCI_Step = 16;
4129
    env->CCRes = 2;
4130
}