Statistics
| Branch: | Revision:

root / target-mips / translate.c @ ca7c2b1b

History | View | Annotate | Download (110.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_SINGLE_STEP
35

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

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

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

    
52
#include "gen-op.h"
53

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

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

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

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

    
198
    OPC_MOVCI    = 0x01 | OPC_SPECIAL,
199

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
393
#ifdef MIPS_USES_FPU
394

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

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

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

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

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

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

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

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

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

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

    
475
FOP_CONDS(d)
476
FOP_CONDS(s)
477

    
478
#endif /* MIPS_USES_FPU */
479

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
794
#ifdef MIPS_USES_FPU
795

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

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

    
843
#endif /* MIPS_USES_FPU */
844

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

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

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

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

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

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

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

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

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

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

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

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

    
1373
/* Branches (before delay slot) */
1374
static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
1375
                                int rs, int rt, int32_t offset)
1376
{
1377
    target_ulong btarget;
1378
    int blink, bcond;
1379

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

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

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

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

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

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

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

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

    
2826
static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd)
2827
{
2828
    const char *opn = "unk";
2829

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

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

    
2916
#ifdef MIPS_USES_FPU
2917

    
2918
/* CP1 Branches (before delay slot) */
2919
static void gen_compute_branch1 (DisasContext *ctx, uint32_t op,
2920
                                 int32_t offset)
2921
{
2922
    target_ulong btarget;
2923

    
2924
    btarget = ctx->pc + 4 + offset;
2925

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

    
2954
    MIPS_DEBUG("enter ds: cond %02x target %08x",
2955
               ctx->hflags, btarget);
2956
    ctx->btarget = btarget;
2957

    
2958
    return;
2959
}
2960

    
2961
/* Coprocessor 1 (FPU) */
2962
static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
2963
{
2964
    const char *opn = "unk";
2965

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

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

    
3030
#define FOP(func, fmt) (((fmt) << 21) | (func))
3031

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

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

    
3332
static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
3333
{
3334
    uint32_t ccbit;
3335

    
3336
    if (cc)
3337
        ccbit = 1 << (24 + cc);
3338
    else
3339
        ccbit = 1 << 23;
3340
    if (!tf)
3341
        gen_op_movf(ccbit, rd, rs);
3342
    else
3343
       gen_op_movt(ccbit, rd, rs);
3344
}
3345

    
3346
#endif /* MIPS_USES_FPU */
3347

    
3348
/* ISA extensions (ASEs) */
3349
/* MIPS16 extension to MIPS32 */
3350
/* SmartMIPS extension to MIPS32 */
3351

    
3352
#ifdef MIPS_HAS_MIPS64
3353
static void gen_arith64 (DisasContext *ctx, uint32_t opc)
3354
{
3355
    if (func == 0x02 && rd == 0) {
3356
        /* NOP */
3357
        return;
3358
    }
3359
    if (rs == 0 || rt == 0) {
3360
        gen_op_reset_T0();
3361
        gen_op_save64();
3362
    } else {
3363
        gen_op_load_gpr_T0(rs);
3364
        gen_op_load_gpr_T1(rt);
3365
        gen_op_save64();
3366
        if (func & 0x01)
3367
            gen_op_mul64u();
3368
        else
3369
            gen_op_mul64s();
3370
    }
3371
    if (func & 0x02)
3372
        gen_op_add64();
3373
    else
3374
        gen_op_sub64();
3375
}
3376

    
3377
/* Coprocessor 3 (FPU) */
3378

    
3379
/* MDMX extension to MIPS64 */
3380
/* MIPS-3D extension to MIPS64 */
3381

    
3382
#endif
3383

    
3384
static void gen_blikely(DisasContext *ctx)
3385
{
3386
    int l1;
3387
    l1 = gen_new_label();
3388
    gen_op_jnz_T2(l1);
3389
    gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
3390
    gen_goto_tb(ctx, 1, ctx->pc + 4);
3391
    gen_set_label(l1);
3392
}
3393

    
3394
static void decode_opc (DisasContext *ctx)
3395
{
3396
    int32_t offset;
3397
    int rs, rt, rd, sa;
3398
    uint32_t op, op1, op2;
3399
    int16_t imm;
3400

    
3401
    /* make sure instructions are on a word boundary */
3402
    if (ctx->pc & 0x3) {
3403
        generate_exception(ctx, EXCP_AdEL);
3404
        return;
3405
    }
3406

    
3407
    if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
3408
        /* Handle blikely not taken case */
3409
        MIPS_DEBUG("blikely condition (%08x)", ctx->pc + 4);
3410
        gen_blikely(ctx);
3411
    }
3412
    op = MASK_OP_MAJOR(ctx->opcode);
3413
    rs = (ctx->opcode >> 21) & 0x1f;
3414
    rt = (ctx->opcode >> 16) & 0x1f;
3415
    rd = (ctx->opcode >> 11) & 0x1f;
3416
    sa = (ctx->opcode >> 6) & 0x1f;
3417
    imm = (int16_t)ctx->opcode;
3418
    switch (op) {
3419
    case OPC_SPECIAL:
3420
        op1 = MASK_SPECIAL(ctx->opcode);
3421
        switch (op1) {
3422
        case OPC_SLL:          /* Arithmetic with immediate */
3423
        case OPC_SRL ... OPC_SRA:
3424
            gen_arith_imm(ctx, op1, rd, rt, sa);
3425
            break;
3426
        case OPC_SLLV:         /* Arithmetic */
3427
        case OPC_SRLV ... OPC_SRAV:
3428
        case OPC_MOVZ ... OPC_MOVN:
3429
        case OPC_ADD ... OPC_NOR:
3430
        case OPC_SLT ... OPC_SLTU:
3431
            gen_arith(ctx, op1, rd, rs, rt);
3432
            break;
3433
        case OPC_MULT ... OPC_DIVU:
3434
            gen_muldiv(ctx, op1, rs, rt);
3435
            break;
3436
        case OPC_JR ... OPC_JALR:
3437
            gen_compute_branch(ctx, op1, rs, rd, sa);
3438
            return;
3439
        case OPC_TGE ... OPC_TEQ: /* Traps */
3440
        case OPC_TNE:
3441
            gen_trap(ctx, op1, rs, rt, -1);
3442
            break;
3443
        case OPC_MFHI:          /* Move from HI/LO */
3444
        case OPC_MFLO:
3445
            gen_HILO(ctx, op1, rd);
3446
            break;
3447
        case OPC_MTHI:
3448
        case OPC_MTLO:          /* Move to HI/LO */
3449
            gen_HILO(ctx, op1, rs);
3450
            break;
3451
        case OPC_PMON:          /* Pmon entry point */
3452
            gen_op_pmon(sa);
3453
            break;
3454
        case OPC_SYSCALL:
3455
            generate_exception(ctx, EXCP_SYSCALL);
3456
            ctx->bstate = BS_EXCP;
3457
            break;
3458
        case OPC_BREAK:
3459
            generate_exception(ctx, EXCP_BREAK);
3460
            break;
3461
        case OPC_SPIM:        /* SPIM ? */
3462
           /* Implemented as RI exception for now. */
3463
            MIPS_INVAL("spim (unofficial)");
3464
            generate_exception(ctx, EXCP_RI);
3465
            break;
3466
        case OPC_SYNC:
3467
            /* Treat as a noop. */
3468
            break;
3469

    
3470
#ifdef MIPS_USES_FPU
3471
        case OPC_MOVCI:
3472
            gen_op_cp1_enabled();
3473
            gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
3474
                      (ctx->opcode >> 16) & 1);
3475
            break;
3476
#endif
3477

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

    
3702
    /* Floating point.  */
3703
    case OPC_LWC1:
3704
    case OPC_LDC1:
3705
    case OPC_SWC1:
3706
    case OPC_SDC1:
3707
#if defined(MIPS_USES_FPU)
3708
        save_cpu_state(ctx, 1);
3709
        gen_op_cp1_enabled();
3710
        gen_flt_ldst(ctx, op, rt, rs, imm);
3711
#else
3712
        generate_exception_err(ctx, EXCP_CpU, 1);
3713
#endif
3714
        break;
3715

    
3716
    case OPC_CP1:
3717
#if defined(MIPS_USES_FPU)
3718
        save_cpu_state(ctx, 1);
3719
        gen_op_cp1_enabled();
3720
        op1 = MASK_CP1(ctx->opcode);
3721
        switch (op1) {
3722
        case OPC_MFC1:
3723
        case OPC_CFC1:
3724
        case OPC_MTC1:
3725
        case OPC_CTC1:
3726
            gen_cp1(ctx, op1, rt, rd);
3727
            break;
3728
        case OPC_BC1:
3729
            gen_compute_branch1(ctx, MASK_CP1_BCOND(ctx->opcode), imm << 2);
3730
            return;
3731
        case OPC_S_FMT:
3732
        case OPC_D_FMT:
3733
        case OPC_W_FMT:
3734
        case OPC_L_FMT:
3735
            gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa);
3736
            break;
3737
        default:
3738
            generate_exception_err(ctx, EXCP_RI, 1);
3739
            break;
3740
        }
3741
#else
3742
        generate_exception_err(ctx, EXCP_CpU, 1);
3743
#endif
3744
        break;
3745

    
3746
    /* COP2.  */
3747
    case OPC_LWC2:
3748
    case OPC_LDC2:
3749
    case OPC_SWC2:
3750
    case OPC_SDC2:
3751
    case OPC_CP2:
3752
        /* COP2: Not implemented. */
3753
        generate_exception_err(ctx, EXCP_CpU, 2);
3754
        break;
3755

    
3756
#ifdef MIPS_USES_FPU
3757
    case OPC_CP3:
3758
        gen_op_cp1_enabled();
3759
        op1 = MASK_CP3(ctx->opcode);
3760
        switch (op1) {
3761
        /* Not implemented */
3762
        default:
3763
            generate_exception_err(ctx, EXCP_RI, 1);
3764
            break;
3765
        }
3766
        break;
3767
#endif
3768

    
3769
#ifdef MIPS_HAS_MIPS64
3770
    /* MIPS64 opcodes */
3771
    case OPC_LWU:
3772
    case OPC_LDL ... OPC_LDR:
3773
    case OPC_SDL ... OPC_SDR:
3774
    case OPC_LLD:
3775
    case OPC_LD:
3776
    case OPC_SCD:
3777
    case OPC_SD:
3778
        gen_ldst(ctx, op, rt, rs, imm);
3779
        break;
3780
    case OPC_DADDI ... OPC_DADDIU:
3781
        gen_arith_imm(ctx, op, rt, rs, imm);
3782
        break;
3783
#endif
3784
#ifdef MIPS_HAS_MIPS16
3785
    case OPC_JALX:
3786
        /* MIPS16: Not implemented. */
3787
#endif
3788
#ifdef MIPS_HAS_MDMX
3789
    case OPC_MDMX:
3790
        /* MDMX: Not implemented. */
3791
#endif
3792
    default:            /* Invalid */
3793
        MIPS_INVAL("");
3794
        generate_exception(ctx, EXCP_RI);
3795
        break;
3796
    }
3797
    if (ctx->hflags & MIPS_HFLAG_BMASK) {
3798
        int hflags = ctx->hflags;
3799
        /* Branches completion */
3800
        ctx->hflags &= ~MIPS_HFLAG_BMASK;
3801
        ctx->bstate = BS_BRANCH;
3802
        save_cpu_state(ctx, 0);
3803
        switch (hflags & MIPS_HFLAG_BMASK) {
3804
        case MIPS_HFLAG_B:
3805
            /* unconditional branch */
3806
            MIPS_DEBUG("unconditional branch");
3807
            gen_goto_tb(ctx, 0, ctx->btarget);
3808
            break;
3809
        case MIPS_HFLAG_BL:
3810
            /* blikely taken case */
3811
            MIPS_DEBUG("blikely branch taken");
3812
            gen_goto_tb(ctx, 0, ctx->btarget);
3813
            break;
3814
        case MIPS_HFLAG_BC:
3815
            /* Conditional branch */
3816
            MIPS_DEBUG("conditional branch");
3817
            {
3818
              int l1;
3819
              l1 = gen_new_label();
3820
              gen_op_jnz_T2(l1);
3821
              gen_goto_tb(ctx, 1, ctx->pc + 4);
3822
              gen_set_label(l1);
3823
              gen_goto_tb(ctx, 0, ctx->btarget);
3824
            }
3825
            break;
3826
        case MIPS_HFLAG_BR:
3827
            /* unconditional branch to register */
3828
            MIPS_DEBUG("branch to register");
3829
            gen_op_breg();
3830
            break;
3831
        default:
3832
            MIPS_DEBUG("unknown branch");
3833
            break;
3834
        }
3835
    }
3836
}
3837

    
3838
int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
3839
                                    int search_pc)
