diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2005-03-13 17:01:22 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2005-03-13 17:01:22 +0000 |
commit | 4ecc31906d7535c4ad88fcc63968bef412dd67ba (patch) | |
tree | 9a38e0726804d67f9458293a32daabf9e7f1d894 /target-ppc/translate.c | |
parent | 4c2e770f377a2c38bb26c24e333b747511ddd040 (diff) |
fpu fixes (Jocelyn Mayer) - soft float support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1335 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-ppc/translate.c')
-rw-r--r-- | target-ppc/translate.c | 95 |
1 files changed, 69 insertions, 26 deletions
diff --git a/target-ppc/translate.c b/target-ppc/translate.c index bb3bbbb544..f41bbb845b 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -740,6 +740,7 @@ __GEN_LOGICAL2(sraw, 0x18, 0x18); GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER) { gen_op_load_gpr_T0(rS(ctx->opcode)); + if (SH(ctx->opcode) != 0) gen_op_srawi(SH(ctx->opcode), MASK(32 - SH(ctx->opcode), 31)); if (Rc(ctx->opcode) != 0) gen_op_set_Rc0(); @@ -749,7 +750,7 @@ GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER) __GEN_LOGICAL2(srw, 0x18, 0x10); /*** Floating-Point arithmetic ***/ -#define _GEN_FLOAT_ACB(name, op1, op2) \ +#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat) \ GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, PPC_FLOAT) \ { \ if (!ctx->fpu_enabled) { \ @@ -760,17 +761,20 @@ GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, PPC_FLOAT) \ gen_op_load_fpr_FT0(rA(ctx->opcode)); \ gen_op_load_fpr_FT1(rC(ctx->opcode)); \ gen_op_load_fpr_FT2(rB(ctx->opcode)); \ - gen_op_f##name(); \ + gen_op_f##op(); \ + if (isfloat) { \ + gen_op_frsp(); \ + } \ gen_op_store_FT0_fpr(rD(ctx->opcode)); \ if (Rc(ctx->opcode)) \ gen_op_set_Rc1(); \ } #define GEN_FLOAT_ACB(name, op2) \ -_GEN_FLOAT_ACB(name, 0x3F, op2); \ -_GEN_FLOAT_ACB(name##s, 0x3B, op2); +_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0); \ +_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1); -#define _GEN_FLOAT_AB(name, op1, op2, inval) \ +#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat) \ GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \ { \ if (!ctx->fpu_enabled) { \ @@ -780,16 +784,19 @@ GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \ gen_op_reset_scrfx(); \ gen_op_load_fpr_FT0(rA(ctx->opcode)); \ gen_op_load_fpr_FT1(rB(ctx->opcode)); \ - gen_op_f##name(); \ + gen_op_f##op(); \ + if (isfloat) { \ + gen_op_frsp(); \ + } \ gen_op_store_FT0_fpr(rD(ctx->opcode)); \ if (Rc(ctx->opcode)) \ gen_op_set_Rc1(); \ } #define GEN_FLOAT_AB(name, op2, inval) \ -_GEN_FLOAT_AB(name, 0x3F, op2, inval); \ -_GEN_FLOAT_AB(name##s, 0x3B, op2, inval); +_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0); \ +_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1); -#define _GEN_FLOAT_AC(name, op1, op2, inval) \ +#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat) \ GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \ { \ if (!ctx->fpu_enabled) { \ @@ -799,14 +806,17 @@ GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \ gen_op_reset_scrfx(); \ gen_op_load_fpr_FT0(rA(ctx->opcode)); \ gen_op_load_fpr_FT1(rC(ctx->opcode)); \ - gen_op_f##name(); \ + gen_op_f##op(); \ + if (isfloat) { \ + gen_op_frsp(); \ + } \ gen_op_store_FT0_fpr(rD(ctx->opcode)); \ if (Rc(ctx->opcode)) \ gen_op_set_Rc1(); \ } #define GEN_FLOAT_AC(name, op2, inval) \ -_GEN_FLOAT_AC(name, 0x3F, op2, inval); \ -_GEN_FLOAT_AC(name##s, 0x3B, op2, inval); +_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0); \ +_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1); #define GEN_FLOAT_B(name, op2, op3) \ GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, PPC_FLOAT) \ @@ -823,8 +833,8 @@ GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, PPC_FLOAT) \ gen_op_set_Rc1(); \ } -#define GEN_FLOAT_BS(name, op2) \ -GEN_HANDLER(f##name, 0x3F, op2, 0xFF, 0x001F07C0, PPC_FLOAT) \ +#define GEN_FLOAT_BS(name, op1, op2) \ +GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, PPC_FLOAT) \ { \ if (!ctx->fpu_enabled) { \ RET_EXCP(ctx, EXCP_NO_FP, 0); \ @@ -840,24 +850,24 @@ GEN_HANDLER(f##name, 0x3F, op2, 0xFF, 0x001F07C0, PPC_FLOAT) \ /* fadd - fadds */ GEN_FLOAT_AB(add, 0x15, 0x000007C0); -/* fdiv */ +/* fdiv - fdivs */ GEN_FLOAT_AB(div, 0x12, 0x000007C0); -/* fmul */ +/* fmul - fmuls */ GEN_FLOAT_AC(mul, 0x19, 0x0000F800); /* fres */ -GEN_FLOAT_BS(res, 0x18); +GEN_FLOAT_BS(res, 0x3B, 0x18); /* frsqrte */ -GEN_FLOAT_BS(rsqrte, 0x1A); +GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A); /* fsel */ -_GEN_FLOAT_ACB(sel, 0x3F, 0x17); -/* fsub */ +_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0); +/* fsub - fsubs */ GEN_FLOAT_AB(sub, 0x14, 0x000007C0); /* Optional: */ /* fsqrt */ -GEN_FLOAT_BS(sqrt, 0x16); +GEN_FLOAT_BS(sqrt, 0x3F, 0x16); GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT) { @@ -867,20 +877,21 @@ GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT) } gen_op_reset_scrfx(); gen_op_load_fpr_FT0(rB(ctx->opcode)); - gen_op_fsqrts(); + gen_op_fsqrt(); + gen_op_frsp(); gen_op_store_FT0_fpr(rD(ctx->opcode)); if (Rc(ctx->opcode)) gen_op_set_Rc1(); } /*** Floating-Point multiply-and-add ***/ -/* fmadd */ +/* fmadd - fmadds */ GEN_FLOAT_ACB(madd, 0x1D); -/* fmsub */ +/* fmsub - fmsubs */ GEN_FLOAT_ACB(msub, 0x1C); -/* fnmadd */ +/* fnmadd - fnmadds */ GEN_FLOAT_ACB(nmadd, 0x1F); -/* fnmsub */ +/* fnmsub - fnmsubs */ GEN_FLOAT_ACB(nmsub, 0x1E); /*** Floating-Point round & convert ***/ @@ -1426,6 +1437,10 @@ GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03FF0801, PPC_MEM) GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ { \ uint32_t simm = SIMM(ctx->opcode); \ + if (!ctx->fpu_enabled) { \ + RET_EXCP(ctx, EXCP_NO_FP, 0); \ + return; \ + } \ if (rA(ctx->opcode) == 0) { \ gen_op_set_T0(simm); \ } else { \ @@ -1441,6 +1456,10 @@ GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ { \ uint32_t simm = SIMM(ctx->opcode); \ + if (!ctx->fpu_enabled) { \ + RET_EXCP(ctx, EXCP_NO_FP, 0); \ + return; \ + } \ if (rA(ctx->opcode) == 0 || \ rA(ctx->opcode) == rD(ctx->opcode)) { \ RET_INVAL(ctx); \ @@ -1457,6 +1476,10 @@ GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ #define GEN_LDUXF(width, opc) \ GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ { \ + if (!ctx->fpu_enabled) { \ + RET_EXCP(ctx, EXCP_NO_FP, 0); \ + return; \ + } \ if (rA(ctx->opcode) == 0 || \ rA(ctx->opcode) == rD(ctx->opcode)) { \ RET_INVAL(ctx); \ @@ -1473,6 +1496,10 @@ GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ #define GEN_LDXF(width, opc2, opc3) \ GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \ { \ + if (!ctx->fpu_enabled) { \ + RET_EXCP(ctx, EXCP_NO_FP, 0); \ + return; \ + } \ if (rA(ctx->opcode) == 0) { \ gen_op_load_gpr_T0(rB(ctx->opcode)); \ } else { \ @@ -1501,6 +1528,10 @@ GEN_LDFS(fs, 0x10); GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ { \ uint32_t simm = SIMM(ctx->opcode); \ + if (!ctx->fpu_enabled) { \ + RET_EXCP(ctx, EXCP_NO_FP, 0); \ + return; \ + } \ if (rA(ctx->opcode) == 0) { \ gen_op_set_T0(simm); \ } else { \ @@ -1516,6 +1547,10 @@ GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ { \ uint32_t simm = SIMM(ctx->opcode); \ + if (!ctx->fpu_enabled) { \ + RET_EXCP(ctx, EXCP_NO_FP, 0); \ + return; \ + } \ if (rA(ctx->opcode) == 0) { \ RET_INVAL(ctx); \ return; \ @@ -1531,6 +1566,10 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ #define GEN_STUXF(width, opc) \ GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ { \ + if (!ctx->fpu_enabled) { \ + RET_EXCP(ctx, EXCP_NO_FP, 0); \ + return; \ + } \ if (rA(ctx->opcode) == 0) { \ RET_INVAL(ctx); \ return; \ @@ -1546,6 +1585,10 @@ GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ #define GEN_STXF(width, opc2, opc3) \ GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \ { \ + if (!ctx->fpu_enabled) { \ + RET_EXCP(ctx, EXCP_NO_FP, 0); \ + return; \ + } \ if (rA(ctx->opcode) == 0) { \ gen_op_load_gpr_T0(rB(ctx->opcode)); \ } else { \ |