Implement FP madd/msub, wire up bc1any[24][ft].
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2802 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
923617a396
commit
fbcc68286a
|
@ -2185,6 +2185,7 @@ FLOAT_OP(name, d) \
|
||||||
FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status); \
|
FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status); \
|
||||||
update_fcr31(); \
|
update_fcr31(); \
|
||||||
DEBUG_FPU_STATE(); \
|
DEBUG_FPU_STATE(); \
|
||||||
|
RETURN(); \
|
||||||
} \
|
} \
|
||||||
FLOAT_OP(name, s) \
|
FLOAT_OP(name, s) \
|
||||||
{ \
|
{ \
|
||||||
|
@ -2192,6 +2193,7 @@ FLOAT_OP(name, s) \
|
||||||
FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \
|
FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \
|
||||||
update_fcr31(); \
|
update_fcr31(); \
|
||||||
DEBUG_FPU_STATE(); \
|
DEBUG_FPU_STATE(); \
|
||||||
|
RETURN(); \
|
||||||
} \
|
} \
|
||||||
FLOAT_OP(name, ps) \
|
FLOAT_OP(name, ps) \
|
||||||
{ \
|
{ \
|
||||||
|
@ -2200,6 +2202,7 @@ FLOAT_OP(name, ps) \
|
||||||
FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fp_status); \
|
FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fp_status); \
|
||||||
update_fcr31(); \
|
update_fcr31(); \
|
||||||
DEBUG_FPU_STATE(); \
|
DEBUG_FPU_STATE(); \
|
||||||
|
RETURN(); \
|
||||||
}
|
}
|
||||||
FLOAT_BINOP(add)
|
FLOAT_BINOP(add)
|
||||||
FLOAT_BINOP(sub)
|
FLOAT_BINOP(sub)
|
||||||
|
@ -2207,6 +2210,16 @@ FLOAT_BINOP(mul)
|
||||||
FLOAT_BINOP(div)
|
FLOAT_BINOP(div)
|
||||||
#undef FLOAT_BINOP
|
#undef FLOAT_BINOP
|
||||||
|
|
||||||
|
FLOAT_OP(addr, ps)
|
||||||
|
{
|
||||||
|
set_float_exception_flags(0, &env->fp_status);
|
||||||
|
FST2 = float32_add (FST0, FSTH0, &env->fp_status);
|
||||||
|
FSTH2 = float32_add (FST1, FSTH1, &env->fp_status);
|
||||||
|
update_fcr31();
|
||||||
|
DEBUG_FPU_STATE();
|
||||||
|
RETURN();
|
||||||
|
}
|
||||||
|
|
||||||
/* ternary operations */
|
/* ternary operations */
|
||||||
#define FLOAT_TERNOP(name1, name2) \
|
#define FLOAT_TERNOP(name1, name2) \
|
||||||
FLOAT_OP(name1 ## name2, d) \
|
FLOAT_OP(name1 ## name2, d) \
|
||||||
|
@ -2214,12 +2227,14 @@ FLOAT_OP(name1 ## name2, d) \
|
||||||
FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fp_status); \
|
FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fp_status); \
|
||||||
FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fp_status); \
|
FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fp_status); \
|
||||||
DEBUG_FPU_STATE(); \
|
DEBUG_FPU_STATE(); \
|
||||||
|
RETURN(); \
|
||||||
} \
|
} \
|
||||||
FLOAT_OP(name1 ## name2, s) \
|
FLOAT_OP(name1 ## name2, s) \
|
||||||
{ \
|
{ \
|
||||||
FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
|
FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
|
||||||
FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
|
FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
|
||||||
DEBUG_FPU_STATE(); \
|
DEBUG_FPU_STATE(); \
|
||||||
|
RETURN(); \
|
||||||
} \
|
} \
|
||||||
FLOAT_OP(name1 ## name2, ps) \
|
FLOAT_OP(name1 ## name2, ps) \
|
||||||
{ \
|
{ \
|
||||||
|
@ -2228,28 +2243,65 @@ FLOAT_OP(name1 ## name2, ps) \
|
||||||
FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
|
FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
|
||||||
FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fp_status); \
|
FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fp_status); \
|
||||||
DEBUG_FPU_STATE(); \
|
DEBUG_FPU_STATE(); \
|
||||||
|
RETURN(); \
|
||||||
}
|
}
|
||||||
FLOAT_TERNOP(mul, add)
|
FLOAT_TERNOP(mul, add)
|
||||||
FLOAT_TERNOP(mul, sub)
|
FLOAT_TERNOP(mul, sub)
|
||||||
#undef FLOAT_TERNOP
|
#undef FLOAT_TERNOP
|
||||||
|
|
||||||
|
/* negated ternary operations */
|
||||||
|
#define FLOAT_NTERNOP(name1, name2) \
|
||||||
|
FLOAT_OP(n ## name1 ## name2, d) \
|
||||||
|
{ \
|
||||||
|
FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fp_status); \
|
||||||
|
FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fp_status); \
|
||||||
|
FDT2 ^= 1ULL << 63; \
|
||||||
|
DEBUG_FPU_STATE(); \
|
||||||
|
RETURN(); \
|
||||||
|
} \
|
||||||
|
FLOAT_OP(n ## name1 ## name2, s) \
|
||||||
|
{ \
|
||||||
|
FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
|
||||||
|
FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
|
||||||
|
FST2 ^= 1 << 31; \
|
||||||
|
DEBUG_FPU_STATE(); \
|
||||||
|
RETURN(); \
|
||||||
|
} \
|
||||||
|
FLOAT_OP(n ## name1 ## name2, ps) \
|
||||||
|
{ \
|
||||||
|
FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
|
||||||
|
FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fp_status); \
|
||||||
|
FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
|
||||||
|
FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fp_status); \
|
||||||
|
FST2 ^= 1 << 31; \
|
||||||
|
FSTH2 ^= 1 << 31; \
|
||||||
|
DEBUG_FPU_STATE(); \
|
||||||
|
RETURN(); \
|
||||||
|
}
|
||||||
|
FLOAT_NTERNOP(mul, add)
|
||||||
|
FLOAT_NTERNOP(mul, sub)
|
||||||
|
#undef FLOAT_NTERNOP
|
||||||
|
|
||||||
/* unary operations, modifying fp status */
|
/* unary operations, modifying fp status */
|
||||||
#define FLOAT_UNOP(name) \
|
#define FLOAT_UNOP(name) \
|
||||||
FLOAT_OP(name, d) \
|
FLOAT_OP(name, d) \
|
||||||
{ \
|
{ \
|
||||||
FDT2 = float64_ ## name(FDT0, &env->fp_status); \
|
FDT2 = float64_ ## name(FDT0, &env->fp_status); \
|
||||||
DEBUG_FPU_STATE(); \
|
DEBUG_FPU_STATE(); \
|
||||||
|
RETURN(); \
|
||||||
} \
|
} \
|
||||||
FLOAT_OP(name, s) \
|
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(); \
|
||||||
} \
|
} \
|
||||||
FLOAT_OP(name, ps) \
|
FLOAT_OP(name, ps) \
|
||||||
{ \
|
{ \
|
||||||
FST2 = float32_ ## name(FST0, &env->fp_status); \
|
FST2 = float32_ ## name(FST0, &env->fp_status); \
|
||||||
FSTH2 = float32_ ## name(FSTH0, &env->fp_status); \
|
FSTH2 = float32_ ## name(FSTH0, &env->fp_status); \
|
||||||
DEBUG_FPU_STATE(); \
|
DEBUG_FPU_STATE(); \
|
||||||
|
RETURN(); \
|
||||||
}
|
}
|
||||||
FLOAT_UNOP(sqrt)
|
FLOAT_UNOP(sqrt)
|
||||||
#undef FLOAT_UNOP
|
#undef FLOAT_UNOP
|
||||||
|
@ -2260,17 +2312,20 @@ FLOAT_OP(name, d) \
|
||||||
{ \
|
{ \
|
||||||
FDT2 = float64_ ## name(FDT0); \
|
FDT2 = float64_ ## name(FDT0); \
|
||||||
DEBUG_FPU_STATE(); \
|
DEBUG_FPU_STATE(); \
|
||||||
|
RETURN(); \
|
||||||
} \
|
} \
|
||||||
FLOAT_OP(name, s) \
|
FLOAT_OP(name, s) \
|
||||||
{ \
|
{ \
|
||||||
FST2 = float32_ ## name(FST0); \
|
FST2 = float32_ ## name(FST0); \
|
||||||
DEBUG_FPU_STATE(); \
|
DEBUG_FPU_STATE(); \
|
||||||
|
RETURN(); \
|
||||||
} \
|
} \
|
||||||
FLOAT_OP(name, ps) \
|
FLOAT_OP(name, ps) \
|
||||||
{ \
|
{ \
|
||||||
FST2 = float32_ ## name(FST0); \
|
FST2 = float32_ ## name(FST0); \
|
||||||
FSTH2 = float32_ ## name(FSTH0); \
|
FSTH2 = float32_ ## name(FSTH0); \
|
||||||
DEBUG_FPU_STATE(); \
|
DEBUG_FPU_STATE(); \
|
||||||
|
RETURN(); \
|
||||||
}
|
}
|
||||||
FLOAT_UNOP(abs)
|
FLOAT_UNOP(abs)
|
||||||
FLOAT_UNOP(chs)
|
FLOAT_UNOP(chs)
|
||||||
|
|
|
@ -402,7 +402,7 @@ enum {
|
||||||
OPC_MSUB_D = 0x29 | OPC_CP3,
|
OPC_MSUB_D = 0x29 | OPC_CP3,
|
||||||
OPC_MSUB_PS = 0x2E | OPC_CP3,
|
OPC_MSUB_PS = 0x2E | OPC_CP3,
|
||||||
OPC_NMADD_S = 0x30 | OPC_CP3,
|
OPC_NMADD_S = 0x30 | OPC_CP3,
|
||||||
OPC_NMADD_D = 0x32 | OPC_CP3,
|
OPC_NMADD_D = 0x31 | OPC_CP3,
|
||||||
OPC_NMADD_PS= 0x36 | OPC_CP3,
|
OPC_NMADD_PS= 0x36 | OPC_CP3,
|
||||||
OPC_NMSUB_S = 0x38 | OPC_CP3,
|
OPC_NMSUB_S = 0x38 | OPC_CP3,
|
||||||
OPC_NMSUB_D = 0x39 | OPC_CP3,
|
OPC_NMSUB_D = 0x39 | OPC_CP3,
|
||||||
|
@ -4955,6 +4955,17 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
|
||||||
GEN_STORE_FTN_FREG(fd, WTH2);
|
GEN_STORE_FTN_FREG(fd, WTH2);
|
||||||
opn = "movn.ps";
|
opn = "movn.ps";
|
||||||
break;
|
break;
|
||||||
|
case FOP(24, 22):
|
||||||
|
CHECK_FR(ctx, fs | fd | ft);
|
||||||
|
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_addr_ps();
|
||||||
|
GEN_STORE_FTN_FREG(fd, WT2);
|
||||||
|
GEN_STORE_FTN_FREG(fd, WTH2);
|
||||||
|
opn = "addr.ps";
|
||||||
|
break;
|
||||||
case FOP(32, 22):
|
case FOP(32, 22):
|
||||||
CHECK_FR(ctx, fs);
|
CHECK_FR(ctx, fs);
|
||||||
GEN_LOAD_FREG_FTN(WTH0, fs);
|
GEN_LOAD_FREG_FTN(WTH0, fs);
|
||||||
|
@ -5120,47 +5131,107 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, int fd,
|
||||||
opn = "madd.s";
|
opn = "madd.s";
|
||||||
break;
|
break;
|
||||||
case OPC_MADD_D:
|
case OPC_MADD_D:
|
||||||
generate_exception (ctx, EXCP_RI);
|
GEN_LOAD_FREG_FTN(DT0, fs);
|
||||||
|
GEN_LOAD_FREG_FTN(DT1, ft);
|
||||||
|
GEN_LOAD_FREG_FTN(DT2, fr);
|
||||||
|
gen_op_float_muladd_d();
|
||||||
|
GEN_STORE_FTN_FREG(fd, DT2);
|
||||||
opn = "madd.d";
|
opn = "madd.d";
|
||||||
break;
|
break;
|
||||||
case OPC_MADD_PS:
|
case OPC_MADD_PS:
|
||||||
generate_exception (ctx, EXCP_RI);
|
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_LOAD_FREG_FTN(WT2, fr);
|
||||||
|
GEN_LOAD_FREG_FTN(WTH2, fr);
|
||||||
|
gen_op_float_muladd_ps();
|
||||||
|
GEN_STORE_FTN_FREG(fd, WT2);
|
||||||
|
GEN_STORE_FTN_FREG(fd, WTH2);
|
||||||
opn = "madd.ps";
|
opn = "madd.ps";
|
||||||
break;
|
break;
|
||||||
case OPC_MSUB_S:
|
case OPC_MSUB_S:
|
||||||
generate_exception (ctx, EXCP_RI);
|
GEN_LOAD_FREG_FTN(WT0, fs);
|
||||||
|
GEN_LOAD_FREG_FTN(WT1, ft);
|
||||||
|
GEN_LOAD_FREG_FTN(WT2, fr);
|
||||||
|
gen_op_float_mulsub_s();
|
||||||
|
GEN_STORE_FTN_FREG(fd, WT2);
|
||||||
opn = "msub.s";
|
opn = "msub.s";
|
||||||
break;
|
break;
|
||||||
case OPC_MSUB_D:
|
case OPC_MSUB_D:
|
||||||
generate_exception (ctx, EXCP_RI);
|
GEN_LOAD_FREG_FTN(DT0, fs);
|
||||||
|
GEN_LOAD_FREG_FTN(DT1, ft);
|
||||||
|
GEN_LOAD_FREG_FTN(DT2, fr);
|
||||||
|
gen_op_float_mulsub_d();
|
||||||
|
GEN_STORE_FTN_FREG(fd, DT2);
|
||||||
opn = "msub.d";
|
opn = "msub.d";
|
||||||
break;
|
break;
|
||||||
case OPC_MSUB_PS:
|
case OPC_MSUB_PS:
|
||||||
generate_exception (ctx, EXCP_RI);
|
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_LOAD_FREG_FTN(WT2, fr);
|
||||||
|
GEN_LOAD_FREG_FTN(WTH2, fr);
|
||||||
|
gen_op_float_mulsub_ps();
|
||||||
|
GEN_STORE_FTN_FREG(fd, WT2);
|
||||||
|
GEN_STORE_FTN_FREG(fd, WTH2);
|
||||||
opn = "msub.ps";
|
opn = "msub.ps";
|
||||||
break;
|
break;
|
||||||
case OPC_NMADD_S:
|
case OPC_NMADD_S:
|
||||||
generate_exception (ctx, EXCP_RI);
|
GEN_LOAD_FREG_FTN(WT0, fs);
|
||||||
|
GEN_LOAD_FREG_FTN(WT1, ft);
|
||||||
|
GEN_LOAD_FREG_FTN(WT2, fr);
|
||||||
|
gen_op_float_nmuladd_s();
|
||||||
|
GEN_STORE_FTN_FREG(fd, WT2);
|
||||||
opn = "nmadd.s";
|
opn = "nmadd.s";
|
||||||
break;
|
break;
|
||||||
case OPC_NMADD_D:
|
case OPC_NMADD_D:
|
||||||
generate_exception (ctx, EXCP_RI);
|
GEN_LOAD_FREG_FTN(DT0, fs);
|
||||||
|
GEN_LOAD_FREG_FTN(DT1, ft);
|
||||||
|
GEN_LOAD_FREG_FTN(DT2, fr);
|
||||||
|
gen_op_float_nmuladd_d();
|
||||||
|
GEN_STORE_FTN_FREG(fd, DT2);
|
||||||
opn = "nmadd.d";
|
opn = "nmadd.d";
|
||||||
break;
|
break;
|
||||||
case OPC_NMADD_PS:
|
case OPC_NMADD_PS:
|
||||||
generate_exception (ctx, EXCP_RI);
|
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_LOAD_FREG_FTN(WT2, fr);
|
||||||
|
GEN_LOAD_FREG_FTN(WTH2, fr);
|
||||||
|
gen_op_float_nmuladd_ps();
|
||||||
|
GEN_STORE_FTN_FREG(fd, WT2);
|
||||||
|
GEN_STORE_FTN_FREG(fd, WTH2);
|
||||||
opn = "nmadd.ps";
|
opn = "nmadd.ps";
|
||||||
break;
|
break;
|
||||||
case OPC_NMSUB_S:
|
case OPC_NMSUB_S:
|
||||||
generate_exception (ctx, EXCP_RI);
|
GEN_LOAD_FREG_FTN(WT0, fs);
|
||||||
|
GEN_LOAD_FREG_FTN(WT1, ft);
|
||||||
|
GEN_LOAD_FREG_FTN(WT2, fr);
|
||||||
|
gen_op_float_nmulsub_s();
|
||||||
|
GEN_STORE_FTN_FREG(fd, WT2);
|
||||||
opn = "nmsub.s";
|
opn = "nmsub.s";
|
||||||
break;
|
break;
|
||||||
case OPC_NMSUB_D:
|
case OPC_NMSUB_D:
|
||||||
generate_exception (ctx, EXCP_RI);
|
GEN_LOAD_FREG_FTN(DT0, fs);
|
||||||
|
GEN_LOAD_FREG_FTN(DT1, ft);
|
||||||
|
GEN_LOAD_FREG_FTN(DT2, fr);
|
||||||
|
gen_op_float_nmulsub_d();
|
||||||
|
GEN_STORE_FTN_FREG(fd, DT2);
|
||||||
opn = "nmsub.d";
|
opn = "nmsub.d";
|
||||||
break;
|
break;
|
||||||
case OPC_NMSUB_PS:
|
case OPC_NMSUB_PS:
|
||||||
generate_exception (ctx, EXCP_RI);
|
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_LOAD_FREG_FTN(WT2, fr);
|
||||||
|
GEN_LOAD_FREG_FTN(WTH2, fr);
|
||||||
|
gen_op_float_nmulsub_ps();
|
||||||
|
GEN_STORE_FTN_FREG(fd, WT2);
|
||||||
|
GEN_STORE_FTN_FREG(fd, WTH2);
|
||||||
opn = "nmsub.ps";
|
opn = "nmsub.ps";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -5562,6 +5633,8 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||||
gen_cp1(ctx, op1, rt, rd);
|
gen_cp1(ctx, op1, rt, rd);
|
||||||
break;
|
break;
|
||||||
case OPC_BC1:
|
case OPC_BC1:
|
||||||
|
case OPC_BC1ANY2:
|
||||||
|
case OPC_BC1ANY4:
|
||||||
gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
|
gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
|
||||||
(rt >> 2) & 0x7, imm << 2);
|
(rt >> 2) & 0x7, imm << 2);
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in a new issue