Commit 5a5012ecbdcd341bb1d2e8200db91f6212aa44df

Authored by ths
1 parent 8b4af705

MIPS 64-bit FPU support, plus some collateral bugfixes in the

conditional branch handling.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2779 c046a42c-6fe2-441c-8c8c-71466251a162
Changelog
@@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
4 - ds1225y nvram support (Herve Poussineau) 4 - ds1225y nvram support (Herve Poussineau)
5 - CPU model selection support (J. Mayer, Paul Brook, Herve Poussineau) 5 - CPU model selection support (J. Mayer, Paul Brook, Herve Poussineau)
6 - Several Sparc fixes (Aurelien Jarno, Blue Swirl) 6 - Several Sparc fixes (Aurelien Jarno, Blue Swirl)
  7 + - MIPS 64-bit FPU support (Thiemo Seufer)
7 8
8 version 0.9.0: 9 version 0.9.0:
9 10
gdbstub.c
@@ -575,7 +575,7 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf) @@ -575,7 +575,7 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
575 { 575 {
576 for (i = 0; i < 32; i++) 576 for (i = 0; i < 32; i++)
577 { 577 {
578 - *(uint32_t *)ptr = tswapl(FPR_W (env, i)); 578 + *(uint32_t *)ptr = tswapl(env->fpr[i].fs[FP_ENDIAN_IDX]);
579 ptr += 4; 579 ptr += 4;
580 } 580 }
581 581
@@ -637,7 +637,7 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size) @@ -637,7 +637,7 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
637 { 637 {
638 for (i = 0; i < 32; i++) 638 for (i = 0; i < 32; i++)
639 { 639 {
640 - FPR_W (env, i) = tswapl(*(uint32_t *)ptr); 640 + env->fpr[i].fs[FP_ENDIAN_IDX] = tswapl(*(uint32_t *)ptr);
641 ptr += 4; 641 ptr += 4;
642 } 642 }
643 643
target-mips/TODO
@@ -10,11 +10,12 @@ General @@ -10,11 +10,12 @@ General
10 when the Qemu FPU emulation is disabled. Also gdb inside the emulated 10 when the Qemu FPU emulation is disabled. Also gdb inside the emulated
11 system does not work. Both problems are caused by insufficient 11 system does not work. Both problems are caused by insufficient
12 handling of self-modifying code. 12 handling of self-modifying code.
  13 +- Floating point exception emulation is incomplete.
13 14
14 MIPS64 15 MIPS64
15 ------ 16 ------
16 - No 64bit TLB support 17 - No 64bit TLB support
17 -- no 64bit wide registers for FPU 18 +- 64bit FPU not fully implemented
18 - 64bit mul/div handling broken 19 - 64bit mul/div handling broken
19 20
20 "Generic" 4Kc system emulation 21 "Generic" 4Kc system emulation
target-mips/cpu.h
@@ -21,7 +21,7 @@ typedef union fpr_t fpr_t; @@ -21,7 +21,7 @@ typedef union fpr_t fpr_t;
21 union fpr_t { 21 union fpr_t {
22 float64 fd; /* ieee double precision */ 22 float64 fd; /* ieee double precision */
23 float32 fs[2];/* ieee single precision */ 23 float32 fs[2];/* ieee single precision */
24 - uint64_t d; /* binary single fixed-point */ 24 + uint64_t d; /* binary double fixed-point */
25 uint32_t w[2]; /* binary single fixed-point */ 25 uint32_t w[2]; /* binary single fixed-point */
26 }; 26 };
27 /* define FP_ENDIAN_IDX to access the same location 27 /* define FP_ENDIAN_IDX to access the same location
@@ -64,31 +64,35 @@ struct CPUMIPSState { @@ -64,31 +64,35 @@ struct CPUMIPSState {
64 target_ulong HI, LO; 64 target_ulong HI, LO;
65 /* Floating point registers */ 65 /* Floating point registers */
66 fpr_t fpr[32]; 66 fpr_t fpr[32];
67 -#define FPR(cpu, n) ((fpr_t*)&(cpu)->fpr[(n) / 2])  
68 -#define FPR_FD(cpu, n) (FPR(cpu, n)->fd)  
69 -#define FPR_FS(cpu, n) (FPR(cpu, n)->fs[((n) & 1) ^ FP_ENDIAN_IDX])  
70 -#define FPR_D(cpu, n) (FPR(cpu, n)->d)  
71 -#define FPR_W(cpu, n) (FPR(cpu, n)->w[((n) & 1) ^ FP_ENDIAN_IDX])  
72 -  
73 #ifndef USE_HOST_FLOAT_REGS 67 #ifndef USE_HOST_FLOAT_REGS
74 fpr_t ft0; 68 fpr_t ft0;
75 fpr_t ft1; 69 fpr_t ft1;
76 fpr_t ft2; 70 fpr_t ft2;
77 #endif 71 #endif
78 float_status fp_status; 72 float_status fp_status;
79 - /* fpu implementation/revision register */ 73 + /* fpu implementation/revision register (fir) */
80 uint32_t fcr0; 74 uint32_t fcr0;
  75 +#define FCR0_F64 22
  76 +#define FCR0_L 21
  77 +#define FCR0_W 20
  78 +#define FCR0_3D 19
  79 +#define FCR0_PS 18
  80 +#define FCR0_D 17
  81 +#define FCR0_S 16
  82 +#define FCR0_PRID 8
  83 +#define FCR0_REV 0
81 /* fcsr */ 84 /* fcsr */
82 uint32_t fcr31; 85 uint32_t fcr31;
83 -#define SET_FP_COND(reg) do { (reg) |= (1<<23); } while(0)  
84 -#define CLEAR_FP_COND(reg) do { (reg) &= ~(1<<23); } while(0)  
85 -#define IS_FP_COND_SET(reg) (((reg) & (1<<23)) != 0)  
86 -#define GET_FP_CAUSE(reg) (((reg) >> 12) & 0x3f)  
87 -#define GET_FP_ENABLE(reg) (((reg) >> 7) & 0x1f)  
88 -#define GET_FP_FLAGS(reg) (((reg) >> 2) & 0x1f)  
89 -#define SET_FP_CAUSE(reg,v) do { (reg) = ((reg) & ~(0x3f << 12)) | ((v) << 12); } while(0)  
90 -#define SET_FP_ENABLE(reg,v) do { (reg) = ((reg) & ~(0x1f << 7)) | ((v) << 7); } while(0)  
91 -#define SET_FP_FLAGS(reg,v) do { (reg) = ((reg) & ~(0x1f << 2)) | ((v) << 2); } while(0) 86 +#define SET_FP_COND(num,env) do { (env->fcr31) |= ((num) ? (1 << ((num) + 24)) : (1 << ((num) + 23))); } while(0)
  87 +#define CLEAR_FP_COND(num,env) do { (env->fcr31) &= ~((num) ? (1 << ((num) + 24)) : (1 << ((num) + 23))); } while(0)
  88 +#define IS_FP_COND_SET(num,env) (((env->fcr31) & ((num) ? (1 << ((num) + 24)) : (1 << ((num) + 23)))) != 0)
  89 +#define GET_FP_CAUSE(reg) (((reg) >> 12) & 0x3f)
  90 +#define GET_FP_ENABLE(reg) (((reg) >> 7) & 0x1f)
  91 +#define GET_FP_FLAGS(reg) (((reg) >> 2) & 0x1f)
  92 +#define SET_FP_CAUSE(reg,v) do { (reg) = ((reg) & ~(0x3f << 12)) | ((v & 0x3f) << 12); } while(0)
  93 +#define SET_FP_ENABLE(reg,v) do { (reg) = ((reg) & ~(0x1f << 7)) | ((v & 0x1f) << 7); } while(0)
  94 +#define SET_FP_FLAGS(reg,v) do { (reg) = ((reg) & ~(0x1f << 2)) | ((v & 0x1f) << 2); } while(0)
  95 +#define UPDATE_FP_FLAGS(reg,v) do { (reg) |= ((v & 0x1f) << 2); } while(0)
92 #define FP_INEXACT 1 96 #define FP_INEXACT 1
93 #define FP_UNDERFLOW 2 97 #define FP_UNDERFLOW 2
94 #define FP_OVERFLOW 4 98 #define FP_OVERFLOW 4
@@ -267,6 +271,7 @@ struct CPUMIPSState { @@ -267,6 +271,7 @@ struct CPUMIPSState {
267 271
268 int SYNCI_Step; /* Address step size for SYNCI */ 272 int SYNCI_Step; /* Address step size for SYNCI */
269 int CCRes; /* Cycle count resolution/divisor */ 273 int CCRes; /* Cycle count resolution/divisor */
  274 + int Status_rw_bitmask; /* Read/write bits in CP0_Status */
270 275
271 #if defined(CONFIG_USER_ONLY) 276 #if defined(CONFIG_USER_ONLY)
272 target_ulong tls_value; 277 target_ulong tls_value;
@@ -330,10 +335,11 @@ enum { @@ -330,10 +335,11 @@ enum {
330 EXCP_RI, 335 EXCP_RI,
331 EXCP_OVERFLOW, 336 EXCP_OVERFLOW,
332 EXCP_TRAP, 337 EXCP_TRAP,
  338 + EXCP_FPE,
333 EXCP_DDBS, 339 EXCP_DDBS,
334 EXCP_DWATCH, 340 EXCP_DWATCH,
335 - EXCP_LAE,  
336 - EXCP_SAE, /* 24 */ 341 + EXCP_LAE, /* 24 */
  342 + EXCP_SAE,
337 EXCP_LTLBL, 343 EXCP_LTLBL,
338 EXCP_TLBL, 344 EXCP_TLBL,
339 EXCP_TLBS, 345 EXCP_TLBS,
target-mips/exec.h
@@ -29,12 +29,18 @@ register target_ulong T2 asm(AREG3); @@ -29,12 +29,18 @@ register target_ulong T2 asm(AREG3);
29 #define FST0 (env->ft0.fs[FP_ENDIAN_IDX]) 29 #define FST0 (env->ft0.fs[FP_ENDIAN_IDX])
30 #define FST1 (env->ft1.fs[FP_ENDIAN_IDX]) 30 #define FST1 (env->ft1.fs[FP_ENDIAN_IDX])
31 #define FST2 (env->ft2.fs[FP_ENDIAN_IDX]) 31 #define FST2 (env->ft2.fs[FP_ENDIAN_IDX])
  32 +#define FSTH0 (env->ft0.fs[!FP_ENDIAN_IDX])
  33 +#define FSTH1 (env->ft1.fs[!FP_ENDIAN_IDX])
  34 +#define FSTH2 (env->ft2.fs[!FP_ENDIAN_IDX])
32 #define DT0 (env->ft0.d) 35 #define DT0 (env->ft0.d)
33 #define DT1 (env->ft1.d) 36 #define DT1 (env->ft1.d)
34 #define DT2 (env->ft2.d) 37 #define DT2 (env->ft2.d)
35 #define WT0 (env->ft0.w[FP_ENDIAN_IDX]) 38 #define WT0 (env->ft0.w[FP_ENDIAN_IDX])
36 #define WT1 (env->ft1.w[FP_ENDIAN_IDX]) 39 #define WT1 (env->ft1.w[FP_ENDIAN_IDX])
37 #define WT2 (env->ft2.w[FP_ENDIAN_IDX]) 40 #define WT2 (env->ft2.w[FP_ENDIAN_IDX])
  41 +#define WTH0 (env->ft0.w[!FP_ENDIAN_IDX])
  42 +#define WTH1 (env->ft1.w[!FP_ENDIAN_IDX])
  43 +#define WTH2 (env->ft2.w[!FP_ENDIAN_IDX])
38 #endif 44 #endif
39 45
40 #if defined (DEBUG_OP) 46 #if defined (DEBUG_OP)
target-mips/fop_template.c
@@ -19,75 +19,103 @@ @@ -19,75 +19,103 @@
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */ 20 */
21 21
22 -#if defined(SFREG) 22 +#if defined(FREG)
23 23
24 -#define OP_WLOAD_FREG(treg, tregname, SFREG) \  
25 - void glue(glue(op_load_fpr_,tregname), SFREG) (void) \  
26 - { \  
27 - treg = FPR_W(env, SFREG); \  
28 - RETURN(); \ 24 +#define OP_WLOAD_FREG(treg, tregname, FREG) \
  25 + void glue(glue(op_load_fpr_,tregname), FREG) (void) \
  26 + { \
  27 + treg = env->fpr[FREG].fs[FP_ENDIAN_IDX]; \
  28 + RETURN(); \
29 } 29 }
30 30
31 -#define OP_WSTORE_FREG(treg, tregname, SFREG) \  
32 - void glue(glue(op_store_fpr_,tregname), SFREG) (void)\  
33 - { \  
34 - FPR_W(env, SFREG) = treg; \  
35 - RETURN(); \ 31 +#define OP_WSTORE_FREG(treg, tregname, FREG) \
  32 + void glue(glue(op_store_fpr_,tregname), FREG) (void) \
  33 + { \
  34 + env->fpr[FREG].fs[FP_ENDIAN_IDX] = treg; \
  35 + RETURN(); \
36 } 36 }
37 37
38 -/* WT0 = SFREG.w: op_load_fpr_WT0_fprSFREG */  
39 -OP_WLOAD_FREG(WT0, WT0_fpr, SFREG)  
40 -/* SFREG.w = WT0: op_store_fpr_WT0_fprSFREG */  
41 -OP_WSTORE_FREG(WT0, WT0_fpr, SFREG) 38 +/* WT0 = FREG.w: op_load_fpr_WT0_fprFREG */
  39 +OP_WLOAD_FREG(WT0, WT0_fpr, FREG)
  40 +/* FREG.w = WT0: op_store_fpr_WT0_fprFREG */
  41 +OP_WSTORE_FREG(WT0, WT0_fpr, FREG)
  42 +
  43 +OP_WLOAD_FREG(WT1, WT1_fpr, FREG)
  44 +OP_WSTORE_FREG(WT1, WT1_fpr, FREG)
  45 +
  46 +OP_WLOAD_FREG(WT2, WT2_fpr, FREG)
  47 +OP_WSTORE_FREG(WT2, WT2_fpr, FREG)
  48 +
  49 +#define OP_DLOAD_FREG(treg, tregname, FREG) \
  50 + void glue(glue(op_load_fpr_,tregname), FREG) (void) \
  51 + { \
  52 + if (env->CP0_Status & (1 << CP0St_FR)) \
  53 + treg = env->fpr[FREG].fd; \
  54 + else \
  55 + treg = (uint64_t)(env->fpr[FREG | 1].fs[FP_ENDIAN_IDX]) << 32 | \
  56 + env->fpr[FREG & ~1].fs[FP_ENDIAN_IDX]; \
  57 + RETURN(); \
  58 + }
42 59
43 -OP_WLOAD_FREG(WT1, WT1_fpr, SFREG)  
44 -OP_WSTORE_FREG(WT1, WT1_fpr, SFREG) 60 +#define OP_DSTORE_FREG(treg, tregname, FREG) \
  61 + void glue(glue(op_store_fpr_,tregname), FREG) (void) \
  62 + { \
  63 + if (env->CP0_Status & (1 << CP0St_FR)) \
  64 + env->fpr[FREG].fd = treg; \
  65 + else { \
  66 + env->fpr[FREG | 1].fs[FP_ENDIAN_IDX] = treg >> 32; \
  67 + env->fpr[FREG & ~1].fs[FP_ENDIAN_IDX] = treg; \
  68 + } \
  69 + RETURN(); \
  70 + }
45 71
46 -OP_WLOAD_FREG(WT2, WT2_fpr, SFREG)  
47 -OP_WSTORE_FREG(WT2, WT2_fpr, SFREG) 72 +OP_DLOAD_FREG(DT0, DT0_fpr, FREG)
  73 +OP_DSTORE_FREG(DT0, DT0_fpr, FREG)
48 74
49 -#endif 75 +OP_DLOAD_FREG(DT1, DT1_fpr, FREG)
  76 +OP_DSTORE_FREG(DT1, DT1_fpr, FREG)
50 77
51 -#if defined(DFREG) 78 +OP_DLOAD_FREG(DT2, DT2_fpr, FREG)
  79 +OP_DSTORE_FREG(DT2, DT2_fpr, FREG)
52 80
53 -#define OP_DLOAD_FREG(treg, tregname, DFREG) \  
54 - void glue(glue(op_load_fpr_,tregname), DFREG) (void) \  
55 - { \  
56 - treg = FPR_D(env, DFREG); \  
57 - RETURN(); \ 81 +#define OP_PSLOAD_FREG(treg, tregname, FREG) \
  82 + void glue(glue(op_load_fpr_,tregname), FREG) (void) \
  83 + { \
  84 + treg = env->fpr[FREG].fs[!FP_ENDIAN_IDX]; \
  85 + RETURN(); \
58 } 86 }
59 87
60 -#define OP_DSTORE_FREG(treg, tregname, DFREG) \  
61 - void glue(glue(op_store_fpr_,tregname), DFREG) (void)\  
62 - { \  
63 - FPR_D(env, DFREG) = treg; \  
64 - RETURN(); \ 88 +#define OP_PSSTORE_FREG(treg, tregname, FREG) \
  89 + void glue(glue(op_store_fpr_,tregname), FREG) (void) \
  90 + { \
  91 + env->fpr[FREG].fs[!FP_ENDIAN_IDX] = treg; \
  92 + RETURN(); \
65 } 93 }
66 94
67 -OP_DLOAD_FREG(DT0, DT0_fpr, DFREG)  
68 -OP_DSTORE_FREG(DT0, DT0_fpr, DFREG) 95 +OP_PSLOAD_FREG(WTH0, WTH0_fpr, FREG)
  96 +OP_PSSTORE_FREG(WTH0, WTH0_fpr, FREG)
69 97
70 -OP_DLOAD_FREG(DT1, DT1_fpr, DFREG)  
71 -OP_DSTORE_FREG(DT1, DT1_fpr, DFREG) 98 +OP_PSLOAD_FREG(WTH1, WTH1_fpr, FREG)
  99 +OP_PSSTORE_FREG(WTH1, WTH1_fpr, FREG)
72 100
73 -OP_DLOAD_FREG(DT2, DT2_fpr, DFREG)  
74 -OP_DSTORE_FREG(DT2, DT2_fpr, DFREG) 101 +OP_PSLOAD_FREG(WTH2, WTH2_fpr, FREG)
  102 +OP_PSSTORE_FREG(WTH2, WTH2_fpr, FREG)
75 103
76 #endif 104 #endif
77 105
78 #if defined (FTN) 106 #if defined (FTN)
79 107
80 -#define SET_RESET(treg, tregname) \ 108 +#define SET_RESET(treg, tregname) \
81 void glue(op_set, tregname)(void) \ 109 void glue(op_set, tregname)(void) \
82 - { \  
83 - treg = PARAM1; \  
84 - RETURN(); \  
85 - } \ 110 + { \
  111 + treg = PARAM1; \
  112 + RETURN(); \
  113 + } \
86 void glue(op_reset, tregname)(void) \ 114 void glue(op_reset, tregname)(void) \
87 - { \  
88 - treg = 0; \  
89 - RETURN(); \  
90 - } \ 115 + { \
  116 + treg = 0; \
  117 + RETURN(); \
  118 + }
91 119
92 SET_RESET(WT0, _WT0) 120 SET_RESET(WT0, _WT0)
93 SET_RESET(WT1, _WT1) 121 SET_RESET(WT1, _WT1)
@@ -95,6 +123,9 @@ SET_RESET(WT2, _WT2) @@ -95,6 +123,9 @@ SET_RESET(WT2, _WT2)
95 SET_RESET(DT0, _DT0) 123 SET_RESET(DT0, _DT0)
96 SET_RESET(DT1, _DT1) 124 SET_RESET(DT1, _DT1)
97 SET_RESET(DT2, _DT2) 125 SET_RESET(DT2, _DT2)
  126 +SET_RESET(WTH0, _WTH0)
  127 +SET_RESET(WTH1, _WTH1)
  128 +SET_RESET(WTH2, _WTH2)
98 129
99 #undef SET_RESET 130 #undef SET_RESET
100 #endif 131 #endif
target-mips/helper.c
@@ -379,6 +379,9 @@ void do_interrupt (CPUState *env) @@ -379,6 +379,9 @@ void do_interrupt (CPUState *env)
379 case EXCP_TRAP: 379 case EXCP_TRAP:
380 cause = 13; 380 cause = 13;
381 goto set_EPC; 381 goto set_EPC;
  382 + case EXCP_FPE:
  383 + cause = 15;
  384 + goto set_EPC;
382 case EXCP_LTLBL: 385 case EXCP_LTLBL:
383 cause = 1; 386 cause = 1;
384 goto set_EPC; 387 goto set_EPC;
target-mips/op.c
@@ -23,27 +23,27 @@ @@ -23,27 +23,27 @@
23 #include "exec.h" 23 #include "exec.h"
24 24
25 #ifndef CALL_FROM_TB0 25 #ifndef CALL_FROM_TB0
26 -#define CALL_FROM_TB0(func) func(); 26 +#define CALL_FROM_TB0(func) func()
27 #endif 27 #endif
28 #ifndef CALL_FROM_TB1 28 #ifndef CALL_FROM_TB1
29 -#define CALL_FROM_TB1(func, arg0) func(arg0); 29 +#define CALL_FROM_TB1(func, arg0) func(arg0)
30 #endif 30 #endif
31 #ifndef CALL_FROM_TB1_CONST16 31 #ifndef CALL_FROM_TB1_CONST16
32 -#define CALL_FROM_TB1_CONST16(func, arg0) CALL_FROM_TB1(func, arg0); 32 +#define CALL_FROM_TB1_CONST16(func, arg0) CALL_FROM_TB1(func, arg0)
33 #endif 33 #endif
34 #ifndef CALL_FROM_TB2 34 #ifndef CALL_FROM_TB2
35 -#define CALL_FROM_TB2(func, arg0, arg1) func(arg0, arg1); 35 +#define CALL_FROM_TB2(func, arg0, arg1) func(arg0, arg1)
36 #endif 36 #endif
37 #ifndef CALL_FROM_TB2_CONST16 37 #ifndef CALL_FROM_TB2_CONST16
38 #define CALL_FROM_TB2_CONST16(func, arg0, arg1) \ 38 #define CALL_FROM_TB2_CONST16(func, arg0, arg1) \
39 -CALL_FROM_TB2(func, arg0, arg1); 39 + CALL_FROM_TB2(func, arg0, arg1)
40 #endif 40 #endif
41 #ifndef CALL_FROM_TB3 41 #ifndef CALL_FROM_TB3
42 -#define CALL_FROM_TB3(func, arg0, arg1, arg2) func(arg0, arg1, arg2); 42 +#define CALL_FROM_TB3(func, arg0, arg1, arg2) func(arg0, arg1, arg2)
43 #endif 43 #endif
44 #ifndef CALL_FROM_TB4 44 #ifndef CALL_FROM_TB4
45 #define CALL_FROM_TB4(func, arg0, arg1, arg2, arg3) \ 45 #define CALL_FROM_TB4(func, arg0, arg1, arg2, arg3) \
46 - func(arg0, arg1, arg2, arg3); 46 + func(arg0, arg1, arg2, arg3)
47 #endif 47 #endif
48 48
49 #define REG 1 49 #define REG 1
@@ -144,134 +144,102 @@ CALL_FROM_TB2(func, arg0, arg1); @@ -144,134 +144,102 @@ CALL_FROM_TB2(func, arg0, arg1);
144 #include "op_template.c" 144 #include "op_template.c"
145 #undef TN 145 #undef TN
146 146
147 -#define SFREG 0  
148 -#define DFREG 0 147 +#define FREG 0
149 #include "fop_template.c" 148 #include "fop_template.c"
150 -#undef SFREG  
151 -#undef DFREG  
152 -#define SFREG 1 149 +#undef FREG
  150 +#define FREG 1
153 #include "fop_template.c" 151 #include "fop_template.c"
154 -#undef SFREG  
155 -#define SFREG 2  
156 -#define DFREG 2 152 +#undef FREG
  153 +#define FREG 2
157 #include "fop_template.c" 154 #include "fop_template.c"
158 -#undef SFREG  
159 -#undef DFREG  
160 -#define SFREG 3 155 +#undef FREG
  156 +#define FREG 3
161 #include "fop_template.c" 157 #include "fop_template.c"
162 -#undef SFREG  
163 -#define SFREG 4  
164 -#define DFREG 4 158 +#undef FREG
  159 +#define FREG 4
165 #include "fop_template.c" 160 #include "fop_template.c"
166 -#undef SFREG  
167 -#undef DFREG  
168 -#define SFREG 5 161 +#undef FREG
  162 +#define FREG 5
169 #include "fop_template.c" 163 #include "fop_template.c"
170 -#undef SFREG  
171 -#define SFREG 6  
172 -#define DFREG 6 164 +#undef FREG
  165 +#define FREG 6
173 #include "fop_template.c" 166 #include "fop_template.c"
174 -#undef SFREG  
175 -#undef DFREG  
176 -#define SFREG 7 167 +#undef FREG
  168 +#define FREG 7
177 #include "fop_template.c" 169 #include "fop_template.c"
178 -#undef SFREG  
179 -#define SFREG 8  
180 -#define DFREG 8 170 +#undef FREG
  171 +#define FREG 8
181 #include "fop_template.c" 172 #include "fop_template.c"
182 -#undef SFREG  
183 -#undef DFREG  
184 -#define SFREG 9 173 +#undef FREG
  174 +#define FREG 9
185 #include "fop_template.c" 175 #include "fop_template.c"
186 -#undef SFREG  
187 -#define SFREG 10  
188 -#define DFREG 10 176 +#undef FREG
  177 +#define FREG 10
189 #include "fop_template.c" 178 #include "fop_template.c"
190 -#undef SFREG  
191 -#undef DFREG  
192 -#define SFREG 11 179 +#undef FREG
  180 +#define FREG 11
193 #include "fop_template.c" 181 #include "fop_template.c"
194 -#undef SFREG  
195 -#define SFREG 12  
196 -#define DFREG 12 182 +#undef FREG
  183 +#define FREG 12
197 #include "fop_template.c" 184 #include "fop_template.c"
198 -#undef SFREG  
199 -#undef DFREG  
200 -#define SFREG 13 185 +#undef FREG
  186 +#define FREG 13
201 #include "fop_template.c" 187 #include "fop_template.c"
202 -#undef SFREG  
203 -#define SFREG 14  
204 -#define DFREG 14 188 +#undef FREG
  189 +#define FREG 14
205 #include "fop_template.c" 190 #include "fop_template.c"
206 -#undef SFREG  
207 -#undef DFREG  
208 -#define SFREG 15 191 +#undef FREG
  192 +#define FREG 15
209 #include "fop_template.c" 193 #include "fop_template.c"
210 -#undef SFREG  
211 -#define SFREG 16  
212 -#define DFREG 16 194 +#undef FREG
  195 +#define FREG 16
213 #include "fop_template.c" 196 #include "fop_template.c"
214 -#undef SFREG  
215 -#undef DFREG  
216 -#define SFREG 17 197 +#undef FREG
  198 +#define FREG 17
217 #include "fop_template.c" 199 #include "fop_template.c"
218 -#undef SFREG  
219 -#define SFREG 18  
220 -#define DFREG 18 200 +#undef FREG
  201 +#define FREG 18
221 #include "fop_template.c" 202 #include "fop_template.c"
222 -#undef SFREG  
223 -#undef DFREG  
224 -#define SFREG 19 203 +#undef FREG
  204 +#define FREG 19
225 #include "fop_template.c" 205 #include "fop_template.c"
226 -#undef SFREG  
227 -#define SFREG 20  
228 -#define DFREG 20 206 +#undef FREG
  207 +#define FREG 20
229 #include "fop_template.c" 208 #include "fop_template.c"
230 -#undef SFREG  
231 -#undef DFREG  
232 -#define SFREG 21 209 +#undef FREG
  210 +#define FREG 21
233 #include "fop_template.c" 211 #include "fop_template.c"
234 -#undef SFREG  
235 -#define SFREG 22  
236 -#define DFREG 22 212 +#undef FREG
  213 +#define FREG 22
237 #include "fop_template.c" 214 #include "fop_template.c"
238 -#undef SFREG  
239 -#undef DFREG  
240 -#define SFREG 23 215 +#undef FREG
  216 +#define FREG 23
241 #include "fop_template.c" 217 #include "fop_template.c"
242 -#undef SFREG  
243 -#define SFREG 24  
244 -#define DFREG 24 218 +#undef FREG
  219 +#define FREG 24
245 #include "fop_template.c" 220 #include "fop_template.c"
246 -#undef SFREG  
247 -#undef DFREG  
248 -#define SFREG 25 221 +#undef FREG
  222 +#define FREG 25
249 #include "fop_template.c" 223 #include "fop_template.c"
250 -#undef SFREG  
251 -#define SFREG 26  
252 -#define DFREG 26 224 +#undef FREG
  225 +#define FREG 26
253 #include "fop_template.c" 226 #include "fop_template.c"
254 -#undef SFREG  
255 -#undef DFREG  
256 -#define SFREG 27 227 +#undef FREG
  228 +#define FREG 27
257 #include "fop_template.c" 229 #include "fop_template.c"
258 -#undef SFREG  
259 -#define SFREG 28  
260 -#define DFREG 28 230 +#undef FREG
  231 +#define FREG 28
261 #include "fop_template.c" 232 #include "fop_template.c"
262 -#undef SFREG  
263 -#undef DFREG  
264 -#define SFREG 29 233 +#undef FREG
  234 +#define FREG 29
265 #include "fop_template.c" 235 #include "fop_template.c"
266 -#undef SFREG  
267 -#define SFREG 30  
268 -#define DFREG 30 236 +#undef FREG
  237 +#define FREG 30
269 #include "fop_template.c" 238 #include "fop_template.c"
270 -#undef SFREG  
271 -#undef DFREG  
272 -#define SFREG 31 239 +#undef FREG
  240 +#define FREG 31
273 #include "fop_template.c" 241 #include "fop_template.c"
274 -#undef SFREG 242 +#undef FREG
275 243
276 #define FTN 244 #define FTN
277 #include "fop_template.c" 245 #include "fop_template.c"
@@ -919,14 +887,14 @@ void op_movz (void) @@ -919,14 +887,14 @@ void op_movz (void)
919 void op_movf (void) 887 void op_movf (void)
920 { 888 {
921 if (!(env->fcr31 & PARAM1)) 889 if (!(env->fcr31 & PARAM1))
922 - env->gpr[PARAM2] = env->gpr[PARAM3]; 890 + T0 = T1;
923 RETURN(); 891 RETURN();
924 } 892 }
925 893
926 void op_movt (void) 894 void op_movt (void)
927 { 895 {
928 if (env->fcr31 & PARAM1) 896 if (env->fcr31 & PARAM1)
929 - env->gpr[PARAM2] = env->gpr[PARAM3]; 897 + T0 = T1;
930 RETURN(); 898 RETURN();
931 } 899 }
932 900
@@ -1354,17 +1322,18 @@ void op_mtc0_compare (void) @@ -1354,17 +1322,18 @@ void op_mtc0_compare (void)
1354 void op_mtc0_status (void) 1322 void op_mtc0_status (void)
1355 { 1323 {
1356 uint32_t val, old; 1324 uint32_t val, old;
  1325 + uint32_t mask = env->Status_rw_bitmask;
1357 1326
1358 - /* No 64bit FPU, no reverse endianness, no MDMX/DSP, no 64bit ops, 1327 + /* No reverse endianness, no MDMX/DSP, no 64bit ops,
1359 no 64bit addressing implemented. */ 1328 no 64bit addressing implemented. */
1360 - val = (int32_t)T0 & 0xF878FF17; 1329 + val = (int32_t)T0 & mask;
1361 old = env->CP0_Status; 1330 old = env->CP0_Status;
1362 if (!(val & (1 << CP0St_EXL)) && 1331 if (!(val & (1 << CP0St_EXL)) &&
1363 !(val & (1 << CP0St_ERL)) && 1332 !(val & (1 << CP0St_ERL)) &&
1364 !(env->hflags & MIPS_HFLAG_DM) && 1333 !(env->hflags & MIPS_HFLAG_DM) &&
1365 (val & (1 << CP0St_UM))) 1334 (val & (1 << CP0St_UM)))
1366 env->hflags |= MIPS_HFLAG_UM; 1335 env->hflags |= MIPS_HFLAG_UM;
1367 - env->CP0_Status = (env->CP0_Status & ~0xF878FF17) | val; 1336 + env->CP0_Status = (env->CP0_Status & ~mask) | val;
1368 if (loglevel & CPU_LOG_EXEC) 1337 if (loglevel & CPU_LOG_EXEC)
1369 CALL_FROM_TB2(do_mtc0_status_debug, old, val); 1338 CALL_FROM_TB2(do_mtc0_status_debug, old, val);
1370 CALL_FROM_TB1(cpu_mips_update_irq, env); 1339 CALL_FROM_TB1(cpu_mips_update_irq, env);
@@ -1643,6 +1612,7 @@ void op_dmtc0_errorepc (void) @@ -1643,6 +1612,7 @@ void op_dmtc0_errorepc (void)
1643 } 1612 }
1644 #endif /* TARGET_MIPS64 */ 1613 #endif /* TARGET_MIPS64 */
1645 1614
  1615 +/* CP1 functions */
1646 #if 0 1616 #if 0
1647 # define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env) 1617 # define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
1648 #else 1618 #else
@@ -1666,20 +1636,6 @@ void op_cp1_enabled(void) @@ -1666,20 +1636,6 @@ void op_cp1_enabled(void)
1666 RETURN(); 1636 RETURN();
1667 } 1637 }
1668 1638
1669 -/* CP1 functions */  
1670 -void op_cfc1 (void)  
1671 -{  
1672 - if (T1 == 0) {  
1673 - T0 = env->fcr0;  
1674 - }  
1675 - else {  
1676 - /* fetch fcr31, masking unused bits */  
1677 - T0 = env->fcr31 & 0x0183FFFF;  
1678 - }  
1679 - DEBUG_FPU_STATE();  
1680 - RETURN();  
1681 -}  
1682 -  
1683 /* convert MIPS rounding mode in FCR31 to IEEE library */ 1639 /* convert MIPS rounding mode in FCR31 to IEEE library */
1684 unsigned int ieee_rm[] = { 1640 unsigned int ieee_rm[] = {
1685 float_round_nearest_even, 1641 float_round_nearest_even,
@@ -1691,26 +1647,93 @@ unsigned int ieee_rm[] = { @@ -1691,26 +1647,93 @@ unsigned int ieee_rm[] = {
1691 #define RESTORE_ROUNDING_MODE \ 1647 #define RESTORE_ROUNDING_MODE \
1692 set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status) 1648 set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status)
1693 1649
1694 -void op_ctc1 (void) 1650 +inline char ieee_ex_to_mips(char ieee)
1695 { 1651 {
1696 - if (T1 == 0) {  
1697 - /* XXX should this throw an exception?  
1698 - * don't write to FCR0.  
1699 - * env->fcr0 = T0;  
1700 - */  
1701 - }  
1702 - else {  
1703 - /* store new fcr31, masking unused bits */  
1704 - env->fcr31 = T0 & 0x0183FFFF; 1652 + return (ieee & float_flag_inexact) >> 5 |
  1653 + (ieee & float_flag_underflow) >> 3 |
  1654 + (ieee & float_flag_overflow) >> 1 |
  1655 + (ieee & float_flag_divbyzero) << 1 |
  1656 + (ieee & float_flag_invalid) << 4;
  1657 +}
1705 1658
1706 - /* set rounding mode */  
1707 - RESTORE_ROUNDING_MODE; 1659 +inline char mips_ex_to_ieee(char mips)
  1660 +{
  1661 + return (mips & FP_INEXACT) << 5 |
  1662 + (mips & FP_UNDERFLOW) << 3 |
  1663 + (mips & FP_OVERFLOW) << 1 |
  1664 + (mips & FP_DIV0) >> 1 |
  1665 + (mips & FP_INVALID) >> 4;
  1666 +}
1708 1667
1709 -#ifndef CONFIG_SOFTFLOAT  
1710 - /* no floating point exception for native float */  
1711 - SET_FP_ENABLE(env->fcr31, 0);  
1712 -#endif 1668 +inline void update_fcr31(void)
  1669 +{
  1670 + int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->fp_status));
  1671 +
  1672 + SET_FP_CAUSE(env->fcr31, tmp);
  1673 + if (GET_FP_ENABLE(env->fcr31) & tmp)
  1674 + CALL_FROM_TB1(do_raise_exception, EXCP_FPE);
  1675 + else
  1676 + UPDATE_FP_FLAGS(env->fcr31, tmp);
  1677 +}
  1678 +
  1679 +
  1680 +void op_cfc1 (void)
  1681 +{
  1682 + switch (T1) {
  1683 + case 0:
  1684 + T0 = (int32_t)env->fcr0;
  1685 + break;
  1686 + case 25:
  1687 + T0 = ((env->fcr31 >> 24) & 0xfe) | ((env->fcr31 >> 23) & 0x1);
  1688 + break;
  1689 + case 26:
  1690 + T0 = env->fcr31 & 0x0003f07c;
  1691 + break;
  1692 + case 28:
  1693 + T0 = (env->fcr31 & 0x00000f83) | ((env->fcr31 >> 22) & 0x4);
  1694 + break;
  1695 + default:
  1696 + T0 = (int32_t)env->fcr31;
  1697 + break;
  1698 + }
  1699 + DEBUG_FPU_STATE();
  1700 + RETURN();
  1701 +}
  1702 +
  1703 +void op_ctc1 (void)
  1704 +{
  1705 + switch(T1) {
  1706 + case 25:
  1707 + if (T0 & 0xffffff00)
  1708 + goto leave;
  1709 + env->fcr31 = (env->fcr31 & 0x017fffff) | ((T0 & 0xfe) << 24) |
  1710 + ((T0 & 0x1) << 23);
  1711 + break;
  1712 + case 26:
  1713 + if (T0 & 0x007c0000)
  1714 + goto leave;
  1715 + env->fcr31 = (env->fcr31 & 0xfffc0f83) | (T0 & 0x0003f07c);
  1716 + break;
  1717 + case 28:
  1718 + if (T0 & 0x007c0000)
  1719 + goto leave;
  1720 + env->fcr31 = (env->fcr31 & 0xfefff07c) | (T0 & 0x00000f83) |
  1721 + ((T0 & 0x4) << 22);
  1722 + break;
  1723 + case 31:
  1724 + if (T0 & 0x007c0000)
  1725 + goto leave;
  1726 + env->fcr31 = T0;
  1727 + break;
  1728 + default:
  1729 + goto leave;
1713 } 1730 }
  1731 + /* set rounding mode */
  1732 + RESTORE_ROUNDING_MODE;
  1733 + set_float_exception_flags(0, &env->fp_status);
  1734 + if ((GET_FP_ENABLE(env->fcr31) | 0x20) & GET_FP_CAUSE(env->fcr31))
  1735 + CALL_FROM_TB1(do_raise_exception, EXCP_FPE);
  1736 + leave:
1714 DEBUG_FPU_STATE(); 1737 DEBUG_FPU_STATE();
1715 RETURN(); 1738 RETURN();
1716 } 1739 }
@@ -1729,55 +1752,219 @@ void op_mtc1 (void) @@ -1729,55 +1752,219 @@ void op_mtc1 (void)
1729 RETURN(); 1752 RETURN();
1730 } 1753 }
1731 1754
  1755 +void op_dmfc1 (void)
  1756 +{
  1757 + T0 = DT0;
  1758 + DEBUG_FPU_STATE();
  1759 + RETURN();
  1760 +}
  1761 +
  1762 +void op_dmtc1 (void)
  1763 +{
  1764 + DT0 = T0;
  1765 + DEBUG_FPU_STATE();
  1766 + RETURN();
  1767 +}
  1768 +
  1769 +void op_mfhc1 (void)
  1770 +{
  1771 + T0 = WTH0;
  1772 + DEBUG_FPU_STATE();
  1773 + RETURN();
  1774 +}
  1775 +
  1776 +void op_mthc1 (void)
  1777 +{
  1778 + WTH0 = T0;
  1779 + DEBUG_FPU_STATE();
  1780 + RETURN();
  1781 +}
  1782 +
1732 /* Float support. 1783 /* Float support.
1733 Single precition routines have a "s" suffix, double precision a 1784 Single precition routines have a "s" suffix, double precision a
1734 - "d" suffix. */ 1785 + "d" suffix, 32bit integer "w", 64bit integer "l", paired singe "ps",
  1786 + paired single lowwer "pl", paired single upper "pu". */
1735 1787
1736 #define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void) 1788 #define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
1737 1789
1738 FLOAT_OP(cvtd, s) 1790 FLOAT_OP(cvtd, s)
1739 { 1791 {
  1792 + set_float_exception_flags(0, &env->fp_status);
1740 FDT2 = float32_to_float64(FST0, &env->fp_status); 1793 FDT2 = float32_to_float64(FST0, &env->fp_status);
  1794 + update_fcr31();
1741 DEBUG_FPU_STATE(); 1795 DEBUG_FPU_STATE();
1742 RETURN(); 1796 RETURN();
1743 } 1797 }
1744 FLOAT_OP(cvtd, w) 1798 FLOAT_OP(cvtd, w)
1745 { 1799 {
  1800 + set_float_exception_flags(0, &env->fp_status);
1746 FDT2 = int32_to_float64(WT0, &env->fp_status); 1801 FDT2 = int32_to_float64(WT0, &env->fp_status);
  1802 + update_fcr31();
  1803 + DEBUG_FPU_STATE();
  1804 + RETURN();
  1805 +}
  1806 +FLOAT_OP(cvtd, l)
  1807 +{
  1808 + set_float_exception_flags(0, &env->fp_status);
  1809 + FDT2 = int64_to_float64(DT0, &env->fp_status);
  1810 + update_fcr31();
  1811 + DEBUG_FPU_STATE();
  1812 + RETURN();
  1813 +}
  1814 +FLOAT_OP(cvtl, d)
  1815 +{
  1816 + set_float_exception_flags(0, &env->fp_status);
  1817 + DT2 = float64_to_int64(FDT0, &env->fp_status);
  1818 + update_fcr31();
  1819 + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
  1820 + DT2 = 0x7fffffffffffffffULL;
  1821 + DEBUG_FPU_STATE();
  1822 + RETURN();
  1823 +}
  1824 +FLOAT_OP(cvtl, s)
  1825 +{
  1826 + set_float_exception_flags(0, &env->fp_status);
  1827 + DT2 = float32_to_int64(FST0, &env->fp_status);
  1828 + update_fcr31();
  1829 + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
  1830 + DT2 = 0x7fffffffffffffffULL;
  1831 + DEBUG_FPU_STATE();
  1832 + RETURN();
  1833 +}
  1834 +FLOAT_OP(cvtps, s)
  1835 +{
  1836 + WT2 = WT0;
  1837 + WTH2 = WT1;
  1838 + DEBUG_FPU_STATE();
  1839 + RETURN();
  1840 +}
  1841 +FLOAT_OP(cvtps, pw)
  1842 +{
  1843 + set_float_exception_flags(0, &env->fp_status);
  1844 + FST2 = int32_to_float32(WT0, &env->fp_status);
  1845 + FSTH2 = int32_to_float32(WTH0, &env->fp_status);
  1846 + update_fcr31();
  1847 + DEBUG_FPU_STATE();
  1848 + RETURN();
  1849 +}
  1850 +FLOAT_OP(cvtpw, ps)
  1851 +{
  1852 + set_float_exception_flags(0, &env->fp_status);
  1853 + WT2 = float32_to_int32(FST0, &env->fp_status);
  1854 + WTH2 = float32_to_int32(FSTH0, &env->fp_status);
  1855 + update_fcr31();
  1856 + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
  1857 + WT2 = 0x7fffffff;
1747 DEBUG_FPU_STATE(); 1858 DEBUG_FPU_STATE();
1748 RETURN(); 1859 RETURN();
1749 } 1860 }
1750 FLOAT_OP(cvts, d) 1861 FLOAT_OP(cvts, d)
1751 { 1862 {
  1863 + set_float_exception_flags(0, &env->fp_status);
1752 FST2 = float64_to_float32(FDT0, &env->fp_status); 1864 FST2 = float64_to_float32(FDT0, &env->fp_status);
  1865 + update_fcr31();
1753 DEBUG_FPU_STATE(); 1866 DEBUG_FPU_STATE();
1754 RETURN(); 1867 RETURN();
1755 } 1868 }
1756 FLOAT_OP(cvts, w) 1869 FLOAT_OP(cvts, w)
1757 { 1870 {
  1871 + set_float_exception_flags(0, &env->fp_status);
1758 FST2 = int32_to_float32(WT0, &env->fp_status); 1872 FST2 = int32_to_float32(WT0, &env->fp_status);
  1873 + update_fcr31();
  1874 + DEBUG_FPU_STATE();
  1875 + RETURN();
  1876 +}
  1877 +FLOAT_OP(cvts, l)
  1878 +{
  1879 + set_float_exception_flags(0, &env->fp_status);
  1880 + FST2 = int64_to_float32(DT0, &env->fp_status);
  1881 + update_fcr31();
  1882 + DEBUG_FPU_STATE();
  1883 + RETURN();
  1884 +}
  1885 +FLOAT_OP(cvts, pl)
  1886 +{
  1887 + set_float_exception_flags(0, &env->fp_status);
  1888 + WT2 = WT0;
  1889 + update_fcr31();
  1890 + DEBUG_FPU_STATE();
  1891 + RETURN();
  1892 +}
  1893 +FLOAT_OP(cvts, pu)
  1894 +{
  1895 + set_float_exception_flags(0, &env->fp_status);
  1896 + WT2 = WTH0;
  1897 + update_fcr31();
1759 DEBUG_FPU_STATE(); 1898 DEBUG_FPU_STATE();
1760 RETURN(); 1899 RETURN();
1761 } 1900 }
1762 FLOAT_OP(cvtw, s) 1901 FLOAT_OP(cvtw, s)
1763 { 1902 {
  1903 + set_float_exception_flags(0, &env->fp_status);
1764 WT2 = float32_to_int32(FST0, &env->fp_status); 1904 WT2 = float32_to_int32(FST0, &env->fp_status);
  1905 + update_fcr31();
  1906 + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
  1907 + WT2 = 0x7fffffff;
1765 DEBUG_FPU_STATE(); 1908 DEBUG_FPU_STATE();
1766 RETURN(); 1909 RETURN();
1767 } 1910 }
1768 FLOAT_OP(cvtw, d) 1911 FLOAT_OP(cvtw, d)
1769 { 1912 {
  1913 + set_float_exception_flags(0, &env->fp_status);
1770 WT2 = float64_to_int32(FDT0, &env->fp_status); 1914 WT2 = float64_to_int32(FDT0, &env->fp_status);
  1915 + update_fcr31();
  1916 + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
  1917 + WT2 = 0x7fffffff;
  1918 + DEBUG_FPU_STATE();
  1919 + RETURN();
  1920 +}
  1921 +
  1922 +FLOAT_OP(pll, ps)
  1923 +{
  1924 + DT2 = ((uint64_t)WT0 << 32) | WT1;
  1925 + DEBUG_FPU_STATE();
  1926 + RETURN();
  1927 +}
  1928 +FLOAT_OP(plu, ps)
  1929 +{
  1930 + DT2 = ((uint64_t)WT0 << 32) | WTH1;
  1931 + DEBUG_FPU_STATE();
  1932 + RETURN();
  1933 +}
  1934 +FLOAT_OP(pul, ps)
  1935 +{
  1936 + DT2 = ((uint64_t)WTH0 << 32) | WT1;
  1937 + DEBUG_FPU_STATE();
  1938 + RETURN();
  1939 +}
  1940 +FLOAT_OP(puu, ps)
  1941 +{
  1942 + DT2 = ((uint64_t)WTH0 << 32) | WTH1;
1771 DEBUG_FPU_STATE(); 1943 DEBUG_FPU_STATE();
1772 RETURN(); 1944 RETURN();
1773 } 1945 }
1774 1946
  1947 +FLOAT_OP(roundl, d)
  1948 +{
  1949 + set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
  1950 + DT2 = float64_round_to_int(FDT0, &env->fp_status);
  1951 + RESTORE_ROUNDING_MODE;
  1952 + DEBUG_FPU_STATE();
  1953 + RETURN();
  1954 +}
  1955 +FLOAT_OP(roundl, s)
  1956 +{
  1957 + set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
  1958 + DT2 = float32_round_to_int(FST0, &env->fp_status);
  1959 + RESTORE_ROUNDING_MODE;
  1960 + DEBUG_FPU_STATE();
  1961 + RETURN();
  1962 +}
1775 FLOAT_OP(roundw, d) 1963 FLOAT_OP(roundw, d)
1776 { 1964 {
1777 set_float_rounding_mode(float_round_nearest_even, &env->fp_status); 1965 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1778 WT2 = float64_round_to_int(FDT0, &env->fp_status); 1966 WT2 = float64_round_to_int(FDT0, &env->fp_status);
1779 RESTORE_ROUNDING_MODE; 1967 RESTORE_ROUNDING_MODE;
1780 -  
1781 DEBUG_FPU_STATE(); 1968 DEBUG_FPU_STATE();
1782 RETURN(); 1969 RETURN();
1783 } 1970 }
@@ -1790,6 +1977,18 @@ FLOAT_OP(roundw, s) @@ -1790,6 +1977,18 @@ FLOAT_OP(roundw, s)
1790 RETURN(); 1977 RETURN();
1791 } 1978 }
1792 1979
  1980 +FLOAT_OP(truncl, d)
  1981 +{
  1982 + DT2 = float64_to_int64_round_to_zero(FDT0, &env->fp_status);
  1983 + DEBUG_FPU_STATE();
  1984 + RETURN();
  1985 +}
  1986 +FLOAT_OP(truncl, s)
  1987 +{
  1988 + DT2 = float32_to_int64_round_to_zero(FST0, &env->fp_status);
  1989 + DEBUG_FPU_STATE();
  1990 + RETURN();
  1991 +}
1793 FLOAT_OP(truncw, d) 1992 FLOAT_OP(truncw, d)
1794 { 1993 {
1795 WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status); 1994 WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status);
@@ -1803,12 +2002,27 @@ FLOAT_OP(truncw, s) @@ -1803,12 +2002,27 @@ FLOAT_OP(truncw, s)
1803 RETURN(); 2002 RETURN();
1804 } 2003 }
1805 2004
  2005 +FLOAT_OP(ceill, d)
  2006 +{
  2007 + set_float_rounding_mode(float_round_up, &env->fp_status);
  2008 + DT2 = float64_round_to_int(FDT0, &env->fp_status);
  2009 + RESTORE_ROUNDING_MODE;
  2010 + DEBUG_FPU_STATE();
  2011 + RETURN();
  2012 +}
  2013 +FLOAT_OP(ceill, s)
  2014 +{
  2015 + set_float_rounding_mode(float_round_up, &env->fp_status);
  2016 + DT2 = float32_round_to_int(FST0, &env->fp_status);
  2017 + RESTORE_ROUNDING_MODE;
  2018 + DEBUG_FPU_STATE();
  2019 + RETURN();
  2020 +}
