Statistics
| Branch: | Revision:

root / target-mips / translate.c @ aa328add

History | View | Annotate | Download (110.3 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
static const char *fregnames[] =
394
    { "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
395
      "f8",  "f9",  "f10", "f11", "f12", "f13", "f14", "f15",
396
      "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
397
      "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
398

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

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

    
431
SFGEN32(gen_op_load_fpr_WT0,  gen_op_load_fpr_WT0_fpr);
432
SFGEN32(gen_op_store_fpr_WT0, gen_op_store_fpr_WT0_fpr);
433

    
434
SFGEN32(gen_op_load_fpr_WT1,  gen_op_load_fpr_WT1_fpr);
435
SFGEN32(gen_op_store_fpr_WT1, gen_op_store_fpr_WT1_fpr);
436

    
437
SFGEN32(gen_op_load_fpr_WT2,  gen_op_load_fpr_WT2_fpr);
438
SFGEN32(gen_op_store_fpr_WT2, gen_op_store_fpr_WT2_fpr);
439

    
440
DFGEN32(gen_op_load_fpr_DT0,  gen_op_load_fpr_DT0_fpr);
441
DFGEN32(gen_op_store_fpr_DT0, gen_op_store_fpr_DT0_fpr);
442

    
443
DFGEN32(gen_op_load_fpr_DT1,  gen_op_load_fpr_DT1_fpr);
444
DFGEN32(gen_op_store_fpr_DT1, gen_op_store_fpr_DT1_fpr);
445

    
446
DFGEN32(gen_op_load_fpr_DT2,  gen_op_load_fpr_DT2_fpr);
447
DFGEN32(gen_op_store_fpr_DT2, gen_op_store_fpr_DT2_fpr);
448

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

    
473
FOP_CONDS(d)
474
FOP_CONDS(s)
475

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

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

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

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

    
515
#define GEN_LOAD_REG_TN(Tn, Rn)                                               \
516
do {                                                                          \
517
    if (Rn == 0) {                                                            \
518
        glue(gen_op_reset_, Tn)();                                            \
519
    } else {                                                                  \
520
        glue(gen_op_load_gpr_, Tn)(Rn);                                       \
521
    }                                                                         \
522
} while (0)
523

    
524
#define GEN_LOAD_IMM_TN(Tn, Imm)                                              \
525
do {                                                                          \
526
    if (Imm == 0) {                                                           \
527
        glue(gen_op_reset_, Tn)();                                            \
528
    } else {                                                                  \
529
        glue(gen_op_set_, Tn)(Imm);                                           \
530
    }                                                                         \
531
} while (0)
532

    
533
#define GEN_STORE_TN_REG(Rn, Tn)                                              \
534
do {                                                                          \
535
    if (Rn != 0) {                                                            \
536
        glue(glue(gen_op_store_, Tn),_gpr)(Rn);                               \
537
    }                                                                         \
538
} while (0)
539

    
540
#define GEN_LOAD_FREG_FTN(FTn, Fn)                                            \
541
do {                                                                          \
542
    glue(gen_op_load_fpr_, FTn)(Fn);                                          \
543
} while (0)
544

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

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

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

    
590
static inline void generate_exception (DisasContext *ctx, int excp)
591
{
592
    generate_exception_err (ctx, excp, 0);
593
}
594

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

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

    
641
/* Load and store */
642
static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
643
                      int base, int16_t offset)
644
{
645
    const char *opn = "unk";
646

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

    
788
/* Load and store */
789
static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
790
                      int base, int16_t offset)
791
{
792
    const char *opn = "unk";
793

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

    
835
/* Arithmetic with immediate operand */
836
static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt,
837
                           int rs, int16_t imm)
838
{
839
    uint32_t uimm;
840
    const char *opn = "unk";
841

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

    
968
/* Arithmetic */
969
static void gen_arith (DisasContext *ctx, uint32_t opc,
970
                       int rd, int rs, int rt)
971
{
972
    const char *opn = "unk";
973

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

    
1105
/* Arithmetic on HI/LO registers */
1106
static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1107
{
1108
    const char *opn = "unk";
1109

    
1110
    if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1111
        /* Treat as a NOP */
1112
        MIPS_DEBUG("NOP");
1113
        return;
1114
    }
1115
    switch (opc) {
1116
    case OPC_MFHI:
1117
        gen_op_load_HI();
1118
        GEN_STORE_TN_REG(reg, T0);
1119
        opn = "mfhi";
1120
        break;
1121
    case OPC_MFLO:
1122
        gen_op_load_LO();
1123
        GEN_STORE_TN_REG(reg, T0);
1124
        opn = "mflo";
1125
        break;
1126
    case OPC_MTHI:
1127
        GEN_LOAD_REG_TN(T0, reg);
1128
        gen_op_store_HI();
1129
        opn = "mthi";
1130
        break;
1131
    case OPC_MTLO:
1132
        GEN_LOAD_REG_TN(T0, reg);
1133
        gen_op_store_LO();
1134
        opn = "mtlo";
1135
        break;
1136
    default:
1137
        MIPS_INVAL("HILO");
1138
        generate_exception(ctx, EXCP_RI);
1139
        return;
1140
    }
1141
    MIPS_DEBUG("%s %s", opn, regnames[reg]);
1142
}
1143

    
1144
static void gen_muldiv (DisasContext *ctx, uint32_t opc,
1145
                        int rs, int rt)
1146
{
1147
    const char *opn = "unk";
1148

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

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

    
1248
/* Traps */
1249
static void gen_trap (DisasContext *ctx, uint32_t opc,
1250
                      int rs, int rt, int16_t imm)
1251
{
1252
    int cond;
1253

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

    
1344
static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
1345
{
1346
    TranslationBlock *tb;
1347
    tb = ctx->tb;
1348
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
1349
        if (n == 0)
1350
            gen_op_goto_tb0(TBPARAM(tb));
1351
        else
1352
            gen_op_goto_tb1(TBPARAM(tb));
1353
        gen_op_save_pc(dest);
1354
        gen_op_set_T0((long)tb + n);
1355
        gen_op_exit_tb();
1356
    } else {
1357
        gen_op_save_pc(dest);
1358
        gen_op_set_T0(0);
1359
        gen_op_exit_tb();
1360
    }
1361
}
1362

    
1363
/* Branches (before delay slot) */
1364
static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
1365
                                int rs, int rt, int32_t offset)
1366
{
1367
    target_ulong btarget;
1368
    int blink, bcond;
1369

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

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

    
1640
/* CP0 (MMU and control) */
1641
static void gen_mfc0 (DisasContext *ctx, int reg, int sel)
1642
{
1643
    const char *rn = "invalid";
1644

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

    
2213
die:
2214
#if defined MIPS_DEBUG_DISAS
2215
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2216
        fprintf(logfile, "mfc0 %s (reg %d sel %d)\n",
2217
                rn, reg, sel);
2218
    }
2219
#endif
2220
    generate_exception(ctx, EXCP_RI);
2221
}
2222

    
2223
static void gen_mtc0 (DisasContext *ctx, int reg, int sel)
2224
{
2225
    const char *rn = "invalid";
2226

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

    
2806
die:
2807
#if defined MIPS_DEBUG_DISAS
2808
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2809
        fprintf(logfile, "mtc0 %s (reg %d sel %d)\n",
2810
                rn, reg, sel);
2811
    }
2812
#endif
2813
    generate_exception(ctx, EXCP_RI);
2814
}
2815

    
2816
static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd)
2817
{
2818
    const char *opn = "unk";
2819

    
2820
    if ((!ctx->CP0_Status & (1 << CP0St_CU0) &&
2821
          (ctx->hflags & MIPS_HFLAG_UM)) &&
2822
        !(ctx->hflags & MIPS_HFLAG_ERL) &&
2823
        !(ctx->hflags & MIPS_HFLAG_EXL)) {
2824
        if (loglevel & CPU_LOG_TB_IN_ASM) {
2825
            fprintf(logfile, "CP0 is not usable\n");
2826
        }
2827
        generate_exception (ctx, EXCP_CpU);
2828
        return;
2829
    }
2830

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

    
2906
/* CP1 Branches (before delay slot) */
2907
static void gen_compute_branch1 (DisasContext *ctx, uint32_t op,
2908
                                 int32_t offset)
2909
{
2910
    target_ulong btarget;
2911

    
2912
    btarget = ctx->pc + 4 + offset;
2913

    
2914
    switch (op) {
2915
    case OPC_BC1F:
2916
        gen_op_bc1f();
2917
        MIPS_DEBUG("bc1f %08x", btarget);
2918
        goto not_likely;
2919
    case OPC_BC1FL:
2920
        gen_op_bc1f();
2921
        MIPS_DEBUG("bc1fl %08x", btarget);
2922
        goto likely;
2923
    case OPC_BC1T:
2924
        gen_op_bc1t();
2925
        MIPS_DEBUG("bc1t %08x", btarget);
2926
    not_likely:
2927
        ctx->hflags |= MIPS_HFLAG_BC;
2928
        break;
2929
    case OPC_BC1TL:
2930
        gen_op_bc1t();
2931
        MIPS_DEBUG("bc1tl %08x", btarget);
2932
    likely:
2933
        ctx->hflags |= MIPS_HFLAG_BL;
2934
        break;
2935
    default:    
2936
        MIPS_INVAL("cp1 branch/jump");
2937
        generate_exception_err (ctx, EXCP_RI, 1);
2938
        return;
2939
    }
2940
    gen_op_set_bcond();
2941

    
2942
    MIPS_DEBUG("enter ds: cond %02x target %08x",
2943
               ctx->hflags, btarget);
2944
    ctx->btarget = btarget;
2945

    
2946
    return;
2947
}
2948

    
2949
/* Coprocessor 1 (FPU) */
2950
static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
2951
{
2952
    const char *opn = "unk";
2953

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

    
3001
/* verify if floating point register is valid; an operation is not defined
3002
 * if bit 0 of any register specification is set and the FR bit in the
3003
 * Status register equals zero, since the register numbers specify an
3004
 * even-odd pair of adjacent coprocessor general registers. When the FR bit
3005
 * in the Status register equals one, both even and odd register numbers
3006
 * are valid.
3007
 * 
3008
 * Multiple float registers can be checked by calling
3009
 * CHECK_FR(ctx, freg1 | freg2 | ... | fregN);
3010
 */
3011
#define CHECK_FR(ctx, freg) do { \
3012
        if (!((ctx)->CP0_Status & (1<<CP0St_FR)) && ((freg) & 1)) { \
3013
            generate_exception_err (ctx, EXCP_RI, 1); \
3014
            return; \
3015
        } \
3016
    } while(0)
3017

    
3018
#define FOP(func, fmt) (((fmt) << 21) | (func))
3019

    
3020
static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, int fs, int fd)
3021
{
3022
    const char *opn = "unk";
3023
    const char *condnames[] = {
3024
            "c.f",
3025
            "c.un",
3026
            "c.eq",
3027
            "c.ueq",
3028
            "c.olt",
3029
            "c.ult",
3030
            "c.ole",
3031
            "c.ule",
3032
            "c.sf",
3033
            "c.ngle",
3034
            "c.seq",
3035
            "c.ngl",
3036
            "c.lt",
3037
            "c.nge",
3038
            "c.le",
3039
            "c.ngt",
3040
    };
3041
    int binary = 0;
3042
    uint32_t func = ctx->opcode & 0x3f;
3043

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

    
3320
static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
3321
{
3322
    uint32_t ccbit;
3323

    
3324
    if (cc)
3325
        ccbit = 1 << (24 + cc);
3326
    else
3327
        ccbit = 1 << 23;
3328
    if (!tf)
3329
        gen_op_movf(ccbit, rd, rs);
3330
    else
3331
       gen_op_movt(ccbit, rd, rs);
3332
}
3333

    
3334
/* ISA extensions (ASEs) */
3335
/* MIPS16 extension to MIPS32 */
3336
/* SmartMIPS extension to MIPS32 */
3337

    
3338
#ifdef MIPS_HAS_MIPS64
3339
static void gen_arith64 (DisasContext *ctx, uint32_t opc)
3340
{
3341
    if (func == 0x02 && rd == 0) {
3342
        /* NOP */
3343
        return;
3344
    }
3345
    if (rs == 0 || rt == 0) {
3346
        gen_op_reset_T0();
3347
        gen_op_save64();
3348
    } else {
3349
        gen_op_load_gpr_T0(rs);
3350
        gen_op_load_gpr_T1(rt);
3351
        gen_op_save64();
3352
        if (func & 0x01)
3353
            gen_op_mul64u();
3354
        else
3355
            gen_op_mul64s();
3356
    }
3357
    if (func & 0x02)
3358
        gen_op_add64();
3359
    else
3360
        gen_op_sub64();
3361
}
3362

    
3363
/* Coprocessor 3 (FPU) */
3364

    
3365
/* MDMX extension to MIPS64 */
3366
/* MIPS-3D extension to MIPS64 */
3367

    
3368
#endif
3369

    
3370
static void gen_blikely(DisasContext *ctx)
3371
{
3372
    int l1;
3373
    l1 = gen_new_label();
3374
    gen_op_jnz_T2(l1);
3375
    gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
3376
    gen_goto_tb(ctx, 1, ctx->pc + 4);
3377
    gen_set_label(l1);
3378
}
3379

    
3380
static void decode_opc (DisasContext *ctx)
3381
{
3382
    int32_t offset;
3383
    int rs, rt, rd, sa;
3384
    uint32_t op, op1, op2;
3385
    int16_t imm;
3386

    
3387
    /* make sure instructions are on a word boundary */
3388
    if (ctx->pc & 0x3) {
3389
        generate_exception(ctx, EXCP_AdEL);
3390
        return;
3391
    }
3392

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

    
3456
        case OPC_MOVCI:
3457
            gen_op_cp1_enabled();
3458
            gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
3459
                      (ctx->opcode >> 16) & 1);
3460
            break;
3461

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

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

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

    
3730
    /* COP2.  */
3731
    case OPC_LWC2:
3732
    case OPC_LDC2:
3733
    case OPC_SWC2:
3734
    case OPC_SDC2:
3735
    case OPC_CP2:
3736
        /* COP2: Not implemented. */
3737
        generate_exception_err(ctx, EXCP_CpU, 2);
3738
        break;
3739

    
3740
    case OPC_CP3:
3741
        gen_op_cp1_enabled();
3742
        op1 = MASK_CP3(ctx->opcode);
3743
        switch (op1) {
3744
        /* Not implemented */
3745
        default:
3746
            generate_exception_err(ctx, EXCP_RI, 1);
3747
            break;
3748
        }
3749
        break;
3750

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

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

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

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

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

    
3899
        if (env->singlestep_enabled)
3900
            break;
3901

    
3902
        if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
3903
            break;
3904

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

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

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

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

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

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

    
3987
#undef printfpr
3988
}
3989

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

    
3999
void cpu_dump_state (CPUState *env, FILE *f, 
4000
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
4001
                     int flags)
