Commit 57fa1fb31c23f1bf78664159d5813206bf2e4d0e

Authored by ths
1 parent f469b9db

More MIPS 64-bit FPU support.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2834 c046a42c-6fe2-441c-8c8c-71466251a162
target-mips/exec.h
... ... @@ -166,6 +166,36 @@ void cpu_mips_clock_init (CPUState *env);
166 166 void cpu_mips_tlb_flush (CPUState *env, int flush_global);
167 167  
168 168 void do_ctc1 (void);
  169 +
  170 +#define FOP_PROTO(op) \
  171 +void do_float_ ## op ## _s(void); \
  172 +void do_float_ ## op ## _d(void);
  173 +FOP_PROTO(roundl)
  174 +FOP_PROTO(roundw)
  175 +FOP_PROTO(truncl)
  176 +FOP_PROTO(truncw)
  177 +FOP_PROTO(ceill)
  178 +FOP_PROTO(ceilw)
  179 +FOP_PROTO(floorl)
  180 +FOP_PROTO(floorw)
  181 +FOP_PROTO(rsqrt)
  182 +FOP_PROTO(recip)
  183 +#undef FOP_PROTO
  184 +
  185 +#define FOP_PROTO(op) \
  186 +void do_float_ ## op ## _s(void); \
  187 +void do_float_ ## op ## _d(void); \
  188 +void do_float_ ## op ## _ps(void);
  189 +FOP_PROTO(add)
  190 +FOP_PROTO(sub)
  191 +FOP_PROTO(mul)
  192 +FOP_PROTO(div)
  193 +FOP_PROTO(recip1)
  194 +FOP_PROTO(recip2)
  195 +FOP_PROTO(rsqrt1)
  196 +FOP_PROTO(rsqrt2)
  197 +#undef FOP_PROTO
  198 +
169 199 void do_float_cvtd_s(void);
170 200 void do_float_cvtd_w(void);
171 201 void do_float_cvtd_l(void);
... ... @@ -180,37 +210,11 @@ void do_float_cvts_pl(void);
180 210 void do_float_cvts_pu(void);
181 211 void do_float_cvtw_s(void);
182 212 void do_float_cvtw_d(void);
183   -void do_float_roundl_d(void);
184   -void do_float_roundl_s(void);
185   -void do_float_roundw_d(void);
186   -void do_float_roundw_s(void);
187   -void do_float_truncl_d(void);
188   -void do_float_truncl_s(void);
189   -void do_float_truncw_d(void);
190   -void do_float_truncw_s(void);
191   -void do_float_ceill_d(void);
192   -void do_float_ceill_s(void);
193   -void do_float_ceilw_d(void);
194   -void do_float_ceilw_s(void);
195   -void do_float_floorl_d(void);
196   -void do_float_floorl_s(void);
197   -void do_float_floorw_d(void);
198   -void do_float_floorw_s(void);
199   -void do_float_add_d(void);
200   -void do_float_add_s(void);
201   -void do_float_add_ps(void);
202   -void do_float_sub_d(void);
203   -void do_float_sub_s(void);
204   -void do_float_sub_ps(void);
205   -void do_float_mul_d(void);
206   -void do_float_mul_s(void);
207   -void do_float_mul_ps(void);
208   -void do_float_div_d(void);
209   -void do_float_div_s(void);
210   -void do_float_div_ps(void);
  213 +
211 214 void do_float_addr_ps(void);
  215 +void do_float_mulr_ps(void);
212 216  
213   -#define CMP_OPS(op) \
  217 +#define FOP_PROTO(op) \
214 218 void do_cmp_d_ ## op(long cc); \
215 219 void do_cmpabs_d_ ## op(long cc); \
216 220 void do_cmp_s_ ## op(long cc); \
... ... @@ -218,22 +222,22 @@ void do_cmpabs_s_ ## op(long cc); \
218 222 void do_cmp_ps_ ## op(long cc); \
219 223 void do_cmpabs_ps_ ## op(long cc);
220 224  
221   -CMP_OPS(f)
222   -CMP_OPS(un)
223   -CMP_OPS(eq)
224   -CMP_OPS(ueq)
225   -CMP_OPS(olt)
226   -CMP_OPS(ult)
227   -CMP_OPS(ole)
228   -CMP_OPS(ule)
229   -CMP_OPS(sf)
230   -CMP_OPS(ngle)
231   -CMP_OPS(seq)
232   -CMP_OPS(ngl)
233   -CMP_OPS(lt)
234   -CMP_OPS(nge)
235   -CMP_OPS(le)
236   -CMP_OPS(ngt)
237   -#undef CMP_OPS
  225 +FOP_PROTO(f)
  226 +FOP_PROTO(un)
  227 +FOP_PROTO(eq)
  228 +FOP_PROTO(ueq)
  229 +FOP_PROTO(olt)
  230 +FOP_PROTO(ult)
  231 +FOP_PROTO(ole)
  232 +FOP_PROTO(ule)
  233 +FOP_PROTO(sf)
  234 +FOP_PROTO(ngle)
  235 +FOP_PROTO(seq)
  236 +FOP_PROTO(ngl)
  237 +FOP_PROTO(lt)
  238 +FOP_PROTO(nge)
  239 +FOP_PROTO(le)
  240 +FOP_PROTO(ngt)
  241 +#undef FOP_PROTO