1806 FLOAT_OP(ceilw, d) 2021 FLOAT_OP(ceilw, d)
1807 { 2022 {
1808 set_float_rounding_mode(float_round_up, &env->fp_status); 2023 set_float_rounding_mode(float_round_up, &env->fp_status);
1809 WT2 = float64_round_to_int(FDT0, &env->fp_status); 2024 WT2 = float64_round_to_int(FDT0, &env->fp_status);
1810 RESTORE_ROUNDING_MODE; 2025 RESTORE_ROUNDING_MODE;
1811 -  
1812 DEBUG_FPU_STATE(); 2026 DEBUG_FPU_STATE();
1813 RETURN(); 2027 RETURN();
1814 } 2028 }
@@ -1821,12 +2035,27 @@ FLOAT_OP(ceilw, s) @@ -1821,12 +2035,27 @@ FLOAT_OP(ceilw, s)
1821 RETURN(); 2035 RETURN();
1822 } 2036 }
1823 2037
  2038 +FLOAT_OP(floorl, d)
  2039 +{
  2040 + set_float_rounding_mode(float_round_down, &env->fp_status);
  2041 + DT2 = float64_round_to_int(FDT0, &env->fp_status);
  2042 + RESTORE_ROUNDING_MODE;
  2043 + DEBUG_FPU_STATE();
  2044 + RETURN();
  2045 +}
  2046 +FLOAT_OP(floorl, s)
  2047 +{
  2048 + set_float_rounding_mode(float_round_down, &env->fp_status);
  2049 + DT2 = float32_round_to_int(FST0, &env->fp_status);
  2050 + RESTORE_ROUNDING_MODE;
  2051 + DEBUG_FPU_STATE();
  2052 + RETURN();
  2053 +}