4002
{
4003
    uint32_t c0_status;
4004
    int i;
4005
    
4006
    cpu_fprintf(f, "pc=0x%08x HI=0x%08x LO=0x%08x ds %04x %08x %d\n",
4007
                env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
4008
    for (i = 0; i < 32; i++) {
4009
        if ((i & 3) == 0)
4010
            cpu_fprintf(f, "GPR%02d:", i);
4011
        cpu_fprintf(f, " %s %08x", regnames[i], env->gpr[i]);
4012
        if ((i & 3) == 3)
4013
            cpu_fprintf(f, "\n");
4014
    }
4015

    
4016
    c0_status = env->CP0_Status;
4017
    if (env->hflags & MIPS_HFLAG_UM)
4018
        c0_status |= (1 << CP0St_UM);
4019
    if (env->hflags & MIPS_HFLAG_ERL)
4020
        c0_status |= (1 << CP0St_ERL);
4021
    if (env->hflags & MIPS_HFLAG_EXL)
4022
        c0_status |= (1 << CP0St_EXL);
4023

    
4024
    cpu_fprintf(f, "CP0 Status  0x%08x Cause   0x%08x EPC    0x%08x\n",
4025
                c0_status, env->CP0_Cause, env->CP0_EPC);
4026
    cpu_fprintf(f, "    Config0 0x%08x Config1 0x%08x LLAddr 0x%08x\n",
4027
                env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
4028
    if (c0_status & (1 << CP0St_CU1))
4029
        fpu_dump_state(env, f, cpu_fprintf, flags);
4030
}
4031

    
4032
CPUMIPSState *cpu_mips_init (void)
4033
{
4034
    CPUMIPSState *env;
4035

    
4036
    env = qemu_mallocz(sizeof(CPUMIPSState));
4037
    if (!env)
4038
        return NULL;
4039
    cpu_exec_init(env);
4040
    cpu_reset(env);
4041
    return env;
4042
}
4043

    
4044
void cpu_reset (CPUMIPSState *env)
4045
{
4046
    memset(env, 0, offsetof(CPUMIPSState, breakpoints));
4047

    
4048
    tlb_flush(env, 1);
4049

    
4050
    /* Minimal init */
4051
    if (env->hflags & MIPS_HFLAG_BMASK) {
4052
        /* If the exception was raised from a delay slot,
4053
         * come back to the jump.  */
4054
        env->CP0_ErrorEPC = env->PC - 4;
4055
        env->hflags &= ~MIPS_HFLAG_BMASK;
4056
    } else {
4057
        env->CP0_ErrorEPC = env->PC;
4058
    }
4059
    env->PC = 0xBFC00000;
4060
#if defined (MIPS_USES_R4K_TLB)
4061
    env->CP0_random = MIPS_TLB_NB - 1;
4062
    env->tlb_in_use = MIPS_TLB_NB;
4063
#endif
4064
    env->CP0_Wired = 0;
4065
    /* SMP not implemented */
4066
    env->CP0_EBase = 0x80000000;
4067
    env->CP0_Config0 = MIPS_CONFIG0;
4068
    env->CP0_Config1 = MIPS_CONFIG1;
4069
    env->CP0_Config2 = MIPS_CONFIG2;
4070
    env->CP0_Config3 = MIPS_CONFIG3;
4071
    env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
4072
    env->CP0_WatchLo = 0;
4073
    env->hflags = MIPS_HFLAG_ERL;
4074
    /* Count register increments in debug mode, EJTAG version 1 */
4075
    env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
4076
    env->CP0_PRid = MIPS_CPU;
4077
    env->exception_index = EXCP_NONE;
4078
#if defined(CONFIG_USER_ONLY)
4079
    env->hflags |= MIPS_HFLAG_UM;
4080
#endif
4081
#ifdef MIPS_USES_FPU
4082
    env->fcr0 = MIPS_FCR0;        
4083
#endif
4084
    /* XXX some guesswork here, values are CPU specific */
4085
    env->SYNCI_Step = 16;
4086
    env->CCRes = 2;
4087
}