More MIPS 64-bit FPU support.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2834 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
ths 2007-05-19 20:29:41 +00:00
parent f469b9db01
commit 57fa1fb31c
4 changed files with 370 additions and 104 deletions

View File

@ -166,6 +166,36 @@ void cpu_mips_clock_init (CPUState *env);
void cpu_mips_tlb_flush (CPUState *env, int flush_global); void cpu_mips_tlb_flush (CPUState *env, int flush_global);
void do_ctc1 (void); void do_ctc1 (void);
#define FOP_PROTO(op) \
void do_float_ ## op ## _s(void); \
void do_float_ ## op ## _d(void);
FOP_PROTO(roundl)
FOP_PROTO(roundw)
FOP_PROTO(truncl)
FOP_PROTO(truncw)
FOP_PROTO(ceill)
FOP_PROTO(ceilw)
FOP_PROTO(floorl)
FOP_PROTO(floorw)
FOP_PROTO(rsqrt)
FOP_PROTO(recip)
#undef FOP_PROTO
#define FOP_PROTO(op) \
void do_float_ ## op ## _s(void); \
void do_float_ ## op ## _d(void); \
void do_float_ ## op ## _ps(void);
FOP_PROTO(add)
FOP_PROTO(sub)
FOP_PROTO(mul)
FOP_PROTO(div)
FOP_PROTO(recip1)
FOP_PROTO(recip2)
FOP_PROTO(rsqrt1)
FOP_PROTO(rsqrt2)
#undef FOP_PROTO
void do_float_cvtd_s(void); void do_float_cvtd_s(void);
void do_float_cvtd_w(void); void do_float_cvtd_w(void);
void do_float_cvtd_l(void); void do_float_cvtd_l(void);
@ -180,37 +210,11 @@ void do_float_cvts_pl(void);
void do_float_cvts_pu(void); void do_float_cvts_pu(void);
void do_float_cvtw_s(void); void do_float_cvtw_s(void);
void do_float_cvtw_d(void); void do_float_cvtw_d(void);
void do_float_roundl_d(void);
void do_float_roundl_s(void);
void do_float_roundw_d(void);
void do_float_roundw_s(void);
void do_float_truncl_d(void);
void do_float_truncl_s(void);
void do_float_truncw_d(void);
void do_float_truncw_s(void);
void do_float_ceill_d(void);
void do_float_ceill_s(void);
void do_float_ceilw_d(void);
void do_float_ceilw_s(void);
void do_float_floorl_d(void);
void do_float_floorl_s(void);
void do_float_floorw_d(void);
void do_float_floorw_s(void);
void do_float_add_d(void);
void do_float_add_s(void);
void do_float_add_ps(void);
void do_float_sub_d(void);
void do_float_sub_s(void);
void do_float_sub_ps(void);
void do_float_mul_d(void);
void do_float_mul_s(void);
void do_float_mul_ps(void);
void do_float_div_d(void);
void do_float_div_s(void);
void do_float_div_ps(void);
void do_float_addr_ps(void);
#define CMP_OPS(op) \ void do_float_addr_ps(void);
void do_float_mulr_ps(void);
#define FOP_PROTO(op) \
void do_cmp_d_ ## op(long cc); \ void do_cmp_d_ ## op(long cc); \
void do_cmpabs_d_ ## op(long cc); \ void do_cmpabs_d_ ## op(long cc); \
void do_cmp_s_ ## op(long cc); \ void do_cmp_s_ ## op(long cc); \
@ -218,22 +222,22 @@ void do_cmpabs_s_ ## op(long cc); \
void do_cmp_ps_ ## op(long cc); \ void do_cmp_ps_ ## op(long cc); \
void do_cmpabs_ps_ ## op(long cc); void do_cmpabs_ps_ ## op(long cc);
CMP_OPS(f) FOP_PROTO(f)
CMP_OPS(un) FOP_PROTO(un)
CMP_OPS(eq) FOP_PROTO(eq)
CMP_OPS(ueq) FOP_PROTO(ueq)
CMP_OPS(olt) FOP_PROTO(olt)
CMP_OPS(ult) FOP_PROTO(ult)
CMP_OPS(ole) FOP_PROTO(ole)
CMP_OPS(ule) FOP_PROTO(ule)
CMP_OPS(sf) FOP_PROTO(sf)
CMP_OPS(ngle) FOP_PROTO(ngle)
CMP_OPS(seq) FOP_PROTO(seq)
CMP_OPS(ngl) FOP_PROTO(ngl)
CMP_OPS(lt) FOP_PROTO(lt)
CMP_OPS(nge) FOP_PROTO(nge)
CMP_OPS(le) FOP_PROTO(le)
CMP_OPS(ngt) FOP_PROTO(ngt)
#undef CMP_OPS #undef FOP_PROTO
#endif /* !defined(__QEMU_MIPS_EXEC_H__) */ #endif /* !defined(__QEMU_MIPS_EXEC_H__) */