1824 FLOAT_OP(floorw, d) 2054 FLOAT_OP(floorw, d)
1825 { 2055 {
1826 set_float_rounding_mode(float_round_down, &env->fp_status); 2056 set_float_rounding_mode(float_round_down, &env->fp_status);
1827 WT2 = float64_round_to_int(FDT0, &env->fp_status); 2057 WT2 = float64_round_to_int(FDT0, &env->fp_status);
1828 RESTORE_ROUNDING_MODE; 2058 RESTORE_ROUNDING_MODE;
1829 -  
1830 DEBUG_FPU_STATE(); 2059 DEBUG_FPU_STATE();
1831 RETURN(); 2060 RETURN();
1832 } 2061 }
@@ -1839,16 +2068,121 @@ FLOAT_OP(floorw, s) @@ -1839,16 +2068,121 @@ FLOAT_OP(floorw, s)
1839 RETURN(); 2068 RETURN();
1840 } 2069 }
1841 2070
  2071 +FLOAT_OP(movf, d)
  2072 +{
  2073 + if (!(env->fcr31 & PARAM1))
  2074 + DT2 = DT0;
  2075 + DEBUG_FPU_STATE();
  2076 + RETURN();
  2077 +}
  2078 +FLOAT_OP(movf, s)
  2079 +{
  2080 + if (!(env->fcr31 & PARAM1))
  2081 + WT2 = WT0;
  2082 + DEBUG_FPU_STATE();
  2083 + RETURN();
  2084 +}
  2085 +FLOAT_OP(movf, ps)
  2086 +{
  2087 + if (!(env->fcr31 & PARAM1)) {
  2088 + WT2 = WT0;
  2089 + WTH2 = WTH0;
  2090 + }
  2091 + DEBUG_FPU_STATE();
  2092 + RETURN();
  2093 +}
  2094 +FLOAT_OP(movt, d)
  2095 +{
  2096 + if (env->fcr31 & PARAM1)
  2097 + DT2 = DT0;
  2098 + DEBUG_FPU_STATE();
  2099 + RETURN();
  2100 +}
  2101 +FLOAT_OP(movt, s)
  2102 +{
  2103 + if (env->fcr31 & PARAM1)
  2104 + WT2 = WT0;
  2105 + DEBUG_FPU_STATE();
  2106 + RETURN();
  2107 +}
  2108 +FLOAT_OP(movt, ps)
  2109 +{
  2110 + if (env->fcr31 & PARAM1) {
  2111 + WT2 = WT0;
  2112 + WTH2 = WTH0;
  2113 + }
  2114 + DEBUG_FPU_STATE();
  2115 + RETURN();
  2116 +}
  2117 +FLOAT_OP(movz, d)
  2118 +{
  2119 + if (!T0)
  2120 + DT2 = DT0;
  2121 + DEBUG_FPU_STATE();
  2122 + RETURN();
  2123 +}
  2124 +FLOAT_OP(movz, s)
  2125 +{
  2126 + if (!T0)
  2127 + WT2 = WT0;
  2128 + DEBUG_FPU_STATE();
  2129 + RETURN();
  2130 +}
  2131 +FLOAT_OP(movz, ps)
  2132 +{
  2133 + if (!T0) {
  2134 + WT2 = WT0;
  2135 + WTH2 = WTH0;
  2136 + }
  2137 + DEBUG_FPU_STATE();
  2138 + RETURN();
  2139 +}
  2140 +FLOAT_OP(movn, d)
  2141 +{
  2142 + if (T0)
  2143 + DT2 = DT0;
  2144 + DEBUG_FPU_STATE();
  2145 + RETURN();
  2146 +}
  2147 +FLOAT_OP(movn, s)
  2148 +{
  2149 + if (T0)
  2150 + WT2 = WT0;
  2151 + DEBUG_FPU_STATE();
  2152 + RETURN();
  2153 +}
  2154 +FLOAT_OP(movn, ps)
  2155 +{
  2156 + if (T0) {
  2157 + WT2 = WT0;
  2158 + WTH2 = WTH0;
  2159 + }
  2160 + DEBUG_FPU_STATE();
  2161 + RETURN();
  2162 +}
  2163 +
1842 /* binary operations */ 2164 /* binary operations */
1843 #define FLOAT_BINOP(name) \ 2165 #define FLOAT_BINOP(name) \
1844 FLOAT_OP(name, d) \ 2166 FLOAT_OP(name, d) \
1845 { \ 2167 { \
  2168 + set_float_exception_flags(0, &env->fp_status); \
1846 FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status); \ 2169 FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status); \
  2170 + update_fcr31(); \
1847 DEBUG_FPU_STATE(); \ 2171 DEBUG_FPU_STATE(); \
1848 } \ 2172 } \
1849 FLOAT_OP(name, s) \ 2173 FLOAT_OP(name, s) \
1850 { \ 2174 { \
  2175 + set_float_exception_flags(0, &env->fp_status); \
1851 FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \ 2176 FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \
  2177 + update_fcr31(); \
  2178 + DEBUG_FPU_STATE(); \
  2179 +} \
  2180 +FLOAT_OP(name, ps) \
  2181 +{ \
  2182 + set_float_exception_flags(0, &env->fp_status); \
  2183 + FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \
  2184 + FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fp_status); \
  2185 + update_fcr31(); \
1852 DEBUG_FPU_STATE(); \ 2186 DEBUG_FPU_STATE(); \
1853 } 2187 }
1854 FLOAT_BINOP(add) 2188 FLOAT_BINOP(add)
@@ -1857,6 +2191,32 @@ FLOAT_BINOP(mul) @@ -1857,6 +2191,32 @@ FLOAT_BINOP(mul)
1857 FLOAT_BINOP(div) 2191 FLOAT_BINOP(div)
1858 #undef FLOAT_BINOP 2192 #undef FLOAT_BINOP
1859 2193
  2194 +/* ternary operations */
  2195 +#define FLOAT_TERNOP(name1, name2) \
  2196 +FLOAT_OP(name1 ## name2, d) \
  2197 +{ \
  2198 + FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fp_status); \
  2199 + FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fp_status); \
  2200 + DEBUG_FPU_STATE(); \
  2201 +} \
  2202 +FLOAT_OP(name1 ## name2, s) \
  2203 +{ \
  2204 + FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
  2205 + FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
  2206 + DEBUG_FPU_STATE(); \
  2207 +} \
  2208 +FLOAT_OP(name1 ## name2, ps) \
  2209 +{ \
  2210 + FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
  2211 + FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fp_status); \
  2212 + FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
  2213 + FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fp_status); \
  2214 + DEBUG_FPU_STATE(); \
  2215 +}
  2216 +FLOAT_TERNOP(mul, add)
  2217 +FLOAT_TERNOP(mul, sub)
  2218 +#undef FLOAT_TERNOP
  2219 +
1860 /* unary operations, modifying fp status */ 2220 /* unary operations, modifying fp status */
1861 #define FLOAT_UNOP(name) \ 2221 #define FLOAT_UNOP(name) \
1862 FLOAT_OP(name, d) \ 2222 FLOAT_OP(name, d) \
@@ -1868,6 +2228,12 @@ FLOAT_OP(name, s) \ @@ -1868,6 +2228,12 @@ FLOAT_OP(name, s) \
1868 { \ 2228 { \
1869 FST2 = float32_ ## name(FST0, &env->fp_status); \ 2229 FST2 = float32_ ## name(FST0, &env->fp_status); \
1870 DEBUG_FPU_STATE(); \ 2230 DEBUG_FPU_STATE(); \
  2231 +} \
  2232 +FLOAT_OP(name, ps) \
  2233 +{ \
  2234 + FST2 = float32_ ## name(FST0, &env->fp_status); \
  2235 + FSTH2 = float32_ ## name(FSTH0, &env->fp_status); \
  2236 + DEBUG_FPU_STATE(); \
1871 } 2237 }
1872 FLOAT_UNOP(sqrt) 2238 FLOAT_UNOP(sqrt)
1873 #undef FLOAT_UNOP 2239 #undef FLOAT_UNOP
@@ -1883,6 +2249,12 @@ FLOAT_OP(name, s) \ @@ -1883,6 +2249,12 @@ FLOAT_OP(name, s) \
1883 { \ 2249 { \
1884 FST2 = float32_ ## name(FST0); \ 2250 FST2 = float32_ ## name(FST0); \
1885 DEBUG_FPU_STATE(); \ 2251 DEBUG_FPU_STATE(); \
  2252 +} \
  2253 +FLOAT_OP(name, ps) \
  2254 +{ \
  2255 + FST2 = float32_ ## name(FST0); \
  2256 + FSTH2 = float32_ ## name(FSTH0); \
  2257 + DEBUG_FPU_STATE(); \
1886 } 2258 }
1887 FLOAT_UNOP(abs) 2259 FLOAT_UNOP(abs)
1888 FLOAT_UNOP(chs) 2260 FLOAT_UNOP(chs)
@@ -1900,6 +2272,35 @@ FLOAT_OP(mov, s) @@ -1900,6 +2272,35 @@ FLOAT_OP(mov, s)
1900 DEBUG_FPU_STATE(); 2272 DEBUG_FPU_STATE();
1901 RETURN(); 2273 RETURN();
1902 } 2274 }
  2275 +FLOAT_OP(mov, ps)
  2276 +{
  2277 + FST2 = FST0;
  2278 + FSTH2 = FSTH0;
  2279 + DEBUG_FPU_STATE();
  2280 + RETURN();
  2281 +}
  2282 +FLOAT_OP(alnv, ps)
  2283 +{
  2284 + switch (T0 & 0x7) {
  2285 + case 0:
  2286 + FST2 = FST0;
  2287 + FSTH2 = FSTH0;
  2288 + break;
  2289 + case 4:
  2290 +#ifdef TARGET_WORDS_BIGENDIAN
  2291 + FSTH2 = FST0;
  2292 + FST2 = FSTH1;
  2293 +#else
  2294 + FSTH2 = FST1;
  2295 + FST2 = FSTH0;
  2296 +#endif
  2297 + break;
  2298 + default: /* unpredictable */
  2299 + break;
  2300 + }
  2301 + DEBUG_FPU_STATE();
  2302 + RETURN();
  2303 +}