3840
{
3841
    DisasContext ctx, *ctxp = &ctx;
3842
    target_ulong pc_start;
3843
    uint16_t *gen_opc_end;
3844
    int j, lj = -1;
3845

    
3846
    if (search_pc && loglevel)
3847
        fprintf (logfile, "search pc %d\n", search_pc);
3848

    
3849
    pc_start = tb->pc;
3850
    gen_opc_ptr = gen_opc_buf;
3851
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3852
    gen_opparam_ptr = gen_opparam_buf;
3853
    nb_gen_labels = 0;
3854
    ctx.pc = pc_start;
3855
    ctx.saved_pc = -1;
3856
    ctx.tb = tb;
3857
    ctx.bstate = BS_NONE;
3858
    /* Restore delay slot state from the tb context.  */
3859
    ctx.hflags = tb->flags;
3860
    ctx.saved_hflags = ctx.hflags;
3861
    if (ctx.hflags & MIPS_HFLAG_BR) {
3862
        gen_op_restore_breg_target();
3863
    } else if (ctx.hflags & MIPS_HFLAG_B) {
3864
        ctx.btarget = env->btarget;
3865
    } else if (ctx.hflags & MIPS_HFLAG_BMASK) {
3866
        /* If we are in the delay slot of a conditional branch,
3867
         * restore the branch condition from env->bcond to T2
3868
         */
3869
        ctx.btarget = env->btarget;
3870
        gen_op_restore_bcond();
3871
    }
3872
#if defined(CONFIG_USER_ONLY)
3873
    ctx.mem_idx = 0;
3874
#else
3875
    ctx.mem_idx = !((ctx.hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM);
3876
#endif
3877
    ctx.CP0_Status = env->CP0_Status;
3878
#ifdef DEBUG_DISAS
3879
    if (loglevel & CPU_LOG_TB_CPU) {
3880
        fprintf(logfile, "------------------------------------------------\n");
3881
        /* FIXME: This may print out stale hflags from env... */
3882
        cpu_dump_state(env, logfile, fprintf, 0);
3883
    }
3884
#endif
3885
#if defined MIPS_DEBUG_DISAS
3886
    if (loglevel & CPU_LOG_TB_IN_ASM)
3887
        fprintf(logfile, "\ntb %p super %d cond %04x\n",
3888
                tb, ctx.mem_idx, ctx.hflags);
3889
#endif
3890
    while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
3891
        if (env->nb_breakpoints > 0) {
3892
            for(j = 0; j < env->nb_breakpoints; j++) {
3893
                if (env->breakpoints[j] == ctx.pc) {
3894
                    save_cpu_state(ctxp, 1);
3895
                    ctx.bstate = BS_BRANCH;
3896
                    gen_op_debug();
3897
                    goto done_generating;
3898
                }
3899
            }
3900
        }
3901

    
3902
        if (search_pc) {
3903
            j = gen_opc_ptr - gen_opc_buf;
3904
            if (lj < j) {
3905
                lj++;
3906
                while (lj < j)
3907
                    gen_opc_instr_start[lj++] = 0;
3908
            }
3909
            gen_opc_pc[lj] = ctx.pc;
3910
            gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
3911
            gen_opc_instr_start[lj] = 1;
3912
        }
3913
        ctx.opcode = ldl_code(ctx.pc);
3914
        decode_opc(&ctx);
3915
        ctx.pc += 4;
3916

    
3917
        if (env->singlestep_enabled)
3918
            break;
3919

    
3920
        if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
3921
            break;
3922

    
3923
#if defined (MIPS_SINGLE_STEP)
3924
        break;
3925
#endif
3926
    }
3927
    if (env->singlestep_enabled) {
3928
        save_cpu_state(ctxp, ctx.bstate == BS_NONE);
3929
        gen_op_debug();
3930
        goto done_generating;
3931
    }
3932
    else if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) {
3933
        save_cpu_state(ctxp, 0);
3934
        gen_goto_tb(&ctx, 0, ctx.pc);
3935
    }