View File

@ -1609,6 +1609,14 @@ void op_cp1_enabled(void)
RETURN(); RETURN();
} }
void op_cp1_64bitmode(void)
{
if (!(env->CP0_Status & (1 << CP0St_FR))) {
CALL_FROM_TB1(do_raise_exception, EXCP_RI);
}
RETURN();
}
/* /*
* Verify if floating point register is valid; an operation is not defined * Verify if floating point register is valid; an operation is not defined
* if bit 0 of any register specification is set and the FR bit in the * if bit 0 of any register specification is set and the FR bit in the
@ -1946,8 +1954,8 @@ FLOAT_OP(movn, ps)
RETURN(); RETURN();
} }
/* binary operations */ /* operations calling helpers, for s, d and ps */
#define FLOAT_BINOP(name) \ #define FLOAT_HOP(name) \
FLOAT_OP(name, d) \ FLOAT_OP(name, d) \
{ \ { \
CALL_FROM_TB0(do_float_ ## name ## _d); \ CALL_FROM_TB0(do_float_ ## name ## _d); \
@ -1966,18 +1974,45 @@ FLOAT_OP(name, ps) \
DEBUG_FPU_STATE(); \ DEBUG_FPU_STATE(); \
RETURN(); \ RETURN(); \
} }
FLOAT_BINOP(add) FLOAT_HOP(add)
FLOAT_BINOP(sub) FLOAT_HOP(sub)
FLOAT_BINOP(mul) FLOAT_HOP(mul)
FLOAT_BINOP(div) FLOAT_HOP(div)
#undef FLOAT_BINOP FLOAT_HOP(recip2)
FLOAT_HOP(rsqrt2)
FLOAT_HOP(rsqrt1)
FLOAT_HOP(recip1)
#undef FLOAT_HOP
FLOAT_OP(addr, ps) /* operations calling helpers, for s and d */
{ #define FLOAT_HOP(name) \
CALL_FROM_TB0(do_float_addr_ps); FLOAT_OP(name, d) \
DEBUG_FPU_STATE(); { \
RETURN(); CALL_FROM_TB0(do_float_ ## name ## _d); \
DEBUG_FPU_STATE(); \
RETURN(); \
} \
FLOAT_OP(name, s) \
{ \
CALL_FROM_TB0(do_float_ ## name ## _s); \
DEBUG_FPU_STATE(); \
RETURN(); \
} }
FLOAT_HOP(rsqrt)
FLOAT_HOP(recip)
#undef FLOAT_HOP
/* operations calling helpers, for ps */
#define FLOAT_HOP(name) \
FLOAT_OP(name, ps) \
{ \
CALL_FROM_TB0(do_float_ ## name ## _ps); \
DEBUG_FPU_STATE(); \
RETURN(); \
}
FLOAT_HOP(addr)
FLOAT_HOP(mulr)
#undef FLOAT_HOP
/* ternary operations */ /* ternary operations */
#define FLOAT_TERNOP(name1, name2) \ #define FLOAT_TERNOP(name1, name2) \
@ -2053,14 +2088,7 @@ FLOAT_OP(name, s) \
{ \ { \
FST2 = float32_ ## name(FST0, &env->fp_status); \ FST2 = float32_ ## name(FST0, &env->fp_status); \
DEBUG_FPU_STATE(); \ DEBUG_FPU_STATE(); \
RETURN(); \ RETURN(); \
} \
FLOAT_OP(name, ps) \
{ \
FST2 = float32_ ## name(FST0, &env->fp_status); \
FSTH2 = float32_ ## name(FSTH0, &env->fp_status); \
DEBUG_FPU_STATE(); \
RETURN(); \
} }
FLOAT_UNOP(sqrt) FLOAT_UNOP(sqrt)
#undef FLOAT_UNOP #undef FLOAT_UNOP

View File

@ -916,6 +916,59 @@ FLOAT_OP(floorw, s)
WT2 = 0x7fffffff; WT2 = 0x7fffffff;
} }
/* unary operations, MIPS specific, s and d */
#define FLOAT_UNOP(name) \
FLOAT_OP(name, d) \
{ \
set_float_exception_flags(0, &env->fp_status); \
/* XXX: not implemented */ \
/* FDT2 = float64_ ## name (FDT0, &env->fp_status);*/ \
do_raise_exception(EXCP_RI); \
update_fcr31(); \
} \
FLOAT_OP(name, s) \
{ \
set_float_exception_flags(0, &env->fp_status); \
/* XXX: not implemented */ \
/* FST2 = float32_ ## name (FST0, &env->fp_status);*/ \
do_raise_exception(EXCP_RI); \
update_fcr31(); \
}
FLOAT_UNOP(rsqrt)
FLOAT_UNOP(recip)
#undef FLOAT_UNOP
/* unary operations, MIPS specific, s, d and ps */
#define FLOAT_UNOP(name) \
FLOAT_OP(name, d) \
{ \
set_float_exception_flags(0, &env->fp_status); \
/* XXX: not implemented */ \
/* FDT2 = float64_ ## name (FDT0, &env->fp_status);*/ \
do_raise_exception(EXCP_RI); \
update_fcr31(); \
} \
FLOAT_OP(name, s) \
{ \
set_float_exception_flags(0, &env->fp_status); \
/* XXX: not implemented */ \
/* FST2 = float32_ ## name (FST0, &env->fp_status);*/ \
do_raise_exception(EXCP_RI); \
update_fcr31(); \
} \
FLOAT_OP(name, ps) \
{ \
set_float_exception_flags(0, &env->fp_status); \
/* XXX: not implemented */ \
/* FST2 = float32_ ## name (FST0, &env->fp_status);*/ \
/* FSTH2 = float32_ ## name (FSTH0, &env->fp_status);*/ \
do_raise_exception(EXCP_RI); \
update_fcr31(); \
}
FLOAT_UNOP(rsqrt1)
FLOAT_UNOP(recip1)
#undef FLOAT_UNOP
/* binary operations */ /* binary operations */
#define FLOAT_BINOP(name) \ #define FLOAT_BINOP(name) \
FLOAT_OP(name, d) \ FLOAT_OP(name, d) \
@ -943,6 +996,37 @@ FLOAT_BINOP(mul)
FLOAT_BINOP(div) FLOAT_BINOP(div)
#undef FLOAT_BINOP #undef FLOAT_BINOP
/* binary operations, MIPS specific */
#define FLOAT_BINOP(name) \
FLOAT_OP(name, d) \
{ \
set_float_exception_flags(0, &env->fp_status); \
/* XXX: not implemented */ \
/* FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status);*/ \
do_raise_exception(EXCP_RI); \
update_fcr31(); \
} \
FLOAT_OP(name, s) \
{ \
set_float_exception_flags(0, &env->fp_status); \
/* XXX: not implemented */ \
/* FST2 = float32_ ## name (FST0, FST1, &env->fp_status);*/ \
do_raise_exception(EXCP_RI); \
update_fcr31(); \
} \
FLOAT_OP(name, ps) \
{ \
set_float_exception_flags(0, &env->fp_status); \
/* XXX: not implemented */ \
/* FST2 = float32_ ## name (FST0, FST1, &env->fp_status);*/ \
/* FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fp_status);*/ \
do_raise_exception(EXCP_RI); \
update_fcr31(); \
}
FLOAT_BINOP(rsqrt2)
FLOAT_BINOP(recip2)
#undef FLOAT_BINOP
FLOAT_OP(addr, ps) FLOAT_OP(addr, ps)
{ {
set_float_exception_flags(0, &env->fp_status); set_float_exception_flags(0, &env->fp_status);
@ -951,6 +1035,14 @@ FLOAT_OP(addr, ps)
update_fcr31(); update_fcr31();
} }
FLOAT_OP(mulr, ps)
{
set_float_exception_flags(0, &env->fp_status);
FST2 = float32_mul (FST0, FSTH0, &env->fp_status);
FSTH2 = float32_mul (FST1, FSTH1, &env->fp_status);
update_fcr31();
}
#define FOP_COND_D(op, cond) \ #define FOP_COND_D(op, cond) \
void do_cmp_d_ ## op (long cc) \ void do_cmp_d_ ## op (long cc) \
{ \ { \

View File

@ -4378,14 +4378,12 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
opn = "dmtc1"; opn = "dmtc1";
break; break;
case OPC_MFHC1: case OPC_MFHC1:
gen_op_cp1_registers(fs);
GEN_LOAD_FREG_FTN(WTH0, fs); GEN_LOAD_FREG_FTN(WTH0, fs);
gen_op_mfhc1(); gen_op_mfhc1();
GEN_STORE_TN_REG(rt, T0); GEN_STORE_TN_REG(rt, T0);
opn = "mfhc1"; opn = "mfhc1";
break; break;
case OPC_MTHC1: case OPC_MTHC1:
gen_op_cp1_registers(fs);
GEN_LOAD_REG_TN(T0, rt); GEN_LOAD_REG_TN(T0, rt);
gen_op_mthc1(); gen_op_mthc1();
GEN_STORE_FTN_FREG(fs, WTH0); GEN_STORE_FTN_FREG(fs, WTH0);
@ -4405,9 +4403,9 @@ static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
GEN_LOAD_REG_TN(T0, rd); GEN_LOAD_REG_TN(T0, rd);
GEN_LOAD_REG_TN(T1, rs); GEN_LOAD_REG_TN(T1, rs);
if (cc) if (cc) {
ccbit = 1 << (24 + cc); ccbit = 1 << (24 + cc);
else } else
ccbit = 1 << 23; ccbit = 1 << 23;
if (!tf) if (!tf)
gen_op_movf(ccbit); gen_op_movf(ccbit);
@ -4421,9 +4419,9 @@ static void glue(gen_movcf_, fmt) (DisasContext *ctx, int cc, int tf) \
{ \ { \
uint32_t ccbit; \ uint32_t ccbit; \
\ \
if (cc) \ if (cc) { \
ccbit = 1 << (24 + cc); \ ccbit = 1 << (24 + cc); \
else \ } else \
ccbit = 1 << 23; \ ccbit = 1 << 23; \
if (!tf) \ if (!tf) \
glue(gen_op_float_movf_, fmt)(ccbit); \ glue(gen_op_float_movf_, fmt)(ccbit); \
@ -4536,28 +4534,28 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
opn = "neg.s"; opn = "neg.s";
break; break;
case FOP(8, 16): case FOP(8, 16):
gen_op_cp1_registers(fs); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs); GEN_LOAD_FREG_FTN(WT0, fs);
gen_op_float_roundl_s(); gen_op_float_roundl_s();
GEN_STORE_FTN_FREG(fd, DT2); GEN_STORE_FTN_FREG(fd, DT2);
opn = "round.l.s"; opn = "round.l.s";
break; break;
case FOP(9, 16): case FOP(9, 16):
gen_op_cp1_registers(fs); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs); GEN_LOAD_FREG_FTN(WT0, fs);
gen_op_float_truncl_s(); gen_op_float_truncl_s();
GEN_STORE_FTN_FREG(fd, DT2); GEN_STORE_FTN_FREG(fd, DT2);
opn = "trunc.l.s"; opn = "trunc.l.s";
break; break;
case FOP(10, 16): case FOP(10, 16):
gen_op_cp1_registers(fs); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs); GEN_LOAD_FREG_FTN(WT0, fs);
gen_op_float_ceill_s(); gen_op_float_ceill_s();
GEN_STORE_FTN_FREG(fd, DT2); GEN_STORE_FTN_FREG(fd, DT2);
opn = "ceil.l.s"; opn = "ceil.l.s";
break; break;
case FOP(11, 16): case FOP(11, 16):
gen_op_cp1_registers(fs); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs); GEN_LOAD_FREG_FTN(WT0, fs);
gen_op_float_floorl_s(); gen_op_float_floorl_s();
GEN_STORE_FTN_FREG(fd, DT2); GEN_STORE_FTN_FREG(fd, DT2);
@ -4611,6 +4609,48 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
GEN_STORE_FTN_FREG(fd, WT2); GEN_STORE_FTN_FREG(fd, WT2);
opn = "movn.s"; opn = "movn.s";
break; break;
case FOP(21, 16):
GEN_LOAD_FREG_FTN(WT0, fs);
gen_op_float_recip_s();
GEN_STORE_FTN_FREG(fd, WT2);
opn = "recip.s";
break;
case FOP(22, 16):
GEN_LOAD_FREG_FTN(WT0, fs);
gen_op_float_rsqrt_s();
GEN_STORE_FTN_FREG(fd, WT2);
opn = "rsqrt.s";
break;
case FOP(28, 16):
gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WT2, fd);
gen_op_float_recip2_s();
GEN_STORE_FTN_FREG(fd, WT2);
opn = "recip2.s";
break;
case FOP(29, 16):
gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs);
gen_op_float_recip1_s();
GEN_STORE_FTN_FREG(fd, WT2);
opn = "recip1.s";
break;
case FOP(30, 16):
gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs);
gen_op_float_rsqrt1_s();
GEN_STORE_FTN_FREG(fd, WT2);
opn = "rsqrt1.s";
break;
case FOP(31, 16):
gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WT2, fd);
gen_op_float_rsqrt2_s();
GEN_STORE_FTN_FREG(fd, WT2);
opn = "rsqrt2.s";
break;
case FOP(33, 16): case FOP(33, 16):
gen_op_cp1_registers(fd); gen_op_cp1_registers(fd);
GEN_LOAD_FREG_FTN(WT0, fs); GEN_LOAD_FREG_FTN(WT0, fs);
@ -4625,14 +4665,14 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
opn = "cvt.w.s"; opn = "cvt.w.s";
break; break;
case FOP(37, 16): case FOP(37, 16):
gen_op_cp1_registers(fs | fd); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs); GEN_LOAD_FREG_FTN(WT0, fs);
gen_op_float_cvtl_s(); gen_op_float_cvtl_s();
GEN_STORE_FTN_FREG(fd, DT2); GEN_STORE_FTN_FREG(fd, DT2);
opn = "cvt.l.s"; opn = "cvt.l.s";
break; break;
case FOP(38, 16): case FOP(38, 16):
gen_op_cp1_registers(fs | ft | fd); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT1, fs); GEN_LOAD_FREG_FTN(WT1, fs);
GEN_LOAD_FREG_FTN(WT0, ft); GEN_LOAD_FREG_FTN(WT0, ft);
gen_op_float_cvtps_s(); gen_op_float_cvtps_s();
@ -4658,6 +4698,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
GEN_LOAD_FREG_FTN(WT0, fs); GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WT1, ft); GEN_LOAD_FREG_FTN(WT1, ft);
if (ctx->opcode & (1 << 6)) { if (ctx->opcode & (1 << 6)) {
gen_op_cp1_64bitmode();
gen_cmpabs_s(func-48, cc); gen_cmpabs_s(func-48, cc);
opn = condnames_abs[func-48]; opn = condnames_abs[func-48];
} else { } else {
@ -4730,28 +4771,28 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
opn = "neg.d"; opn = "neg.d";
break; break;
case FOP(8, 17): case FOP(8, 17):
gen_op_cp1_registers(fs); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(DT0, fs); GEN_LOAD_FREG_FTN(DT0, fs);
gen_op_float_roundl_d(); gen_op_float_roundl_d();
GEN_STORE_FTN_FREG(fd, DT2); GEN_STORE_FTN_FREG(fd, DT2);
opn = "round.l.d"; opn = "round.l.d";
break; break;
case FOP(9, 17): case FOP(9, 17):
gen_op_cp1_registers(fs); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(DT0, fs); GEN_LOAD_FREG_FTN(DT0, fs);
gen_op_float_truncl_d(); gen_op_float_truncl_d();
GEN_STORE_FTN_FREG(fd, DT2); GEN_STORE_FTN_FREG(fd, DT2);
opn = "trunc.l.d"; opn = "trunc.l.d";
break; break;
case FOP(10, 17): case FOP(10, 17):
gen_op_cp1_registers(fs); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(DT0, fs); GEN_LOAD_FREG_FTN(DT0, fs);
gen_op_float_ceill_d(); gen_op_float_ceill_d();
GEN_STORE_FTN_FREG(fd, DT2); GEN_STORE_FTN_FREG(fd, DT2);
opn = "ceil.l.d"; opn = "ceil.l.d";
break; break;
case FOP(11, 17): case FOP(11, 17):
gen_op_cp1_registers(fs); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(DT0, fs); GEN_LOAD_FREG_FTN(DT0, fs);
gen_op_float_floorl_d(); gen_op_float_floorl_d();
GEN_STORE_FTN_FREG(fd, DT2); GEN_STORE_FTN_FREG(fd, DT2);
@ -4809,6 +4850,50 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
GEN_STORE_FTN_FREG(fd, DT2); GEN_STORE_FTN_FREG(fd, DT2);
opn = "movn.d"; opn = "movn.d";
break; break;
case FOP(21, 17):
gen_op_cp1_registers(fs | fd);
GEN_LOAD_FREG_FTN(DT0, fs);
gen_op_float_recip_d();
GEN_STORE_FTN_FREG(fd, DT2);
opn = "recip.d";
break;
case FOP(22, 17):
gen_op_cp1_registers(fs | fd);
GEN_LOAD_FREG_FTN(DT0, fs);
gen_op_float_rsqrt_d();
GEN_STORE_FTN_FREG(fd, DT2);
opn = "rsqrt.d";
break;
case FOP(28, 17):
gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(DT0, fs);
GEN_LOAD_FREG_FTN(DT2, ft);
gen_op_float_recip2_d();
GEN_STORE_FTN_FREG(fd, DT2);
opn = "recip2.d";
break;
case FOP(29, 17):
gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(DT0, fs);
gen_op_float_recip1_d();
GEN_STORE_FTN_FREG(fd, DT2);
opn = "recip1.d";
break;
case FOP(30, 17):
gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(DT0, fs);
gen_op_float_rsqrt1_d();
GEN_STORE_FTN_FREG(fd, DT2);
opn = "rsqrt1.d";
break;
case FOP(31, 17):
gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(DT0, fs);
GEN_LOAD_FREG_FTN(DT2, ft);
gen_op_float_rsqrt2_d();
GEN_STORE_FTN_FREG(fd, DT2);
opn = "rsqrt2.d";
break;
case FOP(48, 17): case FOP(48, 17):
case FOP(49, 17): case FOP(49, 17):
case FOP(50, 17): case FOP(50, 17):
@ -4825,13 +4910,14 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
case FOP(61, 17): case FOP(61, 17):
case FOP(62, 17): case FOP(62, 17):
case FOP(63, 17): case FOP(63, 17):
gen_op_cp1_registers(fs | ft);
GEN_LOAD_FREG_FTN(DT0, fs); GEN_LOAD_FREG_FTN(DT0, fs);
GEN_LOAD_FREG_FTN(DT1, ft); GEN_LOAD_FREG_FTN(DT1, ft);
if (ctx->opcode & (1 << 6)) { if (ctx->opcode & (1 << 6)) {
gen_op_cp1_64bitmode();
gen_cmpabs_d(func-48, cc); gen_cmpabs_d(func-48, cc);
opn = condnames_abs[func-48]; opn = condnames_abs[func-48];
} else { } else {
gen_op_cp1_registers(fs | ft);
gen_cmp_d(func-48, cc); gen_cmp_d(func-48, cc);
opn = condnames[func-48]; opn = condnames[func-48];
} }
@ -4851,7 +4937,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
opn = "cvt.w.d"; opn = "cvt.w.d";
break; break;
case FOP(37, 17): case FOP(37, 17):
gen_op_cp1_registers(fs | fd); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(DT0, fs); GEN_LOAD_FREG_FTN(DT0, fs);
gen_op_float_cvtl_d(); gen_op_float_cvtl_d();
GEN_STORE_FTN_FREG(fd, DT2); GEN_STORE_FTN_FREG(fd, DT2);
@ -4871,14 +4957,14 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
opn = "cvt.d.w"; opn = "cvt.d.w";
break; break;
case FOP(32, 21): case FOP(32, 21):
gen_op_cp1_registers(fs); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(DT0, fs); GEN_LOAD_FREG_FTN(DT0, fs);
gen_op_float_cvts_l(); gen_op_float_cvts_l();
GEN_STORE_FTN_FREG(fd, WT2); GEN_STORE_FTN_FREG(fd, WT2);
opn = "cvt.s.l"; opn = "cvt.s.l";
break; break;
case FOP(33, 21): case FOP(33, 21):
gen_op_cp1_registers(fs | fd); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(DT0, fs); GEN_LOAD_FREG_FTN(DT0, fs);
gen_op_float_cvtd_l(); gen_op_float_cvtd_l();
GEN_STORE_FTN_FREG(fd, DT2); GEN_STORE_FTN_FREG(fd, DT2);
@ -4886,7 +4972,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
break; break;
case FOP(38, 20): case FOP(38, 20):
case FOP(38, 21): case FOP(38, 21):
gen_op_cp1_registers(fs | fd); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs); GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH0, fs); GEN_LOAD_FREG_FTN(WTH0, fs);
gen_op_float_cvtps_pw(); gen_op_float_cvtps_pw();
@ -4895,7 +4981,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
opn = "cvt.ps.pw"; opn = "cvt.ps.pw";
break; break;
case FOP(0, 22): case FOP(0, 22):
gen_op_cp1_registers(fs | ft | fd); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs); GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH0, fs); GEN_LOAD_FREG_FTN(WTH0, fs);
GEN_LOAD_FREG_FTN(WT1, ft); GEN_LOAD_FREG_FTN(WT1, ft);
@ -4906,7 +4992,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
opn = "add.ps"; opn = "add.ps";
break; break;
case FOP(1, 22): case FOP(1, 22):
gen_op_cp1_registers(fs | ft | fd); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs); GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH0, fs); GEN_LOAD_FREG_FTN(WTH0, fs);
GEN_LOAD_FREG_FTN(WT1, ft); GEN_LOAD_FREG_FTN(WT1, ft);
@ -4917,7 +5003,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
opn = "sub.ps"; opn = "sub.ps";
break; break;
case FOP(2, 22): case FOP(2, 22):
gen_op_cp1_registers(fs | ft | fd); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs); GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH0, fs); GEN_LOAD_FREG_FTN(WTH0, fs);
GEN_LOAD_FREG_FTN(WT1, ft); GEN_LOAD_FREG_FTN(WT1, ft);
@ -4928,7 +5014,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
opn = "mul.ps"; opn = "mul.ps";
break; break;
case FOP(5, 22): case FOP(5, 22):
gen_op_cp1_registers(fs | fd); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs); GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH0, fs); GEN_LOAD_FREG_FTN(WTH0, fs);
gen_op_float_abs_ps(); gen_op_float_abs_ps();
@ -4937,7 +5023,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
opn = "abs.ps"; opn = "abs.ps";
break; break;
case FOP(6, 22): case FOP(6, 22):
gen_op_cp1_registers(fs | fd); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs); GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH0, fs); GEN_LOAD_FREG_FTN(WTH0, fs);
gen_op_float_mov_ps(); gen_op_float_mov_ps();
@ -4946,7 +5032,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
opn = "mov.ps"; opn = "mov.ps";
break; break;
case FOP(7, 22): case FOP(7, 22):
gen_op_cp1_registers(fs | fd); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs); GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH0, fs); GEN_LOAD_FREG_FTN(WTH0, fs);
gen_op_float_chs_ps(); gen_op_float_chs_ps();
@ -4955,6 +5041,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
opn = "neg.ps"; opn = "neg.ps";
break; break;
case FOP(17, 22): case FOP(17, 22):
gen_op_cp1_64bitmode();
GEN_LOAD_REG_TN(T0, ft); GEN_LOAD_REG_TN(T0, ft);
GEN_LOAD_FREG_FTN(WT0, fs); GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH0, fs); GEN_LOAD_FREG_FTN(WTH0, fs);
@ -4966,6 +5053,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
opn = "movcf.ps"; opn = "movcf.ps";
break; break;
case FOP(18, 22): case FOP(18, 22):
gen_op_cp1_64bitmode();
GEN_LOAD_REG_TN(T0, ft); GEN_LOAD_REG_TN(T0, ft);
GEN_LOAD_FREG_FTN(WT0, fs); GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH0, fs); GEN_LOAD_FREG_FTN(WTH0, fs);
@ -4977,6 +5065,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
opn = "movz.ps"; opn = "movz.ps";
break; break;
case FOP(19, 22): case FOP(19, 22):
gen_op_cp1_64bitmode();
GEN_LOAD_REG_TN(T0, ft); GEN_LOAD_REG_TN(T0, ft);
GEN_LOAD_FREG_FTN(WT0, fs); GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH0, fs); GEN_LOAD_FREG_FTN(WTH0, fs);
@ -4988,7 +5077,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
opn = "movn.ps"; opn = "movn.ps";
break; break;
case FOP(24, 22): case FOP(24, 22):
gen_op_cp1_registers(fs | fd | ft); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs); GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH0, fs); GEN_LOAD_FREG_FTN(WTH0, fs);
GEN_LOAD_FREG_FTN(WT1, ft); GEN_LOAD_FREG_FTN(WT1, ft);
@ -4998,15 +5087,66 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
GEN_STORE_FTN_FREG(fd, WTH2); GEN_STORE_FTN_FREG(fd, WTH2);
opn = "addr.ps"; opn = "addr.ps";
break; break;
case FOP(26, 22):
gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH0, fs);
GEN_LOAD_FREG_FTN(WT1, ft);
GEN_LOAD_FREG_FTN(WTH1, ft);
gen_op_float_mulr_ps();
GEN_STORE_FTN_FREG(fd, WT2);
GEN_STORE_FTN_FREG(fd, WTH2);
opn = "mulr.ps";
break;
case FOP(28, 22):
gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH0, fs);
GEN_LOAD_FREG_FTN(WT2, fd);
GEN_LOAD_FREG_FTN(WTH2, fd);
gen_op_float_recip2_ps();
GEN_STORE_FTN_FREG(fd, WT2);
GEN_STORE_FTN_FREG(fd, WTH2);
opn = "recip2.ps";
break;
case FOP(29, 22):
gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH0, fs);
gen_op_float_recip1_ps();
GEN_STORE_FTN_FREG(fd, WT2);
GEN_STORE_FTN_FREG(fd, WTH2);
opn = "recip1.ps";
break;
case FOP(30, 22):
gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH0, fs);
gen_op_float_rsqrt1_ps();
GEN_STORE_FTN_FREG(fd, WT2);
GEN_STORE_FTN_FREG(fd, WTH2);
opn = "rsqrt1.ps";
break;
case FOP(31, 22):
gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH0, fs);
GEN_LOAD_FREG_FTN(WT2, fd);
GEN_LOAD_FREG_FTN(WTH2, fd);
gen_op_float_rsqrt2_ps();
GEN_STORE_FTN_FREG(fd, WT2);
GEN_STORE_FTN_FREG(fd, WTH2);
opn = "rsqrt2.ps";
break;
case FOP(32, 22): case FOP(32, 22):
gen_op_cp1_registers(fs); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WTH0, fs); GEN_LOAD_FREG_FTN(WTH0, fs);
gen_op_float_cvts_pu(); gen_op_float_cvts_pu();
GEN_STORE_FTN_FREG(fd, WT2); GEN_STORE_FTN_FREG(fd, WT2);
opn = "cvt.s.pu"; opn = "cvt.s.pu";
break; break;
case FOP(36, 22): case FOP(36, 22):
gen_op_cp1_registers(fs | fd); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs); GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH0, fs); GEN_LOAD_FREG_FTN(WTH0, fs);
gen_op_float_cvtpw_ps(); gen_op_float_cvtpw_ps();
@ -5015,14 +5155,14 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
opn = "cvt.pw.ps"; opn = "cvt.pw.ps";
break; break;
case FOP(40, 22): case FOP(40, 22):
gen_op_cp1_registers(fs); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs); GEN_LOAD_FREG_FTN(WT0, fs);
gen_op_float_cvts_pl(); gen_op_float_cvts_pl();
GEN_STORE_FTN_FREG(fd, WT2); GEN_STORE_FTN_FREG(fd, WT2);
opn = "cvt.s.pl"; opn = "cvt.s.pl";
break; break;
case FOP(44, 22): case FOP(44, 22):
gen_op_cp1_registers(fs | ft | fd); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs); GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WT1, ft); GEN_LOAD_FREG_FTN(WT1, ft);
gen_op_float_pll_ps(); gen_op_float_pll_ps();
@ -5030,7 +5170,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
opn = "pll.ps"; opn = "pll.ps";
break; break;
case FOP(45, 22): case FOP(45, 22):
gen_op_cp1_registers(fs | ft | fd); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs); GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH1, ft); GEN_LOAD_FREG_FTN(WTH1, ft);
gen_op_float_plu_ps(); gen_op_float_plu_ps();
@ -5038,7 +5178,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
opn = "plu.ps"; opn = "plu.ps";
break; break;
case FOP(46, 22): case FOP(46, 22):
gen_op_cp1_registers(fs | ft | fd); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WTH0, fs); GEN_LOAD_FREG_FTN(WTH0, fs);
GEN_LOAD_FREG_FTN(WT1, ft); GEN_LOAD_FREG_FTN(WT1, ft);
gen_op_float_pul_ps(); gen_op_float_pul_ps();
@ -5046,7 +5186,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
opn = "pul.ps"; opn = "pul.ps";
break; break;
case FOP(47, 22): case FOP(47, 22):
gen_op_cp1_registers(fs | ft | fd); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WTH0, fs); GEN_LOAD_FREG_FTN(WTH0, fs);
GEN_LOAD_FREG_FTN(WTH1, ft); GEN_LOAD_FREG_FTN(WTH1, ft);
gen_op_float_puu_ps(); gen_op_float_puu_ps();
@ -5069,7 +5209,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
case FOP(61, 22): case FOP(61, 22):
case FOP(62, 22): case FOP(62, 22):
case FOP(63, 22): case FOP(63, 22):
gen_op_cp1_registers(fs | ft); gen_op_cp1_64bitmode();
GEN_LOAD_FREG_FTN(WT0, fs); GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH0, fs); GEN_LOAD_FREG_FTN(WTH0, fs);
GEN_LOAD_FREG_FTN(WT1, ft); GEN_LOAD_FREG_FTN(WT1, ft);
@ -5106,6 +5246,8 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc, int fd,
{ {
const char *opn = "extended float load/store"; const char *opn = "extended float load/store";
/* All of those work only on 64bit FPUs. */
gen_op_cp1_64bitmode();
GEN_LOAD_REG_TN(T0, base); GEN_LOAD_REG_TN(T0, base);
GEN_LOAD_REG_TN(T1, index); GEN_LOAD_REG_TN(T1, index);
/* Don't do NOP if destination is zero: we must perform the actual /* 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,
const char *opn = "flt3_arith"; const char *opn = "flt3_arith";
/* All of those work only on 64bit FPUs. */ /* All of those work only on 64bit FPUs. */
gen_op_cp1_registers(fd | fr | fs | ft); gen_op_cp1_64bitmode();
switch (opc) { switch (opc) {
case OPC_ALNV_PS: case OPC_ALNV_PS:
GEN_LOAD_REG_TN(T0, fr); GEN_LOAD_REG_TN(T0, fr);