1903 2304
1904 #ifdef CONFIG_SOFTFLOAT 2305 #ifdef CONFIG_SOFTFLOAT
1905 #define clear_invalid() do { \ 2306 #define clear_invalid() do { \
@@ -1913,96 +2314,200 @@ FLOAT_OP(mov, s) @@ -1913,96 +2314,200 @@ FLOAT_OP(mov, s)
1913 2314
1914 extern void dump_fpu_s(CPUState *env); 2315 extern void dump_fpu_s(CPUState *env);
1915 2316
1916 -#define FOP_COND(fmt, op, sig, cond) \  
1917 -void op_cmp_ ## fmt ## _ ## op (void) \ 2317 +#define FOP_COND_D(op, cond) \
  2318 +void op_cmp_d_ ## op (void) \
1918 { \ 2319 { \
1919 - if (cond) \  
1920 - SET_FP_COND(env->fcr31); \ 2320 + int c = cond; \
  2321 + update_fcr31(); \
  2322 + if (c) \
  2323 + SET_FP_COND(PARAM1, env); \
1921 else \ 2324 else \
1922 - CLEAR_FP_COND(env->fcr31); \  
1923 - if (!sig) \  
1924 - clear_invalid(); \  
1925 - /*CALL_FROM_TB1(dump_fpu_s, env);*/ \ 2325 + CLEAR_FP_COND(PARAM1, env); \
1926 DEBUG_FPU_STATE(); \ 2326 DEBUG_FPU_STATE(); \
1927 RETURN(); \ 2327 RETURN(); \
1928 } 2328 }
1929 2329
1930 -int float64_is_unordered(float64 a, float64 b STATUS_PARAM) 2330 +int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM)
1931 { 2331 {
1932 - if (float64_is_nan(a) || float64_is_nan(b)) { 2332 + if (float64_is_signaling_nan(a) ||
  2333 + float64_is_signaling_nan(b) ||
  2334 + (sig && (float64_is_nan(a) || float64_is_nan(b)))) {
1933 float_raise(float_flag_invalid, status); 2335 float_raise(float_flag_invalid, status);
1934 return 1; 2336 return 1;
1935 - }  
1936 - else { 2337 + } else if (float64_is_nan(a) || float64_is_nan(b)) {
  2338 + return 1;
  2339 + } else {
1937 return 0; 2340 return 0;
1938 } 2341 }
1939 } 2342 }
1940 2343
1941 -FOP_COND(d, f, 0, 0)  
1942 -FOP_COND(d, un, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status))  
1943 -FOP_COND(d, eq, 0, float64_eq(FDT0, FDT1, &env->fp_status))  
1944 -FOP_COND(d, ueq, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))  
1945 -FOP_COND(d, olt, 0, float64_lt(FDT0, FDT1, &env->fp_status))  
1946 -FOP_COND(d, ult, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))  
1947 -FOP_COND(d, ole, 0, float64_le(FDT0, FDT1, &env->fp_status))  
1948 -FOP_COND(d, ule, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))  
1949 /* NOTE: the comma operator will make "cond" to eval to false, 2344 /* NOTE: the comma operator will make "cond" to eval to false,
1950 - * but float*_is_unordered() is still called  
1951 - */  
1952 -FOP_COND(d, sf, 1, (float64_is_unordered(FDT0, FDT1, &env->fp_status), 0))  
1953 -FOP_COND(d, ngle,1, float64_is_unordered(FDT1, FDT0, &env->fp_status))  
1954 -FOP_COND(d, seq, 1, float64_eq(FDT0, FDT1, &env->fp_status))  
1955 -FOP_COND(d, ngl, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))  
1956 -FOP_COND(d, lt, 1, float64_lt(FDT0, FDT1, &env->fp_status))  
1957 -FOP_COND(d, nge, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))  
1958 -FOP_COND(d, le, 1, float64_le(FDT0, FDT1, &env->fp_status))  
1959 -FOP_COND(d, ngt, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))  
1960 -  
1961 -flag float32_is_unordered(float32 a, float32 b STATUS_PARAM)  
1962 -{  
1963 - extern flag float32_is_nan( float32 a );  
1964 - if (float32_is_nan(a) || float32_is_nan(b)) { 2345 + * but float*_is_unordered() is still called. */
  2346 +FOP_COND_D(f, (float64_is_unordered(0, FDT1, FDT0, &env->fp_status), 0))
  2347 +FOP_COND_D(un, float64_is_unordered(0, FDT1, FDT0, &env->fp_status))
  2348 +FOP_COND_D(eq, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_eq(FDT0, FDT1, &env->fp_status))
  2349 +FOP_COND_D(ueq, float64_is_unordered(0, FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
  2350 +FOP_COND_D(olt, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_lt(FDT0, FDT1, &env->fp_status))
  2351 +FOP_COND_D(ult, float64_is_unordered(0, FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
  2352 +FOP_COND_D(ole, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_le(FDT0, FDT1, &env->fp_status))
  2353 +FOP_COND_D(ule, float64_is_unordered(0, FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
  2354 +/* NOTE: the comma operator will make "cond" to eval to false,
  2355 + * but float*_is_unordered() is still called. */
  2356 +FOP_COND_D(sf, (float64_is_unordered(1, FDT1, FDT0, &env->fp_status), 0))
  2357 +FOP_COND_D(ngle,float64_is_unordered(1, FDT1, FDT0, &env->fp_status))
  2358 +FOP_COND_D(seq, !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_eq(FDT0, FDT1, &env->fp_status))
  2359 +FOP_COND_D(ngl, float64_is_unordered(1, FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
  2360 +FOP_COND_D(lt, !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_lt(FDT0, FDT1, &env->fp_status))
  2361 +FOP_COND_D(nge, float64_is_unordered(1, FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
  2362 +FOP_COND_D(le, !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_le(FDT0, FDT1, &env->fp_status))
  2363 +FOP_COND_D(ngt, float64_is_unordered(1, FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
  2364 +
  2365 +#define FOP_COND_S(op, cond) \
  2366 +void op_cmp_s_ ## op (void) \
  2367 +{ \
  2368 + int c = cond; \
  2369 + update_fcr31(); \
  2370 + if (c) \
  2371 + SET_FP_COND(PARAM1, env); \
  2372 + else \
  2373 + CLEAR_FP_COND(PARAM1, env); \
  2374 + DEBUG_FPU_STATE(); \
  2375 + RETURN(); \
  2376 +}
  2377 +
  2378 +flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM)
  2379 +{
  2380 + extern flag float32_is_nan(float32 a);
  2381 + if (float32_is_signaling_nan(a) ||
  2382 + float32_is_signaling_nan(b) ||
  2383 + (sig && (float32_is_nan(a) || float32_is_nan(b)))) {
1965 float_raise(float_flag_invalid, status); 2384 float_raise(float_flag_invalid, status);
1966 return 1; 2385 return 1;
1967 - }  
1968 - else { 2386 + } else if (float32_is_nan(a) || float32_is_nan(b)) {
  2387 + return 1;
  2388 + } else {
1969 return 0; 2389 return 0;
1970 } 2390 }
1971 } 2391 }
1972 2392
1973 /* NOTE: the comma operator will make "cond" to eval to false, 2393 /* NOTE: the comma operator will make "cond" to eval to false,
1974 - * but float*_is_unordered() is still called  
1975 - */  
1976 -FOP_COND(s, f, 0, 0)  
1977 -FOP_COND(s, un, 0, float32_is_unordered(FST1, FST0, &env->fp_status))  
1978 -FOP_COND(s, eq, 0, float32_eq(FST0, FST1, &env->fp_status))  
1979 -FOP_COND(s, ueq, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))  
1980 -FOP_COND(s, olt, 0, float32_lt(FST0, FST1, &env->fp_status))  
1981 -FOP_COND(s, ult, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))  
1982 -FOP_COND(s, ole, 0, float32_le(FST0, FST1, &env->fp_status))  
1983 -FOP_COND(s, ule, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status)) 2394 + * but float*_is_unordered() is still called. */
  2395 +FOP_COND_S(f, (float32_is_unordered(0, FST1, FST0, &env->fp_status), 0))
  2396 +FOP_COND_S(un, float32_is_unordered(0, FST1, FST0, &env->fp_status))
  2397 +FOP_COND_S(eq, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status))
  2398 +FOP_COND_S(ueq, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
  2399 +FOP_COND_S(olt, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status))
  2400 +FOP_COND_S(ult, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
  2401 +FOP_COND_S(ole, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status))
  2402 +FOP_COND_S(ule, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
1984 /* NOTE: the comma operator will make "cond" to eval to false, 2403 /* NOTE: the comma operator will make "cond" to eval to false,
1985 - * but float*_is_unordered() is still called  
1986 - */  
1987 -FOP_COND(s, sf, 1, (float32_is_unordered(FST0, FST1, &env->fp_status), 0))  
1988 -FOP_COND(s, ngle,1, float32_is_unordered(FST1, FST0, &env->fp_status))  
1989 -FOP_COND(s, seq, 1, float32_eq(FST0, FST1, &env->fp_status))  
1990 -FOP_COND(s, ngl, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))  
1991 -FOP_COND(s, lt, 1, float32_lt(FST0, FST1, &env->fp_status))  
1992 -FOP_COND(s, nge, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))  
1993 -FOP_COND(s, le, 1, float32_le(FST0, FST1, &env->fp_status))  
1994 -FOP_COND(s, ngt, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status)) 2404 + * but float*_is_unordered() is still called. */
  2405 +FOP_COND_S(sf, (float32_is_unordered(1, FST1, FST0, &env->fp_status), 0))
  2406 +FOP_COND_S(ngle,float32_is_unordered(1, FST1, FST0, &env->fp_status))
  2407 +FOP_COND_S(seq, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status))
  2408 +FOP_COND_S(ngl, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
  2409 +FOP_COND_S(lt, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status))
  2410 +FOP_COND_S(nge, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
  2411 +FOP_COND_S(le, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status))
  2412 +FOP_COND_S(ngt, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
  2413 +
  2414 +#define FOP_COND_PS(op, condl, condh) \
  2415 +void op_cmp_ps_ ## op (void) \
  2416 +{ \
  2417 + int cl = condl; \
  2418 + int ch = condh; \
  2419 + update_fcr31(); \
  2420 + if (cl) \
  2421 + SET_FP_COND(PARAM1, env); \
  2422 + else \
  2423 + CLEAR_FP_COND(PARAM1, env); \
  2424 + if (ch) \
  2425 + SET_FP_COND(PARAM1 + 1, env); \
  2426 + else \
  2427 + CLEAR_FP_COND(PARAM1 + 1, env); \
  2428 + DEBUG_FPU_STATE(); \
  2429 + RETURN(); \
  2430 +}
  2431 +
  2432 +/* NOTE: the comma operator will make "cond" to eval to false,
  2433 + * but float*_is_unordered() is still called. */
  2434 +FOP_COND_PS(f, (float32_is_unordered(0, FST1, FST0, &env->fp_status), 0),
  2435 + (float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status), 0))
  2436 +FOP_COND_PS(un, float32_is_unordered(0, FST1, FST0, &env->fp_status),
  2437 + float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status))
  2438 +FOP_COND_PS(eq, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status),
  2439 + !float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_eq(FSTH0, FSTH1, &env->fp_status))
  2440 +FOP_COND_PS(ueq, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status),
  2441 + float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) || float32_eq(FSTH0, FSTH1, &env->fp_status))
  2442 +FOP_COND_PS(olt, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status),
  2443 + !float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_lt(FSTH0, FSTH1, &env->fp_status))
  2444 +FOP_COND_PS(ult, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status),
  2445 + float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) || float32_lt(FSTH0, FSTH1, &env->fp_status))
  2446 +FOP_COND_PS(ole, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status),
  2447 + !float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_le(FSTH0, FSTH1, &env->fp_status))
  2448 +FOP_COND_PS(ule, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status),
  2449 + float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) || float32_le(FSTH0, FSTH1, &env->fp_status))
  2450 +/* NOTE: the comma operator will make "cond" to eval to false,
  2451 + * but float*_is_unordered() is still called. */
  2452 +FOP_COND_PS(sf, (float32_is_unordered(1, FST1, FST0, &env->fp_status), 0),
  2453 + (float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status), 0))
  2454 +FOP_COND_PS(ngle,float32_is_unordered(1, FST1, FST0, &env->fp_status),
  2455 + float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status))
  2456 +FOP_COND_PS(seq, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status),
  2457 + !float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_eq(FSTH0, FSTH1, &env->fp_status))
  2458 +FOP_COND_PS(ngl, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status),
  2459 + float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) || float32_eq(FSTH0, FSTH1, &env->fp_status))
  2460 +FOP_COND_PS(lt, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status),
  2461 + !float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_lt(FSTH0, FSTH1, &env->fp_status))
  2462 +FOP_COND_PS(nge, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status),
  2463 + float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) || float32_lt(FSTH0, FSTH1, &env->fp_status))
  2464 +FOP_COND_PS(le, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status),
  2465 + !float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_le(FSTH0, FSTH1, &env->fp_status))
  2466 +FOP_COND_PS(ngt, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status),
  2467 + float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) || float32_le(FSTH0, FSTH1, &env->fp_status))
1995 2468
1996 void op_bc1f (void) 2469 void op_bc1f (void)
1997 { 2470 {
1998 - T0 = ! IS_FP_COND_SET(env->fcr31); 2471 + T0 = !IS_FP_COND_SET(PARAM1, env);
  2472 + DEBUG_FPU_STATE();
  2473 + RETURN();
  2474 +}
  2475 +void op_bc1fany2 (void)
  2476 +{
  2477 + T0 = (!IS_FP_COND_SET(PARAM1, env) ||
  2478 + !IS_FP_COND_SET(PARAM1 + 1, env));
  2479 + DEBUG_FPU_STATE();
  2480 + RETURN();
  2481 +}
  2482 +void op_bc1fany4 (void)
  2483 +{
  2484 + T0 = (!IS_FP_COND_SET(PARAM1, env) ||
  2485 + !IS_FP_COND_SET(PARAM1 + 1, env) ||
  2486 + !IS_FP_COND_SET(PARAM1 + 2, env) ||
  2487 + !IS_FP_COND_SET(PARAM1 + 3, env));
1999 DEBUG_FPU_STATE(); 2488 DEBUG_FPU_STATE();
2000 RETURN(); 2489 RETURN();
2001 } 2490 }
2002 2491
2003 void op_bc1t (void) 2492 void op_bc1t (void)
2004 { 2493 {
2005 - T0 = IS_FP_COND_SET(env->fcr31); 2494 + T0 = IS_FP_COND_SET(PARAM1, env);
  2495 + DEBUG_FPU_STATE();
  2496 + RETURN();
  2497 +}
  2498 +void op_bc1tany2 (void)
  2499 +{
  2500 + T0 = (IS_FP_COND_SET(PARAM1, env) ||
  2501 + IS_FP_COND_SET(PARAM1 + 1, env));
  2502 + DEBUG_FPU_STATE();
  2503 + RETURN();
  2504 +}
  2505 +void op_bc1tany4 (void)
  2506 +{
  2507 + T0 = (IS_FP_COND_SET(PARAM1, env) ||
  2508 + IS_FP_COND_SET(PARAM1 + 1, env) ||
  2509 + IS_FP_COND_SET(PARAM1 + 2, env) ||
  2510 + IS_FP_COND_SET(PARAM1 + 3, env));
2006 DEBUG_FPU_STATE(); 2511 DEBUG_FPU_STATE();
2007 RETURN(); 2512 RETURN();
2008 } 2513 }
@@ -2037,7 +2542,7 @@ void op_tlbr (void) @@ -2037,7 +2542,7 @@ void op_tlbr (void)
2037 #if defined (CONFIG_USER_ONLY) 2542 #if defined (CONFIG_USER_ONLY)
2038 void op_tls_value (void) 2543 void op_tls_value (void)
2039 { 2544 {
2040 - T0 = env->tls_value; 2545 + T0 = env->tls_value;
2041 } 2546 }
2042 #endif 2547 #endif
2043 2548
@@ -2180,6 +2685,17 @@ void op_save_pc (void) @@ -2180,6 +2685,17 @@ void op_save_pc (void)
2180 RETURN(); 2685 RETURN();
2181 } 2686 }
2182 2687
  2688 +void op_save_fp_status (void)
  2689 +{
  2690 + union fps {
  2691 + uint32_t i;
  2692 + float_status f;
  2693 + } fps;
  2694 + fps.i = PARAM1;
  2695 + env->fp_status = fps.f;
  2696 + RETURN();
  2697 +}
  2698 +