238 242  
239 243 #endif /* !defined(__QEMU_MIPS_EXEC_H__) */
... ...
target-mips/op.c
... ... @@ -1609,6 +1609,14 @@ void op_cp1_enabled(void)
1609 1609 RETURN();
1610 1610 }
1611 1611  
  1612 +void op_cp1_64bitmode(void)
  1613 +{
  1614 + if (!(env->CP0_Status & (1 << CP0St_FR))) {
  1615 + CALL_FROM_TB1(do_raise_exception, EXCP_RI);
  1616 + }
  1617 + RETURN();
  1618 +}
  1619 +
1612 1620 /*
1613 1621 * Verify if floating point register is valid; an operation is not defined
1614 1622 * if bit 0 of any register specification is set and the FR bit in the
... ... @@ -1946,8 +1954,8 @@ FLOAT_OP(movn, ps)
1946 1954 RETURN();
1947 1955 }
1948 1956  
1949   -/* binary operations */
1950   -#define FLOAT_BINOP(name) \
  1957 +/* operations calling helpers, for s, d and ps */
  1958 +#define FLOAT_HOP(name) \
1951 1959 FLOAT_OP(name, d) \
1952 1960 { \
1953 1961 CALL_FROM_TB0(do_float_ ## name ## _d); \
... ... @@ -1966,18 +1974,45 @@ FLOAT_OP(name, ps) \
1966 1974 DEBUG_FPU_STATE(); \
1967 1975 RETURN(); \
1968 1976 }
1969   -FLOAT_BINOP(add)
1970   -FLOAT_BINOP(sub)
1971   -FLOAT_BINOP(mul)
1972   -FLOAT_BINOP(div)
1973   -#undef FLOAT_BINOP
  1977 +FLOAT_HOP(add)
  1978 +FLOAT_HOP(sub)
  1979 +FLOAT_HOP(mul)
  1980 +FLOAT_HOP(div)
  1981 +FLOAT_HOP(recip2)
  1982 +FLOAT_HOP(rsqrt2)
  1983 +FLOAT_HOP(rsqrt1)
  1984 +FLOAT_HOP(recip1)
  1985 +#undef FLOAT_HOP
  1986 +
  1987 +/* operations calling helpers, for s and d */
  1988 +#define FLOAT_HOP(name) \
  1989 +FLOAT_OP(name, d) \
  1990 +{ \
  1991 + CALL_FROM_TB0(do_float_ ## name ## _d); \
  1992 + DEBUG_FPU_STATE(); \
  1993 + RETURN(); \
  1994 +} \
  1995 +FLOAT_OP(name, s) \
  1996 +{ \
  1997 + CALL_FROM_TB0(do_float_ ## name ## _s); \
  1998 + DEBUG_FPU_STATE(); \
  1999 + RETURN(); \
  2000 +}
  2001 +FLOAT_HOP(rsqrt)
  2002 +FLOAT_HOP(recip)
  2003 +#undef FLOAT_HOP
1974 2004  
1975   -FLOAT_OP(addr, ps)
1976   -{
1977   - CALL_FROM_TB0(do_float_addr_ps);
1978   - DEBUG_FPU_STATE();
1979   - RETURN();
  2005 +/* operations calling helpers, for ps */
  2006 +#define FLOAT_HOP(name) \
  2007 +FLOAT_OP(name, ps) \
  2008 +{ \
  2009 + CALL_FROM_TB0(do_float_ ## name ## _ps); \
  2010 + DEBUG_FPU_STATE(); \
  2011 + RETURN(); \
1980 2012 }
  2013 +FLOAT_HOP(addr)
  2014 +FLOAT_HOP(mulr)
  2015 +#undef FLOAT_HOP
1981 2016  
1982 2017 /* ternary operations */
1983 2018 #define FLOAT_TERNOP(name1, name2) \
... ... @@ -2053,14 +2088,7 @@ FLOAT_OP(name, s) \
2053 2088 { \
2054 2089 FST2 = float32_ ## name(FST0, &env->fp_status); \
2055 2090 DEBUG_FPU_STATE(); \
2056   - RETURN(); \
2057   -} \
2058   -FLOAT_OP(name, ps) \
2059   -{ \
2060   - FST2 = float32_ ## name(FST0, &env->fp_status); \
2061   - FSTH2 = float32_ ## name(FSTH0, &env->fp_status); \
2062   - DEBUG_FPU_STATE(); \
2063   - RETURN(); \
  2091 + RETURN(); \
2064 2092 }
2065 2093 FLOAT_UNOP(sqrt)
2066 2094 #undef FLOAT_UNOP
... ...
target-mips/op_helper.c
... ... @@ -916,6 +916,59 @@ FLOAT_OP(floorw, s)
916 916 WT2 = 0x7fffffff;
917 917 }
918 918  
  919 +/* unary operations, MIPS specific, s and d */
  920 +#define FLOAT_UNOP(name) \
  921 +FLOAT_OP(name, d) \
  922 +{ \
  923 + set_float_exception_flags(0, &env->fp_status); \
  924 +/* XXX: not implemented */ \
  925 +/* FDT2 = float64_ ## name (FDT0, &env->fp_status);*/ \
  926 +do_raise_exception(EXCP_RI); \
  927 + update_fcr31(); \
  928 +} \
  929 +FLOAT_OP(name, s) \
  930 +{ \
  931 + set_float_exception_flags(0, &env->fp_status); \
  932 +/* XXX: not implemented */ \
  933 +/* FST2 = float32_ ## name (FST0, &env->fp_status);*/ \
  934 +do_raise_exception(EXCP_RI); \
  935 + update_fcr31(); \
  936 +}
  937 +FLOAT_UNOP(rsqrt)
  938 +FLOAT_UNOP(recip)
  939 +#undef FLOAT_UNOP
  940 +
  941 +/* unary operations, MIPS specific, s, d and ps */
  942 +#define FLOAT_UNOP(name) \
  943 +FLOAT_OP(name, d) \
  944 +{ \
  945 + set_float_exception_flags(0, &env->fp_status); \
  946 +/* XXX: not implemented */ \
  947 +/* FDT2 = float64_ ## name (FDT0, &env->fp_status);*/ \
  948 +do_raise_exception(EXCP_RI); \
  949 + update_fcr31(); \
  950 +} \
  951 +FLOAT_OP(name, s) \
  952 +{ \
  953 + set_float_exception_flags(0, &env->fp_status); \
  954 +/* XXX: not implemented */ \
  955 +/* FST2 = float32_ ## name (FST0, &env->fp_status);*/ \
  956 +do_raise_exception(EXCP_RI); \
  957 + update_fcr31(); \
  958 +} \
  959 +FLOAT_OP(name, ps) \
  960 +{ \
  961 + set_float_exception_flags(0, &env->fp_status); \
  962 +/* XXX: not implemented */ \
  963 +/* FST2 = float32_ ## name (FST0, &env->fp_status);*/ \
  964 +/* FSTH2 = float32_ ## name (FSTH0, &env->fp_status);*/ \
  965 +do_raise_exception(EXCP_RI); \
  966 + update_fcr31(); \
  967 +}
  968 +FLOAT_UNOP(rsqrt1)
  969 +FLOAT_UNOP(recip1)
  970 +#undef FLOAT_UNOP
  971 +
919 972 /* binary operations */
920 973 #define FLOAT_BINOP(name) \
921 974 FLOAT_OP(name, d) \
... ... @@ -943,6 +996,37 @@ FLOAT_BINOP(mul)
943 996 FLOAT_BINOP(div)
944 997 #undef FLOAT_BINOP
945 998  
  999 +/* binary operations, MIPS specific */
  1000 +#define FLOAT_BINOP(name) \
  1001 +FLOAT_OP(name, d) \
  1002 +{ \
  1003 + set_float_exception_flags(0, &env->fp_status); \
  1004 +/* XXX: not implemented */ \
  1005 +/* FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status);*/ \
  1006 +do_raise_exception(EXCP_RI); \
  1007 + update_fcr31(); \
  1008 +} \
  1009 +FLOAT_OP(name, s) \
  1010 +{ \
  1011 + set_float_exception_flags(0, &env->fp_status); \
  1012 +/* XXX: not implemented */ \
  1013 +/* FST2 = float32_ ## name (FST0, FST1, &env->fp_status);*/ \
  1014 +do_raise_exception(EXCP_RI); \
  1015 + update_fcr31(); \
  1016 +} \
  1017 +FLOAT_OP(name, ps) \
  1018 +{ \
  1019 + set_float_exception_flags(0, &env->fp_status); \
  1020 +/* XXX: not implemented */ \
  1021 +/* FST2 = float32_ ## name (FST0, FST1, &env->fp_status);*/ \
  1022 +/* FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fp_status);*/ \
  1023 +do_raise_exception(EXCP_RI); \
  1024 + update_fcr31(); \
  1025 +}
  1026 +FLOAT_BINOP(rsqrt2)
  1027 +FLOAT_BINOP(recip2)
  1028 +#undef FLOAT_BINOP
  1029 +
946 1030 FLOAT_OP(addr, ps)
947 1031 {
948 1032 set_float_exception_flags(0, &env->fp_status);
... ... @@ -951,6 +1035,14 @@ FLOAT_OP(addr, ps)
951 1035 update_fcr31();
952 1036 }
953 1037  
  1038 +FLOAT_OP(mulr, ps)
  1039 +{
  1040 + set_float_exception_flags(0, &env->fp_status);
  1041 + FST2 = float32_mul (FST0, FSTH0, &env->fp_status);
  1042 + FSTH2 = float32_mul (FST1, FSTH1, &env->fp_status);
  1043 + update_fcr31();
  1044 +}
  1045 +
954 1046 #define FOP_COND_D(op, cond) \
955 1047 void do_cmp_d_ ## op (long cc) \
956 1048 { \
... ...
target-mips/translate.c
... ... @@ -4378,14 +4378,12 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
4378 4378 opn = "dmtc1";
4379 4379 break;
4380 4380 case OPC_MFHC1:
4381   - gen_op_cp1_registers(fs);
4382 4381 GEN_LOAD_FREG_FTN(WTH0, fs);
4383 4382 gen_op_mfhc1();
4384 4383 GEN_STORE_TN_REG(rt, T0);
4385 4384 opn = "mfhc1";
4386 4385 break;
4387 4386 case OPC_MTHC1:
4388   - gen_op_cp1_registers(fs);
4389 4387 GEN_LOAD_REG_TN(T0, rt);
4390 4388 gen_op_mthc1();
4391 4389 GEN_STORE_FTN_FREG(fs, WTH0);
... ... @@ -4405,9 +4403,9 @@ static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
4405 4403  
4406 4404 GEN_LOAD_REG_TN(T0, rd);
4407 4405 GEN_LOAD_REG_TN(T1, rs);
4408   - if (cc)
  4406 + if (cc) {
4409 4407 ccbit = 1 << (24 + cc);
4410   - else
  4408 + } else
4411 4409 ccbit = 1 << 23;
4412 4410 if (!tf)
4413 4411 gen_op_movf(ccbit);
... ... @@ -4421,9 +4419,9 @@ static void glue(gen_movcf_, fmt) (DisasContext *ctx, int cc, int tf) \
4421 4419 { \
4422 4420 uint32_t ccbit; \
4423 4421 \
4424   - if (cc) \
  4422 + if (cc) { \
4425 4423 ccbit = 1 << (24 + cc); \
4426   - else \
  4424 + } else \
4427 4425 ccbit = 1 << 23; \
4428 4426 if (!tf) \
4429 4427 glue(gen_op_float_movf_, fmt)(ccbit); \
... ... @@ -4536,28 +4534,28 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4536 4534 opn = "neg.s";
4537 4535 break;
4538 4536 case FOP(8, 16):
4539   - gen_op_cp1_registers(fs);
  4537 + gen_op_cp1_64bitmode();
4540 4538 GEN_LOAD_FREG_FTN(WT0, fs);
4541 4539 gen_op_float_roundl_s();
4542 4540 GEN_STORE_FTN_FREG(fd, DT2);
4543 4541 opn = "round.l.s";
4544 4542 break;
4545 4543 case FOP(9, 16):
4546   - gen_op_cp1_registers(fs);
  4544 + gen_op_cp1_64bitmode();
4547 4545 GEN_LOAD_FREG_FTN(WT0, fs);
4548 4546 gen_op_float_truncl_s();
4549 4547 GEN_STORE_FTN_FREG(fd, DT2);
4550 4548 opn = "trunc.l.s";
4551 4549 break;
4552 4550 case FOP(10, 16):
4553   - gen_op_cp1_registers(fs);
  4551 + gen_op_cp1_64bitmode();
4554 4552 GEN_LOAD_FREG_FTN(WT0, fs);
4555 4553 gen_op_float_ceill_s();
4556 4554 GEN_STORE_FTN_FREG(fd, DT2);
4557 4555 opn = "ceil.l.s";
4558 4556 break;
4559 4557 case FOP(11, 16):
4560   - gen_op_cp1_registers(fs);
  4558 + gen_op_cp1_64bitmode();
4561 4559 GEN_LOAD_FREG_FTN(WT0, fs);
4562 4560 gen_op_float_floorl_s();
4563 4561 GEN_STORE_FTN_FREG(fd, DT2);
... ... @@ -4611,6 +4609,48 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4611 4609 GEN_STORE_FTN_FREG(fd, WT2);
4612 4610 opn = "movn.s";
4613 4611 break;
  4612 + case FOP(21, 16):
  4613 + GEN_LOAD_FREG_FTN(WT0, fs);
  4614 + gen_op_float_recip_s();
  4615 + GEN_STORE_FTN_FREG(fd, WT2);
  4616 + opn = "recip.s";
  4617 + break;
  4618 + case FOP(22, 16):
  4619 + GEN_LOAD_FREG_FTN(WT0, fs);
  4620 + gen_op_float_rsqrt_s();
  4621 + GEN_STORE_FTN_FREG(fd, WT2);
  4622 + opn = "rsqrt.s";
  4623 + break;
  4624 + case FOP(28, 16):
  4625 + gen_op_cp1_64bitmode();
  4626 + GEN_LOAD_FREG_FTN(WT0, fs);
  4627 + GEN_LOAD_FREG_FTN(WT2, fd);
  4628 + gen_op_float_recip2_s();
  4629 + GEN_STORE_FTN_FREG(fd, WT2);
  4630 + opn = "recip2.s";
  4631 + break;
  4632 + case FOP(29, 16):
  4633 + gen_op_cp1_64bitmode();
  4634 + GEN_LOAD_FREG_FTN(WT0, fs);
  4635 + gen_op_float_recip1_s();
  4636 + GEN_STORE_FTN_FREG(fd, WT2);
  4637 + opn = "recip1.s";
  4638 + break;
  4639 + case FOP(30, 16):
  4640 + gen_op_cp1_64bitmode();
  4641 + GEN_LOAD_FREG_FTN(WT0, fs);
  4642 + gen_op_float_rsqrt1_s();
  4643 + GEN_STORE_FTN_FREG(fd, WT2);
  4644 + opn = "rsqrt1.s";
  4645 + break;
  4646 + case FOP(31, 16):
  4647 + gen_op_cp1_64bitmode();
  4648 + GEN_LOAD_FREG_FTN(WT0, fs);
  4649 + GEN_LOAD_FREG_FTN(WT2, fd);
  4650 + gen_op_float_rsqrt2_s();
  4651 + GEN_STORE_FTN_FREG(fd, WT2);
  4652 + opn = "rsqrt2.s";
  4653 + break;
4614 4654 case FOP(33, 16):
4615 4655 gen_op_cp1_registers(fd);
4616 4656 GEN_LOAD_FREG_FTN(WT0, fs);
... ... @@ -4625,14 +4665,14 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4625 4665 opn = "cvt.w.s";
4626 4666 break;
4627 4667 case FOP(37, 16):
4628   - gen_op_cp1_registers(fs | fd);
  4668 + gen_op_cp1_64bitmode();
4629 4669 GEN_LOAD_FREG_FTN(WT0, fs);
4630 4670 gen_op_float_cvtl_s();
4631 4671 GEN_STORE_FTN_FREG(fd, DT2);
4632 4672 opn = "cvt.l.s";
4633 4673 break;
4634 4674 case FOP(38, 16):
4635   - gen_op_cp1_registers(fs | ft | fd);
  4675 + gen_op_cp1_64bitmode();
4636 4676 GEN_LOAD_FREG_FTN(WT1, fs);
4637 4677 GEN_LOAD_FREG_FTN(WT0, ft);
4638 4678 gen_op_float_cvtps_s();
... ... @@ -4658,6 +4698,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4658 4698 GEN_LOAD_FREG_FTN(WT0, fs);
4659 4699 GEN_LOAD_FREG_FTN(WT1, ft);
4660 4700 if (ctx->opcode & (1 << 6)) {
  4701 + gen_op_cp1_64bitmode();
4661 4702 gen_cmpabs_s(func-48, cc);
4662 4703 opn = condnames_abs[func-48];
4663 4704 } else {
... ... @@ -4730,28 +4771,28 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4730 4771 opn = "neg.d";
4731 4772 break;
4732 4773 case FOP(8, 17):
4733   - gen_op_cp1_registers(fs);
  4774 + gen_op_cp1_64bitmode();
4734 4775 GEN_LOAD_FREG_FTN(DT0, fs);
4735 4776 gen_op_float_roundl_d();
4736 4777 GEN_STORE_FTN_FREG(fd, DT2);
4737 4778 opn = "round.l.d";
4738 4779 break;
4739 4780 case FOP(9, 17):
4740   - gen_op_cp1_registers(fs);
  4781 + gen_op_cp1_64bitmode();
4741 4782 GEN_LOAD_FREG_FTN(DT0, fs);
4742 4783 gen_op_float_truncl_d();
4743 4784 GEN_STORE_FTN_FREG(fd, DT2);
4744 4785 opn = "trunc.l.d";
4745 4786 break;
4746 4787 case FOP(10, 17):
4747   - gen_op_cp1_registers(fs);
  4788 + gen_op_cp1_64bitmode();
4748 4789 GEN_LOAD_FREG_FTN(DT0, fs);
4749 4790 gen_op_float_ceill_d();
4750 4791 GEN_STORE_FTN_FREG(fd, DT2);
4751 4792 opn = "ceil.l.d";
4752 4793 break;
4753 4794 case FOP(11, 17):
4754   - gen_op_cp1_registers(fs);
  4795 + gen_op_cp1_64bitmode();
4755 4796 GEN_LOAD_FREG_FTN(DT0, fs);
4756 4797 gen_op_float_floorl_d();
4757 4798 GEN_STORE_FTN_FREG(fd, DT2);
... ... @@ -4809,6 +4850,50 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4809 4850 GEN_STORE_FTN_FREG(fd, DT2);
4810 4851 opn = "movn.d";
4811 4852 break;
  4853 + case FOP(21, 17):
  4854 + gen_op_cp1_registers(fs | fd);
  4855 + GEN_LOAD_FREG_FTN(DT0, fs);
  4856 + gen_op_float_recip_d();
  4857 + GEN_STORE_FTN_FREG(fd, DT2);
  4858 + opn = "recip.d";
  4859 + break;
  4860 + case FOP(22, 17):
  4861 + gen_op_cp1_registers(fs | fd);
  4862 + GEN_LOAD_FREG_FTN(DT0, fs);
  4863 + gen_op_float_rsqrt_d();
  4864 + GEN_STORE_FTN_FREG(fd, DT2);
  4865 + opn = "rsqrt.d";
  4866 + break;
  4867 + case FOP(28, 17):
  4868 + gen_op_cp1_64bitmode();
  4869 + GEN_LOAD_FREG_FTN(DT0, fs);
  4870 + GEN_LOAD_FREG_FTN(DT2, ft);
  4871 + gen_op_float_recip2_d();
  4872 + GEN_STORE_FTN_FREG(fd, DT2);
  4873 + opn = "recip2.d";
  4874 + break;
  4875 + case FOP(29, 17):
  4876 + gen_op_cp1_64bitmode();
  4877 + GEN_LOAD_FREG_FTN(DT0, fs);
  4878 + gen_op_float_recip1_d();
  4879 + GEN_STORE_FTN_FREG(fd, DT2);
  4880 + opn = "recip1.d";
  4881 + break;
  4882 + case FOP(30, 17):
  4883 + gen_op_cp1_64bitmode();
  4884 + GEN_LOAD_FREG_FTN(DT0, fs);
  4885 + gen_op_float_rsqrt1_d();
  4886 + GEN_STORE_FTN_FREG(fd, DT2);
  4887 + opn = "rsqrt1.d";
  4888 + break;
  4889 + case FOP(31, 17):
  4890 + gen_op_cp1_64bitmode();
  4891 + GEN_LOAD_FREG_FTN(DT0, fs);
  4892 + GEN_LOAD_FREG_FTN(DT2, ft);
  4893 + gen_op_float_rsqrt2_d();
  4894 + GEN_STORE_FTN_FREG(fd, DT2);
  4895 + opn = "rsqrt2.d";
  4896 + break;
4812 4897 case FOP(48, 17):
4813 4898 case FOP(49, 17):
4814 4899 case FOP(50, 17):
... ... @@ -4825,13 +4910,14 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4825 4910 case FOP(61, 17):
4826 4911 case FOP(62, 17):
4827 4912 case FOP(63, 17):
4828   - gen_op_cp1_registers(fs | ft);
4829 4913 GEN_LOAD_FREG_FTN(DT0, fs);
4830 4914 GEN_LOAD_FREG_FTN(DT1, ft);
4831 4915 if (ctx->opcode & (1 << 6)) {
  4916 + gen_op_cp1_64bitmode();
4832 4917 gen_cmpabs_d(func-48, cc);
4833 4918 opn = condnames_abs[func-48];
4834 4919 } else {
  4920 + gen_op_cp1_registers(fs | ft);
4835 4921 gen_cmp_d(func-48, cc);
4836 4922 opn = condnames[func-48];
4837 4923 }
... ... @@ -4851,7 +4937,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4851 4937 opn = "cvt.w.d";
4852 4938 break;
4853 4939 case FOP(37, 17):
4854   - gen_op_cp1_registers(fs | fd);
  4940 + gen_op_cp1_64bitmode();
4855 4941 GEN_LOAD_FREG_FTN(DT0, fs);
4856 4942 gen_op_float_cvtl_d();
4857 4943 GEN_STORE_FTN_FREG(fd, DT2);
... ... @@ -4871,14 +4957,14 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4871 4957 opn = "cvt.d.w";
4872 4958 break;
4873 4959 case FOP(32, 21):
4874   - gen_op_cp1_registers(fs);
  4960 + gen_op_cp1_64bitmode();
4875 4961 GEN_LOAD_FREG_FTN(DT0, fs);
4876 4962 gen_op_float_cvts_l();
4877 4963 GEN_STORE_FTN_FREG(fd, WT2);
4878 4964 opn = "cvt.s.l";
4879 4965 break;
4880 4966 case FOP(33, 21):
4881   - gen_op_cp1_registers(fs | fd);
  4967 + gen_op_cp1_64bitmode();
4882 4968 GEN_LOAD_FREG_FTN(DT0, fs);
4883 4969 gen_op_float_cvtd_l();
4884 4970 GEN_STORE_FTN_FREG(fd, DT2);
... ... @@ -4886,7 +4972,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4886 4972 break;
4887 4973 case FOP(38, 20):
4888 4974 case FOP(38, 21):
4889   - gen_op_cp1_registers(fs | fd);
  4975 + gen_op_cp1_64bitmode();
4890 4976 GEN_LOAD_FREG_FTN(WT0, fs);
4891 4977 GEN_LOAD_FREG_FTN(WTH0, fs);
4892 4978 gen_op_float_cvtps_pw();
... ... @@ -4895,7 +4981,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4895 4981 opn = "cvt.ps.pw";
4896 4982 break;
4897 4983 case FOP(0, 22):
4898   - gen_op_cp1_registers(fs | ft | fd);
  4984 + gen_op_cp1_64bitmode();
4899 4985 GEN_LOAD_FREG_FTN(WT0, fs);
4900 4986 GEN_LOAD_FREG_FTN(WTH0, fs);
4901 4987 GEN_LOAD_FREG_FTN(WT1, ft);
... ... @@ -4906,7 +4992,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4906 4992 opn = "add.ps";
4907 4993 break;
4908 4994 case FOP(1, 22):
4909   - gen_op_cp1_registers(fs | ft | fd);
  4995 + gen_op_cp1_64bitmode();
4910 4996 GEN_LOAD_FREG_FTN(WT0, fs);
4911 4997 GEN_LOAD_FREG_FTN(WTH0, fs);
4912 4998 GEN_LOAD_FREG_FTN(WT1, ft);
... ... @@ -4917,7 +5003,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4917 5003 opn = "sub.ps";
4918 5004 break;
4919 5005 case FOP(2, 22):
4920   - gen_op_cp1_registers(fs | ft | fd);
  5006 + gen_op_cp1_64bitmode();
4921 5007 GEN_LOAD_FREG_FTN(WT0, fs);
4922 5008 GEN_LOAD_FREG_FTN(WTH0, fs);
4923 5009 GEN_LOAD_FREG_FTN(WT1, ft);
... ... @@ -4928,7 +5014,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4928 5014 opn = "mul.ps";
4929 5015 break;
4930 5016 case FOP(5, 22):
4931   - gen_op_cp1_registers(fs | fd);
  5017 + gen_op_cp1_64bitmode();
4932 5018 GEN_LOAD_FREG_FTN(WT0, fs);
4933 5019 GEN_LOAD_FREG_FTN(WTH0, fs);
4934 5020 gen_op_float_abs_ps();
... ... @@ -4937,7 +5023,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4937 5023 opn = "abs.ps";
4938 5024 break;
4939 5025 case FOP(6, 22):
4940   - gen_op_cp1_registers(fs | fd);
  5026 + gen_op_cp1_64bitmode();
4941 5027 GEN_LOAD_FREG_FTN(WT0, fs);
4942 5028 GEN_LOAD_FREG_FTN(WTH0, fs);
4943 5029 gen_op_float_mov_ps();
... ... @@ -4946,7 +5032,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4946 5032 opn = "mov.ps";
4947 5033 break;
4948 5034 case FOP(7, 22):
4949   - gen_op_cp1_registers(fs | fd);
  5035 + gen_op_cp1_64bitmode();
4950 5036 GEN_LOAD_FREG_FTN(WT0, fs);
4951 5037 GEN_LOAD_FREG_FTN(WTH0, fs);
4952 5038 gen_op_float_chs_ps();
... ... @@ -4955,6 +5041,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4955 5041 opn = "neg.ps";
4956 5042 break;
4957 5043 case FOP(17, 22):
  5044 + gen_op_cp1_64bitmode();
4958 5045 GEN_LOAD_REG_TN(T0, ft);
4959 5046 GEN_LOAD_FREG_FTN(WT0, fs);
4960 5047 GEN_LOAD_FREG_FTN(WTH0, fs);
... ... @@ -4966,6 +5053,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4966 5053 opn = "movcf.ps";
4967 5054 break;
4968 5055 case FOP(18, 22):
  5056 + gen_op_cp1_64bitmode();
4969 5057 GEN_LOAD_REG_TN(T0, ft);
4970 5058 GEN_LOAD_FREG_FTN(WT0, fs);
4971 5059 GEN_LOAD_FREG_FTN(WTH0, fs);
... ... @@ -4977,6 +5065,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4977 5065 opn = "movz.ps";
4978 5066 break;
4979 5067 case FOP(19, 22):
  5068 + gen_op_cp1_64bitmode();
4980 5069 GEN_LOAD_REG_TN(T0, ft);
4981 5070 GEN_LOAD_FREG_FTN(WT0, fs);
4982 5071 GEN_LOAD_FREG_FTN(WTH0, fs);
... ... @@ -4988,7 +5077,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4988 5077 opn = "movn.ps";
4989 5078 break;
4990 5079 case FOP(24, 22):
4991   - gen_op_cp1_registers(fs | fd | ft);
  5080 + gen_op_cp1_64bitmode();
4992 5081 GEN_LOAD_FREG_FTN(WT0, fs);
4993 5082 GEN_LOAD_FREG_FTN(WTH0, fs);
4994 5083 GEN_LOAD_FREG_FTN(WT1, ft);
... ... @@ -4998,15 +5087,66 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4998 5087 GEN_STORE_FTN_FREG(fd, WTH2);
4999 5088 opn = "addr.ps";
5000 5089 break;
  5090 + case FOP(26, 22):
  5091 + gen_op_cp1_64bitmode();
  5092 + GEN_LOAD_FREG_FTN(WT0, fs);
  5093 + GEN_LOAD_FREG_FTN(WTH0, fs);
  5094 + GEN_LOAD_FREG_FTN(WT1, ft);
  5095 + GEN_LOAD_FREG_FTN(WTH1, ft);
  5096 + gen_op_float_mulr_ps();
  5097 + GEN_STORE_FTN_FREG(fd, WT2);
  5098 + GEN_STORE_FTN_FREG(fd, WTH2);
  5099 + opn = "mulr.ps";
  5100 + break;
  5101 + case FOP(28, 22):
  5102 + gen_op_cp1_64bitmode();
  5103 + GEN_LOAD_FREG_FTN(WT0, fs);
  5104 + GEN_LOAD_FREG_FTN(WTH0, fs);
  5105 + GEN_LOAD_FREG_FTN(WT2, fd);
  5106 + GEN_LOAD_FREG_FTN(WTH2, fd);
  5107 + gen_op_float_recip2_ps();
  5108 + GEN_STORE_FTN_FREG(fd, WT2);
  5109 + GEN_STORE_FTN_FREG(fd, WTH2);
  5110 + opn = "recip2.ps";
  5111 + break;
  5112 + case FOP(29, 22):
  5113 + gen_op_cp1_64bitmode();
  5114 + GEN_LOAD_FREG_FTN(WT0, fs);
  5115 + GEN_LOAD_FREG_FTN(WTH0, fs);
  5116 + gen_op_float_recip1_ps();
  5117 + GEN_STORE_FTN_FREG(fd, WT2);
  5118 + GEN_STORE_FTN_FREG(fd, WTH2);
  5119 + opn = "recip1.ps";
  5120 + break;
  5121 + case FOP(30, 22):
  5122 + gen_op_cp1_64bitmode();
  5123 + GEN_LOAD_FREG_FTN(WT0, fs);
  5124 + GEN_LOAD_FREG_FTN(WTH0, fs);
  5125 + gen_op_float_rsqrt1_ps();
  5126 + GEN_STORE_FTN_FREG(fd, WT2);
  5127 + GEN_STORE_FTN_FREG(fd, WTH2);
  5128 + opn = "rsqrt1.ps";
  5129 + break;
  5130 + case FOP(31, 22):
  5131 + gen_op_cp1_64bitmode();
  5132 + GEN_LOAD_FREG_FTN(WT0, fs);
  5133 + GEN_LOAD_FREG_FTN(WTH0, fs);
  5134 + GEN_LOAD_FREG_FTN(WT2, fd);
  5135 + GEN_LOAD_FREG_FTN(WTH2, fd);
  5136 + gen_op_float_rsqrt2_ps();
  5137 + GEN_STORE_FTN_FREG(fd, WT2);
  5138 + GEN_STORE_FTN_FREG(fd, WTH2);
  5139 + opn = "rsqrt2.ps";
  5140 + break;
5001 5141 case FOP(32, 22):
5002   - gen_op_cp1_registers(fs);
  5142 + gen_op_cp1_64bitmode();
5003 5143 GEN_LOAD_FREG_FTN(WTH0, fs);
5004 5144 gen_op_float_cvts_pu();
5005 5145 GEN_STORE_FTN_FREG(fd, WT2);
5006 5146 opn = "cvt.s.pu";
5007 5147 break;
5008 5148 case FOP(36, 22):
5009   - gen_op_cp1_registers(fs | fd);
  5149 + gen_op_cp1_64bitmode();
5010 5150 GEN_LOAD_FREG_FTN(WT0, fs);
5011 5151 GEN_LOAD_FREG_FTN(WTH0, fs);
5012 5152 gen_op_float_cvtpw_ps();
... ... @@ -5015,14 +5155,14 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
5015 5155 opn = "cvt.pw.ps";
5016 5156 break;
5017 5157 case FOP(40, 22):
5018   - gen_op_cp1_registers(fs);
  5158 + gen_op_cp1_64bitmode();
5019 5159 GEN_LOAD_FREG_FTN(WT0, fs);
5020 5160 gen_op_float_cvts_pl();
5021 5161 GEN_STORE_FTN_FREG(fd, WT2);
5022 5162 opn = "cvt.s.pl";
5023 5163 break;
5024 5164 case FOP(44, 22):
5025   - gen_op_cp1_registers(fs | ft | fd);
  5165 + gen_op_cp1_64bitmode();
5026 5166 GEN_LOAD_FREG_FTN(WT0, fs);
5027 5167 GEN_LOAD_FREG_FTN(WT1, ft);
5028 5168 gen_op_float_pll_ps();
... ... @@ -5030,7 +5170,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
5030 5170 opn = "pll.ps";
5031 5171 break;
5032 5172 case FOP(45, 22):
5033   - gen_op_cp1_registers(fs | ft | fd);
  5173 + gen_op_cp1_64bitmode();
5034 5174 GEN_LOAD_FREG_FTN(WT0, fs);
5035 5175 GEN_LOAD_FREG_FTN(WTH1, ft);
5036 5176 gen_op_float_plu_ps();
... ... @@ -5038,7 +5178,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
5038 5178 opn = "plu.ps";
5039 5179 break;
5040 5180 case FOP(46, 22):
5041   - gen_op_cp1_registers(fs | ft | fd);
  5181 + gen_op_cp1_64bitmode();
5042 5182 GEN_LOAD_FREG_FTN(WTH0, fs);
5043 5183 GEN_LOAD_FREG_FTN(WT1, ft);
5044 5184 gen_op_float_pul_ps();
... ... @@ -5046,7 +5186,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
5046 5186 opn = "pul.ps";
5047 5187 break;
5048 5188 case FOP(47, 22):
5049   - gen_op_cp1_registers(fs | ft | fd);
  5189 + gen_op_cp1_64bitmode();
5050 5190 GEN_LOAD_FREG_FTN(WTH0, fs);
5051 5191 GEN_LOAD_FREG_FTN(WTH1, ft);
5052 5192 gen_op_float_puu_ps();
... ... @@ -5069,7 +5209,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
5069 5209 case FOP(61, 22):
5070 5210 case FOP(62, 22):
5071 5211 case FOP(63, 22):
5072   - gen_op_cp1_registers(fs | ft);
  5212 + gen_op_cp1_64bitmode();
5073 5213 GEN_LOAD_FREG_FTN(WT0, fs);
5074 5214 GEN_LOAD_FREG_FTN(WTH0, fs);
5075 5215 GEN_LOAD_FREG_FTN(WT1, ft);
... ... @@ -5106,6 +5246,8 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc, int fd,
5106 5246 {
5107 5247 const char *opn = "extended float load/store";
5108 5248  
  5249 + /* All of those work only on 64bit FPUs. */
  5250 + gen_op_cp1_64bitmode();
5109 5251 GEN_LOAD_REG_TN(T0, base);
5110 5252 GEN_LOAD_REG_TN(T1, index);
5111 5253 /* Don't do NOP if destination is zero: we must perform the actual
... ... @@ -5156,7 +5298,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, int fd,
5156 5298 const char *opn = "flt3_arith";
5157 5299  
5158 5300 /* All of those work only on 64bit FPUs. */
5159   - gen_op_cp1_registers(fd | fr | fs | ft);
  5301 + gen_op_cp1_64bitmode();
5160 5302 switch (opc) {
5161 5303 case OPC_ALNV_PS:
5162 5304 GEN_LOAD_REG_TN(T0, fr);
... ...