3936
    gen_op_reset_T0();
3937
    /* Generate the return instruction */
3938
    gen_op_exit_tb();
3939
done_generating:
3940
    *gen_opc_ptr = INDEX_op_end;
3941
    if (search_pc) {
3942
        j = gen_opc_ptr - gen_opc_buf;
3943
        lj++;
3944
        while (lj <= j)
3945
            gen_opc_instr_start[lj++] = 0;
3946
        tb->size = 0;
3947
    } else {
3948
        tb->size = ctx.pc - pc_start;
3949
    }
3950
#ifdef DEBUG_DISAS
3951
#if defined MIPS_DEBUG_DISAS
3952
    if (loglevel & CPU_LOG_TB_IN_ASM)
3953
        fprintf(logfile, "\n");
3954
#endif
3955
    if (loglevel & CPU_LOG_TB_IN_ASM) {
3956
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
3957
    target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
3958
        fprintf(logfile, "\n");
3959
    }
3960
    if (loglevel & CPU_LOG_TB_OP) {
3961
        fprintf(logfile, "OP:\n");
3962
        dump_ops(gen_opc_buf, gen_opparam_buf);
3963
        fprintf(logfile, "\n");
3964
    }
3965
    if (loglevel & CPU_LOG_TB_CPU) {
3966
        fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
3967
    }