2183 void op_interrupt_restart (void) 2699 void op_interrupt_restart (void)
2184 { 2700 {
2185 if (!(env->CP0_Status & (1 << CP0St_EXL)) && 2701 if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
target-mips/op_mem.c
@@ -220,3 +220,35 @@ void glue(op_sdc1, MEMSUFFIX) (void) @@ -220,3 +220,35 @@ void glue(op_sdc1, MEMSUFFIX) (void)
220 glue(stq, MEMSUFFIX)(T0, DT0); 220 glue(stq, MEMSUFFIX)(T0, DT0);
221 RETURN(); 221 RETURN();
222 } 222 }
  223 +void glue(op_lwxc1, MEMSUFFIX) (void)
  224 +{
  225 + WT0 = glue(ldl, MEMSUFFIX)(T0 + T1);
  226 + RETURN();
  227 +}
  228 +void glue(op_swxc1, MEMSUFFIX) (void)
  229 +{
  230 + glue(stl, MEMSUFFIX)(T0 + T1, WT0);
  231 + RETURN();
  232 +}
  233 +void glue(op_ldxc1, MEMSUFFIX) (void)
  234 +{
  235 + DT0 = glue(ldq, MEMSUFFIX)(T0 + T1);
  236 + RETURN();
  237 +}
  238 +void glue(op_sdxc1, MEMSUFFIX) (void)
  239 +{
  240 + glue(stq, MEMSUFFIX)(T0 + T1, DT0);
  241 + RETURN();
  242 +}
  243 +void glue(op_luxc1, MEMSUFFIX) (void)
  244 +{
  245 + /* XXX: is defined as unaligned */
  246 + DT0 = glue(ldq, MEMSUFFIX)(T0 + T1);
  247 + RETURN();
  248 +}
  249 +void glue(op_suxc1, MEMSUFFIX) (void)
  250 +{
  251 + /* XXX: is defined as unaligned */
  252 + glue(stq, MEMSUFFIX)(T0 + T1, DT0);
  253 + RETURN();
  254 +}
target-mips/translate.c
@@ -333,20 +333,26 @@ enum { @@ -333,20 +333,26 @@ enum {
333 OPC_MFC1 = (0x00 << 21) | OPC_CP1, 333 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
334 OPC_DMFC1 = (0x01 << 21) | OPC_CP1, 334 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
335 OPC_CFC1 = (0x02 << 21) | OPC_CP1, 335 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
336 - OPC_MFHCI = (0x03 << 21) | OPC_CP1, 336 + OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
337 OPC_MTC1 = (0x04 << 21) | OPC_CP1, 337 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
338 OPC_DMTC1 = (0x05 << 21) | OPC_CP1, 338 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
339 OPC_CTC1 = (0x06 << 21) | OPC_CP1, 339 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
340 - OPC_MTHCI = (0x07 << 21) | OPC_CP1, 340 + OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
341 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */ 341 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
  342 + OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
  343 + OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
342 OPC_S_FMT = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */ 344 OPC_S_FMT = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */
343 OPC_D_FMT = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */ 345 OPC_D_FMT = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */
344 OPC_E_FMT = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */ 346 OPC_E_FMT = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */
345 OPC_Q_FMT = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */ 347 OPC_Q_FMT = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */
346 OPC_W_FMT = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */ 348 OPC_W_FMT = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
347 OPC_L_FMT = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */ 349 OPC_L_FMT = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
  350 + OPC_PS_FMT = (0x16 << 21) | OPC_CP1, /* 22: fmt=paired single fp */
348 }; 351 };
349 352
  353 +#define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
  354 +#define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
  355 +
350 enum { 356 enum {
351 OPC_BC1F = (0x00 << 16) | OPC_BC1, 357 OPC_BC1F = (0x00 << 16) | OPC_BC1,
352 OPC_BC1T = (0x01 << 16) | OPC_BC1, 358 OPC_BC1T = (0x01 << 16) | OPC_BC1,
@@ -354,8 +360,15 @@ enum { @@ -354,8 +360,15 @@ enum {
354 OPC_BC1TL = (0x03 << 16) | OPC_BC1, 360 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
355 }; 361 };
356 362
357 -#define MASK_CP1_BCOND(op) MASK_CP1(op) | (op & (0x3 << 16))  
358 -#define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F) 363 +enum {
  364 + OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
  365 + OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
  366 +};
  367 +
  368 +enum {
  369 + OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
  370 + OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
  371 +};
359 372
360 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21)) 373 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
361 374
@@ -404,20 +417,20 @@ const unsigned char *regnames[] = @@ -404,20 +417,20 @@ const unsigned char *regnames[] =
404 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", }; 417 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
405 418
406 /* Warning: no function for r0 register (hard wired to zero) */ 419 /* Warning: no function for r0 register (hard wired to zero) */
407 -#define GEN32(func, NAME) \  
408 -static GenOpFunc *NAME ## _table [32] = { \  
409 -NULL, NAME ## 1, NAME ## 2, NAME ## 3, \  
410 -NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \  
411 -NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \  
412 -NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \  
413 -NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \  
414 -NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \  
415 -NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \  
416 -NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \  
417 -}; \  
418 -static inline void func(int n) \  
419 -{ \  
420 - NAME ## _table[n](); \ 420 +#define GEN32(func, NAME) \
  421 +static GenOpFunc *NAME ## _table [32] = { \
  422 +NULL, NAME ## 1, NAME ## 2, NAME ## 3, \
  423 +NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
  424 +NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
  425 +NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
  426 +NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
  427 +NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
  428 +NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
  429 +NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
  430 +}; \
  431 +static inline void func(int n) \
  432 +{ \
  433 + NAME ## _table[n](); \
421 } 434 }
422 435
423 /* General purpose registers moves */ 436 /* General purpose registers moves */
@@ -434,58 +447,51 @@ static const char *fregnames[] = @@ -434,58 +447,51 @@ static const char *fregnames[] =
434 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", 447 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
435 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", }; 448 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
436 449
437 -# define SFGEN32(func, NAME) \  
438 -static GenOpFunc *NAME ## _table [32] = { \  
439 -NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \  
440 -NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \  
441 -NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \  
442 -NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \  
443 -NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \  
444 -NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \  
445 -NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \  
446 -NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \  
447 -}; \  
448 -static inline void func(int n) \  
449 -{ \  
450 - NAME ## _table[n](); \ 450 +#define FGEN32(func, NAME) \
  451 +static GenOpFunc *NAME ## _table [32] = { \
  452 +NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
  453 +NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
  454 +NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
  455 +NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
  456 +NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
  457 +NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
  458 +NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
  459 +NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
  460 +}; \
  461 +static inline void func(int n) \
  462 +{ \
  463 + NAME ## _table[n](); \
451 } 464 }
452 465
453 -# define DFGEN32(func, NAME) \  
454 -static GenOpFunc *NAME ## _table [32] = { \  
455 -NAME ## 0, 0, NAME ## 2, 0, \  
456 -NAME ## 4, 0, NAME ## 6, 0, \  
457 -NAME ## 8, 0, NAME ## 10, 0, \  
458 -NAME ## 12, 0, NAME ## 14, 0, \  
459 -NAME ## 16, 0, NAME ## 18, 0, \  
460 -NAME ## 20, 0, NAME ## 22, 0, \  
461 -NAME ## 24, 0, NAME ## 26, 0, \  
462 -NAME ## 28, 0, NAME ## 30, 0, \  
463 -}; \  
464 -static inline void func(int n) \  
465 -{ \  
466 - NAME ## _table[n](); \  
467 -} 466 +FGEN32(gen_op_load_fpr_WT0, gen_op_load_fpr_WT0_fpr);
  467 +FGEN32(gen_op_store_fpr_WT0, gen_op_store_fpr_WT0_fpr);
  468 +
  469 +FGEN32(gen_op_load_fpr_WT1, gen_op_load_fpr_WT1_fpr);
  470 +FGEN32(gen_op_store_fpr_WT1, gen_op_store_fpr_WT1_fpr);
468 471
469 -SFGEN32(gen_op_load_fpr_WT0, gen_op_load_fpr_WT0_fpr);  
470 -SFGEN32(gen_op_store_fpr_WT0, gen_op_store_fpr_WT0_fpr); 472 +FGEN32(gen_op_load_fpr_WT2, gen_op_load_fpr_WT2_fpr);
  473 +FGEN32(gen_op_store_fpr_WT2, gen_op_store_fpr_WT2_fpr);
471 474
472 -SFGEN32(gen_op_load_fpr_WT1, gen_op_load_fpr_WT1_fpr);  
473 -SFGEN32(gen_op_store_fpr_WT1, gen_op_store_fpr_WT1_fpr); 475 +FGEN32(gen_op_load_fpr_DT0, gen_op_load_fpr_DT0_fpr);
  476 +FGEN32(gen_op_store_fpr_DT0, gen_op_store_fpr_DT0_fpr);
474 477
475 -SFGEN32(gen_op_load_fpr_WT2, gen_op_load_fpr_WT2_fpr);  
476 -SFGEN32(gen_op_store_fpr_WT2, gen_op_store_fpr_WT2_fpr); 478 +FGEN32(gen_op_load_fpr_DT1, gen_op_load_fpr_DT1_fpr);
  479 +FGEN32(gen_op_store_fpr_DT1, gen_op_store_fpr_DT1_fpr);
477 480
478 -DFGEN32(gen_op_load_fpr_DT0, gen_op_load_fpr_DT0_fpr);  
479 -DFGEN32(gen_op_store_fpr_DT0, gen_op_store_fpr_DT0_fpr); 481 +FGEN32(gen_op_load_fpr_DT2, gen_op_load_fpr_DT2_fpr);
  482 +FGEN32(gen_op_store_fpr_DT2, gen_op_store_fpr_DT2_fpr);
480 483
481 -DFGEN32(gen_op_load_fpr_DT1, gen_op_load_fpr_DT1_fpr);  
482 -DFGEN32(gen_op_store_fpr_DT1, gen_op_store_fpr_DT1_fpr); 484 +FGEN32(gen_op_load_fpr_WTH0, gen_op_load_fpr_WTH0_fpr);
  485 +FGEN32(gen_op_store_fpr_WTH0, gen_op_store_fpr_WTH0_fpr);
483 486
484 -DFGEN32(gen_op_load_fpr_DT2, gen_op_load_fpr_DT2_fpr);  
485 -DFGEN32(gen_op_store_fpr_DT2, gen_op_store_fpr_DT2_fpr); 487 +FGEN32(gen_op_load_fpr_WTH1, gen_op_load_fpr_WTH1_fpr);
  488 +FGEN32(gen_op_store_fpr_WTH1, gen_op_store_fpr_WTH1_fpr);
  489 +
  490 +FGEN32(gen_op_load_fpr_WTH2, gen_op_load_fpr_WTH2_fpr);
  491 +FGEN32(gen_op_store_fpr_WTH2, gen_op_store_fpr_WTH2_fpr);
486 492
487 #define FOP_CONDS(fmt) \ 493 #define FOP_CONDS(fmt) \
488 -static GenOpFunc * cond_ ## fmt ## _table[16] = { \ 494 +static GenOpFunc1 * cond_ ## fmt ## _table[16] = { \
489 gen_op_cmp_ ## fmt ## _f, \ 495 gen_op_cmp_ ## fmt ## _f, \
490 gen_op_cmp_ ## fmt ## _un, \ 496 gen_op_cmp_ ## fmt ## _un, \
491 gen_op_cmp_ ## fmt ## _eq, \ 497 gen_op_cmp_ ## fmt ## _eq, \
@@ -503,18 +509,20 @@ static GenOpFunc * cond_ ## fmt ## _table[16] = { \ @@ -503,18 +509,20 @@ static GenOpFunc * cond_ ## fmt ## _table[16] = { \
503 gen_op_cmp_ ## fmt ## _le, \ 509 gen_op_cmp_ ## fmt ## _le, \
504 gen_op_cmp_ ## fmt ## _ngt, \ 510 gen_op_cmp_ ## fmt ## _ngt, \
505 }; \ 511 }; \
506 -static inline void gen_cmp_ ## fmt(int n) \ 512 +static inline void gen_cmp_ ## fmt(int n, long cc) \
507 { \ 513 { \
508 - cond_ ## fmt ## _table[n](); \ 514 + cond_ ## fmt ## _table[n](cc); \
509 } 515 }
510 516
511 FOP_CONDS(d) 517 FOP_CONDS(d)
512 FOP_CONDS(s) 518 FOP_CONDS(s)
  519 +FOP_CONDS(ps)
513 520
514 typedef struct DisasContext { 521 typedef struct DisasContext {
515 struct TranslationBlock *tb; 522 struct TranslationBlock *tb;
516 target_ulong pc, saved_pc; 523 target_ulong pc, saved_pc;
517 uint32_t opcode; 524 uint32_t opcode;
  525 + uint32_t fp_status, saved_fp_status;
518 /* Routine used to access memory */ 526 /* Routine used to access memory */
519 int mem_idx; 527 int mem_idx;
520 uint32_t hflags, saved_hflags; 528 uint32_t hflags, saved_hflags;
@@ -600,17 +608,31 @@ static inline void save_cpu_state (DisasContext *ctx, int do_save_pc) @@ -600,17 +608,31 @@ static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
600 if (ctx->hflags != ctx->saved_hflags) { 608 if (ctx->hflags != ctx->saved_hflags) {
601 gen_op_save_state(ctx->hflags); 609 gen_op_save_state(ctx->hflags);
602 ctx->saved_hflags = ctx->hflags; 610 ctx->saved_hflags = ctx->hflags;
603 - if (ctx->hflags & MIPS_HFLAG_BR) { 611 + switch (ctx->hflags & MIPS_HFLAG_BMASK) {
  612 + case MIPS_HFLAG_BR:
604 gen_op_save_breg_target(); 613 gen_op_save_breg_target();
605 - } else if (ctx->hflags & MIPS_HFLAG_B) {  
606 - gen_op_save_btarget(ctx->btarget);  
607 - } else if (ctx->hflags & MIPS_HFLAG_BMASK) { 614 + break;
  615 + case MIPS_HFLAG_BC:
608 gen_op_save_bcond(); 616 gen_op_save_bcond();
  617 + /* fall through */
  618 + case MIPS_HFLAG_BL:
  619 + /* bcond was already saved by the BL insn */
  620 + /* fall through */
  621 + case MIPS_HFLAG_B:
609 gen_op_save_btarget(ctx->btarget); 622 gen_op_save_btarget(ctx->btarget);
  623 + break;
610 } 624 }
611 } 625 }
612 } 626 }
613 627
  628 +static inline void save_fpu_state (DisasContext *ctx)
  629 +{
  630 + if (ctx->fp_status != ctx->saved_fp_status) {
  631 + gen_op_save_fp_status(ctx->fp_status);
  632 + ctx->saved_fp_status = ctx->fp_status;
  633 + }
  634 +}
  635 +
614 static inline void generate_exception_err (DisasContext *ctx, int excp, int err) 636 static inline void generate_exception_err (DisasContext *ctx, int excp, int err)
615 { 637 {
616 #if defined MIPS_DEBUG_DISAS 638 #if defined MIPS_DEBUG_DISAS
@@ -677,6 +699,12 @@ OP_LD_TABLE(wc1); @@ -677,6 +699,12 @@ OP_LD_TABLE(wc1);
677 OP_ST_TABLE(wc1); 699 OP_ST_TABLE(wc1);
678 OP_LD_TABLE(dc1); 700 OP_LD_TABLE(dc1);
679 OP_ST_TABLE(dc1); 701 OP_ST_TABLE(dc1);
  702 +OP_LD_TABLE(wxc1);
  703 +OP_ST_TABLE(wxc1);
  704 +OP_LD_TABLE(dxc1);
  705 +OP_ST_TABLE(dxc1);
  706 +OP_LD_TABLE(uxc1);
  707 +OP_ST_TABLE(uxc1);
680 708
681 /* Load and store */ 709 /* Load and store */
682 static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, 710 static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
@@ -1472,7 +1500,7 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, @@ -1472,7 +1500,7 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
1472 if (ctx->hflags & MIPS_HFLAG_BMASK) { 1500 if (ctx->hflags & MIPS_HFLAG_BMASK) {
1473 if (loglevel & CPU_LOG_TB_IN_ASM) { 1501 if (loglevel & CPU_LOG_TB_IN_ASM) {
1474 fprintf(logfile, 1502 fprintf(logfile,
1475 - "undefined branch in delay slot at PC " TARGET_FMT_lx "\n", 1503 + "Branch in delay slot at PC 0x" TARGET_FMT_lx "\n",
1476 ctx->pc); 1504 ctx->pc);
1477 } 1505 }
1478 MIPS_INVAL("branch/jump in bdelay slot"); 1506 MIPS_INVAL("branch/jump in bdelay slot");
@@ -1672,6 +1700,7 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, @@ -1672,6 +1700,7 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
1672 MIPS_DEBUG("bltzal %s, %08x", regnames[rs], btarget); 1700 MIPS_DEBUG("bltzal %s, %08x", regnames[rs], btarget);
1673 not_likely: 1701 not_likely:
1674 ctx->hflags |= MIPS_HFLAG_BC; 1702 ctx->hflags |= MIPS_HFLAG_BC;
  1703 + gen_op_set_bcond();
1675 break; 1704 break;
1676 case OPC_BLTZALL: 1705 case OPC_BLTZALL:
1677 gen_op_ltz(); 1706 gen_op_ltz();
@@ -1679,13 +1708,14 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, @@ -1679,13 +1708,14 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
1679 MIPS_DEBUG("bltzall %s, %08x", regnames[rs], btarget); 1708 MIPS_DEBUG("bltzall %s, %08x", regnames[rs], btarget);
1680 likely: 1709 likely:
1681 ctx->hflags |= MIPS_HFLAG_BL; 1710 ctx->hflags |= MIPS_HFLAG_BL;
  1711 + gen_op_set_bcond();
  1712 + gen_op_save_bcond();
1682 break; 1713 break;
1683 default: 1714 default:
1684 MIPS_INVAL("conditional branch/jump"); 1715 MIPS_INVAL("conditional branch/jump");
1685 generate_exception(ctx, EXCP_RI); 1716 generate_exception(ctx, EXCP_RI);
1686 return; 1717 return;
1687 } 1718 }
1688 - gen_op_set_bcond();  
1689 } 1719 }
1690 MIPS_DEBUG("enter ds: link %d cond %02x target %08x", 1720 MIPS_DEBUG("enter ds: link %d cond %02x target %08x",
1691 blink, ctx->hflags, btarget); 1721 blink, ctx->hflags, btarget);
@@ -4220,7 +4250,7 @@ static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd) @@ -4220,7 +4250,7 @@ static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd)
4220 4250
4221 /* CP1 Branches (before delay slot) */ 4251 /* CP1 Branches (before delay slot) */
4222 static void gen_compute_branch1 (DisasContext *ctx, uint32_t op, 4252 static void gen_compute_branch1 (DisasContext *ctx, uint32_t op,
4223 - int32_t offset) 4253 + int32_t cc, int32_t offset)
4224 { 4254 {
4225 target_ulong btarget; 4255 target_ulong btarget;
4226 4256
@@ -4228,31 +4258,49 @@ static void gen_compute_branch1 (DisasContext *ctx, uint32_t op, @@ -4228,31 +4258,49 @@ static void gen_compute_branch1 (DisasContext *ctx, uint32_t op,
4228 4258
4229 switch (op) { 4259 switch (op) {
4230 case OPC_BC1F: 4260 case OPC_BC1F:
4231 - gen_op_bc1f(); 4261 + gen_op_bc1f(cc);
4232 MIPS_DEBUG("bc1f " TARGET_FMT_lx, btarget); 4262 MIPS_DEBUG("bc1f " TARGET_FMT_lx, btarget);
4233 goto not_likely; 4263 goto not_likely;
4234 case OPC_BC1FL: 4264 case OPC_BC1FL:
4235 - gen_op_bc1f(); 4265 + gen_op_bc1f(cc);
4236 MIPS_DEBUG("bc1fl " TARGET_FMT_lx, btarget); 4266 MIPS_DEBUG("bc1fl " TARGET_FMT_lx, btarget);
4237 goto likely; 4267 goto likely;
4238 case OPC_BC1T: 4268 case OPC_BC1T:
4239 - gen_op_bc1t(); 4269 + gen_op_bc1t(cc);
4240 MIPS_DEBUG("bc1t " TARGET_FMT_lx, btarget); 4270 MIPS_DEBUG("bc1t " TARGET_FMT_lx, btarget);
4241 - not_likely:  
4242 - ctx->hflags |= MIPS_HFLAG_BC;  
4243 - break; 4271 + goto not_likely;
4244 case OPC_BC1TL: 4272 case OPC_BC1TL:
4245 - gen_op_bc1t(); 4273 + gen_op_bc1t(cc);
4246 MIPS_DEBUG("bc1tl " TARGET_FMT_lx, btarget); 4274 MIPS_DEBUG("bc1tl " TARGET_FMT_lx, btarget);
4247 likely: 4275 likely:
4248 ctx->hflags |= MIPS_HFLAG_BL; 4276 ctx->hflags |= MIPS_HFLAG_BL;
  4277 + gen_op_set_bcond();
  4278 + gen_op_save_bcond();
4249 break; 4279 break;
4250 - default:  
4251 - MIPS_INVAL("cp1 branch/jump"); 4280 + case OPC_BC1FANY2:
  4281 + gen_op_bc1fany2(cc);
  4282 + MIPS_DEBUG("bc1fany2 " TARGET_FMT_lx, btarget);
  4283 + goto not_likely;
  4284 + case OPC_BC1TANY2:
  4285 + gen_op_bc1tany2(cc);
  4286 + MIPS_DEBUG("bc1tany2 " TARGET_FMT_lx, btarget);
  4287 + goto not_likely;
  4288 + case OPC_BC1FANY4:
  4289 + gen_op_bc1fany4(cc);
  4290 + MIPS_DEBUG("bc1fany4 " TARGET_FMT_lx, btarget);
  4291 + goto not_likely;
  4292 + case OPC_BC1TANY4:
  4293 + gen_op_bc1tany4(cc);
  4294 + MIPS_DEBUG("bc1tany4 " TARGET_FMT_lx, btarget);
  4295 + not_likely:
  4296 + ctx->hflags |= MIPS_HFLAG_BC;
  4297 + gen_op_set_bcond();
  4298 + break;
  4299 + default:
  4300 + MIPS_INVAL("cp1 branch");
4252 generate_exception (ctx, EXCP_RI); 4301 generate_exception (ctx, EXCP_RI);
4253 return; 4302 return;
4254 } 4303 }
4255 - gen_op_set_bcond();  
4256 4304
4257 MIPS_DEBUG("enter ds: cond %02x target " TARGET_FMT_lx, 4305 MIPS_DEBUG("enter ds: cond %02x target " TARGET_FMT_lx,
4258 ctx->hflags, btarget); 4306 ctx->hflags, btarget);
@@ -4262,6 +4310,29 @@ static void gen_compute_branch1 (DisasContext *ctx, uint32_t op, @@ -4262,6 +4310,29 @@ static void gen_compute_branch1 (DisasContext *ctx, uint32_t op,
4262 } 4310 }
4263 4311
4264 /* Coprocessor 1 (FPU) */ 4312 /* Coprocessor 1 (FPU) */
  4313 +
  4314 +/* verify if floating point register is valid; an operation is not defined
  4315 + * if bit 0 of any register specification is set and the FR bit in the
  4316 + * Status register equals zero, since the register numbers specify an
  4317 + * even-odd pair of adjacent coprocessor general registers. When the FR bit
  4318 + * in the Status register equals one, both even and odd register numbers
  4319 + * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
  4320 + *
  4321 + * Multiple 64 bit wide registers can be checked by calling
  4322 + * CHECK_FR(ctx, freg1 | freg2 | ... | fregN);
  4323 + *
  4324 + * FIXME: This is broken for R2, it needs to be checked at runtime, not
  4325 + * at translation time.
  4326 + */
  4327 +#define CHECK_FR(ctx, freg) do { \
  4328 + if (!((ctx)->CP0_Status & (1 << CP0St_FR)) && ((freg) & 1)) { \
  4329 + generate_exception (ctx, EXCP_RI); \
  4330 + return; \
  4331 + } \
  4332 + } while(0)
  4333 +
  4334 +#define FOP(func, fmt) (((fmt) << 21) | (func))
  4335 +
4265 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs) 4336 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
4266 { 4337 {
4267 const char *opn = "unk"; 4338 const char *opn = "unk";
@@ -4280,30 +4351,43 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs) @@ -4280,30 +4351,43 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
4280 opn = "mtc1"; 4351 opn = "mtc1";
4281 break; 4352 break;
4282 case OPC_CFC1: 4353 case OPC_CFC1:
4283 - if (fs != 0 && fs != 31) {  
4284 - MIPS_INVAL("cfc1 freg");  
4285 - generate_exception (ctx, EXCP_RI);  
4286 - return;  
4287 - }  
4288 GEN_LOAD_IMM_TN(T1, fs); 4354 GEN_LOAD_IMM_TN(T1, fs);
4289 gen_op_cfc1(); 4355 gen_op_cfc1();
4290 GEN_STORE_TN_REG(rt, T0); 4356 GEN_STORE_TN_REG(rt, T0);
4291 opn = "cfc1"; 4357 opn = "cfc1";
4292 break; 4358 break;
4293 case OPC_CTC1: 4359 case OPC_CTC1:
4294 - if (fs != 0 && fs != 31) {  
4295 - MIPS_INVAL("ctc1 freg");  
4296 - generate_exception (ctx, EXCP_RI);  
4297 - return;  
4298 - }  
4299 GEN_LOAD_IMM_TN(T1, fs); 4360 GEN_LOAD_IMM_TN(T1, fs);
4300 GEN_LOAD_REG_TN(T0, rt); 4361 GEN_LOAD_REG_TN(T0, rt);
4301 gen_op_ctc1(); 4362 gen_op_ctc1();
4302 opn = "ctc1"; 4363 opn = "ctc1";
4303 break; 4364 break;
4304 case OPC_DMFC1: 4365 case OPC_DMFC1:
  4366 + GEN_LOAD_FREG_FTN(DT0, fs);
  4367 + gen_op_dmfc1();
  4368 + GEN_STORE_TN_REG(rt, T0);
  4369 + opn = "dmfc1";
  4370 + break;
4305 case OPC_DMTC1: 4371 case OPC_DMTC1:
4306 - /* Not implemented, fallthrough. */ 4372 + GEN_LOAD_REG_TN(T0, rt);
  4373 + gen_op_dmtc1();
  4374 + GEN_STORE_FTN_FREG(fs, DT0);
  4375 + opn = "dmtc1";
  4376 + break;
  4377 + case OPC_MFHC1:
  4378 + CHECK_FR(ctx, fs);
  4379 + GEN_LOAD_FREG_FTN(WTH0, fs);
  4380 + gen_op_mfhc1();
  4381 + GEN_STORE_TN_REG(rt, T0);
  4382 + opn = "mfhc1";
  4383 + break;
  4384 + case OPC_MTHC1:
  4385 + CHECK_FR(ctx, fs);
  4386 + GEN_LOAD_REG_TN(T0, rt);
  4387 + gen_op_mthc1();
  4388 + GEN_STORE_FTN_FREG(fs, WTH0);
  4389 + opn = "mthc1";
  4390 + break;
4307 default: 4391 default:
4308 if (loglevel & CPU_LOG_TB_IN_ASM) { 4392 if (loglevel & CPU_LOG_TB_IN_ASM) {
4309 fprintf(logfile, "Invalid CP1 opcode: %08x %03x %03x %03x\n", 4393 fprintf(logfile, "Invalid CP1 opcode: %08x %03x %03x %03x\n",
@@ -4316,26 +4400,44 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs) @@ -4316,26 +4400,44 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
4316 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]); 4400 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
4317 } 4401 }
4318 4402
4319 -/* verify if floating point register is valid; an operation is not defined  
4320 - * if bit 0 of any register specification is set and the FR bit in the  
4321 - * Status register equals zero, since the register numbers specify an  
4322 - * even-odd pair of adjacent coprocessor general registers. When the FR bit  
4323 - * in the Status register equals one, both even and odd register numbers  
4324 - * are valid. This limitation exists only for 64 bit wide (d,l) registers.  
4325 - *  
4326 - * Multiple 64 bit wide registers can be checked by calling  
4327 - * CHECK_FR(ctx, freg1 | freg2 | ... | fregN);  
4328 - */  
4329 -#define CHECK_FR(ctx, freg) do { \  
4330 - if (!((ctx)->CP0_Status & (1<<CP0St_FR)) && ((freg) & 1)) { \  
4331 - generate_exception (ctx, EXCP_RI); \  
4332 - return; \  
4333 - } \  
4334 - } while(0) 4403 +static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
  4404 +{
  4405 + uint32_t ccbit;
4335 4406
4336 -#define FOP(func, fmt) (((fmt) << 21) | (func)) 4407 + GEN_LOAD_REG_TN(T0, rd);
  4408 + GEN_LOAD_REG_TN(T1, rs);
  4409 + if (cc)
  4410 + ccbit = 1 << (24 + cc);
  4411 + else
  4412 + ccbit = 1 << 23;
  4413 + if (!tf)
  4414 + gen_op_movf(ccbit);
  4415 + else
  4416 + gen_op_movt(ccbit);
  4417 + GEN_STORE_TN_REG(rd, T0);
  4418 +}
  4419 +
  4420 +#define GEN_MOVCF(fmt) \
  4421 +static void glue(gen_movcf_, fmt) (DisasContext *ctx, int cc, int tf) \
  4422 +{ \
  4423 + uint32_t ccbit; \
  4424 + \
  4425 + if (cc) \
  4426 + ccbit = 1 << (24 + cc); \
  4427 + else \
  4428 + ccbit = 1 << 23; \
  4429 + if (!tf) \
  4430 + glue(gen_op_float_movf_, fmt)(ccbit); \
  4431 + else \
  4432 + glue(gen_op_float_movt_, fmt)(ccbit); \
  4433 +}
  4434 +GEN_MOVCF(d);
  4435 +GEN_MOVCF(s);
  4436 +GEN_MOVCF(ps);
  4437 +#undef GEN_MOVCF
4337 4438
4338 -static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, int fs, int fd) 4439 +static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
  4440 + int fs, int fd, int cc)
