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:
ths 2007-05-11 09:59:10 +00:00
parent 923617a396
commit fbcc68286a
2 changed files with 140 additions and 12 deletions

View file

@ -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)

View file

@ -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;