3968
#endif
3969
    
3970
    return 0;
3971
}
3972

    
3973
int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
3974
{
3975
    return gen_intermediate_code_internal(env, tb, 0);
3976
}
3977

    
3978
int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
3979
{
3980
    return gen_intermediate_code_internal(env, tb, 1);
3981
}
3982

    
3983
#ifdef MIPS_USES_FPU
3984

    
3985
void fpu_dump_state(CPUState *env, FILE *f, 
3986
                    int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
3987
                    int flags)
3988
{
3989
    int i;
3990

    
3991
#   define printfpr(fp) do { \
3992
        fpu_fprintf(f, "w:%08x d:%08lx%08lx fd:%g fs:%g\n", \
3993
                (fp)->w[FP_ENDIAN_IDX], (fp)->w[0], (fp)->w[1], (fp)->fd, (fp)->fs[FP_ENDIAN_IDX]); \
3994
    } while(0)
3995

    
3996
    fpu_fprintf(f, "CP1 FCR0 0x%08x  FCR31 0x%08x  SR.FR %d\n",
3997
                env->fcr0, env->fcr31,
3998
                (env->CP0_Status & (1 << CP0St_FR)) != 0);
3999
    fpu_fprintf(f, "FT0: "); printfpr(&env->ft0);
4000
    fpu_fprintf(f, "FT1: "); printfpr(&env->ft1);