4339 { 4441 {
4340 const char *opn = "unk"; 4442 const char *opn = "unk";
4341 const char *condnames[] = { 4443 const char *condnames[] = {
@@ -4360,6 +4462,187 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, int fs, int fd) @@ -4360,6 +4462,187 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, int fs, int fd)
4360 uint32_t func = ctx->opcode & 0x3f; 4462 uint32_t func = ctx->opcode & 0x3f;
4361 4463
4362 switch (ctx->opcode & FOP(0x3f, 0x1f)) { 4464 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
  4465 + case FOP(0, 16):
  4466 + GEN_LOAD_FREG_FTN(WT0, fs);
  4467 + GEN_LOAD_FREG_FTN(WT1, ft);
  4468 + gen_op_float_add_s();
  4469 + GEN_STORE_FTN_FREG(fd, WT2);
  4470 + opn = "add.s";
  4471 + binary = 1;
  4472 + break;
  4473 + case FOP(1, 16):
  4474 + GEN_LOAD_FREG_FTN(WT0, fs);
  4475 + GEN_LOAD_FREG_FTN(WT1, ft);
  4476 + gen_op_float_sub_s();
  4477 + GEN_STORE_FTN_FREG(fd, WT2);
  4478 + opn = "sub.s";
  4479 + binary = 1;
  4480 + break;
  4481 + case FOP(2, 16):
  4482 + GEN_LOAD_FREG_FTN(WT0, fs);
  4483 + GEN_LOAD_FREG_FTN(WT1, ft);
  4484 + gen_op_float_mul_s();
  4485 + GEN_STORE_FTN_FREG(fd, WT2);
  4486 + opn = "mul.s";
  4487 + binary = 1;
  4488 + break;
  4489 + case FOP(3, 16):
  4490 + GEN_LOAD_FREG_FTN(WT0, fs);
  4491 + GEN_LOAD_FREG_FTN(WT1, ft);
  4492 + gen_op_float_div_s();
  4493 + GEN_STORE_FTN_FREG(fd, WT2);
  4494 + opn = "div.s";
  4495 + binary = 1;
  4496 + break;
  4497 + case FOP(4, 16):
  4498 + GEN_LOAD_FREG_FTN(WT0, fs);
  4499 + gen_op_float_sqrt_s();
  4500 + GEN_STORE_FTN_FREG(fd, WT2);
  4501 + opn = "sqrt.s";
  4502 + break;
  4503 + case FOP(5, 16):
  4504 + GEN_LOAD_FREG_FTN(WT0, fs);
  4505 + gen_op_float_abs_s();
  4506 + GEN_STORE_FTN_FREG(fd, WT2);
  4507 + opn = "abs.s";
  4508 + break;
  4509 + case FOP(6, 16):
  4510 + GEN_LOAD_FREG_FTN(WT0, fs);
  4511 + gen_op_float_mov_s();
  4512 + GEN_STORE_FTN_FREG(fd, WT2);
  4513 + opn = "mov.s";
  4514 + break;
  4515 + case FOP(7, 16):
  4516 + GEN_LOAD_FREG_FTN(WT0, fs);
  4517 + gen_op_float_chs_s();
  4518 + GEN_STORE_FTN_FREG(fd, WT2);
  4519 + opn = "neg.s";
  4520 + break;
  4521 + case FOP(8, 16):
  4522 + CHECK_FR(ctx, fs);
  4523 + GEN_LOAD_FREG_FTN(WT0, fs);
  4524 + gen_op_float_roundl_s();
  4525 + GEN_STORE_FTN_FREG(fd, DT2);
  4526 + opn = "round.l.s";
  4527 + break;
  4528 + case FOP(9, 16):
  4529 + CHECK_FR(ctx, fs);
  4530 + GEN_LOAD_FREG_FTN(WT0, fs);
  4531 + gen_op_float_truncl_s();
  4532 + GEN_STORE_FTN_FREG(fd, DT2);
  4533 + opn = "trunc.l.s";
  4534 + break;
  4535 + case FOP(10, 16):
  4536 + CHECK_FR(ctx, fs);
  4537 + GEN_LOAD_FREG_FTN(WT0, fs);
  4538 + gen_op_float_ceill_s();
  4539 + GEN_STORE_FTN_FREG(fd, DT2);
  4540 + opn = "ceil.l.s";
  4541 + break;
  4542 + case FOP(11, 16):
  4543 + CHECK_FR(ctx, fs);
  4544 + GEN_LOAD_FREG_FTN(WT0, fs);
  4545 + gen_op_float_floorl_s();
  4546 + GEN_STORE_FTN_FREG(fd, DT2);
  4547 + opn = "floor.l.s";
  4548 + break;
  4549 + case FOP(12, 16):
  4550 + GEN_LOAD_FREG_FTN(WT0, fs);
  4551 + gen_op_float_roundw_s();
  4552 + GEN_STORE_FTN_FREG(fd, WT2);
  4553 + opn = "round.w.s";
  4554 + break;
  4555 + case FOP(13, 16):
  4556 + GEN_LOAD_FREG_FTN(WT0, fs);
  4557 + gen_op_float_truncw_s();
  4558 + GEN_STORE_FTN_FREG(fd, WT2);
  4559 + opn = "trunc.w.s";
  4560 + break;
  4561 + case FOP(14, 16):
  4562 + GEN_LOAD_FREG_FTN(WT0, fs);
  4563 + gen_op_float_ceilw_s();
  4564 + GEN_STORE_FTN_FREG(fd, WT2);
  4565 + opn = "ceil.w.s";
  4566 + break;
  4567 + case FOP(15, 16):
  4568 + GEN_LOAD_FREG_FTN(WT0, fs);
  4569 + gen_op_float_floorw_s();
  4570 + GEN_STORE_FTN_FREG(fd, WT2);
  4571 + opn = "floor.w.s";
  4572 + break;
  4573 + case FOP(17, 16):
  4574 + GEN_LOAD_REG_TN(T0, ft);
  4575 + GEN_LOAD_FREG_FTN(WT0, fs);
  4576 + GEN_LOAD_FREG_FTN(WT2, fd);
  4577 + gen_movcf_s(ctx, (ft >> 2) & 0x7, ft & 0x1);
  4578 + GEN_STORE_FTN_FREG(fd, WT2);
  4579 + opn = "movcf.s";
  4580 + break;
  4581 + case FOP(18, 16):
  4582 + GEN_LOAD_REG_TN(T0, ft);
  4583 + GEN_LOAD_FREG_FTN(WT0, fs);
  4584 + GEN_LOAD_FREG_FTN(WT2, fd);
  4585 + gen_op_float_movz_s();
  4586 + GEN_STORE_FTN_FREG(fd, WT2);
  4587 + opn = "movz.s";
  4588 + break;
  4589 + case FOP(19, 16):
  4590 + GEN_LOAD_REG_TN(T0, ft);
  4591 + GEN_LOAD_FREG_FTN(WT0, fs);
  4592 + GEN_LOAD_FREG_FTN(WT2, fd);
  4593 + gen_op_float_movn_s();
  4594 + GEN_STORE_FTN_FREG(fd, WT2);
  4595 + opn = "movn.s";
  4596 + break;
  4597 + case FOP(33, 16):
  4598 + CHECK_FR(ctx, fd);
  4599 + GEN_LOAD_FREG_FTN(WT0, fs);
  4600 + gen_op_float_cvtd_s();
  4601 + GEN_STORE_FTN_FREG(fd, DT2);
  4602 + opn = "cvt.d.s";
  4603 + break;
  4604 + case FOP(36, 16):
  4605 + GEN_LOAD_FREG_FTN(WT0, fs);
  4606 + gen_op_float_cvtw_s();
  4607 + GEN_STORE_FTN_FREG(fd, WT2);
  4608 + opn = "cvt.w.s";
  4609 + break;
  4610 + case FOP(37, 16):
  4611 + CHECK_FR(ctx, fs | fd);
  4612 + GEN_LOAD_FREG_FTN(WT0, fs);
  4613 + gen_op_float_cvtl_s();
  4614 + GEN_STORE_FTN_FREG(fd, DT2);
  4615 + opn = "cvt.l.s";
  4616 + break;
  4617 + case FOP(38, 16):
  4618 + CHECK_FR(ctx, fs | ft | fd);
  4619 + GEN_LOAD_FREG_FTN(WT1, fs);
  4620 + GEN_LOAD_FREG_FTN(WT0, ft);
  4621 + gen_op_float_cvtps_s();
  4622 + GEN_STORE_FTN_FREG(fd, DT2);
  4623 + opn = "cvt.ps.s";
  4624 + break;
  4625 + case FOP(48, 16):
  4626 + case FOP(49, 16):
  4627 + case FOP(50, 16):
  4628 + case FOP(51, 16):
  4629 + case FOP(52, 16):
  4630 + case FOP(53, 16):
  4631 + case FOP(54, 16):
  4632 + case FOP(55, 16):
  4633 + case FOP(56, 16):
  4634 + case FOP(57, 16):
  4635 + case FOP(58, 16):
  4636 + case FOP(59, 16):
  4637 + case FOP(60, 16):
  4638 + case FOP(61, 16):
  4639 + case FOP(62, 16):
  4640 + case FOP(63, 16):
  4641 + GEN_LOAD_FREG_FTN(WT0, fs);
  4642 + GEN_LOAD_FREG_FTN(WT1, ft);
  4643 + gen_cmp_s(func-48, cc);
  4644 + opn = condnames[func-48];
  4645 + break;
4363 case FOP(0, 17): 4646 case FOP(0, 17):
4364 CHECK_FR(ctx, fs | ft | fd); 4647 CHECK_FR(ctx, fs | ft | fd);
4365 GEN_LOAD_FREG_FTN(DT0, fs); 4648 GEN_LOAD_FREG_FTN(DT0, fs);
@@ -4424,10 +4707,34 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, int fs, int fd) @@ -4424,10 +4707,34 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, int fs, int fd)
4424 GEN_STORE_FTN_FREG(fd, DT2); 4707 GEN_STORE_FTN_FREG(fd, DT2);
4425 opn = "neg.d"; 4708 opn = "neg.d";
4426 break; 4709 break;
4427 - /* 8 - round.l */  
4428 - /* 9 - trunc.l */  
4429 - /* 10 - ceil.l */  
4430 - /* 11 - floor.l */ 4710 + case FOP(8, 17):
  4711 + CHECK_FR(ctx, fs);
  4712 + GEN_LOAD_FREG_FTN(DT0, fs);
  4713 + gen_op_float_roundl_d();
  4714 + GEN_STORE_FTN_FREG(fd, DT2);
  4715 + opn = "round.l.d";
  4716 + break;
  4717 + case FOP(9, 17):
  4718 + CHECK_FR(ctx, fs);
  4719 + GEN_LOAD_FREG_FTN(DT0, fs);
  4720 + gen_op_float_truncl_d();
  4721 + GEN_STORE_FTN_FREG(fd, DT2);
  4722 + opn = "trunc.l.d";
  4723 + break;
  4724 + case FOP(10, 17):
  4725 + CHECK_FR(ctx, fs);
  4726 + GEN_LOAD_FREG_FTN(DT0, fs);
  4727 + gen_op_float_ceill_d();
  4728 + GEN_STORE_FTN_FREG(fd, DT2);
  4729 + opn = "ceil.l.d";
  4730 + break;
  4731 + case FOP(11, 17):
  4732 + CHECK_FR(ctx, fs);
  4733 + GEN_LOAD_FREG_FTN(DT0, fs);
  4734 + gen_op_float_floorl_d();
  4735 + GEN_STORE_FTN_FREG(fd, DT2);
  4736 + opn = "floor.l.d";
  4737 + break;
4431 case FOP(12, 17): 4738 case FOP(12, 17):
4432 CHECK_FR(ctx, fs); 4739 CHECK_FR(ctx, fs);
4433 GEN_LOAD_FREG_FTN(DT0, fs); 4740 GEN_LOAD_FREG_FTN(DT0, fs);
@@ -4456,19 +4763,29 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, int fs, int fd) @@ -4456,19 +4763,29 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, int fs, int fd)
4456 GEN_STORE_FTN_FREG(fd, WT2); 4763 GEN_STORE_FTN_FREG(fd, WT2);
4457 opn = "floor.w.d"; 4764 opn = "floor.w.d";
4458 break; 4765 break;
4459 - case FOP(33, 16):  
4460 - CHECK_FR(ctx, fd);  
4461 - GEN_LOAD_FREG_FTN(WT0, fs);  
4462 - gen_op_float_cvtd_s(); 4766 + case FOP(17, 17):
  4767 + GEN_LOAD_REG_TN(T0, ft);
  4768 + GEN_LOAD_FREG_FTN(DT0, fs);
  4769 + GEN_LOAD_FREG_FTN(DT2, fd);
  4770 + gen_movcf_d(ctx, (ft >> 2) & 0x7, ft & 0x1);
4463 GEN_STORE_FTN_FREG(fd, DT2); 4771 GEN_STORE_FTN_FREG(fd, DT2);
4464 - opn = "cvt.d.s"; 4772 + opn = "movcf.d";
4465 break; 4773 break;
4466 - case FOP(33, 20):  
4467 - CHECK_FR(ctx, fd);  
4468 - GEN_LOAD_FREG_FTN(WT0, fs);  
4469 - gen_op_float_cvtd_w(); 4774 + case FOP(18, 17):
  4775 + GEN_LOAD_REG_TN(T0, ft);
  4776 + GEN_LOAD_FREG_FTN(DT0, fs);
  4777 + GEN_LOAD_FREG_FTN(DT2, fd);
  4778 + gen_op_float_movz_d();
4470 GEN_STORE_FTN_FREG(fd, DT2); 4779 GEN_STORE_FTN_FREG(fd, DT2);
4471 - opn = "cvt.d.w"; 4780 + opn = "movz.d";
  4781 + break;
  4782 + case FOP(19, 17):
  4783 + GEN_LOAD_REG_TN(T0, ft);
  4784 + GEN_LOAD_FREG_FTN(DT0, fs);
  4785 + GEN_LOAD_FREG_FTN(DT2, fd);
  4786 + gen_op_float_movn_d();
  4787 + GEN_STORE_FTN_FREG(fd, DT2);
  4788 + opn = "movn.d";
4472 break; 4789 break;
4473 case FOP(48, 17): 4790 case FOP(48, 17):
4474 case FOP(49, 17): 4791 case FOP(49, 17):
@@ -4489,125 +4806,240 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, int fs, int fd) @@ -4489,125 +4806,240 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, int fs, int fd)
4489 CHECK_FR(ctx, fs | ft); 4806 CHECK_FR(ctx, fs | ft);
4490 GEN_LOAD_FREG_FTN(DT0, fs); 4807 GEN_LOAD_FREG_FTN(DT0, fs);
4491 GEN_LOAD_FREG_FTN(DT1, ft); 4808 GEN_LOAD_FREG_FTN(DT1, ft);
4492 - gen_cmp_d(func-48); 4809 + gen_cmp_d(func-48, cc);
4493 opn = condnames[func-48]; 4810 opn = condnames[func-48];
4494 break; 4811 break;
4495 - case FOP(0, 16): 4812 + case FOP(32, 17):
  4813 + CHECK_FR(ctx, fs);
  4814 + GEN_LOAD_FREG_FTN(DT0, fs);
  4815 + gen_op_float_cvts_d();
  4816 + GEN_STORE_FTN_FREG(fd, WT2);
  4817 + opn = "cvt.s.d";
  4818 + break;
  4819 + case FOP(36, 17):
  4820 + CHECK_FR(ctx, fs);
  4821 + GEN_LOAD_FREG_FTN(DT0, fs);
  4822 + gen_op_float_cvtw_d();
  4823 + GEN_STORE_FTN_FREG(fd, WT2);
  4824 + opn = "cvt.w.d";
  4825 + break;
  4826 + case FOP(37, 17):
  4827 + CHECK_FR(ctx, fs | fd);
  4828 + GEN_LOAD_FREG_FTN(DT0, fs);
  4829 + gen_op_float_cvtl_d();
  4830 + GEN_STORE_FTN_FREG(fd, DT2);
  4831 + opn = "cvt.l.d";
  4832 + break;
  4833 + case FOP(32, 20):
