]> Git Repo - qemu.git/blob - target-mips/translate.c
sparc64 fixes (Blue Swirl)
[qemu.git] / target-mips / translate.c
1 /*
2  *  MIPS32 emulation for qemu: main translation routines.
3  * 
4  *  Copyright (c) 2004-2005 Jocelyn Mayer
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <inttypes.h>
26
27 #include "cpu.h"
28 #include "exec-all.h"
29 #include "disas.h"
30
31 #define MIPS_DEBUG_DISAS
32 //#define MIPS_SINGLE_STEP
33
34 enum {
35 #define DEF(s, n, copy_size) INDEX_op_ ## s,
36 #include "opc.h"
37 #undef DEF
38     NB_OPS,
39 };
40
41 static uint16_t *gen_opc_ptr;
42 static uint32_t *gen_opparam_ptr;
43
44 #include "gen-op.h"
45
46 /* MIPS opcodes */
47 #define EXT_SPECIAL  0x100
48 #define EXT_SPECIAL2 0x200
49 #define EXT_REGIMM   0x300
50 #define EXT_CP0      0x400
51 #define EXT_CP1      0x500
52 #define EXT_CP2      0x600
53 #define EXT_CP3      0x700
54
55 enum {
56     /* indirect opcode tables */
57     OPC_SPECIAL  = 0x00,
58     OPC_BREGIMM  = 0x01,
59     OPC_CP0      = 0x10,
60     OPC_CP1      = 0x11,
61     OPC_CP2      = 0x12,
62     OPC_CP3      = 0x13,
63     OPC_SPECIAL2 = 0x1C,
64     /* arithmetic with immediate */
65     OPC_ADDI     = 0x08,
66     OPC_ADDIU    = 0x09,
67     OPC_SLTI     = 0x0A,
68     OPC_SLTIU    = 0x0B,
69     OPC_ANDI     = 0x0C,
70     OPC_ORI      = 0x0D,
71     OPC_XORI     = 0x0E,
72     OPC_LUI      = 0x0F,
73     /* Jump and branches */
74     OPC_J        = 0x02,
75     OPC_JAL      = 0x03,
76     OPC_BEQ      = 0x04,  /* Unconditional if rs = rt = 0 (B) */
77     OPC_BEQL     = 0x14,
78     OPC_BNE      = 0x05,
79     OPC_BNEL     = 0x15,
80     OPC_BLEZ     = 0x06,
81     OPC_BLEZL    = 0x16,
82     OPC_BGTZ     = 0x07,
83     OPC_BGTZL    = 0x17,
84     OPC_JALX     = 0x1D,  /* MIPS 16 only */
85     /* Load and stores */
86     OPC_LB       = 0x20,
87     OPC_LH       = 0x21,
88     OPC_LWL      = 0x22,
89     OPC_LW       = 0x23,
90     OPC_LBU      = 0x24,
91     OPC_LHU      = 0x25,
92     OPC_LWR      = 0x26,
93     OPC_SB       = 0x28,
94     OPC_SH       = 0x29,
95     OPC_SWL      = 0x2A,
96     OPC_SW       = 0x2B,
97     OPC_SWR      = 0x2E,
98     OPC_LL       = 0x30,
99     OPC_SC       = 0x38,
100     /* Floating point load/store */
101     OPC_LWC1     = 0x31,
102     OPC_LWC2     = 0x32,
103     OPC_LDC1     = 0x35,
104     OPC_LDC2     = 0x36,
105     OPC_SWC1     = 0x39,
106     OPC_SWC2     = 0x3A,
107     OPC_SDC1     = 0x3D,
108     OPC_SDC2     = 0x3E,
109     /* Cache and prefetch */
110     OPC_CACHE    = 0x2F,
111     OPC_PREF     = 0x33,
112 };
113
114 /* MIPS special opcodes */
115 enum {
116     /* Shifts */
117     OPC_SLL      = 0x00 | EXT_SPECIAL,
118     /* NOP is SLL r0, r0, 0   */
119     /* SSNOP is SLL r0, r0, 1 */
120     OPC_SRL      = 0x02 | EXT_SPECIAL,
121     OPC_SRA      = 0x03 | EXT_SPECIAL,
122     OPC_SLLV     = 0x04 | EXT_SPECIAL,
123     OPC_SRLV     = 0x06 | EXT_SPECIAL,
124     OPC_SRAV     = 0x07 | EXT_SPECIAL,
125     /* Multiplication / division */
126     OPC_MULT     = 0x18 | EXT_SPECIAL,
127     OPC_MULTU    = 0x19 | EXT_SPECIAL,
128     OPC_DIV      = 0x1A | EXT_SPECIAL,
129     OPC_DIVU     = 0x1B | EXT_SPECIAL,
130     /* 2 registers arithmetic / logic */
131     OPC_ADD      = 0x20 | EXT_SPECIAL,
132     OPC_ADDU     = 0x21 | EXT_SPECIAL,
133     OPC_SUB      = 0x22 | EXT_SPECIAL,
134     OPC_SUBU     = 0x23 | EXT_SPECIAL,
135     OPC_AND      = 0x24 | EXT_SPECIAL,
136     OPC_OR       = 0x25 | EXT_SPECIAL,
137     OPC_XOR      = 0x26 | EXT_SPECIAL,
138     OPC_NOR      = 0x27 | EXT_SPECIAL,
139     OPC_SLT      = 0x2A | EXT_SPECIAL,
140     OPC_SLTU     = 0x2B | EXT_SPECIAL,
141     /* Jumps */
142     OPC_JR       = 0x08 | EXT_SPECIAL,
143     OPC_JALR     = 0x09 | EXT_SPECIAL,
144     /* Traps */
145     OPC_TGE      = 0x30 | EXT_SPECIAL,
146     OPC_TGEU     = 0x31 | EXT_SPECIAL,
147     OPC_TLT      = 0x32 | EXT_SPECIAL,
148     OPC_TLTU     = 0x33 | EXT_SPECIAL,
149     OPC_TEQ      = 0x34 | EXT_SPECIAL,
150     OPC_TNE      = 0x36 | EXT_SPECIAL,
151     /* HI / LO registers load & stores */
152     OPC_MFHI     = 0x10 | EXT_SPECIAL,
153     OPC_MTHI     = 0x11 | EXT_SPECIAL,
154     OPC_MFLO     = 0x12 | EXT_SPECIAL,
155     OPC_MTLO     = 0x13 | EXT_SPECIAL,
156     /* Conditional moves */
157     OPC_MOVZ     = 0x0A | EXT_SPECIAL,
158     OPC_MOVN     = 0x0B | EXT_SPECIAL,
159
160     OPC_MOVCI    = 0x01 | EXT_SPECIAL,
161
162     /* Special */
163     OPC_PMON     = 0x05 | EXT_SPECIAL,
164     OPC_SYSCALL  = 0x0C | EXT_SPECIAL,
165     OPC_BREAK    = 0x0D | EXT_SPECIAL,
166     OPC_SYNC     = 0x0F | EXT_SPECIAL,
167 };
168
169 enum {
170     /* Mutiply & xxx operations */
171     OPC_MADD     = 0x00 | EXT_SPECIAL2,
172     OPC_MADDU    = 0x01 | EXT_SPECIAL2,
173     OPC_MUL      = 0x02 | EXT_SPECIAL2,
174     OPC_MSUB     = 0x04 | EXT_SPECIAL2,
175     OPC_MSUBU    = 0x05 | EXT_SPECIAL2,
176     /* Misc */
177     OPC_CLZ      = 0x20 | EXT_SPECIAL2,
178     OPC_CLO      = 0x21 | EXT_SPECIAL2,
179     /* Special */
180     OPC_SDBBP    = 0x3F | EXT_SPECIAL2,
181 };
182
183 /* Branch REGIMM */
184 enum {
185     OPC_BLTZ     = 0x00 | EXT_REGIMM,
186     OPC_BLTZL    = 0x02 | EXT_REGIMM,
187     OPC_BGEZ     = 0x01 | EXT_REGIMM,
188     OPC_BGEZL    = 0x03 | EXT_REGIMM,
189     OPC_BLTZAL   = 0x10 | EXT_REGIMM,
190     OPC_BLTZALL  = 0x12 | EXT_REGIMM,
191     OPC_BGEZAL   = 0x11 | EXT_REGIMM,
192     OPC_BGEZALL  = 0x13 | EXT_REGIMM,
193     OPC_TGEI     = 0x08 | EXT_REGIMM,
194     OPC_TGEIU    = 0x09 | EXT_REGIMM,
195     OPC_TLTI     = 0x0A | EXT_REGIMM,
196     OPC_TLTIU    = 0x0B | EXT_REGIMM,
197     OPC_TEQI     = 0x0C | EXT_REGIMM,
198     OPC_TNEI     = 0x0E | EXT_REGIMM,
199 };
200
201 enum {
202     /* Coprocessor 0 (MMU) */
203     OPC_MFC0     = 0x00 | EXT_CP0,
204     OPC_MTC0     = 0x04 | EXT_CP0,
205     OPC_TLBR     = 0x01 | EXT_CP0,
206     OPC_TLBWI    = 0x02 | EXT_CP0,
207     OPC_TLBWR    = 0x06 | EXT_CP0,
208     OPC_TLBP     = 0x08 | EXT_CP0,
209     OPC_ERET     = 0x18 | EXT_CP0,
210     OPC_DERET    = 0x1F | EXT_CP0,
211     OPC_WAIT     = 0x20 | EXT_CP0,
212 };
213
214 const unsigned char *regnames[] =
215     { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
216       "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
217       "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
218       "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
219
220 /* Warning: no function for r0 register (hard wired to zero) */
221 #define GEN32(func, NAME) \
222 static GenOpFunc *NAME ## _table [32] = {                                     \
223 NULL,       NAME ## 1, NAME ## 2, NAME ## 3,                                  \
224 NAME ## 4,  NAME ## 5, NAME ## 6, NAME ## 7,                                  \
225 NAME ## 8,  NAME ## 9, NAME ## 10, NAME ## 11,                                \
226 NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
227 NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
228 NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
229 NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
230 NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
231 };                                                                            \
232 static inline void func(int n)                                                \
233 {                                                                             \
234     NAME ## _table[n]();                                                      \
235 }
236
237 /* General purpose registers moves */
238 GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
239 GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
240 GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr);
241
242 GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
243 GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
244
245 typedef struct DisasContext {
246     struct TranslationBlock *tb;
247     target_ulong pc, saved_pc;
248     uint32_t opcode;
249     /* Routine used to access memory */
250     int mem_idx;
251     uint32_t hflags, saved_hflags;
252     uint32_t CP0_Status;
253     int bstate;
254     target_ulong btarget;
255 } DisasContext;
256
257 enum {
258     BS_NONE     = 0, /* We go out of the TB without reaching a branch or an
259                       * exception condition
260                       */
261     BS_STOP     = 1, /* We want to stop translation for any reason */
262     BS_BRANCH   = 2, /* We reached a branch condition     */
263     BS_EXCP     = 3, /* We reached an exception condition */
264 };
265
266 #if defined MIPS_DEBUG_DISAS
267 #define MIPS_DEBUG(fmt, args...)                                              \
268 do {                                                                          \
269     if (loglevel & CPU_LOG_TB_IN_ASM) {                                       \
270         fprintf(logfile, "%08x: %08x " fmt "\n",                              \
271                 ctx->pc, ctx->opcode , ##args);                               \
272     }                                                                         \
273 } while (0)
274 #else
275 #define MIPS_DEBUG(fmt, args...) do { } while(0)
276 #endif
277
278 #define MIPS_INVAL(op)                                                        \
279 do {                                                                          \
280     MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26,            \
281                ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F));             \
282 } while (0)
283
284 #define GEN_LOAD_REG_TN(Tn, Rn)                                               \
285 do {                                                                          \
286     if (Rn == 0) {                                                            \
287         glue(gen_op_reset_, Tn)();                                            \
288     } else {                                                                  \
289         glue(gen_op_load_gpr_, Tn)(Rn);                                       \
290     }                                                                         \
291 } while (0)
292
293 #define GEN_LOAD_IMM_TN(Tn, Imm)                                              \
294 do {                                                                          \
295     if (Imm == 0) {                                                           \
296         glue(gen_op_reset_, Tn)();                                            \
297     } else {                                                                  \
298         glue(gen_op_set_, Tn)(Imm);                                           \
299     }                                                                         \
300 } while (0)
301
302 #define GEN_STORE_TN_REG(Rn, Tn)                                              \
303 do {                                                                          \
304     if (Rn != 0) {                                                            \
305         glue(glue(gen_op_store_, Tn),_gpr)(Rn);                               \
306     }                                                                         \
307 } while (0)
308
309 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
310 {
311 #if defined MIPS_DEBUG_DISAS
312     if (loglevel & CPU_LOG_TB_IN_ASM) {
313             fprintf(logfile, "hflags %08x saved %08x\n",
314                     ctx->hflags, ctx->saved_hflags);
315     }
316 #endif
317     if (do_save_pc && ctx->pc != ctx->saved_pc) {
318         gen_op_save_pc(ctx->pc);
319         ctx->saved_pc = ctx->pc;
320     }
321     if (ctx->hflags != ctx->saved_hflags) {
322         gen_op_save_state(ctx->hflags);
323         ctx->saved_hflags = ctx->hflags;
324         if (ctx->hflags & MIPS_HFLAG_BR) {
325             gen_op_save_breg_target();
326         } else if (ctx->hflags & MIPS_HFLAG_B) {
327             gen_op_save_btarget(ctx->btarget);
328         } else if (ctx->hflags & MIPS_HFLAG_BMASK) {
329             gen_op_save_bcond();
330             gen_op_save_btarget(ctx->btarget);
331         }
332     }
333 }
334
335 static inline void generate_exception (DisasContext *ctx, int excp)
336 {
337 #if defined MIPS_DEBUG_DISAS
338     if (loglevel & CPU_LOG_TB_IN_ASM)
339             fprintf(logfile, "%s: raise exception %d\n", __func__, excp);
340 #endif
341     save_cpu_state(ctx, 1);
342     gen_op_raise_exception(excp);
343     ctx->bstate = BS_EXCP;
344 }
345
346 #if defined(CONFIG_USER_ONLY)
347 #define op_ldst(name)        gen_op_##name##_raw()
348 #define OP_LD_TABLE(width)
349 #define OP_ST_TABLE(width)
350 #else
351 #define op_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
352 #define OP_LD_TABLE(width)                                                    \
353 static GenOpFunc *gen_op_l##width[] = {                                       \
354     &gen_op_l##width##_user,                                                  \
355     &gen_op_l##width##_kernel,                                                \
356 }
357 #define OP_ST_TABLE(width)                                                    \
358 static GenOpFunc *gen_op_s##width[] = {                                       \
359     &gen_op_s##width##_user,                                                  \
360     &gen_op_s##width##_kernel,                                                \
361 }
362 #endif
363
364 #ifdef TARGET_MIPS64
365 OP_LD_TABLE(d);
366 OP_LD_TABLE(dl);
367 OP_LD_TABLE(dr);
368 OP_ST_TABLE(d);
369 OP_ST_TABLE(dl);
370 OP_ST_TABLE(dr);
371 #endif
372 OP_LD_TABLE(w);
373 OP_LD_TABLE(wl);
374 OP_LD_TABLE(wr);
375 OP_ST_TABLE(w);
376 OP_ST_TABLE(wl);
377 OP_ST_TABLE(wr);
378 OP_LD_TABLE(h);
379 OP_LD_TABLE(hu);
380 OP_ST_TABLE(h);
381 OP_LD_TABLE(b);
382 OP_LD_TABLE(bu);
383 OP_ST_TABLE(b);
384 OP_LD_TABLE(l);
385 OP_ST_TABLE(c);
386
387 /* Load and store */
388 static void gen_ldst (DisasContext *ctx, uint16_t opc, int rt,
389                       int base, int16_t offset)
390 {
391     const unsigned char *opn = "unk";
392
393     if (base == 0) {
394         GEN_LOAD_IMM_TN(T0, offset);
395     } else if (offset == 0) {
396         gen_op_load_gpr_T0(base);
397     } else {
398         gen_op_load_gpr_T0(base);
399         gen_op_set_T1(offset);
400         gen_op_add();
401     }
402     /* Don't do NOP if destination is zero: we must perform the actual
403      * memory access
404      */
405     switch (opc) {
406 #if defined(TARGET_MIPS64)
407     case OPC_LD:
408 #if defined (MIPS_HAS_UNALIGNED_LS)
409     case OPC_ULD:
410 #endif
411         op_ldst(ld);
412         GEN_STORE_TN_REG(rt, T0);
413         opn = "ld";
414         break;
415     case OPC_SD:
416 #if defined (MIPS_HAS_UNALIGNED_LS)
417     case OPC_USD:
418 #endif
419         GEN_LOAD_REG_TN(T1, rt);
420         op_ldst(sd);
421         opn = "sd";
422         break;
423     case OPC_LDL:
424         op_ldst(ldl);
425         GEN_STORE_TN_REG(rt, T0);
426         opn = "ldl";
427         break;
428     case OPC_SDL:
429         GEN_LOAD_REG_TN(T1, rt);
430         op_ldst(sdl);
431         opn = "sdl";
432         break;
433     case OPC_LDR:
434         op_ldst(ldr);
435         GEN_STORE_TN_REG(rt, T0);
436         opn = "ldr";
437         break;
438     case OPC_SDR:
439         GEN_LOAD_REG_TN(T1, rt);
440         op_ldst(sdr);
441         opn = "sdr";
442         break;
443 #endif
444     case OPC_LW:
445 #if defined (MIPS_HAS_UNALIGNED_LS)
446     case OPC_ULW:
447 #endif
448         op_ldst(lw);
449         GEN_STORE_TN_REG(rt, T0);
450         opn = "lw";
451         break;
452     case OPC_SW:
453 #if defined (MIPS_HAS_UNALIGNED_LS)
454     case OPC_USW:
455 #endif
456         GEN_LOAD_REG_TN(T1, rt);
457         op_ldst(sw);
458         opn = "sw";
459         break;
460     case OPC_LH:
461 #if defined (MIPS_HAS_UNALIGNED_LS)
462     case OPC_ULH:
463 #endif
464         op_ldst(lh);
465         GEN_STORE_TN_REG(rt, T0);
466         opn = "lh";
467         break;
468     case OPC_SH:
469 #if defined (MIPS_HAS_UNALIGNED_LS)
470     case OPC_USH:
471 #endif
472         GEN_LOAD_REG_TN(T1, rt);
473         op_ldst(sh);
474         opn = "sh";
475         break;
476     case OPC_LHU:
477 #if defined (MIPS_HAS_UNALIGNED_LS)
478     case OPC_ULHU:
479 #endif
480         op_ldst(lhu);
481         GEN_STORE_TN_REG(rt, T0);
482         opn = "lhu";
483         break;
484     case OPC_LB:
485         op_ldst(lb);
486         GEN_STORE_TN_REG(rt, T0);
487         opn = "lb";
488         break;
489     case OPC_SB:
490         GEN_LOAD_REG_TN(T1, rt);
491         op_ldst(sb);
492         opn = "sb";
493         break;
494     case OPC_LBU:
495         op_ldst(lbu);
496         GEN_STORE_TN_REG(rt, T0);
497         opn = "lbu";
498         break;
499     case OPC_LWL:
500         GEN_LOAD_REG_TN(T1, rt);
501         op_ldst(lwl);
502         GEN_STORE_TN_REG(rt, T0);
503         opn = "lwl";
504         break;
505     case OPC_SWL:
506         GEN_LOAD_REG_TN(T1, rt);
507         op_ldst(swl);
508         opn = "swr";
509         break;
510     case OPC_LWR:
511         GEN_LOAD_REG_TN(T1, rt);
512         op_ldst(lwr);
513         GEN_STORE_TN_REG(rt, T0);
514         opn = "lwr";
515         break;
516     case OPC_SWR:
517         GEN_LOAD_REG_TN(T1, rt);
518         op_ldst(swr);
519         opn = "swr";
520         break;
521     case OPC_LL:
522         op_ldst(ll);
523         GEN_STORE_TN_REG(rt, T0);
524         opn = "ll";
525         break;
526     case OPC_SC:
527         GEN_LOAD_REG_TN(T1, rt);
528         op_ldst(sc);
529         GEN_STORE_TN_REG(rt, T0);
530         opn = "sc";
531         break;
532     default:
533         MIPS_INVAL("load/store");
534         generate_exception(ctx, EXCP_RI);
535         return;
536     }
537     MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
538 }
539
540 /* Arithmetic with immediate operand */
541 static void gen_arith_imm (DisasContext *ctx, uint16_t opc, int rt,
542                            int rs, int16_t imm)
543 {
544     uint32_t uimm;
545     const unsigned char *opn = "unk";
546
547     if (rt == 0 && opc != OPC_ADDI) {
548         /* if no destination, treat it as a NOP 
549          * For addi, we must generate the overflow exception when needed.
550          */
551         MIPS_DEBUG("NOP");
552         return;
553     }
554     if (opc == OPC_ADDI || opc == OPC_ADDIU ||
555         opc == OPC_SLTI || opc == OPC_SLTIU)
556         uimm = (int32_t)imm; /* Sign extent to 32 bits */
557     else
558         uimm = (uint16_t)imm;
559     if (opc != OPC_LUI) {
560         GEN_LOAD_REG_TN(T0, rs);
561         GEN_LOAD_IMM_TN(T1, uimm);
562     } else {
563         uimm = uimm << 16;
564         GEN_LOAD_IMM_TN(T0, uimm);
565     }
566     switch (opc) {
567     case OPC_ADDI:
568         save_cpu_state(ctx, 1);
569         gen_op_addo();
570         opn = "addi";
571         break;
572     case OPC_ADDIU:
573         gen_op_add();
574         opn = "addiu";
575         break;
576     case OPC_SLTI:
577         gen_op_lt();
578         opn = "slti";
579         break;
580     case OPC_SLTIU:
581         gen_op_ltu();
582         opn = "sltiu";
583         break;
584     case OPC_ANDI:
585         gen_op_and();
586         opn = "andi";
587         break;
588     case OPC_ORI:
589         gen_op_or();
590         opn = "ori";
591         break;
592     case OPC_XORI:
593         gen_op_xor();
594         opn = "xori";
595         break;
596     case OPC_LUI:
597         opn = "lui";
598         break;
599     case OPC_SLL:
600         gen_op_sll();
601         opn = "sll";
602         break;
603     case OPC_SRA:
604         gen_op_sra();
605         opn = "sra";
606         break;
607     case OPC_SRL:
608         gen_op_srl();
609         opn = "srl";
610         break;
611     default:
612         MIPS_INVAL("imm arith");
613         generate_exception(ctx, EXCP_RI);
614         return;
615     }
616     GEN_STORE_TN_REG(rt, T0);
617     MIPS_DEBUG("%s %s, %s, %x", opn, regnames[rt], regnames[rs], uimm);
618 }
619
620 /* Arithmetic */
621 static void gen_arith (DisasContext *ctx, uint16_t opc,
622                        int rd, int rs, int rt)
623 {
624     const unsigned char *opn = "unk";
625
626     if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB) {
627         /* if no destination, treat it as a NOP 
628          * For add & sub, we must generate the overflow exception when needed.
629          */
630         MIPS_DEBUG("NOP");
631         return;
632     }
633     GEN_LOAD_REG_TN(T0, rs);
634     GEN_LOAD_REG_TN(T1, rt);
635     switch (opc) {
636     case OPC_ADD:
637         save_cpu_state(ctx, 1);
638         gen_op_addo();
639         opn = "add";
640         break;
641     case OPC_ADDU:
642         gen_op_add();
643         opn = "addu";
644         break;
645     case OPC_SUB:
646         save_cpu_state(ctx, 1);
647         gen_op_subo();
648         opn = "sub";
649         break;
650     case OPC_SUBU:
651         gen_op_sub();
652         opn = "subu";
653         break;
654     case OPC_SLT:
655         gen_op_lt();
656         opn = "slt";
657         break;
658     case OPC_SLTU:
659         gen_op_ltu();
660         opn = "sltu";
661         break;
662     case OPC_AND:
663         gen_op_and();
664         opn = "and";
665         break;
666     case OPC_NOR:
667         gen_op_nor();
668         opn = "nor";
669         break;
670     case OPC_OR:
671         gen_op_or();
672         opn = "or";
673         break;
674     case OPC_XOR:
675         gen_op_xor();
676         opn = "xor";
677         break;
678     case OPC_MUL:
679         gen_op_mul();
680         opn = "mul";
681         break;
682     case OPC_MOVN:
683         gen_op_movn(rd);
684         opn = "movn";
685         goto print;
686     case OPC_MOVZ:
687         gen_op_movz(rd);
688         opn = "movz";
689         goto print;
690     case OPC_SLLV:
691         gen_op_sllv();
692         opn = "sllv";
693         break;
694     case OPC_SRAV:
695         gen_op_srav();
696         opn = "srav";
697         break;
698     case OPC_SRLV:
699         gen_op_srlv();
700         opn = "srlv";
701         break;
702     default:
703         MIPS_INVAL("arith");
704         generate_exception(ctx, EXCP_RI);
705         return;
706     }
707     GEN_STORE_TN_REG(rd, T0);
708  print:
709     MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
710 }
711
712 /* Arithmetic on HI/LO registers */
713 static void gen_HILO (DisasContext *ctx, uint16_t opc, int reg)
714 {
715     const unsigned char *opn = "unk";
716
717     if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
718         /* Treat as a NOP */
719         MIPS_DEBUG("NOP");
720         return;
721     }
722     switch (opc) {
723     case OPC_MFHI:
724         gen_op_load_HI();
725         GEN_STORE_TN_REG(reg, T0);
726         opn = "mfhi";
727         break;
728     case OPC_MFLO:
729         gen_op_load_LO();
730         GEN_STORE_TN_REG(reg, T0);
731         opn = "mflo";
732         break;
733     case OPC_MTHI:
734         GEN_LOAD_REG_TN(T0, reg);
735         gen_op_store_HI();
736         opn = "mthi";
737         break;
738     case OPC_MTLO:
739         GEN_LOAD_REG_TN(T0, reg);
740         gen_op_store_LO();
741         opn = "mtlo";
742         break;
743     default:
744         MIPS_INVAL("HILO");
745         generate_exception(ctx, EXCP_RI);
746         return;
747     }
748     MIPS_DEBUG("%s %s", opn, regnames[reg]);
749 }
750
751 static void gen_muldiv (DisasContext *ctx, uint16_t opc,
752                         int rs, int rt)
753 {
754     const unsigned char *opn = "unk";
755
756     GEN_LOAD_REG_TN(T0, rs);
757     GEN_LOAD_REG_TN(T1, rt);
758     switch (opc) {
759     case OPC_DIV:
760         gen_op_div();
761         opn = "div";
762         break;
763     case OPC_DIVU:
764         gen_op_divu();
765         opn = "divu";
766         break;
767     case OPC_MULT:
768         gen_op_mult();
769         opn = "mult";
770         break;
771     case OPC_MULTU:
772         gen_op_multu();
773         opn = "multu";
774         break;
775     case OPC_MADD:
776         gen_op_madd();
777         opn = "madd";
778         break;
779     case OPC_MADDU:
780         gen_op_maddu();
781         opn = "maddu";
782         break;
783     case OPC_MSUB:
784         gen_op_msub();
785         opn = "msub";
786         break;
787     case OPC_MSUBU:
788         gen_op_msubu();
789         opn = "msubu";
790         break;
791     default:
792         MIPS_INVAL("mul/div");
793         generate_exception(ctx, EXCP_RI);
794         return;
795     }
796     MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
797 }
798
799 static void gen_cl (DisasContext *ctx, uint16_t opc,
800                     int rd, int rs)
801 {
802     const unsigned char *opn = "unk";
803     if (rd == 0) {
804         /* Treat as a NOP */
805         MIPS_DEBUG("NOP");
806         return;
807     }
808     GEN_LOAD_REG_TN(T0, rs);
809     switch (opc) {
810     case OPC_CLO:
811         /* CLO */
812         gen_op_clo();
813         opn = "clo";
814         break;
815     case OPC_CLZ:
816         /* CLZ */
817         gen_op_clz();
818         opn = "clz";
819         break;
820     default:
821         MIPS_INVAL("CLx");
822         generate_exception(ctx, EXCP_RI);
823         return;
824     }
825     gen_op_store_T0_gpr(rd);
826     MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
827 }
828
829 /* Traps */
830 static void gen_trap (DisasContext *ctx, uint16_t opc,
831                       int rs, int rt, int16_t imm)
832 {
833     int cond;
834
835     cond = 0;
836     /* Load needed operands */
837     switch (opc) {
838     case OPC_TEQ:
839     case OPC_TGE:
840     case OPC_TGEU:
841     case OPC_TLT:
842     case OPC_TLTU:
843     case OPC_TNE:
844         /* Compare two registers */
845         if (rs != rt) {
846             GEN_LOAD_REG_TN(T0, rs);
847             GEN_LOAD_REG_TN(T1, rt);
848             cond = 1;
849         }
850     case OPC_TEQI:
851     case OPC_TGEI:
852     case OPC_TGEIU:
853     case OPC_TLTI:
854     case OPC_TLTIU:
855     case OPC_TNEI:
856         /* Compare register to immediate */
857         if (rs != 0 || imm != 0) {
858             GEN_LOAD_REG_TN(T0, rs);
859             GEN_LOAD_IMM_TN(T1, (int32_t)imm);
860             cond = 1;
861         }
862         break;
863     }
864     if (cond == 0) {
865         switch (opc) {
866         case OPC_TEQ:   /* rs == rs */
867         case OPC_TEQI:  /* r0 == 0  */
868         case OPC_TGE:   /* rs >= rs */
869         case OPC_TGEI:  /* r0 >= 0  */
870         case OPC_TGEU:  /* rs >= rs unsigned */
871         case OPC_TGEIU: /* r0 >= 0  unsigned */
872             /* Always trap */
873             gen_op_set_T0(1);
874             break;
875         case OPC_TLT:   /* rs < rs           */
876         case OPC_TLTI:  /* r0 < 0            */
877         case OPC_TLTU:  /* rs < rs unsigned  */
878         case OPC_TLTIU: /* r0 < 0  unsigned  */
879         case OPC_TNE:   /* rs != rs          */
880         case OPC_TNEI:  /* r0 != 0           */
881             /* Never trap: treat as NOP */
882             return;
883         default:
884             MIPS_INVAL("TRAP");
885             generate_exception(ctx, EXCP_RI);
886             return;
887         }
888     } else {
889         switch (opc) {
890         case OPC_TEQ:
891         case OPC_TEQI:
892             gen_op_eq();
893             break;
894         case OPC_TGE:
895         case OPC_TGEI:
896             gen_op_ge();
897             break;
898         case OPC_TGEU:
899         case OPC_TGEIU:
900             gen_op_geu();
901             break;
902         case OPC_TLT:
903         case OPC_TLTI:
904             gen_op_lt();
905             break;
906         case OPC_TLTU:
907         case OPC_TLTIU:
908             gen_op_ltu();
909             break;
910         case OPC_TNE:
911         case OPC_TNEI:
912             gen_op_ne();
913             break;
914         default:
915             MIPS_INVAL("TRAP");
916             generate_exception(ctx, EXCP_RI);
917             return;
918         }
919     }
920     save_cpu_state(ctx, 1);
921     gen_op_trap();
922     ctx->bstate = BS_STOP;
923 }
924
925 /* Branches (before delay slot) */
926 static void gen_compute_branch (DisasContext *ctx, uint16_t opc,
927                                 int rs, int rt, int32_t offset)
928 {
929     target_ulong btarget;
930     int blink, bcond;
931
932     btarget = -1;
933     blink = 0;
934     bcond = 0;
935     /* Load needed operands */
936     switch (opc) {
937     case OPC_BEQ:
938     case OPC_BEQL:
939     case OPC_BNE:
940     case OPC_BNEL:
941         /* Compare two registers */
942         if (rs != rt) {
943             GEN_LOAD_REG_TN(T0, rs);
944             GEN_LOAD_REG_TN(T1, rt);
945             bcond = 1;
946         }
947         btarget = ctx->pc + 4 + offset;
948         break;
949     case OPC_BGEZ:
950     case OPC_BGEZAL:
951     case OPC_BGEZALL:
952     case OPC_BGEZL:
953     case OPC_BGTZ:
954     case OPC_BGTZL:
955     case OPC_BLEZ:
956     case OPC_BLEZL:
957     case OPC_BLTZ:
958     case OPC_BLTZAL:
959     case OPC_BLTZALL:
960     case OPC_BLTZL:
961         /* Compare to zero */
962         if (rs != 0) {
963             gen_op_load_gpr_T0(rs);
964             bcond = 1;
965         }
966         btarget = ctx->pc + 4 + offset;
967         break;
968     case OPC_J:
969     case OPC_JAL:
970         /* Jump to immediate */
971         btarget = ((ctx->pc + 4) & 0xF0000000) | offset;
972         break;
973     case OPC_JR:
974     case OPC_JALR:
975         /* Jump to register */
976         if (offset != 0) {
977             /* Only hint = 0 is valid */
978             generate_exception(ctx, EXCP_RI);
979             return;
980         }
981         GEN_LOAD_REG_TN(T2, rs);
982         break;
983     default:
984         MIPS_INVAL("branch/jump");
985         generate_exception(ctx, EXCP_RI);
986         return;
987     }
988     if (bcond == 0) {
989         /* No condition to be computed */
990         switch (opc) {
991         case OPC_BEQ:     /* rx == rx        */
992         case OPC_BEQL:    /* rx == rx likely */
993         case OPC_BGEZ:    /* 0 >= 0          */
994         case OPC_BGEZL:   /* 0 >= 0 likely   */
995         case OPC_BLEZ:    /* 0 <= 0          */
996         case OPC_BLEZL:   /* 0 <= 0 likely   */
997             /* Always take */
998             ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B;
999             MIPS_DEBUG("balways");
1000             break;
1001         case OPC_BGEZAL:  /* 0 >= 0          */
1002         case OPC_BGEZALL: /* 0 >= 0 likely   */
1003             /* Always take and link */
1004             blink = 31;
1005             ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B;
1006             MIPS_DEBUG("balways and link");
1007             break;
1008         case OPC_BNE:     /* rx != rx        */
1009         case OPC_BGTZ:    /* 0 > 0           */
1010         case OPC_BLTZ:    /* 0 < 0           */
1011         case OPC_BLTZAL:  /* 0 < 0           */
1012             /* Treated as NOP */
1013             MIPS_DEBUG("bnever (NOP)");
1014             return;
1015         case OPC_BNEL:    /* rx != rx likely */
1016         case OPC_BGTZL:   /* 0 > 0 likely */
1017         case OPC_BLTZALL: /* 0 < 0 likely */
1018         case OPC_BLTZL:   /* 0 < 0 likely */
1019             /* Skip the instruction in the delay slot */
1020             MIPS_DEBUG("bnever and skip");
1021             gen_op_branch((long)ctx->tb, ctx->pc + 4);
1022             return;
1023         case OPC_J:
1024             ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B;
1025             MIPS_DEBUG("j %08x", btarget);
1026             break;
1027         case OPC_JAL:
1028             blink = 31;
1029             ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B;
1030             MIPS_DEBUG("jal %08x", btarget);
1031             break;
1032         case OPC_JR:
1033             ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BR;
1034             MIPS_DEBUG("jr %s", regnames[rs]);
1035             break;
1036         case OPC_JALR:
1037             blink = rt;
1038             ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BR;
1039             MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
1040             break;
1041         default:
1042             MIPS_INVAL("branch/jump");
1043             generate_exception(ctx, EXCP_RI);
1044             return;
1045         }
1046     } else {
1047         switch (opc) {
1048         case OPC_BEQ:
1049             gen_op_eq();
1050             MIPS_DEBUG("beq %s, %s, %08x",
1051                        regnames[rs], regnames[rt], btarget);
1052             goto not_likely;
1053         case OPC_BEQL:
1054             gen_op_eq();
1055             MIPS_DEBUG("beql %s, %s, %08x",
1056                        regnames[rs], regnames[rt], btarget);
1057             goto likely;
1058         case OPC_BNE:
1059             gen_op_ne();
1060             MIPS_DEBUG("bne %s, %s, %08x",
1061                        regnames[rs], regnames[rt], btarget);
1062             goto not_likely;
1063         case OPC_BNEL:
1064             gen_op_ne();
1065             MIPS_DEBUG("bnel %s, %s, %08x",
1066                        regnames[rs], regnames[rt], btarget);
1067             goto likely;
1068         case OPC_BGEZ:
1069             gen_op_gez();
1070             MIPS_DEBUG("bgez %s, %08x", regnames[rs], btarget);
1071             goto not_likely;
1072         case OPC_BGEZL:
1073             gen_op_gez();
1074             MIPS_DEBUG("bgezl %s, %08x", regnames[rs], btarget);
1075             goto likely;
1076         case OPC_BGEZAL:
1077             gen_op_gez();
1078             MIPS_DEBUG("bgezal %s, %08x", regnames[rs], btarget);
1079             blink = 31;
1080             goto not_likely;
1081         case OPC_BGEZALL:
1082             gen_op_gez();
1083             blink = 31;
1084             MIPS_DEBUG("bgezall %s, %08x", regnames[rs], btarget);
1085             goto likely;
1086         case OPC_BGTZ:
1087             gen_op_gtz();
1088             MIPS_DEBUG("bgtz %s, %08x", regnames[rs], btarget);
1089             goto not_likely;
1090         case OPC_BGTZL:
1091             gen_op_gtz();
1092             MIPS_DEBUG("bgtzl %s, %08x", regnames[rs], btarget);
1093             goto likely;
1094         case OPC_BLEZ:
1095             gen_op_lez();
1096             MIPS_DEBUG("blez %s, %08x", regnames[rs], btarget);
1097             goto not_likely;
1098         case OPC_BLEZL:
1099             gen_op_lez();
1100             MIPS_DEBUG("blezl %s, %08x", regnames[rs], btarget);
1101             goto likely;
1102         case OPC_BLTZ:
1103             gen_op_ltz();
1104             MIPS_DEBUG("bltz %s, %08x", regnames[rs], btarget);
1105             goto not_likely;
1106         case OPC_BLTZL:
1107             gen_op_ltz();
1108             MIPS_DEBUG("bltzl %s, %08x", regnames[rs], btarget);
1109             goto likely;
1110         case OPC_BLTZAL:
1111             gen_op_ltz();
1112             blink = 31;
1113             MIPS_DEBUG("bltzal %s, %08x", regnames[rs], btarget);
1114         not_likely:
1115             ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BC;
1116             break;
1117         case OPC_BLTZALL:
1118             gen_op_ltz();
1119             blink = 31;
1120             MIPS_DEBUG("bltzall %s, %08x", regnames[rs], btarget);
1121         likely:
1122             ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_BL;
1123             break;
1124         }
1125         gen_op_set_bcond();
1126     }
1127     MIPS_DEBUG("enter ds: link %d cond %02x target %08x",
1128                blink, ctx->hflags, btarget);
1129     ctx->btarget = btarget;
1130     if (blink > 0) {
1131         gen_op_set_T0(ctx->pc + 8);
1132         gen_op_store_T0_gpr(blink);
1133     }
1134     return;
1135 }
1136
1137 /* CP0 (MMU and control) */
1138 static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd)
1139 {
1140     const unsigned char *opn = "unk";
1141
1142     if (!(ctx->CP0_Status & (1 << CP0St_CU0)) &&
1143         !(ctx->hflags & MIPS_HFLAG_UM) &&
1144         !(ctx->hflags & MIPS_HFLAG_ERL) &&
1145         !(ctx->hflags & MIPS_HFLAG_EXL)) {
1146         if (loglevel & CPU_LOG_TB_IN_ASM) {
1147             fprintf(logfile, "CP0 is not usable\n");
1148         }
1149         gen_op_raise_exception_err(EXCP_CpU, 0);
1150         return;
1151     }
1152     switch (opc) {
1153     case OPC_MFC0:
1154         if (rt == 0) {
1155             /* Treat as NOP */
1156             return;
1157         }
1158         gen_op_mfc0(rd, ctx->opcode & 0x7);
1159         gen_op_store_T0_gpr(rt);
1160         opn = "mfc0";
1161         break;
1162     case OPC_MTC0:
1163         /* If we get an exception, we want to restart at next instruction */
1164         ctx->pc += 4;
1165         save_cpu_state(ctx, 1);
1166         ctx->pc -= 4;
1167         GEN_LOAD_REG_TN(T0, rt);
1168         gen_op_mtc0(rd, ctx->opcode & 0x7);
1169         /* Stop translation as we may have switched the execution mode */
1170         ctx->bstate = BS_STOP;
1171         opn = "mtc0";
1172         break;
1173 #if defined(MIPS_USES_R4K_TLB)
1174     case OPC_TLBWI:
1175         gen_op_tlbwi();
1176         opn = "tlbwi";
1177         break;
1178     case OPC_TLBWR:
1179         gen_op_tlbwr();
1180         opn = "tlbwr";
1181         break;
1182     case OPC_TLBP:
1183         gen_op_tlbp();
1184         opn = "tlbp";
1185         break;
1186     case OPC_TLBR:
1187         gen_op_tlbr();
1188         opn = "tlbr";
1189         break;
1190 #endif
1191     case OPC_ERET:
1192         opn = "eret";
1193         save_cpu_state(ctx, 0);
1194         gen_op_eret();
1195         ctx->bstate = BS_EXCP;
1196         break;
1197     case OPC_DERET:
1198         opn = "deret";
1199         if (!(ctx->hflags & MIPS_HFLAG_DM)) {
1200             generate_exception(ctx, EXCP_RI);
1201         } else {
1202             save_cpu_state(ctx, 0);
1203             gen_op_deret();
1204             ctx->bstate = BS_EXCP;
1205         }
1206         break;
1207     /* XXX: TODO: WAIT */
1208     default:
1209         if (loglevel & CPU_LOG_TB_IN_ASM) {
1210             fprintf(logfile, "Invalid CP0 opcode: %08x %03x %03x %03x\n",
1211                     ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
1212                     ((ctx->opcode >> 16) & 0x1F));
1213         }
1214         generate_exception(ctx, EXCP_RI);
1215         return;
1216     }
1217     MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
1218 }
1219
1220 /* Coprocessor 1 (FPU) */
1221
1222 /* ISA extensions */
1223 /* MIPS16 extension to MIPS32 */
1224 /* SmartMIPS extension to MIPS32 */
1225
1226 #ifdef TARGET_MIPS64
1227 static void gen_arith64 (DisasContext *ctx, uint16_t opc)
1228 {
1229     if (func == 0x02 && rd == 0) {
1230         /* NOP */
1231         return;
1232     }
1233     if (rs == 0 || rt == 0) {
1234         gen_op_reset_T0();
1235         gen_op_save64();
1236     } else {
1237         gen_op_load_gpr_T0(rs);
1238         gen_op_load_gpr_T1(rt);
1239         gen_op_save64();
1240         if (func & 0x01)
1241             gen_op_mul64u();
1242         else
1243             gen_op_mul64s();
1244     }
1245     if (func & 0x02)
1246         gen_op_add64();
1247     else
1248         gen_op_sub64();
1249 }
1250
1251 /* Coprocessor 3 (FPU) */
1252
1253 /* MDMX extension to MIPS64 */
1254 /* MIPS-3D extension to MIPS64 */
1255
1256 #endif
1257
1258 static void decode_opc (DisasContext *ctx)
1259 {
1260     int32_t offset;
1261     int rs, rt, rd, sa;
1262     uint16_t op, op1;
1263     int16_t imm;
1264
1265     if ((ctx->hflags & MIPS_HFLAG_DS) &&
1266         (ctx->hflags & MIPS_HFLAG_BL)) {
1267         /* Handle blikely not taken case */
1268         MIPS_DEBUG("blikely condition (%08x)", ctx->pc + 4);
1269         gen_op_blikely((long)ctx->tb, ctx->pc + 4,
1270                        ctx->hflags & ~(MIPS_HFLAG_BMASK | MIPS_HFLAG_DS));
1271     }
1272     op = ctx->opcode >> 26;
1273     rs = ((ctx->opcode >> 21) & 0x1F);
1274     rt = ((ctx->opcode >> 16) & 0x1F);
1275     rd = ((ctx->opcode >> 11) & 0x1F);
1276     sa = ((ctx->opcode >> 6) & 0x1F);
1277     imm = (int16_t)ctx->opcode;
1278     switch (op) {
1279     case 0x00:          /* Special opcode */
1280         op1 = ctx->opcode & 0x3F;
1281         switch (op1) {
1282         case 0x00:          /* Arithmetic with immediate */
1283         case 0x02 ... 0x03:
1284             gen_arith_imm(ctx, op1 | EXT_SPECIAL, rd, rt, sa);
1285             break;
1286         case 0x04:          /* Arithmetic */
1287         case 0x06 ... 0x07:
1288         case 0x0A ... 0x0B:
1289         case 0x20 ... 0x27:
1290         case 0x2A ... 0x2B:
1291             gen_arith(ctx, op1 | EXT_SPECIAL, rd, rs, rt);
1292             break;
1293         case 0x18 ... 0x1B: /* MULT / DIV */
1294             gen_muldiv(ctx, op1 | EXT_SPECIAL, rs, rt);
1295             break;
1296         case 0x08 ... 0x09: /* Jumps */
1297             gen_compute_branch(ctx, op1 | EXT_SPECIAL, rs, rd, sa);
1298             return;
1299         case 0x30 ... 0x34: /* Traps */
1300         case 0x36:
1301             gen_trap(ctx, op1 | EXT_SPECIAL, rs, rt, -1);
1302             break;
1303         case 0x10:          /* Move from HI/LO */
1304         case 0x12:
1305             gen_HILO(ctx, op1 | EXT_SPECIAL, rd);
1306             break;
1307         case 0x11:
1308         case 0x13:          /* Move to HI/LO */
1309             gen_HILO(ctx, op1 | EXT_SPECIAL, rs);
1310             break;
1311         case 0x0C:          /* SYSCALL */
1312             generate_exception(ctx, EXCP_SYSCALL);
1313             break;
1314         case 0x0D:          /* BREAK */
1315             generate_exception(ctx, EXCP_BREAK);
1316             break;
1317         case 0x0F:          /* SYNC */
1318             /* Treat as a noop */
1319             break;
1320         case 0x05:          /* Pmon entry point */
1321             gen_op_pmon((ctx->opcode >> 6) & 0x1F);
1322             break;
1323 #if defined (MIPS_HAS_MOVCI)
1324         case 0x01:          /* MOVCI */
1325 #endif
1326 #if defined (TARGET_MIPS64)
1327         case 0x14: /* MIPS64 specific opcodes */
1328         case 0x16:
1329         case 0x17:
1330         case 0x1C ... 0x1F:
1331         case 0x2C ... 0x2F:
1332         case 0x37:
1333         case 0x39 ... 0x3B:
1334         case 0x3E ... 0x3F:
1335 #endif
1336         default:            /* Invalid */
1337             MIPS_INVAL("special");
1338             generate_exception(ctx, EXCP_RI);
1339             break;
1340         }
1341         break;
1342     case 0x1C:          /* Special2 opcode */
1343         op1 = ctx->opcode & 0x3F;
1344         switch (op1) {
1345 #if defined (MIPS_USES_R4K_EXT)
1346         /* Those instructions are not part of MIPS32 core */
1347         case 0x00 ... 0x01: /* Multiply and add/sub */
1348         case 0x04 ... 0x05:
1349             gen_muldiv(ctx, op1 | EXT_SPECIAL2, rs, rt);
1350             break;
1351         case 0x02:          /* MUL */
1352             gen_arith(ctx, op1 | EXT_SPECIAL2, rd, rs, rt);
1353             break;
1354         case 0x20 ... 0x21: /* CLO / CLZ */
1355             gen_cl(ctx, op1 | EXT_SPECIAL2, rd, rs);
1356             break;
1357 #endif
1358         case 0x3F:          /* SDBBP */
1359             /* XXX: not clear which exception should be raised
1360              *      when in debug mode...
1361              */
1362             if (!(ctx->hflags & MIPS_HFLAG_DM)) {
1363                 generate_exception(ctx, EXCP_DBp);
1364             } else {
1365                 generate_exception(ctx, EXCP_DBp);
1366             }
1367             /* Treat as a noop */
1368             break;
1369         default:            /* Invalid */
1370             MIPS_INVAL("special2");
1371             generate_exception(ctx, EXCP_RI);
1372             break;
1373         }
1374         break;
1375     case 0x01:          /* B REGIMM opcode */
1376         op1 = ((ctx->opcode >> 16) & 0x1F);
1377         switch (op1) {
1378         case 0x00 ... 0x03: /* REGIMM branches */
1379         case 0x10 ... 0x13:
1380             gen_compute_branch(ctx, op1 | EXT_REGIMM, rs, -1, imm << 2);
1381             return;
1382         case 0x08 ... 0x0C: /* Traps */
1383         case 0x0E:
1384             gen_trap(ctx, op1 | EXT_REGIMM, rs, -1, imm);
1385             break;
1386         default:            /* Invalid */
1387             MIPS_INVAL("REGIMM");
1388             generate_exception(ctx, EXCP_RI);
1389             break;
1390         }
1391         break;
1392     case 0x10:          /* CP0 opcode */
1393         op1 = ((ctx->opcode >> 21) & 0x1F);
1394         switch (op1) {
1395         case 0x00:
1396         case 0x04:
1397             gen_cp0(ctx, op1 | EXT_CP0, rt, rd);
1398             break;
1399         default:
1400             gen_cp0(ctx, (ctx->opcode & 0x1F) | EXT_CP0, rt, rd);
1401             break;
1402         }
1403         break;
1404     case 0x08 ... 0x0F: /* Arithmetic with immediate opcode */
1405         gen_arith_imm(ctx, op, rt, rs, imm);
1406         break;
1407     case 0x02 ... 0x03: /* Jump */
1408         offset = (int32_t)(ctx->opcode & 0x03FFFFFF) << 2;
1409         gen_compute_branch(ctx, op, rs, rt, offset);
1410         return;
1411     case 0x04 ... 0x07: /* Branch */
1412     case 0x14 ... 0x17:
1413         gen_compute_branch(ctx, op, rs, rt, imm << 2);
1414         return;
1415     case 0x20 ... 0x26: /* Load and stores */
1416     case 0x28 ... 0x2E:
1417     case 0x30:
1418     case 0x38:
1419         gen_ldst(ctx, op, rt, rs, imm);
1420         break;
1421     case 0x2F:          /* Cache operation */
1422         /* Treat as a noop */
1423         break;
1424     case 0x33:          /* Prefetch */
1425         /* Treat as a noop */
1426         break;
1427     case 0x3F: /* HACK */
1428         break;
1429 #if defined(MIPS_USES_FPU)
1430     case 0x31 ... 0x32: /* Floating point load/store */
1431     case 0x35 ... 0x36:
1432     case 0x3A ... 0x3B:
1433     case 0x3D ... 0x3E:
1434         /* Not implemented */
1435         /* XXX: not correct */
1436 #endif
1437     case 0x11:          /* CP1 opcode */
1438         /* Not implemented */
1439         /* XXX: not correct */
1440     case 0x12:          /* CP2 opcode */
1441         /* Not implemented */
1442         /* XXX: not correct */
1443     case 0x13:          /* CP3 opcode */
1444         /* Not implemented */
1445         /* XXX: not correct */
1446 #if defined (TARGET_MIPS64)
1447     case 0x18 ... 0x1B:
1448     case 0x27:
1449     case 0x34:
1450     case 0x37:
1451         /* MIPS64 opcodes */
1452 #endif
1453 #if defined (MIPS_HAS_JALX)
1454     case 0x1D:
1455         /* JALX: not implemented */
1456 #endif
1457     case 0x1E:
1458         /* ASE specific */
1459 #if defined (MIPS_HAS_LSC)
1460     case 0x31: /* LWC1 */
1461     case 0x32: /* LWC2 */
1462     case 0x35: /* SDC1 */
1463     case 0x36: /* SDC2 */
1464 #endif
1465     default:            /* Invalid */
1466         MIPS_INVAL("");
1467         generate_exception(ctx, EXCP_RI);
1468         break;
1469     }
1470     if (ctx->hflags & MIPS_HFLAG_DS) {
1471         int hflags = ctx->hflags;
1472         /* Branches completion */
1473         ctx->hflags &= ~(MIPS_HFLAG_BMASK | MIPS_HFLAG_DS);
1474         ctx->bstate = BS_BRANCH;
1475         save_cpu_state(ctx, 0);
1476         switch (hflags & MIPS_HFLAG_BMASK) {
1477         case MIPS_HFLAG_B:
1478             /* unconditional branch */
1479             MIPS_DEBUG("unconditional branch");
1480             gen_op_branch((long)ctx->tb, ctx->btarget);
1481             break;
1482         case MIPS_HFLAG_BL:
1483             /* blikely taken case */
1484             MIPS_DEBUG("blikely branch taken");
1485             gen_op_branch((long)ctx->tb, ctx->btarget);
1486             break;
1487         case MIPS_HFLAG_BC:
1488             /* Conditional branch */
1489             MIPS_DEBUG("conditional branch");
1490             gen_op_bcond((long)ctx->tb, ctx->btarget, ctx->pc + 4);
1491             break;
1492         case MIPS_HFLAG_BR:
1493             /* unconditional branch to register */
1494             MIPS_DEBUG("branch to register");
1495             gen_op_breg();
1496             break;
1497         default:
1498             MIPS_DEBUG("unknown branch");
1499             break;
1500         }
1501     }
1502 }
1503
1504 int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
1505                                     int search_pc)
1506 {
1507     DisasContext ctx, *ctxp = &ctx;
1508     target_ulong pc_start;
1509     uint16_t *gen_opc_end;
1510     int j, lj = -1;
1511
1512     pc_start = tb->pc;
1513     gen_opc_ptr = gen_opc_buf;
1514     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1515     gen_opparam_ptr = gen_opparam_buf;
1516     ctx.pc = pc_start;
1517     ctx.tb = tb;
1518     ctx.bstate = BS_NONE;
1519     /* Restore delay slot state */
1520     ctx.hflags = env->hflags;
1521     ctx.saved_hflags = ctx.hflags;
1522     if (ctx.hflags & MIPS_HFLAG_BR) {
1523         gen_op_restore_breg_target();
1524     } else if (ctx.hflags & MIPS_HFLAG_B) {
1525         ctx.btarget = env->btarget;
1526     } else if (ctx.hflags & MIPS_HFLAG_BMASK) {
1527         /* If we are in the delay slot of a conditional branch,
1528          * restore the branch condition from env->bcond to T2
1529          */
1530         ctx.btarget = env->btarget;
1531         gen_op_restore_bcond();
1532     }
1533 #if defined(CONFIG_USER_ONLY)
1534     ctx.mem_idx = 0;
1535 #else
1536     ctx.mem_idx = (ctx.hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM ? 0 : 1;
1537 #endif
1538     ctx.CP0_Status = env->CP0_Status;
1539 #ifdef DEBUG_DISAS
1540     if (loglevel & CPU_LOG_TB_CPU) {
1541         fprintf(logfile, "------------------------------------------------\n");
1542         cpu_dump_state(env, logfile, fprintf, 0);
1543     }
1544 #endif
1545 #if defined MIPS_DEBUG_DISAS
1546     if (loglevel & CPU_LOG_TB_IN_ASM)
1547         fprintf(logfile, "\ntb %p super %d cond %04x %04x\n",
1548                 tb, ctx.mem_idx, ctx.hflags, env->hflags);
1549 #endif
1550     while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
1551         if (search_pc) {
1552             j = gen_opc_ptr - gen_opc_buf;
1553             save_cpu_state(ctxp, 1);
1554             if (lj < j) {
1555                 lj++;
1556                 while (lj < j)
1557                     gen_opc_instr_start[lj++] = 0;
1558                 gen_opc_pc[lj] = ctx.pc;
1559                 gen_opc_instr_start[lj] = 1;
1560             }
1561         }
1562         ctx.opcode = ldl_code(ctx.pc);
1563         decode_opc(&ctx);
1564         ctx.pc += 4;
1565         if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
1566             break;
1567 #if defined (MIPS_SINGLE_STEP)
1568         break;
1569 #endif
1570     }
1571     if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) {
1572         save_cpu_state(ctxp, 0);
1573         gen_op_branch((long)ctx.tb, ctx.pc);
1574     }
1575     gen_op_reset_T0();
1576     /* Generate the return instruction */
1577     gen_op_exit_tb();
1578     *gen_opc_ptr = INDEX_op_end;
1579     if (search_pc) {
1580         j = gen_opc_ptr - gen_opc_buf;
1581         lj++;
1582         while (lj <= j)
1583             gen_opc_instr_start[lj++] = 0;
1584         tb->size = 0;
1585     } else {
1586         tb->size = ctx.pc - pc_start;
1587     }
1588 #ifdef DEBUG_DISAS
1589 #if defined MIPS_DEBUG_DISAS
1590     if (loglevel & CPU_LOG_TB_IN_ASM)
1591         fprintf(logfile, "\n");
1592 #endif
1593     if (loglevel & CPU_LOG_TB_IN_ASM) {
1594         fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
1595         target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
1596         fprintf(logfile, "\n");
1597     }
1598     if (loglevel & CPU_LOG_TB_OP) {
1599         fprintf(logfile, "OP:\n");
1600         dump_ops(gen_opc_buf, gen_opparam_buf);
1601         fprintf(logfile, "\n");
1602     }
1603     if (loglevel & CPU_LOG_TB_CPU) {
1604         fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
1605     }
1606 #endif
1607     
1608     return 0;
1609 }
1610
1611 int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
1612 {
1613     return gen_intermediate_code_internal(env, tb, 0);
1614 }
1615
1616 int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
1617 {
1618     return gen_intermediate_code_internal(env, tb, 1);
1619 }
1620
1621 void cpu_dump_state (CPUState *env, FILE *f, 
1622                      int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1623                      int flags)
1624 {
1625     uint32_t c0_status;
1626     int i;
1627     
1628     cpu_fprintf(f, "pc=0x%08x HI=0x%08x LO=0x%08x ds %04x %08x %d\n",
1629                 env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
1630     for (i = 0; i < 32; i++) {
1631         if ((i & 3) == 0)
1632             cpu_fprintf(f, "GPR%02d:", i);
1633         cpu_fprintf(f, " %s %08x", regnames[i], env->gpr[i]);
1634         if ((i & 3) == 3)
1635             cpu_fprintf(f, "\n");
1636     }
1637
1638     c0_status = env->CP0_Status;
1639     if (env->hflags & MIPS_HFLAG_UM)
1640         c0_status |= (1 << CP0St_UM);
1641     if (env->hflags & MIPS_HFLAG_ERL)
1642         c0_status |= (1 << CP0St_ERL);
1643     if (env->hflags & MIPS_HFLAG_EXL)
1644         c0_status |= (1 << CP0St_EXL);
1645
1646     cpu_fprintf(f, "CP0 Status  0x%08x Cause   0x%08x EPC    0x%08x\n",
1647                 c0_status, env->CP0_Cause, env->CP0_EPC);
1648     cpu_fprintf(f, "    Config0 0x%08x Config1 0x%08x LLAddr 0x%08x\n",
1649                 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
1650 }
1651
1652 CPUMIPSState *cpu_mips_init (void)
1653 {
1654     CPUMIPSState *env;
1655
1656     cpu_exec_init();
1657     env = qemu_mallocz(sizeof(CPUMIPSState));
1658     if (!env)
1659         return NULL;
1660     tlb_flush(env, 1);
1661     /* Minimal init */
1662     env->PC = 0xBFC00000;
1663 #if defined (MIPS_USES_R4K_TLB)
1664     env->CP0_random = MIPS_TLB_NB - 1;
1665 #endif
1666     env->CP0_Wired = 0;
1667     env->CP0_Config0 = MIPS_CONFIG0;
1668 #if defined (MIPS_CONFIG1)
1669         env->CP0_Config1 = MIPS_CONFIG1;
1670 #endif
1671 #if defined (MIPS_CONFIG2)
1672         env->CP0_Config2 = MIPS_CONFIG2;
1673 #endif
1674 #if defined (MIPS_CONFIG3)
1675         env->CP0_Config3 = MIPS_CONFIG3;
1676 #endif
1677     env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV);
1678     env->CP0_WatchLo = 0;
1679     env->hflags = MIPS_HFLAG_ERL;
1680     /* Count register increments in debug mode, EJTAG version 1 */
1681     env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
1682     env->CP0_PRid = MIPS_CPU;
1683     env->exception_index = EXCP_NONE;
1684
1685     cpu_single_env = env;
1686
1687     return env;
1688 }
This page took 0.118509 seconds and 4 git commands to generate.