4001
    fpu_fprintf(f, "FT2: "); printfpr(&env->ft2);
4002
    for(i = 0; i < 32; i += 2) {
4003
        fpu_fprintf(f, "%s: ", fregnames[i]);
4004
        printfpr(FPR(env, i));
4005
    }
4006

    
4007
#undef printfpr
4008
}
4009

    
4010
void dump_fpu (CPUState *env)
4011
{
4012
    if (loglevel) { 
4013
       fprintf(logfile, "pc=0x%08x HI=0x%08x LO=0x%08x ds %04x %08x %d\n",
4014
               env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
4015
       fpu_dump_state(env, logfile, fprintf, 0);
4016
    }
4017
}
4018

    
4019
#endif /* MIPS_USES_FPU */
4020

    
4021
void cpu_dump_state (CPUState *env, FILE *f, 
4022
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
4023
                     int flags)
4024
{
4025
    uint32_t c0_status;
4026
    int i;
4027
    
4028
    cpu_fprintf(f, "pc=0x%08x HI=0x%08x LO=0x%08x ds %04x %08x %d\n",
4029
                env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
4030
    for (i = 0; i < 32; i++) {
4031
        if ((i & 3) == 0)
4032
            cpu_fprintf(f, "GPR%02d:", i);
4033
        cpu_fprintf(f, " %s %08x", regnames[i], env->gpr[i]);
4034
        if ((i & 3) == 3)
4035
            cpu_fprintf(f, "\n");
4036
    }
4037

    
4038
    c0_status = env->CP0_Status;
4039
    if (env->hflags & MIPS_HFLAG_UM)
4040
        c0_status |= (1 << CP0St_UM);
4041
    if (env->hflags & MIPS_HFLAG_ERL)
4042
        c0_status |= (1 << CP0St_ERL);
4043
    if (env->hflags & MIPS_HFLAG_EXL)
4044
        c0_status |= (1 << CP0St_EXL);
4045

    
4046
    cpu_fprintf(f, "CP0 Status  0x%08x Cause   0x%08x EPC    0x%08x\n",
4047
                c0_status, env->CP0_Cause, env->CP0_EPC);
4048
    cpu_fprintf(f, "    Config0 0x%08x Config1 0x%08x LLAddr 0x%08x\n",
4049
                env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
4050
#ifdef MIPS_USES_FPU
4051
    if (c0_status & (1 << CP0St_CU1))
4052
        fpu_dump_state(env, f, cpu_fprintf, flags);
4053
#endif
4054
}
4055

    
4056
CPUMIPSState *cpu_mips_init (void)
4057
{
4058
    CPUMIPSState *env;
4059

    
4060
    env = qemu_mallocz(sizeof(CPUMIPSState));
4061
    if (!env)
4062
        return NULL;
4063
    cpu_exec_init(env);
4064
    cpu_reset(env);
4065
    return env;
4066
}
4067

    
4068
void cpu_reset (CPUMIPSState *env)
4069
{
4070
    memset(env, 0, offsetof(CPUMIPSState, breakpoints));
4071

    
4072
    tlb_flush(env, 1);
4073

    
4074
    /* Minimal init */
4075
#if !defined(CONFIG_USER_ONLY)
4076
    if (env->hflags & MIPS_HFLAG_BMASK) {
4077
        /* If the exception was raised from a delay slot,
4078
         * come back to the jump.  */
4079
        env->CP0_ErrorEPC = env->PC - 4;
4080
        env->hflags &= ~MIPS_HFLAG_BMASK;
4081
    } else {
4082
        env->CP0_ErrorEPC = env->PC;
4083
    }
4084
    env->PC = 0xBFC00000;
4085
#if defined (MIPS_USES_R4K_TLB)
4086
    env->CP0_random = MIPS_TLB_NB - 1;
4087
    env->tlb_in_use = MIPS_TLB_NB;
4088
#endif
4089
    env->CP0_Wired = 0;
4090
    /* SMP not implemented */
4091
    env->CP0_EBase = 0x80000000;
4092
    env->CP0_Config0 = MIPS_CONFIG0;
4093
    env->CP0_Config1 = MIPS_CONFIG1;
4094
    env->CP0_Config2 = MIPS_CONFIG2;
4095
    env->CP0_Config3 = MIPS_CONFIG3;
4096
    env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
4097
    env->CP0_WatchLo = 0;
4098
    env->hflags = MIPS_HFLAG_ERL;
4099
    /* Count register increments in debug mode, EJTAG version 1 */
4100
    env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
4101
    env->CP0_PRid = MIPS_CPU;
4102
#endif
4103
    env->exception_index = EXCP_NONE;
4104
#if defined(CONFIG_USER_ONLY)
4105
    env->hflags |= MIPS_HFLAG_UM;
4106
    env->user_mode_only = 1;
4107
#endif
4108
#ifdef MIPS_USES_FPU
4109
    env->fcr0 = MIPS_FCR0;        
4110
#endif
4111
    /* XXX some guesswork here, values are CPU specific */
4112
    env->SYNCI_Step = 16;
4113
    env->CCRes = 2;
4114
}