4496 GEN_LOAD_FREG_FTN(WT0, fs); 4834 GEN_LOAD_FREG_FTN(WT0, fs);
4497 - GEN_LOAD_FREG_FTN(WT1, ft);  
4498 - gen_op_float_add_s(); 4835 + gen_op_float_cvts_w();
4499 GEN_STORE_FTN_FREG(fd, WT2); 4836 GEN_STORE_FTN_FREG(fd, WT2);
4500 - opn = "add.s";  
4501 - binary = 1; 4837 + opn = "cvt.s.w";
4502 break; 4838 break;
4503 - case FOP(1, 16): 4839 + case FOP(33, 20):
  4840 + CHECK_FR(ctx, fd);
4504 GEN_LOAD_FREG_FTN(WT0, fs); 4841 GEN_LOAD_FREG_FTN(WT0, fs);
  4842 + gen_op_float_cvtd_w();
  4843 + GEN_STORE_FTN_FREG(fd, DT2);
  4844 + opn = "cvt.d.w";
  4845 + break;
  4846 + case FOP(32, 21):
  4847 + CHECK_FR(ctx, fs);
  4848 + GEN_LOAD_FREG_FTN(DT0, fs);
  4849 + gen_op_float_cvts_l();
  4850 + GEN_STORE_FTN_FREG(fd, WT2);
  4851 + opn = "cvt.s.l";
  4852 + break;
  4853 + case FOP(33, 21):
  4854 + CHECK_FR(ctx, fs | fd);
  4855 + GEN_LOAD_FREG_FTN(DT0, fs);
  4856 + gen_op_float_cvtd_l();
  4857 + GEN_STORE_FTN_FREG(fd, DT2);
  4858 + opn = "cvt.d.l";
  4859 + break;
  4860 + case FOP(38, 20):
  4861 + case FOP(38, 21):
  4862 + CHECK_FR(ctx, fs | fd);
  4863 + GEN_LOAD_FREG_FTN(WT0, fs);
  4864 + GEN_LOAD_FREG_FTN(WTH0, fs);
  4865 + gen_op_float_cvtps_pw();
  4866 + GEN_STORE_FTN_FREG(fd, WT2);
  4867 + GEN_STORE_FTN_FREG(fd, WTH2);
  4868 + opn = "cvt.ps.pw";
  4869 + break;
  4870 + case FOP(0, 22):
  4871 + CHECK_FR(ctx, fs | ft | fd);
  4872 + GEN_LOAD_FREG_FTN(WT0, fs);
  4873 + GEN_LOAD_FREG_FTN(WTH0, fs);
4505 GEN_LOAD_FREG_FTN(WT1, ft); 4874 GEN_LOAD_FREG_FTN(WT1, ft);
4506 - gen_op_float_sub_s(); 4875 + GEN_LOAD_FREG_FTN(WTH1, ft);
  4876 + gen_op_float_add_ps();
4507 GEN_STORE_FTN_FREG(fd, WT2); 4877 GEN_STORE_FTN_FREG(fd, WT2);
4508 - opn = "sub.s";  
4509 - binary = 1; 4878 + GEN_STORE_FTN_FREG(fd, WTH2);
  4879 + opn = "add.ps";
4510 break; 4880 break;
4511 - case FOP(2, 16): 4881 + case FOP(1, 22):
  4882 + CHECK_FR(ctx, fs | ft | fd);
4512 GEN_LOAD_FREG_FTN(WT0, fs); 4883 GEN_LOAD_FREG_FTN(WT0, fs);
  4884 + GEN_LOAD_FREG_FTN(WTH0, fs);
4513 GEN_LOAD_FREG_FTN(WT1, ft); 4885 GEN_LOAD_FREG_FTN(WT1, ft);
4514 - gen_op_float_mul_s(); 4886 + GEN_LOAD_FREG_FTN(WTH1, ft);
  4887 + gen_op_float_sub_ps();
4515 GEN_STORE_FTN_FREG(fd, WT2); 4888 GEN_STORE_FTN_FREG(fd, WT2);
4516 - opn = "mul.s";  
4517 - binary = 1; 4889 + GEN_STORE_FTN_FREG(fd, WTH2);
  4890 + opn = "sub.ps";
4518 break; 4891 break;
4519 - case FOP(3, 16): 4892 + case FOP(2, 22):
  4893 + CHECK_FR(ctx, fs | ft | fd);
4520 GEN_LOAD_FREG_FTN(WT0, fs); 4894 GEN_LOAD_FREG_FTN(WT0, fs);
  4895 + GEN_LOAD_FREG_FTN(WTH0, fs);
4521 GEN_LOAD_FREG_FTN(WT1, ft); 4896 GEN_LOAD_FREG_FTN(WT1, ft);
4522 - gen_op_float_div_s(); 4897 + GEN_LOAD_FREG_FTN(WTH1, ft);
  4898 + gen_op_float_mul_ps();
4523 GEN_STORE_FTN_FREG(fd, WT2); 4899 GEN_STORE_FTN_FREG(fd, WT2);
4524 - opn = "div.s";  
4525 - binary = 1; 4900 + GEN_STORE_FTN_FREG(fd, WTH2);
  4901 + opn = "mul.ps";
4526 break; 4902 break;
4527 - case FOP(4, 16): 4903 + case FOP(5, 22):
  4904 + CHECK_FR(ctx, fs | fd);
4528 GEN_LOAD_FREG_FTN(WT0, fs); 4905 GEN_LOAD_FREG_FTN(WT0, fs);
4529 - gen_op_float_sqrt_s(); 4906 + GEN_LOAD_FREG_FTN(WTH0, fs);
  4907 + gen_op_float_abs_ps();
4530 GEN_STORE_FTN_FREG(fd, WT2); 4908 GEN_STORE_FTN_FREG(fd, WT2);
4531 - opn = "sqrt.s"; 4909 + GEN_STORE_FTN_FREG(fd, WTH2);
  4910 + opn = "abs.ps";
4532 break; 4911 break;
4533 - case FOP(5, 16): 4912 + case FOP(6, 22):
  4913 + CHECK_FR(ctx, fs | fd);
4534 GEN_LOAD_FREG_FTN(WT0, fs); 4914 GEN_LOAD_FREG_FTN(WT0, fs);
4535 - gen_op_float_abs_s(); 4915 + GEN_LOAD_FREG_FTN(WTH0, fs);
  4916 + gen_op_float_mov_ps();
4536 GEN_STORE_FTN_FREG(fd, WT2); 4917 GEN_STORE_FTN_FREG(fd, WT2);
4537 - opn = "abs.s"; 4918 + GEN_STORE_FTN_FREG(fd, WTH2);
  4919 + opn = "mov.ps";
4538 break; 4920 break;
4539 - case FOP(6, 16): 4921 + case FOP(7, 22):
  4922 + CHECK_FR(ctx, fs | fd);
4540 GEN_LOAD_FREG_FTN(WT0, fs); 4923 GEN_LOAD_FREG_FTN(WT0, fs);
4541 - gen_op_float_mov_s(); 4924 + GEN_LOAD_FREG_FTN(WTH0, fs);
  4925 + gen_op_float_chs_ps();
4542 GEN_STORE_FTN_FREG(fd, WT2); 4926 GEN_STORE_FTN_FREG(fd, WT2);
4543 - opn = "mov.s"; 4927 + GEN_STORE_FTN_FREG(fd, WTH2);
  4928 + opn = "neg.ps";
4544 break; 4929 break;
4545 - case FOP(7, 16): 4930 + case FOP(17, 22):
  4931 + GEN_LOAD_REG_TN(T0, ft);
4546 GEN_LOAD_FREG_FTN(WT0, fs); 4932 GEN_LOAD_FREG_FTN(WT0, fs);
4547 - gen_op_float_chs_s(); 4933 + GEN_LOAD_FREG_FTN(WTH0, fs);
  4934 + GEN_LOAD_FREG_FTN(WT2, fd);
  4935 + GEN_LOAD_FREG_FTN(WTH2, fd);
  4936 + gen_movcf_ps(ctx, (ft >> 2) & 0x7, ft & 0x1);
4548 GEN_STORE_FTN_FREG(fd, WT2); 4937 GEN_STORE_FTN_FREG(fd, WT2);
4549 - opn = "neg.s"; 4938 + GEN_STORE_FTN_FREG(fd, WTH2);
  4939 + opn = "movcf.ps";
4550 break; 4940 break;
4551 - case FOP(12, 16): 4941 + case FOP(18, 22):
  4942 + GEN_LOAD_REG_TN(T0, ft);
4552 GEN_LOAD_FREG_FTN(WT0, fs); 4943 GEN_LOAD_FREG_FTN(WT0, fs);
4553 - gen_op_float_roundw_s(); 4944 + GEN_LOAD_FREG_FTN(WTH0, fs);
  4945 + GEN_LOAD_FREG_FTN(WT2, fd);
  4946 + GEN_LOAD_FREG_FTN(WTH2, fd);
  4947 + gen_op_float_movz_ps();
4554 GEN_STORE_FTN_FREG(fd, WT2); 4948 GEN_STORE_FTN_FREG(fd, WT2);
4555 - opn = "round.w.s"; 4949 + GEN_STORE_FTN_FREG(fd, WTH2);
  4950 + opn = "movz.ps";
4556 break; 4951 break;
4557 - case FOP(13, 16): 4952 + case FOP(19, 22):
  4953 + GEN_LOAD_REG_TN(T0, ft);
4558 GEN_LOAD_FREG_FTN(WT0, fs); 4954 GEN_LOAD_FREG_FTN(WT0, fs);
4559 - gen_op_float_truncw_s(); 4955 + GEN_LOAD_FREG_FTN(WTH0, fs);
  4956 + GEN_LOAD_FREG_FTN(WT2, fd);
  4957 + GEN_LOAD_FREG_FTN(WTH2, fd);
  4958 + gen_op_float_movn_ps();
4560 GEN_STORE_FTN_FREG(fd, WT2); 4959 GEN_STORE_FTN_FREG(fd, WT2);
4561 - opn = "trunc.w.s"; 4960 + GEN_STORE_FTN_FREG(fd, WTH2);
  4961 + opn = "movn.ps";
4562 break; 4962 break;
4563 - case FOP(32, 17): 4963 + case FOP(32, 22):
4564 CHECK_FR(ctx, fs); 4964 CHECK_FR(ctx, fs);
4565 - GEN_LOAD_FREG_FTN(DT0, fs);  
4566 - gen_op_float_cvts_d(); 4965 + GEN_LOAD_FREG_FTN(WTH0, fs);
  4966 + gen_op_float_cvts_pu();
4567 GEN_STORE_FTN_FREG(fd, WT2); 4967 GEN_STORE_FTN_FREG(fd, WT2);
4568 - opn = "cvt.s.d"; 4968 + opn = "cvt.s.pu";
4569 break; 4969 break;
4570 - case FOP(32, 20): 4970 + case FOP(36, 22):
  4971 + CHECK_FR(ctx, fs | fd);
4571 GEN_LOAD_FREG_FTN(WT0, fs); 4972 GEN_LOAD_FREG_FTN(WT0, fs);
4572 - gen_op_float_cvts_w(); 4973 + GEN_LOAD_FREG_FTN(WTH0, fs);
  4974 + gen_op_float_cvtpw_ps();
4573 GEN_STORE_FTN_FREG(fd, WT2); 4975 GEN_STORE_FTN_FREG(fd, WT2);
4574 - opn = "cvt.s.w"; 4976 + GEN_STORE_FTN_FREG(fd, WTH2);
  4977 + opn = "cvt.pw.ps";
4575 break; 4978 break;
4576 - case FOP(36, 16): 4979 + case FOP(40, 22):
  4980 + CHECK_FR(ctx, fs);
4577 GEN_LOAD_FREG_FTN(WT0, fs); 4981 GEN_LOAD_FREG_FTN(WT0, fs);
4578 - gen_op_float_cvtw_s(); 4982 + gen_op_float_cvts_pl();
4579 GEN_STORE_FTN_FREG(fd, WT2); 4983 GEN_STORE_FTN_FREG(fd, WT2);
4580 - opn = "cvt.w.s"; 4984 + opn = "cvt.s.pl";
4581 break; 4985 break;
4582 - case FOP(36, 17):  
4583 - CHECK_FR(ctx, fs);  
4584 - GEN_LOAD_FREG_FTN(DT0, fs);  
4585 - gen_op_float_cvtw_d();  
4586 - GEN_STORE_FTN_FREG(fd, WT2);  
4587 - opn = "cvt.w.d"; 4986 + case FOP(44, 22):
  4987 + CHECK_FR(ctx, fs | ft | fd);
  4988 + GEN_LOAD_FREG_FTN(WT0, fs);
  4989 + GEN_LOAD_FREG_FTN(WT1, ft);
  4990 + gen_op_float_pll_ps();
  4991 + GEN_STORE_FTN_FREG(fd, DT2);
  4992 + opn = "pll.ps";
4588 break; 4993 break;
4589 - case FOP(48, 16):  
4590 - case FOP(49, 16):  
4591 - case FOP(50, 16):  
4592 - case FOP(51, 16):  
4593 - case FOP(52, 16):  
4594 - case FOP(53, 16):  
4595 - case FOP(54, 16):  
4596 - case FOP(55, 16):  
4597 - case FOP(56, 16):  
4598 - case FOP(57, 16):  
4599 - case FOP(58, 16):  
4600 - case FOP(59, 16):  
4601 - case FOP(60, 16):  
4602 - case FOP(61, 16):  
4603 - case FOP(62, 16):  
4604 - case FOP(63, 16): 4994 + case FOP(45, 22):
  4995 + CHECK_FR(ctx, fs | ft | fd);
4605 GEN_LOAD_FREG_FTN(WT0, fs); 4996 GEN_LOAD_FREG_FTN(WT0, fs);
  4997 + GEN_LOAD_FREG_FTN(WTH1, ft);
  4998 + gen_op_float_plu_ps();
  4999 + GEN_STORE_FTN_FREG(fd, DT2);
  5000 + opn = "plu.ps";
  5001 + break;
  5002 + case FOP(46, 22):
  5003 + CHECK_FR(ctx, fs | ft | fd);
  5004 + GEN_LOAD_FREG_FTN(WTH0, fs);
4606 GEN_LOAD_FREG_FTN(WT1, ft); 5005 GEN_LOAD_FREG_FTN(WT1, ft);
4607 - gen_cmp_s(func-48); 5006 + gen_op_float_pul_ps();
  5007 + GEN_STORE_FTN_FREG(fd, DT2);
  5008 + opn = "pul.ps";
  5009 + break;
  5010 + case FOP(47, 22):
  5011 + CHECK_FR(ctx, fs | ft | fd);
  5012 + GEN_LOAD_FREG_FTN(WTH0, fs);
  5013 + GEN_LOAD_FREG_FTN(WTH1, ft);
  5014 + gen_op_float_puu_ps();
  5015 + GEN_STORE_FTN_FREG(fd, DT2);
  5016 + opn = "puu.ps";
  5017 + break;
  5018 + case FOP(48, 22):
  5019 + case FOP(49, 22):
  5020 + case FOP(50, 22):
  5021 + case FOP(51, 22):
  5022 + case FOP(52, 22):
  5023 + case FOP(53, 22):
  5024 + case FOP(54, 22):
  5025 + case FOP(55, 22):
  5026 + case FOP(56, 22):
  5027 + case FOP(57, 22):
  5028 + case FOP(58, 22):
  5029 + case FOP(59, 22):
  5030 + case FOP(60, 22):
  5031 + case FOP(61, 22):
  5032 + case FOP(62, 22):
  5033 + case FOP(63, 22):
  5034 + CHECK_FR(ctx, fs | ft);
  5035 + GEN_LOAD_FREG_FTN(WT0, fs);
  5036 + GEN_LOAD_FREG_FTN(WTH0, fs);
  5037 + GEN_LOAD_FREG_FTN(WT1, ft);
  5038 + GEN_LOAD_FREG_FTN(WTH1, ft);
  5039 + gen_cmp_ps(func-48, cc);
4608 opn = condnames[func-48]; 5040 opn = condnames[func-48];
4609 break; 5041 break;
4610 - default: 5042 + default:
4611 if (loglevel & CPU_LOG_TB_IN_ASM) { 5043 if (loglevel & CPU_LOG_TB_IN_ASM) {
4612 fprintf(logfile, "Invalid FP arith function: %08x %03x %03x %03x\n", 5044 fprintf(logfile, "Invalid FP arith function: %08x %03x %03x %03x\n",
4613 ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F, 5045 ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
@@ -4622,18 +5054,134 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, int fs, int fd) @@ -4622,18 +5054,134 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, int fs, int fd)
4622 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]); 5054 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
4623 } 5055 }
4624 5056
4625 -static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf) 5057 +/* Coprocessor 3 (FPU) */
  5058 +static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc, int fd,
  5059 + int base, int index)
4626 { 5060 {
4627 - uint32_t ccbit; 5061 + const char *opn = "unk";
4628 5062
4629 - if (cc)  
4630 - ccbit = 1 << (24 + cc);  
4631 - else  
4632 - ccbit = 1 << 23;  
4633 - if (!tf)  
4634 - gen_op_movf(ccbit, rd, rs);  
4635 - else  
4636 - gen_op_movt(ccbit, rd, rs); 5063 + GEN_LOAD_REG_TN(T0, base);
  5064 + GEN_LOAD_REG_TN(T1, index);
  5065 + /* Don't do NOP if destination is zero: we must perform the actual
  5066 + * memory access
  5067 + */
  5068 + switch (opc) {
  5069 + case OPC_LWXC1:
  5070 + op_ldst(lwxc1);
  5071 + GEN_STORE_FTN_FREG(fd, WT0);
  5072 + opn = "lwxc1";
  5073 + break;
  5074 + case OPC_LDXC1:
  5075 + op_ldst(ldxc1);
  5076 + GEN_STORE_FTN_FREG(fd, DT0);
  5077 + opn = "ldxc1";
  5078 + break;
  5079 + case OPC_LUXC1:
  5080 + op_ldst(luxc1);
  5081 + GEN_STORE_FTN_FREG(fd, DT0);
  5082 + opn = "luxc1";
  5083 + break;
  5084 + case OPC_SWXC1:
  5085 + GEN_LOAD_FREG_FTN(WT0, fd);
  5086 + op_ldst(swxc1);
  5087 + opn = "swxc1";
  5088 + break;
  5089 + case OPC_SDXC1:
  5090 + GEN_LOAD_FREG_FTN(DT0, fd);
  5091 + op_ldst(sdxc1);
  5092 + opn = "sdxc1";
  5093 + break;
  5094 + case OPC_SUXC1:
  5095 + GEN_LOAD_FREG_FTN(DT0, fd);
  5096 + op_ldst(suxc1);
  5097 + opn = "suxc1";
  5098 + break;
  5099 + default:
  5100 + MIPS_INVAL("extended float load/store");
  5101 + generate_exception(ctx, EXCP_RI);
  5102 + return;
  5103 + }
  5104 + MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[fd],regnames[index], regnames[base]);
  5105 +}
  5106 +
  5107 +static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, int fd,
  5108 + int fr, int fs, int ft)
  5109 +{
  5110 + const char *opn = "unk";
  5111 +
  5112 + /* All of those work only on 64bit FPUs. */
  5113 + CHECK_FR(ctx, fd | fr | fs | ft);
  5114 + switch (opc) {
  5115 + case OPC_ALNV_PS:
  5116 + GEN_LOAD_REG_TN(T0, fr);
  5117 + GEN_LOAD_FREG_FTN(DT0, fs);
  5118 + GEN_LOAD_FREG_FTN(DT1, ft);
  5119 + gen_op_float_alnv_ps();
  5120 + GEN_STORE_FTN_FREG(fd, DT2);
  5121 + opn = "alnv.ps";
  5122 + break;
  5123 + case OPC_MADD_S:
  5124 + GEN_LOAD_FREG_FTN(WT0, fs);
  5125 + GEN_LOAD_FREG_FTN(WT1, ft);
  5126 + GEN_LOAD_FREG_FTN(WT2, fr);
  5127 + gen_op_float_muladd_s();
  5128 + GEN_STORE_FTN_FREG(fd, WT2);
  5129 + opn = "madd.s";
  5130 + break;
  5131 + case OPC_MADD_D:
  5132 + generate_exception (ctx, EXCP_RI);
  5133 + opn = "madd.d";
  5134 + break;
  5135 + case OPC_MADD_PS:
  5136 + generate_exception (ctx, EXCP_RI);
  5137 + opn = "madd.ps";
  5138 + break;
  5139 + case OPC_MSUB_S:
  5140 + generate_exception (ctx, EXCP_RI);
  5141 + opn = "msub.s";
  5142 + break;
  5143 + case OPC_MSUB_D:
  5144 + generate_exception (ctx, EXCP_RI);
  5145 + opn = "msub.d";
  5146 + break;
  5147 + case OPC_MSUB_PS:
  5148 + generate_exception (ctx, EXCP_RI);
  5149 + opn = "msub.ps";
  5150 + break;
  5151 + case OPC_NMADD_S:
  5152 + generate_exception (ctx, EXCP_RI);
  5153 + opn = "nmadd.s";
  5154 + break;
  5155 + case OPC_NMADD_D:
  5156 + generate_exception (ctx, EXCP_RI);
  5157 + opn = "nmadd.d";
  5158 + break;
  5159 + case OPC_NMADD_PS:
  5160 + generate_exception (ctx, EXCP_RI);
  5161 + opn = "nmadd.ps";
  5162 + break;
  5163 + case OPC_NMSUB_S:
  5164 + generate_exception (ctx, EXCP_RI);
  5165 + opn = "nmsub.s";
  5166 + break;
  5167 + case OPC_NMSUB_D:
  5168 + generate_exception (ctx, EXCP_RI);
  5169 + opn = "nmsub.d";
  5170 + break;
  5171 + case OPC_NMSUB_PS:
  5172 + generate_exception (ctx, EXCP_RI);
  5173 + opn = "nmsub.ps";
  5174 + break;
  5175 + default:
  5176 + if (loglevel & CPU_LOG_TB_IN_ASM) {
  5177 + fprintf(logfile, "Invalid extended FP arith function: %08x %03x %03x\n",
  5178 + ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F);
  5179 + }
  5180 + generate_exception (ctx, EXCP_RI);
  5181 + return;
  5182 + }
  5183 + MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
  5184 + fregnames[fs], fregnames[ft]);
