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 4 - ds1225y nvram support (Herve Poussineau)
5 5 - CPU model selection support (J. Mayer, Paul Brook, Herve Poussineau)
6 6 - Several Sparc fixes (Aurelien Jarno, Blue Swirl)
  7 + - MIPS 64-bit FPU support (Thiemo Seufer)
7 8  
8 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 575 {
576 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 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 637 {
638 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 641 ptr += 4;
642 642 }
643 643  
... ...
target-mips/TODO
... ... @@ -10,11 +10,12 @@ General
10 10 when the Qemu FPU emulation is disabled. Also gdb inside the emulated
11 11 system does not work. Both problems are caused by insufficient
12 12 handling of self-modifying code.
  13 +- Floating point exception emulation is incomplete.
13 14  
14 15 MIPS64
15 16 ------
16 17 - No 64bit TLB support
17   -- no 64bit wide registers for FPU
  18 +- 64bit FPU not fully implemented
18 19 - 64bit mul/div handling broken
19 20  
20 21 "Generic" 4Kc system emulation
... ...
target-mips/cpu.h
... ... @@ -21,7 +21,7 @@ typedef union fpr_t fpr_t;
21 21 union fpr_t {
22 22 float64 fd; /* ieee double precision */
23 23 float32 fs[2];/* ieee single precision */
24   - uint64_t d; /* binary single fixed-point */
  24 + uint64_t d; /* binary double fixed-point */
25 25 uint32_t w[2]; /* binary single fixed-point */
26 26 };
27 27 /* define FP_ENDIAN_IDX to access the same location
... ... @@ -64,31 +64,35 @@ struct CPUMIPSState {
64 64 target_ulong HI, LO;
65 65 /* Floating point registers */
66 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 67 #ifndef USE_HOST_FLOAT_REGS
74 68 fpr_t ft0;
75 69 fpr_t ft1;
76 70 fpr_t ft2;
77 71 #endif
78 72 float_status fp_status;
79   - /* fpu implementation/revision register */
  73 + /* fpu implementation/revision register (fir) */
80 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 84 /* fcsr */
82 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 96 #define FP_INEXACT 1
93 97 #define FP_UNDERFLOW 2
94 98 #define FP_OVERFLOW 4
... ... @@ -267,6 +271,7 @@ struct CPUMIPSState {
267 271  
268 272 int SYNCI_Step; /* Address step size for SYNCI */
269 273 int CCRes; /* Cycle count resolution/divisor */
  274 + int Status_rw_bitmask; /* Read/write bits in CP0_Status */
270 275  
271 276 #if defined(CONFIG_USER_ONLY)
272 277 target_ulong tls_value;
... ... @@ -330,10 +335,11 @@ enum {
330 335 EXCP_RI,
331 336 EXCP_OVERFLOW,
332 337 EXCP_TRAP,
  338 + EXCP_FPE,
333 339 EXCP_DDBS,
334 340 EXCP_DWATCH,
335   - EXCP_LAE,
336   - EXCP_SAE, /* 24 */
  341 + EXCP_LAE, /* 24 */
  342 + EXCP_SAE,
337 343 EXCP_LTLBL,
338 344 EXCP_TLBL,
339 345 EXCP_TLBS,
... ...
target-mips/exec.h
... ... @@ -29,12 +29,18 @@ register target_ulong T2 asm(AREG3);
29 29 #define FST0 (env->ft0.fs[FP_ENDIAN_IDX])
30 30 #define FST1 (env->ft1.fs[FP_ENDIAN_IDX])
31 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 35 #define DT0 (env->ft0.d)
33 36 #define DT1 (env->ft1.d)
34 37 #define DT2 (env->ft2.d)
35 38 #define WT0 (env->ft0.w[FP_ENDIAN_IDX])
36 39 #define WT1 (env->ft1.w[FP_ENDIAN_IDX])
37 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 44 #endif
39 45  
40 46 #if defined (DEBUG_OP)
... ...
target-mips/fop_template.c
... ... @@ -19,75 +19,103 @@
19 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 104 #endif
77 105  
78 106 #if defined (FTN)
79 107  
80   -#define SET_RESET(treg, tregname) \
  108 +#define SET_RESET(treg, tregname) \
81 109 void glue(op_set, tregname)(void) \
82   - { \
83   - treg = PARAM1; \
84   - RETURN(); \
85   - } \
  110 + { \
  111 + treg = PARAM1; \
  112 + RETURN(); \
  113 + } \
86 114 void glue(op_reset, tregname)(void) \
87   - { \
88   - treg = 0; \
89   - RETURN(); \
90   - } \
  115 + { \
  116 + treg = 0; \
  117 + RETURN(); \
  118 + }
91 119  
92 120 SET_RESET(WT0, _WT0)
93 121 SET_RESET(WT1, _WT1)
... ... @@ -95,6 +123,9 @@ SET_RESET(WT2, _WT2)
95 123 SET_RESET(DT0, _DT0)
96 124 SET_RESET(DT1, _DT1)
97 125 SET_RESET(DT2, _DT2)
  126 +SET_RESET(WTH0, _WTH0)
  127 +SET_RESET(WTH1, _WTH1)
  128 +SET_RESET(WTH2, _WTH2)
98 129  
99 130 #undef SET_RESET
100 131 #endif
... ...
target-mips/helper.c
... ... @@ -379,6 +379,9 @@ void do_interrupt (CPUState *env)
379 379 case EXCP_TRAP:
380 380 cause = 13;
381 381 goto set_EPC;
  382 + case EXCP_FPE:
  383 + cause = 15;
  384 + goto set_EPC;
382 385 case EXCP_LTLBL:
383 386 cause = 1;
384 387 goto set_EPC;
... ...
target-mips/op.c
... ... @@ -23,27 +23,27 @@
23 23 #include "exec.h"
24 24  
25 25 #ifndef CALL_FROM_TB0
26   -#define CALL_FROM_TB0(func) func();
  26 +#define CALL_FROM_TB0(func) func()
27 27 #endif
28 28 #ifndef CALL_FROM_TB1
29   -#define CALL_FROM_TB1(func, arg0) func(arg0);
  29 +#define CALL_FROM_TB1(func, arg0) func(arg0)
30 30 #endif
31 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 33 #endif
34 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 36 #endif
37 37 #ifndef CALL_FROM_TB2_CONST16
38 38 #define CALL_FROM_TB2_CONST16(func, arg0, arg1) \
39   -CALL_FROM_TB2(func, arg0, arg1);
  39 + CALL_FROM_TB2(func, arg0, arg1)
40 40 #endif
41 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 43 #endif
44 44 #ifndef CALL_FROM_TB4
45 45 #define CALL_FROM_TB4(func, arg0, arg1, arg2, arg3) \
46   - func(arg0, arg1, arg2, arg3);
  46 + func(arg0, arg1, arg2, arg3)
47 47 #endif
48 48  
49 49 #define REG 1
... ... @@ -144,134 +144,102 @@ CALL_FROM_TB2(func, arg0, arg1);
144 144 #include "op_template.c"
145 145 #undef TN
146 146  
147   -#define SFREG 0
148   -#define DFREG 0
  147 +#define FREG 0
149 148 #include "fop_template.c"
150   -#undef SFREG
151   -#undef DFREG
152   -#define SFREG 1
  149 +#undef FREG
  150 +#define FREG 1
153 151 #include "fop_template.c"
154   -#undef SFREG
155   -#define SFREG 2
156   -#define DFREG 2
  152 +#undef FREG
  153 +#define FREG 2
157 154 #include "fop_template.c"
158   -#undef SFREG
159   -#undef DFREG
160   -#define SFREG 3
  155 +#undef FREG
  156 +#define FREG 3
161 157 #include "fop_template.c"
162   -#undef SFREG
163   -#define SFREG 4
164   -#define DFREG 4
  158 +#undef FREG
  159 +#define FREG 4
165 160 #include "fop_template.c"
166   -#undef SFREG
167   -#undef DFREG
168   -#define SFREG 5
  161 +#undef FREG
  162 +#define FREG 5
169 163 #include "fop_template.c"
170   -#undef SFREG
171   -#define SFREG 6
172   -#define DFREG 6
  164 +#undef FREG
  165 +#define FREG 6
173 166 #include "fop_template.c"
174   -#undef SFREG
175   -#undef DFREG
176   -#define SFREG 7
  167 +#undef FREG
  168 +#define FREG 7
177 169 #include "fop_template.c"
178   -#undef SFREG
179   -#define SFREG 8
180   -#define DFREG 8
  170 +#undef FREG
  171 +#define FREG 8
181 172 #include "fop_template.c"
182   -#undef SFREG
183   -#undef DFREG
184   -#define SFREG 9
  173 +#undef FREG
  174 +#define FREG 9
185 175 #include "fop_template.c"
186   -#undef SFREG
187   -#define SFREG 10
188   -#define DFREG 10
  176 +#undef FREG
  177 +#define FREG 10
189 178 #include "fop_template.c"
190   -#undef SFREG
191   -#undef DFREG
192   -#define SFREG 11
  179 +#undef FREG
  180 +#define FREG 11
193 181 #include "fop_template.c"
194   -#undef SFREG
195   -#define SFREG 12
196   -#define DFREG 12
  182 +#undef FREG
  183 +#define FREG 12
197 184 #include "fop_template.c"
198   -#undef SFREG
199   -#undef DFREG
200   -#define SFREG 13
  185 +#undef FREG
  186 +#define FREG 13
201 187 #include "fop_template.c"
202   -#undef SFREG
203   -#define SFREG 14
204   -#define DFREG 14
  188 +#undef FREG
  189 +#define FREG 14
205 190 #include "fop_template.c"
206   -#undef SFREG
207   -#undef DFREG
208   -#define SFREG 15
  191 +#undef FREG
  192 +#define FREG 15
209 193 #include "fop_template.c"
210   -#undef SFREG
211   -#define SFREG 16
212   -#define DFREG 16
  194 +#undef FREG
  195 +#define FREG 16
213 196 #include "fop_template.c"
214   -#undef SFREG
215   -#undef DFREG
216   -#define SFREG 17
  197 +#undef FREG
  198 +#define FREG 17
217 199 #include "fop_template.c"
218   -#undef SFREG
219   -#define SFREG 18
220   -#define DFREG 18
  200 +#undef FREG
  201 +#define FREG 18
221 202 #include "fop_template.c"
222   -#undef SFREG
223   -#undef DFREG
224   -#define SFREG 19
  203 +#undef FREG
  204 +#define FREG 19
225 205 #include "fop_template.c"
226   -#undef SFREG
227   -#define SFREG 20
228   -#define DFREG 20
  206 +#undef FREG
  207 +#define FREG 20
229 208 #include "fop_template.c"
230   -#undef SFREG
231   -#undef DFREG
232   -#define SFREG 21
  209 +#undef FREG
  210 +#define FREG 21
233 211 #include "fop_template.c"
234   -#undef SFREG
235   -#define SFREG 22
236   -#define DFREG 22
  212 +#undef FREG
  213 +#define FREG 22
237 214 #include "fop_template.c"
238   -#undef SFREG
239   -#undef DFREG
240   -#define SFREG 23
  215 +#undef FREG
  216 +#define FREG 23
241 217 #include "fop_template.c"
242   -#undef SFREG
243   -#define SFREG 24
244   -#define DFREG 24
  218 +#undef FREG
  219 +#define FREG 24
245 220 #include "fop_template.c"
246   -#undef SFREG
247   -#undef DFREG
248   -#define SFREG 25
  221 +#undef FREG
  222 +#define FREG 25
249 223 #include "fop_template.c"
250   -#undef SFREG
251   -#define SFREG 26
252   -#define DFREG 26
  224 +#undef FREG
  225 +#define FREG 26
253 226 #include "fop_template.c"
254   -#undef SFREG
255   -#undef DFREG
256   -#define SFREG 27
  227 +#undef FREG
  228 +#define FREG 27
257 229 #include "fop_template.c"
258   -#undef SFREG
259   -#define SFREG 28
260   -#define DFREG 28
  230 +#undef FREG
  231 +#define FREG 28
261 232 #include "fop_template.c"
262   -#undef SFREG
263   -#undef DFREG
264   -#define SFREG 29
  233 +#undef FREG
  234 +#define FREG 29
265 235 #include "fop_template.c"
266   -#undef SFREG
267   -#define SFREG 30
268   -#define DFREG 30
  236 +#undef FREG
  237 +#define FREG 30
269 238 #include "fop_template.c"
270   -#undef SFREG
271   -#undef DFREG
272   -#define SFREG 31
  239 +#undef FREG
  240 +#define FREG 31
273 241 #include "fop_template.c"
274   -#undef SFREG
  242 +#undef FREG
275 243  
276 244 #define FTN
277 245 #include "fop_template.c"
... ... @@ -919,14 +887,14 @@ void op_movz (void)
919 887 void op_movf (void)
920 888 {
921 889 if (!(env->fcr31 & PARAM1))
922   - env->gpr[PARAM2] = env->gpr[PARAM3];
  890 + T0 = T1;
923 891 RETURN();
924 892 }
925 893  
926 894 void op_movt (void)
927 895 {
928 896 if (env->fcr31 & PARAM1)
929   - env->gpr[PARAM2] = env->gpr[PARAM3];
  897 + T0 = T1;
930 898 RETURN();
931 899 }
932 900  
... ... @@ -1354,17 +1322,18 @@ void op_mtc0_compare (void)
1354 1322 void op_mtc0_status (void)
1355 1323 {
1356 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 1328 no 64bit addressing implemented. */
1360   - val = (int32_t)T0 & 0xF878FF17;
  1329 + val = (int32_t)T0 & mask;
1361 1330 old = env->CP0_Status;
1362 1331 if (!(val & (1 << CP0St_EXL)) &&
1363 1332 !(val & (1 << CP0St_ERL)) &&
1364 1333 !(env->hflags & MIPS_HFLAG_DM) &&
1365 1334 (val & (1 << CP0St_UM)))
1366 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 1337 if (loglevel & CPU_LOG_EXEC)
1369 1338 CALL_FROM_TB2(do_mtc0_status_debug, old, val);
1370 1339 CALL_FROM_TB1(cpu_mips_update_irq, env);
... ... @@ -1643,6 +1612,7 @@ void op_dmtc0_errorepc (void)
1643 1612 }
1644 1613 #endif /* TARGET_MIPS64 */
1645 1614  
  1615 +/* CP1 functions */
1646 1616 #if 0
1647 1617 # define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
1648 1618 #else
... ... @@ -1666,20 +1636,6 @@ void op_cp1_enabled(void)
1666 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 1639 /* convert MIPS rounding mode in FCR31 to IEEE library */
1684 1640 unsigned int ieee_rm[] = {
1685 1641 float_round_nearest_even,
... ... @@ -1691,26 +1647,93 @@ unsigned int ieee_rm[] = {
1691 1647 #define RESTORE_ROUNDING_MODE \
1692 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 1737 DEBUG_FPU_STATE();
1715 1738 RETURN();
1716 1739 }
... ... @@ -1729,55 +1752,219 @@ void op_mtc1 (void)
1729 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 1783 /* Float support.
1733 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 1788 #define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
1737 1789  
1738 1790 FLOAT_OP(cvtd, s)
1739 1791 {
  1792 + set_float_exception_flags(0, &env->fp_status);
1740 1793 FDT2 = float32_to_float64(FST0, &env->fp_status);
  1794 + update_fcr31();
1741 1795 DEBUG_FPU_STATE();
1742 1796 RETURN();
1743 1797 }
1744 1798 FLOAT_OP(cvtd, w)
1745 1799 {
  1800 + set_float_exception_flags(0, &env->fp_status);
1746 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 1858 DEBUG_FPU_STATE();
1748 1859 RETURN();
1749 1860 }
1750 1861 FLOAT_OP(cvts, d)
1751 1862 {
  1863 + set_float_exception_flags(0, &env->fp_status);
1752 1864 FST2 = float64_to_float32(FDT0, &env->fp_status);
  1865 + update_fcr31();
1753 1866 DEBUG_FPU_STATE();
1754 1867 RETURN();
1755 1868 }
1756 1869 FLOAT_OP(cvts, w)
1757 1870 {
  1871 + set_float_exception_flags(0, &env->fp_status);
1758 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 1898 DEBUG_FPU_STATE();
1760 1899 RETURN();
1761 1900 }
1762 1901 FLOAT_OP(cvtw, s)
1763 1902 {
  1903 + set_float_exception_flags(0, &env->fp_status);
1764 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 1908 DEBUG_FPU_STATE();
1766 1909 RETURN();
1767 1910 }
1768 1911 FLOAT_OP(cvtw, d)
1769 1912 {
  1913 + set_float_exception_flags(0, &env->fp_status);
1770 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 1943 DEBUG_FPU_STATE();
1772 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 1963 FLOAT_OP(roundw, d)
1776 1964 {
1777 1965 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1778 1966 WT2 = float64_round_to_int(FDT0, &env->fp_status);
1779 1967 RESTORE_ROUNDING_MODE;
1780   -
1781 1968 DEBUG_FPU_STATE();
1782 1969 RETURN();
1783 1970 }
... ... @@ -1790,6 +1977,18 @@ FLOAT_OP(roundw, s)
1790 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 1992 FLOAT_OP(truncw, d)
1794 1993 {
1795 1994 WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status);
... ... @@ -1803,12 +2002,27 @@ FLOAT_OP(truncw, s)
1803 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 2021 FLOAT_OP(ceilw, d)
1807 2022 {
1808 2023 set_float_rounding_mode(float_round_up, &env->fp_status);
1809 2024 WT2 = float64_round_to_int(FDT0, &env->fp_status);
1810 2025 RESTORE_ROUNDING_MODE;
1811   -
1812 2026 DEBUG_FPU_STATE();
1813 2027 RETURN();
1814 2028 }
... ... @@ -1821,12 +2035,27 @@ FLOAT_OP(ceilw, s)
1821 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 2054 FLOAT_OP(floorw, d)
1825 2055 {
1826 2056 set_float_rounding_mode(float_round_down, &env->fp_status);
1827 2057 WT2 = float64_round_to_int(FDT0, &env->fp_status);
1828 2058 RESTORE_ROUNDING_MODE;
1829   -
1830 2059 DEBUG_FPU_STATE();
1831 2060 RETURN();
1832 2061 }
... ... @@ -1839,16 +2068,121 @@ FLOAT_OP(floorw, s)
1839 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 2164 /* binary operations */
1843 2165 #define FLOAT_BINOP(name) \
1844 2166 FLOAT_OP(name, d) \
1845 2167 { \
  2168 + set_float_exception_flags(0, &env->fp_status); \
1846 2169 FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status); \
  2170 + update_fcr31(); \
1847 2171 DEBUG_FPU_STATE(); \
1848 2172 } \
1849 2173 FLOAT_OP(name, s) \
1850 2174 { \
  2175 + set_float_exception_flags(0, &env->fp_status); \
1851 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 2186 DEBUG_FPU_STATE(); \
1853 2187 }
1854 2188 FLOAT_BINOP(add)
... ... @@ -1857,6 +2191,32 @@ FLOAT_BINOP(mul)
1857 2191 FLOAT_BINOP(div)
1858 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 2220 /* unary operations, modifying fp status */
1861 2221 #define FLOAT_UNOP(name) \
1862 2222 FLOAT_OP(name, d) \
... ... @@ -1868,6 +2228,12 @@ FLOAT_OP(name, s) \
1868 2228 { \
1869 2229 FST2 = float32_ ## name(FST0, &env->fp_status); \
1870 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 2238 FLOAT_UNOP(sqrt)
1873 2239 #undef FLOAT_UNOP
... ... @@ -1883,6 +2249,12 @@ FLOAT_OP(name, s) \
1883 2249 { \
1884 2250 FST2 = float32_ ## name(FST0); \
1885 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 2259 FLOAT_UNOP(abs)
1888 2260 FLOAT_UNOP(chs)
... ... @@ -1900,6 +2272,35 @@ FLOAT_OP(mov, s)
1900 2272 DEBUG_FPU_STATE();
1901 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 2305 #ifdef CONFIG_SOFTFLOAT
1905 2306 #define clear_invalid() do { \
... ... @@ -1913,96 +2314,200 @@ FLOAT_OP(mov, s)
1913 2314  
1914 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 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 2326 DEBUG_FPU_STATE(); \
1927 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 2335 float_raise(float_flag_invalid, status);
1934 2336 return 1;
1935   - }
1936   - else {
  2337 + } else if (float64_is_nan(a) || float64_is_nan(b)) {
  2338 + return 1;
  2339 + } else {
1937 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 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 2384 float_raise(float_flag_invalid, status);
1966 2385 return 1;
1967   - }
1968   - else {
  2386 + } else if (float32_is_nan(a) || float32_is_nan(b)) {
  2387 + return 1;
  2388 + } else {
1969 2389 return 0;
1970 2390 }
1971 2391 }
1972 2392  
1973 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 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 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 2488 DEBUG_FPU_STATE();
2000 2489 RETURN();
2001 2490 }
2002 2491  
2003 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 2511 DEBUG_FPU_STATE();
2007 2512 RETURN();
2008 2513 }
... ... @@ -2037,7 +2542,7 @@ void op_tlbr (void)
2037 2542 #if defined (CONFIG_USER_ONLY)
2038 2543 void op_tls_value (void)
2039 2544 {
2040   - T0 = env->tls_value;
  2545 + T0 = env->tls_value;
2041 2546 }
2042 2547 #endif
2043 2548  
... ... @@ -2180,6 +2685,17 @@ void op_save_pc (void)
2180 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 2699 void op_interrupt_restart (void)
2184 2700 {
2185 2701 if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
... ...
target-mips/op_mem.c
... ... @@ -220,3 +220,35 @@ void glue(op_sdc1, MEMSUFFIX) (void)
220 220 glue(stq, MEMSUFFIX)(T0, DT0);
221 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 333 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
334 334 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
335 335 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
336   - OPC_MFHCI = (0x03 << 21) | OPC_CP1,
  336 + OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
337 337 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
338 338 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
339 339 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
340   - OPC_MTHCI = (0x07 << 21) | OPC_CP1,
  340 + OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
341 341 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
  342 + OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
  343 + OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
342 344 OPC_S_FMT = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */
343 345 OPC_D_FMT = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */
344 346 OPC_E_FMT = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */
345 347 OPC_Q_FMT = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */
346 348 OPC_W_FMT = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
347 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 356 enum {
351 357 OPC_BC1F = (0x00 << 16) | OPC_BC1,
352 358 OPC_BC1T = (0x01 << 16) | OPC_BC1,
... ... @@ -354,8 +360,15 @@ enum {
354 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 373 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
361 374  
... ... @@ -404,20 +417,20 @@ const unsigned char *regnames[] =
404 417 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
405 418  
406 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 436 /* General purpose registers moves */
... ... @@ -434,58 +447,51 @@ static const char *fregnames[] =
434 447 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
435 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 493 #define FOP_CONDS(fmt) \
488   -static GenOpFunc * cond_ ## fmt ## _table[16] = { \
  494 +static GenOpFunc1 * cond_ ## fmt ## _table[16] = { \
489 495 gen_op_cmp_ ## fmt ## _f, \
490 496 gen_op_cmp_ ## fmt ## _un, \
491 497 gen_op_cmp_ ## fmt ## _eq, \
... ... @@ -503,18 +509,20 @@ static GenOpFunc * cond_ ## fmt ## _table[16] = { \
503 509 gen_op_cmp_ ## fmt ## _le, \
504 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 517 FOP_CONDS(d)
512 518 FOP_CONDS(s)
  519 +FOP_CONDS(ps)
513 520  
514 521 typedef struct DisasContext {
515 522 struct TranslationBlock *tb;
516 523 target_ulong pc, saved_pc;
517 524 uint32_t opcode;
  525 + uint32_t fp_status, saved_fp_status;
518 526 /* Routine used to access memory */
519 527 int mem_idx;
520 528 uint32_t hflags, saved_hflags;
... ... @@ -600,17 +608,31 @@ static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
600 608 if (ctx->hflags != ctx->saved_hflags) {
601 609 gen_op_save_state(ctx->hflags);
602 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 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 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 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 636 static inline void generate_exception_err (DisasContext *ctx, int excp, int err)
615 637 {
616 638 #if defined MIPS_DEBUG_DISAS
... ... @@ -677,6 +699,12 @@ OP_LD_TABLE(wc1);
677 699 OP_ST_TABLE(wc1);
678 700 OP_LD_TABLE(dc1);
679 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 709 /* Load and store */
682 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 1500 if (ctx->hflags & MIPS_HFLAG_BMASK) {
1473 1501 if (loglevel & CPU_LOG_TB_IN_ASM) {
1474 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 1504 ctx->pc);
1477 1505 }
1478 1506 MIPS_INVAL("branch/jump in bdelay slot");
... ... @@ -1672,6 +1700,7 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
1672 1700 MIPS_DEBUG("bltzal %s, %08x", regnames[rs], btarget);
1673 1701 not_likely:
1674 1702 ctx->hflags |= MIPS_HFLAG_BC;
  1703 + gen_op_set_bcond();
1675 1704 break;
1676 1705 case OPC_BLTZALL:
1677 1706 gen_op_ltz();
... ... @@ -1679,13 +1708,14 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
1679 1708 MIPS_DEBUG("bltzall %s, %08x", regnames[rs], btarget);
1680 1709 likely:
1681 1710 ctx->hflags |= MIPS_HFLAG_BL;
  1711 + gen_op_set_bcond();
  1712 + gen_op_save_bcond();
1682 1713 break;
1683 1714 default:
1684 1715 MIPS_INVAL("conditional branch/jump");
1685 1716 generate_exception(ctx, EXCP_RI);
1686 1717 return;
1687 1718 }
1688   - gen_op_set_bcond();
1689 1719 }
1690 1720 MIPS_DEBUG("enter ds: link %d cond %02x target %08x",
1691 1721 blink, ctx->hflags, btarget);
... ... @@ -4220,7 +4250,7 @@ static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd)
4220 4250  
4221 4251 /* CP1 Branches (before delay slot) */
4222 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 4255 target_ulong btarget;
4226 4256  
... ... @@ -4228,31 +4258,49 @@ static void gen_compute_branch1 (DisasContext *ctx, uint32_t op,
4228 4258  
4229 4259 switch (op) {
4230 4260 case OPC_BC1F:
4231   - gen_op_bc1f();
  4261 + gen_op_bc1f(cc);
4232 4262 MIPS_DEBUG("bc1f " TARGET_FMT_lx, btarget);
4233 4263 goto not_likely;
4234 4264 case OPC_BC1FL:
4235   - gen_op_bc1f();
  4265 + gen_op_bc1f(cc);
4236 4266 MIPS_DEBUG("bc1fl " TARGET_FMT_lx, btarget);
4237 4267 goto likely;
4238 4268 case OPC_BC1T:
4239   - gen_op_bc1t();
  4269 + gen_op_bc1t(cc);
4240 4270 MIPS_DEBUG("bc1t " TARGET_FMT_lx, btarget);
4241   - not_likely:
4242   - ctx->hflags |= MIPS_HFLAG_BC;
4243   - break;
  4271 + goto not_likely;
4244 4272 case OPC_BC1TL:
4245   - gen_op_bc1t();
  4273 + gen_op_bc1t(cc);
4246 4274 MIPS_DEBUG("bc1tl " TARGET_FMT_lx, btarget);
4247 4275 likely:
4248 4276 ctx->hflags |= MIPS_HFLAG_BL;
  4277 + gen_op_set_bcond();
  4278 + gen_op_save_bcond();
4249 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 4301 generate_exception (ctx, EXCP_RI);
4253 4302 return;
4254 4303 }
4255   - gen_op_set_bcond();
4256 4304  
4257 4305 MIPS_DEBUG("enter ds: cond %02x target " TARGET_FMT_lx,
4258 4306 ctx->hflags, btarget);
... ... @@ -4262,6 +4310,29 @@ static void gen_compute_branch1 (DisasContext *ctx, uint32_t op,
4262 4310 }
4263 4311  
4264 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 4336 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
4266 4337 {
4267 4338 const char *opn = "unk";
... ... @@ -4280,30 +4351,43 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
4280 4351 opn = "mtc1";
4281 4352 break;
4282 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 4354 GEN_LOAD_IMM_TN(T1, fs);
4289 4355 gen_op_cfc1();
4290 4356 GEN_STORE_TN_REG(rt, T0);
4291 4357 opn = "cfc1";
4292 4358 break;
4293 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 4360 GEN_LOAD_IMM_TN(T1, fs);
4300 4361 GEN_LOAD_REG_TN(T0, rt);
4301 4362 gen_op_ctc1();
4302 4363 opn = "ctc1";
4303 4364 break;
4304 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 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 4391 default:
4308 4392 if (loglevel & CPU_LOG_TB_IN_ASM) {
4309 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 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 4442 const char *opn = "unk";
4341 4443 const char *condnames[] = {
... ... @@ -4360,6 +4462,187 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, int fs, int fd)
4360 4462 uint32_t func = ctx->opcode & 0x3f;
4361 4463  
4362 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 4646 case FOP(0, 17):
4364 4647 CHECK_FR(ctx, fs | ft | fd);
4365 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 4707 GEN_STORE_FTN_FREG(fd, DT2);
4425 4708 opn = "neg.d";
4426 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 4738 case FOP(12, 17):
4432 4739 CHECK_FR(ctx, fs);
4433 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 4763 GEN_STORE_FTN_FREG(fd, WT2);
4457 4764 opn = "floor.w.d";
4458 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 4771 GEN_STORE_FTN_FREG(fd, DT2);
4464   - opn = "cvt.d.s";
  4772 + opn = "movcf.d";
4465 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 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 4789 break;
4473 4790 case FOP(48, 17):
4474 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 4806 CHECK_FR(ctx, fs | ft);
4490 4807 GEN_LOAD_FREG_FTN(DT0, fs);
4491 4808 GEN_LOAD_FREG_FTN(DT1, ft);
4492   - gen_cmp_d(func-48);
  4809 + gen_cmp_d(func-48, cc);
4493 4810 opn = condnames[func-48];
4494 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 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 4836 GEN_STORE_FTN_FREG(fd, WT2);
4500   - opn = "add.s";
4501   - binary = 1;
  4837 + opn = "cvt.s.w";
4502 4838 break;
4503   - case FOP(1, 16):
  4839 + case FOP(33, 20):
  4840 + CHECK_FR(ctx, fd);
4504 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 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 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 4880 break;
4511   - case FOP(2, 16):
  4881 + case FOP(1, 22):
  4882 + CHECK_FR(ctx, fs | ft | fd);
4512 4883 GEN_LOAD_FREG_FTN(WT0, fs);
  4884 + GEN_LOAD_FREG_FTN(WTH0, fs);
4513 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 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 4891 break;
4519   - case FOP(3, 16):
  4892 + case FOP(2, 22):
  4893 + CHECK_FR(ctx, fs | ft | fd);
4520 4894 GEN_LOAD_FREG_FTN(WT0, fs);
  4895 + GEN_LOAD_FREG_FTN(WTH0, fs);
4521 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 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 4902 break;
4527   - case FOP(4, 16):
  4903 + case FOP(5, 22):
  4904 + CHECK_FR(ctx, fs | fd);
4528 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 4908 GEN_STORE_FTN_FREG(fd, WT2);
4531   - opn = "sqrt.s";
  4909 + GEN_STORE_FTN_FREG(fd, WTH2);
  4910 + opn = "abs.ps";
4532 4911 break;
4533   - case FOP(5, 16):
  4912 + case FOP(6, 22):
  4913 + CHECK_FR(ctx, fs | fd);
4534 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 4917 GEN_STORE_FTN_FREG(fd, WT2);
4537   - opn = "abs.s";
  4918 + GEN_STORE_FTN_FREG(fd, WTH2);
  4919 + opn = "mov.ps";
4538 4920 break;
4539   - case FOP(6, 16):
  4921 + case FOP(7, 22):
  4922 + CHECK_FR(ctx, fs | fd);
4540 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 4926 GEN_STORE_FTN_FREG(fd, WT2);
4543   - opn = "mov.s";
  4927 + GEN_STORE_FTN_FREG(fd, WTH2);
  4928 + opn = "neg.ps";
4544 4929 break;
4545   - case FOP(7, 16):
  4930 + case FOP(17, 22):
  4931 + GEN_LOAD_REG_TN(T0, ft);
4546 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 4937 GEN_STORE_FTN_FREG(fd, WT2);
4549   - opn = "neg.s";
  4938 + GEN_STORE_FTN_FREG(fd, WTH2);
  4939 + opn = "movcf.ps";
4550 4940 break;
4551   - case FOP(12, 16):
  4941 + case FOP(18, 22):
  4942 + GEN_LOAD_REG_TN(T0, ft);
4552 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 4948 GEN_STORE_FTN_FREG(fd, WT2);
4555   - opn = "round.w.s";
  4949 + GEN_STORE_FTN_FREG(fd, WTH2);
  4950 + opn = "movz.ps";
4556 4951 break;
4557   - case FOP(13, 16):
  4952 + case FOP(19, 22):
  4953 + GEN_LOAD_REG_TN(T0, ft);
4558 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 4959 GEN_STORE_FTN_FREG(fd, WT2);
4561   - opn = "trunc.w.s";
  4960 + GEN_STORE_FTN_FREG(fd, WTH2);
  4961 + opn = "movn.ps";
4562 4962 break;
4563   - case FOP(32, 17):
  4963 + case FOP(32, 22):
4564 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 4967 GEN_STORE_FTN_FREG(fd, WT2);
4568   - opn = "cvt.s.d";
  4968 + opn = "cvt.s.pu";
4569 4969 break;
4570   - case FOP(32, 20):
  4970 + case FOP(36, 22):
  4971 + CHECK_FR(ctx, fs | fd);
4571 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 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 4978 break;
4576   - case FOP(36, 16):
  4979 + case FOP(40, 22):
  4980 + CHECK_FR(ctx, fs);
4577 4981 GEN_LOAD_FREG_FTN(WT0, fs);
4578   - gen_op_float_cvtw_s();
  4982 + gen_op_float_cvts_pl();
4579 4983 GEN_STORE_FTN_FREG(fd, WT2);
4580   - opn = "cvt.w.s";
  4984 + opn = "cvt.s.pl";
4581 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 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 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 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 5040 opn = condnames[func-48];
4609 5041 break;
4610   - default:
  5042 + default:
4611 5043 if (loglevel & CPU_LOG_TB_IN_ASM) {
4612 5044 fprintf(logfile, "Invalid FP arith function: %08x %03x %03x %03x\n",
4613 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 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 5187 /* ISA extensions (ASEs) */
... ... @@ -4641,23 +5189,12 @@ static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
4641 5189 /* SmartMIPS extension to MIPS32 */
4642 5190  
4643 5191 #ifdef TARGET_MIPS64
4644   -/* Coprocessor 3 (FPU) */
4645 5192  
4646 5193 /* MDMX extension to MIPS64 */
4647 5194 /* MIPS-3D extension to MIPS64 */
4648 5195  
4649 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 5198 static void decode_opc (CPUState *env, DisasContext *ctx)
4662 5199 {
4663 5200 int32_t offset;
... ... @@ -4673,9 +5210,14 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
4673 5210 }
4674 5211  
4675 5212 if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
  5213 + int l1;
4676 5214 /* Handle blikely not taken case */
4677 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 5222 op = MASK_OP_MAJOR(ctx->opcode);
4681 5223 rs = (ctx->opcode >> 21) & 0x1f;
... ... @@ -5024,16 +5566,21 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
5024 5566 case OPC_DMFC1:
5025 5567 case OPC_DMTC1:
5026 5568 #endif
  5569 + case OPC_MFHC1:
  5570 + case OPC_MTHC1:
5027 5571 gen_cp1(ctx, op1, rt, rd);
5028 5572 break;
5029 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 5576 return;
5032 5577 case OPC_S_FMT:
5033 5578 case OPC_D_FMT:
5034 5579 case OPC_W_FMT:
5035 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 5584 break;
5038 5585 default:
5039 5586 generate_exception (ctx, EXCP_RI);
... ... @@ -5060,10 +5607,32 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
5060 5607 gen_op_cp1_enabled();
5061 5608 op1 = MASK_CP3(ctx->opcode);
5062 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 5618 case OPC_PREFX:
5064 5619 /* treat as noop */
5065 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 5636 default:
5068 5637 generate_exception (ctx, EXCP_RI);
5069 5638 break;
... ... @@ -5107,7 +5676,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
5107 5676 ctx->hflags &= ~MIPS_HFLAG_BMASK;
5108 5677 ctx->bstate = BS_BRANCH;
5109 5678 save_cpu_state(ctx, 0);
5110   - switch (hflags & MIPS_HFLAG_BMASK) {
  5679 + switch (hflags) {
5111 5680 case MIPS_HFLAG_B:
5112 5681 /* unconditional branch */
5113 5682 MIPS_DEBUG("unconditional branch");
... ... @@ -5134,6 +5703,8 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
5134 5703 /* unconditional branch to register */
5135 5704 MIPS_DEBUG("branch to register");
5136 5705 gen_op_breg();
  5706 + gen_op_reset_T0();
  5707 + gen_op_exit_tb();
5137 5708 break;
5138 5709 default:
5139 5710 MIPS_DEBUG("unknown branch");
... ... @@ -5166,16 +5737,18 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
5166 5737 /* Restore delay slot state from the tb context. */
5167 5738 ctx.hflags = tb->flags;
5168 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 5742 gen_op_restore_breg_target();
5171   - } else if (ctx.hflags & MIPS_HFLAG_B) {
  5743 + break;
  5744 + case MIPS_HFLAG_B:
5172 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 5749 ctx.btarget = env->btarget;
5178 5750 gen_op_restore_bcond();
  5751 + break;
5179 5752 }
5180 5753 #if defined(CONFIG_USER_ONLY)
5181 5754 ctx.mem_idx = 0;
... ... @@ -5237,12 +5810,6 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
5237 5810 gen_op_debug();
5238 5811 } else {
5239 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 5813 case BS_STOP:
5247 5814 gen_op_interrupt_restart();
5248 5815 /* Fall through. */
... ... @@ -5250,12 +5817,14 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
5250 5817 save_cpu_state(ctxp, 0);
5251 5818 gen_goto_tb(&ctx, 0, ctx.pc);
5252 5819 break;
5253   - case BS_BRANCH:
5254   - default:
  5820 + case BS_EXCP:
  5821 + gen_op_interrupt_restart();
5255 5822 gen_op_reset_T0();
5256   - /* Generate the return instruction. */
5257 5823 gen_op_exit_tb();
5258 5824 break;
  5825 + case BS_BRANCH:
  5826 + default:
  5827 + break;
5259 5828 }
5260 5829 }
5261 5830 done_generating:
... ... @@ -5307,21 +5876,33 @@ void fpu_dump_state(CPUState *env, FILE *f,
5307 5876 int flags)
5308 5877 {
5309 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 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 5900 fpu_fprintf(f, "FT0: "); printfpr(&env->ft0);
5320 5901 fpu_fprintf(f, "FT1: "); printfpr(&env->ft1);
5321 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 5908 #undef printfpr
... ...
target-mips/translate_init.c
... ... @@ -55,7 +55,7 @@
55 55  
56 56 /* Define a implementation number of 1.
57 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 61 struct mips_def_t {
... ... @@ -69,6 +69,7 @@ struct mips_def_t {
69 69 int32_t CP0_Config7;
70 70 int32_t SYNCI_Step;
71 71 int32_t CCRes;
  72 + int32_t Status_rw_bitmask;
72 73 int32_t CP1_fcr0;
73 74 };
74 75  
... ... @@ -86,7 +87,7 @@ static mips_def_t mips_defs[] =
86 87 .CP0_Config3 = MIPS_CONFIG3,
87 88 .SYNCI_Step = 32,
88 89 .CCRes = 2,
89   - .CP1_fcr0 = MIPS_FCR0,
  90 + .Status_rw_bitmask = 0x3278FF17,
90 91 },
91 92 {
92 93 .name = "4KEcR1",
... ... @@ -97,7 +98,6 @@ static mips_def_t mips_defs[] =
97 98 .CP0_Config3 = MIPS_CONFIG3,
98 99 .SYNCI_Step = 32,
99 100 .CCRes = 2,
100   - .CP1_fcr0 = MIPS_FCR0,
101 101 },
102 102 {
103 103 .name = "4KEc",
... ... @@ -108,7 +108,7 @@ static mips_def_t mips_defs[] =
108 108 .CP0_Config3 = MIPS_CONFIG3,
109 109 .SYNCI_Step = 32,
110 110 .CCRes = 2,
111   - .CP1_fcr0 = MIPS_FCR0,
  111 + .Status_rw_bitmask = 0x3278FF17,
112 112 },
113 113 {
114 114 .name = "24Kc",
... ... @@ -119,7 +119,7 @@ static mips_def_t mips_defs[] =
119 119 .CP0_Config3 = MIPS_CONFIG3,
120 120 .SYNCI_Step = 32,
121 121 .CCRes = 2,
122   - .CP1_fcr0 = MIPS_FCR0,
  122 + .Status_rw_bitmask = 0x3278FF17,
123 123 },
124 124 {
125 125 .name = "24Kf",
... ... @@ -130,7 +130,9 @@ static mips_def_t mips_defs[] =
130 130 .CP0_Config3 = MIPS_CONFIG3,
131 131 .SYNCI_Step = 32,
132 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 137 #else
136 138 {
... ... @@ -142,7 +144,10 @@ static mips_def_t mips_defs[] =
142 144 .CP0_Config3 = MIPS_CONFIG3,
143 145 .SYNCI_Step = 16,
144 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 152 #endif
148 153 };
... ... @@ -191,6 +196,7 @@ int cpu_mips_register (CPUMIPSState *env, mips_def_t *def)
191 196 env->CP0_Config7 = def->CP0_Config7;
192 197 env->SYNCI_Step = def->SYNCI_Step;
193 198 env->CCRes = def->CCRes;
  199 + env->Status_rw_bitmask = def->Status_rw_bitmask;
194 200 env->fcr0 = def->CP1_fcr0;
195 201 #if defined (MIPS_USES_R4K_TLB)
196 202 env->nb_tlb = 1 + ((def->CP0_Config1 >> CP0C1_MMU) & 63);
... ...