4637 } 5185 }
4638 5186
4639 /* ISA extensions (ASEs) */ 5187 /* ISA extensions (ASEs) */
@@ -4641,23 +5189,12 @@ static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf) @@ -4641,23 +5189,12 @@ static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
4641 /* SmartMIPS extension to MIPS32 */ 5189 /* SmartMIPS extension to MIPS32 */
4642 5190
4643 #ifdef TARGET_MIPS64 5191 #ifdef TARGET_MIPS64
4644 -/* Coprocessor 3 (FPU) */  
4645 5192
4646 /* MDMX extension to MIPS64 */ 5193 /* MDMX extension to MIPS64 */
4647 /* MIPS-3D extension to MIPS64 */ 5194 /* MIPS-3D extension to MIPS64 */
4648 5195
4649 #endif 5196 #endif
4650 5197
4651 -static void gen_blikely(DisasContext *ctx)  
4652 -{  
4653 - int l1;  
4654 - l1 = gen_new_label();  
4655 - gen_op_jnz_T2(l1);  
4656 - gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);  
4657 - gen_goto_tb(ctx, 1, ctx->pc + 4);  
4658 - gen_set_label(l1);  
4659 -}  
4660 -  
4661 static void decode_opc (CPUState *env, DisasContext *ctx) 5198 static void decode_opc (CPUState *env, DisasContext *ctx)
4662 { 5199 {
4663 int32_t offset; 5200 int32_t offset;
@@ -4673,9 +5210,14 @@ static void decode_opc (CPUState *env, DisasContext *ctx) @@ -4673,9 +5210,14 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
4673 } 5210 }
4674 5211
4675 if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) { 5212 if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
  5213 + int l1;
4676 /* Handle blikely not taken case */ 5214 /* Handle blikely not taken case */
4677 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4); 5215 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
4678 - gen_blikely(ctx); 5216 + l1 = gen_new_label();
  5217 + gen_op_jnz_T2(l1);
  5218 + gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
  5219 + gen_goto_tb(ctx, 1, ctx->pc + 4);
  5220 + gen_set_label(l1);
4679 } 5221 }
4680 op = MASK_OP_MAJOR(ctx->opcode); 5222 op = MASK_OP_MAJOR(ctx->opcode);
4681 rs = (ctx->opcode >> 21) & 0x1f; 5223 rs = (ctx->opcode >> 21) & 0x1f;
@@ -5024,16 +5566,21 @@ static void decode_opc (CPUState *env, DisasContext *ctx) @@ -5024,16 +5566,21 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
5024 case OPC_DMFC1: 5566 case OPC_DMFC1:
5025 case OPC_DMTC1: 5567 case OPC_DMTC1:
5026 #endif 5568 #endif
  5569 + case OPC_MFHC1:
  5570 + case OPC_MTHC1:
5027 gen_cp1(ctx, op1, rt, rd); 5571 gen_cp1(ctx, op1, rt, rd);
5028 break; 5572 break;
5029 case OPC_BC1: 5573 case OPC_BC1:
5030 - gen_compute_branch1(ctx, MASK_CP1_BCOND(ctx->opcode), imm << 2); 5574 + gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
  5575 + (rt >> 2) & 0x7, imm << 2);
5031 return; 5576 return;
5032 case OPC_S_FMT: 5577 case OPC_S_FMT:
5033 case OPC_D_FMT: 5578 case OPC_D_FMT:
5034 case OPC_W_FMT: 5579 case OPC_W_FMT:
5035 case OPC_L_FMT: 5580 case OPC_L_FMT:
5036 - gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa); 5581 + case OPC_PS_FMT:
  5582 + gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
  5583 + (imm >> 8) & 0x7);
5037 break; 5584 break;
5038 default: 5585 default:
5039 generate_exception (ctx, EXCP_RI); 5586 generate_exception (ctx, EXCP_RI);
@@ -5060,10 +5607,32 @@ static void decode_opc (CPUState *env, DisasContext *ctx) @@ -5060,10 +5607,32 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
5060 gen_op_cp1_enabled(); 5607 gen_op_cp1_enabled();
5061 op1 = MASK_CP3(ctx->opcode); 5608 op1 = MASK_CP3(ctx->opcode);
5062 switch (op1) { 5609 switch (op1) {
  5610 + case OPC_LWXC1:
  5611 + case OPC_LDXC1:
  5612 + case OPC_LUXC1:
  5613 + case OPC_SWXC1:
  5614 + case OPC_SDXC1:
  5615 + case OPC_SUXC1:
  5616 + gen_flt3_ldst(ctx, op1, sa, rs, rt);
  5617 + break;
5063 case OPC_PREFX: 5618 case OPC_PREFX:
5064 /* treat as noop */ 5619 /* treat as noop */
5065 break; 5620 break;
5066 - /* Not implemented */ 5621 + case OPC_ALNV_PS:
  5622 + case OPC_MADD_S:
  5623 + case OPC_MADD_D:
  5624 + case OPC_MADD_PS:
  5625 + case OPC_MSUB_S:
  5626 + case OPC_MSUB_D:
  5627 + case OPC_MSUB_PS:
  5628 + case OPC_NMADD_S:
  5629 + case OPC_NMADD_D:
  5630 + case OPC_NMADD_PS:
  5631 + case OPC_NMSUB_S:
  5632 + case OPC_NMSUB_D:
  5633 + case OPC_NMSUB_PS:
  5634 + gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
  5635 + break;
5067 default: 5636 default:
5068 generate_exception (ctx, EXCP_RI); 5637 generate_exception (ctx, EXCP_RI);
5069 break; 5638 break;
@@ -5107,7 +5676,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx) @@ -5107,7 +5676,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
5107 ctx->hflags &= ~MIPS_HFLAG_BMASK; 5676 ctx->hflags &= ~MIPS_HFLAG_BMASK;
5108 ctx->bstate = BS_BRANCH; 5677 ctx->bstate = BS_BRANCH;
5109 save_cpu_state(ctx, 0); 5678 save_cpu_state(ctx, 0);
5110 - switch (hflags & MIPS_HFLAG_BMASK) { 5679 + switch (hflags) {
5111 case MIPS_HFLAG_B: 5680 case MIPS_HFLAG_B:
5112 /* unconditional branch */ 5681 /* unconditional branch */
5113 MIPS_DEBUG("unconditional branch"); 5682 MIPS_DEBUG("unconditional branch");
@@ -5134,6 +5703,8 @@ static void decode_opc (CPUState *env, DisasContext *ctx) @@ -5134,6 +5703,8 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
5134 /* unconditional branch to register */ 5703 /* unconditional branch to register */
5135 MIPS_DEBUG("branch to register"); 5704 MIPS_DEBUG("branch to register");
5136 gen_op_breg(); 5705 gen_op_breg();
  5706 + gen_op_reset_T0();
  5707 + gen_op_exit_tb();
5137 break; 5708 break;
5138 default: 5709 default:
5139 MIPS_DEBUG("unknown branch"); 5710 MIPS_DEBUG("unknown branch");
@@ -5166,16 +5737,18 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, @@ -5166,16 +5737,18 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
5166 /* Restore delay slot state from the tb context. */ 5737 /* Restore delay slot state from the tb context. */
5167 ctx.hflags = tb->flags; 5738 ctx.hflags = tb->flags;
5168 ctx.saved_hflags = ctx.hflags; 5739 ctx.saved_hflags = ctx.hflags;
5169 - if (ctx.hflags & MIPS_HFLAG_BR) { 5740 + switch (ctx.hflags & MIPS_HFLAG_BMASK) {
  5741 + case MIPS_HFLAG_BR:
5170 gen_op_restore_breg_target(); 5742 gen_op_restore_breg_target();
5171 - } else if (ctx.hflags & MIPS_HFLAG_B) { 5743 + break;
  5744 + case MIPS_HFLAG_B:
5172 ctx.btarget = env->btarget; 5745 ctx.btarget = env->btarget;
5173 - } else if (ctx.hflags & MIPS_HFLAG_BMASK) {  
5174 - /* If we are in the delay slot of a conditional branch,  
5175 - * restore the branch condition from env->bcond to T2  
5176 - */ 5746 + break;
  5747 + case MIPS_HFLAG_BC:
  5748 + case MIPS_HFLAG_BL:
5177 ctx.btarget = env->btarget; 5749 ctx.btarget = env->btarget;
5178 gen_op_restore_bcond(); 5750 gen_op_restore_bcond();
  5751 + break;
5179 } 5752 }
5180 #if defined(CONFIG_USER_ONLY) 5753 #if defined(CONFIG_USER_ONLY)
5181 ctx.mem_idx = 0; 5754 ctx.mem_idx = 0;
@@ -5237,12 +5810,6 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, @@ -5237,12 +5810,6 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
5237 gen_op_debug(); 5810 gen_op_debug();
5238 } else { 5811 } else {
5239 switch (ctx.bstate) { 5812 switch (ctx.bstate) {
5240 - case BS_EXCP:  
5241 - gen_op_interrupt_restart();  
5242 - gen_op_reset_T0();  
5243 - /* Generate the return instruction. */  
5244 - gen_op_exit_tb();  
5245 - break;  
5246 case BS_STOP: 5813 case BS_STOP:
5247 gen_op_interrupt_restart(); 5814 gen_op_interrupt_restart();
5248 /* Fall through. */ 5815 /* Fall through. */
@@ -5250,12 +5817,14 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, @@ -5250,12 +5817,14 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
5250 save_cpu_state(ctxp, 0); 5817 save_cpu_state(ctxp, 0);
5251 gen_goto_tb(&ctx, 0, ctx.pc); 5818 gen_goto_tb(&ctx, 0, ctx.pc);
5252 break; 5819 break;
5253 - case BS_BRANCH:  
5254 - default: 5820 + case BS_EXCP:
  5821 + gen_op_interrupt_restart();
5255 gen_op_reset_T0(); 5822 gen_op_reset_T0();
5256 - /* Generate the return instruction. */  
5257 gen_op_exit_tb(); 5823 gen_op_exit_tb();
5258 break; 5824 break;
  5825 + case BS_BRANCH:
  5826 + default:
  5827 + break;
5259 } 5828 }
5260 } 5829 }
5261 done_generating: 5830 done_generating:
@@ -5307,21 +5876,33 @@ void fpu_dump_state(CPUState *env, FILE *f, @@ -5307,21 +5876,33 @@ void fpu_dump_state(CPUState *env, FILE *f,
5307 int flags) 5876 int flags)
5308 { 5877 {
5309 int i; 5878 int i;
5310 -  
5311 -# define printfpr(fp) do { \  
5312 - fpu_fprintf(f, "w:%08x d:%08lx%08lx fd:%g fs:%g\n", \  
5313 - (fp)->w[FP_ENDIAN_IDX], (fp)->w[0], (fp)->w[1], (fp)->fd, (fp)->fs[FP_ENDIAN_IDX]); \ 5879 + int is_fpu64 = !!(env->CP0_Status & (1 << CP0St_FR));
  5880 +
  5881 +#define printfpr(fp) \
  5882 + do { \
  5883 + if (is_fpu64) \
  5884 + fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n", \
  5885 + (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd, \
  5886 + (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
  5887 + else { \
  5888 + fpr_t tmp; \
  5889 + tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
  5890 + tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
  5891 + fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n", \
  5892 + tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd, \
  5893 + tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]); \
  5894 + } \
5314 } while(0) 5895 } while(0)
5315 5896
5316 - fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d\n",  
5317 - env->fcr0, env->fcr31,  
5318 - (env->CP0_Status & (1 << CP0St_FR)) != 0); 5897 +
  5898 + fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
  5899 + env->fcr0, env->fcr31, is_fpu64, env->fp_status, get_float_exception_flags(&env->fp_status));
5319 fpu_fprintf(f, "FT0: "); printfpr(&env->ft0); 5900 fpu_fprintf(f, "FT0: "); printfpr(&env->ft0);
5320 fpu_fprintf(f, "FT1: "); printfpr(&env->ft1); 5901 fpu_fprintf(f, "FT1: "); printfpr(&env->ft1);
5321 fpu_fprintf(f, "FT2: "); printfpr(&env->ft2); 5902 fpu_fprintf(f, "FT2: "); printfpr(&env->ft2);
5322 - for(i = 0; i < 32; i += 2) {  
5323 - fpu_fprintf(f, "%s: ", fregnames[i]);  
5324 - printfpr(FPR(env, i)); 5903 + for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
  5904 + fpu_fprintf(f, "%3s: ", fregnames[i]);
  5905 + printfpr(&env->fpr[i]);
5325 } 5906 }
5326 5907
5327 #undef printfpr 5908 #undef printfpr
target-mips/translate_init.c
@@ -55,7 +55,7 @@ @@ -55,7 +55,7 @@
55 55
56 /* Define a implementation number of 1. 56 /* Define a implementation number of 1.
57 Define a major version 1, minor version 0. */ 57 Define a major version 1, minor version 0. */
58 -#define MIPS_FCR0 ((0 << 16) | (1 << 8) | (1 << 4) | 0) 58 +#define MIPS_FCR0 ((0 << FCR0_S) | (0x1 << FCR0_PRID) | (0x10 << FCR0_REV))
59 59
60 60
61 struct mips_def_t { 61 struct mips_def_t {
@@ -69,6 +69,7 @@ struct mips_def_t { @@ -69,6 +69,7 @@ struct mips_def_t {
69 int32_t CP0_Config7; 69 int32_t CP0_Config7;
70 int32_t SYNCI_Step; 70 int32_t SYNCI_Step;
71 int32_t CCRes; 71 int32_t CCRes;
  72 + int32_t Status_rw_bitmask;
72 int32_t CP1_fcr0; 73 int32_t CP1_fcr0;
73 }; 74 };
74 75
@@ -86,7 +87,7 @@ static mips_def_t mips_defs[] = @@ -86,7 +87,7 @@ static mips_def_t mips_defs[] =
86 .CP0_Config3 = MIPS_CONFIG3, 87 .CP0_Config3 = MIPS_CONFIG3,
87 .SYNCI_Step = 32, 88 .SYNCI_Step = 32,
88 .CCRes = 2, 89 .CCRes = 2,
89 - .CP1_fcr0 = MIPS_FCR0, 90 + .Status_rw_bitmask = 0x3278FF17,
90 }, 91 },
91 { 92 {
92 .name = "4KEcR1", 93 .name = "4KEcR1",
@@ -97,7 +98,6 @@ static mips_def_t mips_defs[] = @@ -97,7 +98,6 @@ static mips_def_t mips_defs[] =
97 .CP0_Config3 = MIPS_CONFIG3, 98 .CP0_Config3 = MIPS_CONFIG3,
98 .SYNCI_Step = 32, 99 .SYNCI_Step = 32,
99 .CCRes = 2, 100 .CCRes = 2,
100 - .CP1_fcr0 = MIPS_FCR0,  
101 }, 101 },
102 { 102 {
103 .name = "4KEc", 103 .name = "4KEc",
@@ -108,7 +108,7 @@ static mips_def_t mips_defs[] = @@ -108,7 +108,7 @@ static mips_def_t mips_defs[] =
108 .CP0_Config3 = MIPS_CONFIG3, 108 .CP0_Config3 = MIPS_CONFIG3,
109 .SYNCI_Step = 32, 109 .SYNCI_Step = 32,
110 .CCRes = 2, 110 .CCRes = 2,
111 - .CP1_fcr0 = MIPS_FCR0, 111 + .Status_rw_bitmask = 0x3278FF17,
112 }, 112 },
113 { 113 {
114 .name = "24Kc", 114 .name = "24Kc",
@@ -119,7 +119,7 @@ static mips_def_t mips_defs[] = @@ -119,7 +119,7 @@ static mips_def_t mips_defs[] =
119 .CP0_Config3 = MIPS_CONFIG3, 119 .CP0_Config3 = MIPS_CONFIG3,
120 .SYNCI_Step = 32, 120 .SYNCI_Step = 32,
121 .CCRes = 2, 121 .CCRes = 2,
122 - .CP1_fcr0 = MIPS_FCR0, 122 + .Status_rw_bitmask = 0x3278FF17,
123 }, 123 },
124 { 124 {
125 .name = "24Kf", 125 .name = "24Kf",
@@ -130,7 +130,9 @@ static mips_def_t mips_defs[] = @@ -130,7 +130,9 @@ static mips_def_t mips_defs[] =
130 .CP0_Config3 = MIPS_CONFIG3, 130 .CP0_Config3 = MIPS_CONFIG3,
131 .SYNCI_Step = 32, 131 .SYNCI_Step = 32,
132 .CCRes = 2, 132 .CCRes = 2,
133 - .CP1_fcr0 = MIPS_FCR0, 133 + .Status_rw_bitmask = 0x3678FF17,
  134 + .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
  135 + (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID),
134 }, 136 },
135 #else 137 #else
136 { 138 {
@@ -142,7 +144,10 @@ static mips_def_t mips_defs[] = @@ -142,7 +144,10 @@ static mips_def_t mips_defs[] =
142 .CP0_Config3 = MIPS_CONFIG3, 144 .CP0_Config3 = MIPS_CONFIG3,
143 .SYNCI_Step = 16, 145 .SYNCI_Step = 16,
144 .CCRes = 2, 146 .CCRes = 2,
145 - .CP1_fcr0 = MIPS_FCR0, 147 + .Status_rw_bitmask = 0x3678FFFF,
  148 + .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
  149 + (1 << FCR0_D) | (1 << FCR0_S) |
  150 + (0x4 << FCR0_PRID) | (0x0 << FCR0_REV),
146 }, 151 },
147 #endif 152 #endif
148 }; 153 };
@@ -191,6 +196,7 @@ int cpu_mips_register (CPUMIPSState *env, mips_def_t *def) @@ -191,6 +196,7 @@ int cpu_mips_register (CPUMIPSState *env, mips_def_t *def)
191 env->CP0_Config7 = def->CP0_Config7; 196 env->CP0_Config7 = def->CP0_Config7;
192 env->SYNCI_Step = def->SYNCI_Step; 197 env->SYNCI_Step = def->SYNCI_Step;
193 env->CCRes = def->CCRes; 198 env->CCRes = def->CCRes;
  199 + env->Status_rw_bitmask = def->Status_rw_bitmask;
194 env->fcr0 = def->CP1_fcr0; 200 env->fcr0 = def->CP1_fcr0;
195 #if defined (MIPS_USES_R4K_TLB) 201 #if defined (MIPS_USES_R4K_TLB)
196 env->nb_tlb = 1 + ((def->CP0_Config1 >> CP0C1_MMU) & 63); 202 env->nb_tlb = 1 + ((def->CP0_Config1 >> CP0C1_MMU) & 63);