Commit ea6cf6be8e078cbe87f0e3fe226e3afdd92505e0

Authored by ths
1 parent 6db45e65

Emulate more fpu opcodes, by Magnus Damm.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3002 c046a42c-6fe2-441c-8c8c-71466251a162
target-sh4/cpu.h
@@ -99,6 +99,7 @@ typedef struct CPUSH4State { @@ -99,6 +99,7 @@ typedef struct CPUSH4State {
99 /* temporary float registers */ 99 /* temporary float registers */
100 float32 ft0, ft1; 100 float32 ft0, ft1;
101 float64 dt0, dt1; 101 float64 dt0, dt1;
  102 + float_status fp_status;
102 103
103 /* Those belong to the specific unit (SH7750) but are handled here */ 104 /* Those belong to the specific unit (SH7750) but are handled here */
104 uint32_t mmucr; /* MMU control register */ 105 uint32_t mmucr; /* MMU control register */
target-sh4/op.c
@@ -509,6 +509,9 @@ void OPPROTO op_##store##_##target##_T0 (void) \ @@ -509,6 +509,9 @@ void OPPROTO op_##store##_##target##_T0 (void) \
509 void OPPROTO op_lds_T0_fpscr(void) 509 void OPPROTO op_lds_T0_fpscr(void)
510 { 510 {
511 env->fpscr = T0 & 0x003fffff; 511 env->fpscr = T0 & 0x003fffff;
  512 + env->fp_status.float_rounding_mode = T0 & 0x01 ?
  513 + float_round_to_zero : float_round_nearest_even;
  514 +
512 RETURN(); 515 RETURN();
513 } 516 }
514 517
@@ -705,6 +708,18 @@ void OPPROTO op_fmov_drN_DT0(void) @@ -705,6 +708,18 @@ void OPPROTO op_fmov_drN_DT0(void)
705 RETURN(); 708 RETURN();
706 } 709 }
707 710
  711 +void OPPROTO op_fmov_frN_FT1(void)
  712 +{
  713 + FT1 = *(float32 *)&env->fregs[PARAM1];
  714 + RETURN();
  715 +}
  716 +
  717 +void OPPROTO op_fmov_drN_DT1(void)
  718 +{
  719 + DT1 = *(float64 *)&env->fregs[PARAM1];
  720 + RETURN();
  721 +}
  722 +
708 void OPPROTO op_fmov_FT0_frN(void) 723 void OPPROTO op_fmov_FT0_frN(void)
709 { 724 {
710 *(float32 *)&env->fregs[PARAM1] = FT0; 725 *(float32 *)&env->fregs[PARAM1] = FT0;
@@ -717,6 +732,84 @@ void OPPROTO op_fmov_DT0_drN(void) @@ -717,6 +732,84 @@ void OPPROTO op_fmov_DT0_drN(void)
717 RETURN(); 732 RETURN();
718 } 733 }
719 734
  735 +void OPPROTO op_fadd_FT(void)
  736 +{
  737 + FT0 = float32_add(FT0, FT1, &env->fp_status);
  738 + RETURN();
  739 +}
  740 +
  741 +void OPPROTO op_fadd_DT(void)
  742 +{
  743 + DT0 = float64_add(DT0, DT1, &env->fp_status);
  744 + RETURN();
  745 +}
  746 +
  747 +void OPPROTO op_fsub_FT(void)
  748 +{
  749 + FT0 = float32_sub(FT0, FT1, &env->fp_status);
  750 + RETURN();
  751 +}
  752 +
  753 +void OPPROTO op_fsub_DT(void)
  754 +{
  755 + DT0 = float64_sub(DT0, DT1, &env->fp_status);
  756 + RETURN();
  757 +}
  758 +
  759 +void OPPROTO op_fmul_FT(void)
  760 +{
  761 + FT0 = float32_mul(FT0, FT1, &env->fp_status);
  762 + RETURN();
  763 +}
  764 +
  765 +void OPPROTO op_fmul_DT(void)
  766 +{
  767 + DT0 = float64_mul(DT0, DT1, &env->fp_status);
  768 + RETURN();
  769 +}
  770 +
  771 +void OPPROTO op_fdiv_FT(void)
  772 +{
  773 + FT0 = float32_div(FT0, FT1, &env->fp_status);
  774 + RETURN();
  775 +}
  776 +
  777 +void OPPROTO op_fdiv_DT(void)
  778 +{
  779 + DT0 = float64_div(DT0, DT1, &env->fp_status);
  780 + RETURN();
  781 +}
  782 +
  783 +void OPPROTO op_float_FT(void)
  784 +{
  785 + FT0 = int32_to_float32(env->fpul, &env->fp_status);
  786 + RETURN();
  787 +}
  788 +
  789 +void OPPROTO op_float_DT(void)
  790 +{
  791 + DT0 = int32_to_float64(env->fpul, &env->fp_status);
  792 + RETURN();
  793 +}
  794 +
  795 +void OPPROTO op_ftrc_FT(void)
  796 +{
  797 + env->fpul = float32_to_int32_round_to_zero(FT0, &env->fp_status);
  798 + RETURN();
  799 +}
  800 +
  801 +void OPPROTO op_ftrc_DT(void)
  802 +{
  803 + env->fpul = float64_to_int32_round_to_zero(DT0, &env->fp_status);
  804 + RETURN();
  805 +}
  806 +
  807 +void OPPROTO op_fmov_T0_frN(void)
  808 +{
  809 + *(unsigned int *)&env->fregs[PARAM1] = T0;
  810 + RETURN();
  811 +}
  812 +
720 void OPPROTO op_dec1_rN(void) 813 void OPPROTO op_dec1_rN(void)
721 { 814 {
722 env->gregs[PARAM1] -= 1; 815 env->gregs[PARAM1] -= 1;
target-sh4/translate.c
@@ -131,7 +131,13 @@ void cpu_sh4_reset(CPUSH4State * env) @@ -131,7 +131,13 @@ void cpu_sh4_reset(CPUSH4State * env)
131 #endif 131 #endif
132 env->vbr = 0; 132 env->vbr = 0;
133 env->pc = 0xA0000000; 133 env->pc = 0xA0000000;
134 - env->fpscr = 0x00040001; 134 +#if defined(CONFIG_USER_ONLY)
  135 + env->fpscr = FPSCR_PR; /* value for userspace according to the kernel */
  136 + env->fp_status.float_rounding_mode = float_round_nearest_even; /* ?! */
  137 +#else
  138 + env->fpscr = 0x00040001; /* CPU reset value according to SH4 manual */
  139 + env->fp_status.float_rounding_mode = float_round_to_zero;
  140 +#endif
135 env->mmucr = 0; 141 env->mmucr = 0;
136 } 142 }
137 143
@@ -238,6 +244,7 @@ static void gen_delayed_conditional_jump(DisasContext * ctx) @@ -238,6 +244,7 @@ static void gen_delayed_conditional_jump(DisasContext * ctx)
238 #define FREG(x) (ctx->fpscr & FPSCR_FR ? (x) ^ 0x10 : (x)) 244 #define FREG(x) (ctx->fpscr & FPSCR_FR ? (x) ^ 0x10 : (x))
239 #define XHACK(x) ((((x) & 1 ) << 4) | ((x) & 0xe)) 245 #define XHACK(x) ((((x) & 1 ) << 4) | ((x) & 0xe))
240 #define XREG(x) (ctx->fpscr & FPSCR_FR ? XHACK(x) ^ 0x10 : XHACK(x)) 246 #define XREG(x) (ctx->fpscr & FPSCR_FR ? XHACK(x) ^ 0x10 : XHACK(x))
  247 +#define DREG(x) FREG(x) /* Assumes lsb of (x) is always 0 */
241 248
242 #define CHECK_NOT_DELAY_SLOT \ 249 #define CHECK_NOT_DELAY_SLOT \
243 if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) \ 250 if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) \
@@ -768,6 +775,49 @@ void decode_opc(DisasContext * ctx) @@ -768,6 +775,49 @@ void decode_opc(DisasContext * ctx)
768 gen_op_stfl_FT0_T1(ctx); 775 gen_op_stfl_FT0_T1(ctx);
769 } 776 }
770 return; 777 return;
  778 + case 0xf000: /* fadd Rm,Rn */
  779 + case 0xf001: /* fsub Rm,Rn */
  780 + case 0xf002: /* fmul Rm,Rn */
  781 + case 0xf003: /* fdiv Rm,Rn */
  782 + case 0xf004: /* fcmp/eq Rm,Rn */
  783 + case 0xf005: /* fcmp/gt Rm,Rn */
  784 + if (ctx->fpscr & FPSCR_PR) {
  785 + if (ctx->opcode & 0x0110)
  786 + break; /* illegal instruction */
  787 + gen_op_fmov_drN_DT1(DREG(B7_4));
  788 + gen_op_fmov_drN_DT0(DREG(B11_8));
  789 + }
  790 + else {
  791 + gen_op_fmov_frN_FT1(FREG(B7_4));
  792 + gen_op_fmov_frN_FT0(FREG(B11_8));
  793 + }
  794 +
  795 + switch (ctx->opcode & 0xf00f) {
  796 + case 0xf000: /* fadd Rm,Rn */
  797 + ctx->fpscr & FPSCR_PR ? gen_op_fadd_DT() : gen_op_fadd_FT();
  798 + break;
  799 + case 0xf001: /* fsub Rm,Rn */
  800 + ctx->fpscr & FPSCR_PR ? gen_op_fsub_DT() : gen_op_fsub_FT();
  801 + break;
  802 + case 0xf002: /* fmul Rm,Rn */
  803 + ctx->fpscr & FPSCR_PR ? gen_op_fmul_DT() : gen_op_fmul_FT();
  804 + break;
  805 + case 0xf003: /* fdiv Rm,Rn */
  806 + ctx->fpscr & FPSCR_PR ? gen_op_fdiv_DT() : gen_op_fdiv_FT();
  807 + break;
  808 + case 0xf004: /* fcmp/eq Rm,Rn */
  809 + return;
  810 + case 0xf005: /* fcmp/gt Rm,Rn */
  811 + return;
  812 + }
  813 +
  814 + if (ctx->fpscr & FPSCR_PR) {
  815 + gen_op_fmov_DT0_drN(DREG(B11_8));
  816 + }
  817 + else {
  818 + gen_op_fmov_FT0_frN(FREG(B11_8));
  819 + }
  820 + return;
771 } 821 }
772 822
773 switch (ctx->opcode & 0xff00) { 823 switch (ctx->opcode & 0xff00) {
@@ -1079,6 +1129,44 @@ void decode_opc(DisasContext * ctx) @@ -1079,6 +1129,44 @@ void decode_opc(DisasContext * ctx)
1079 gen_op_fmov_frN_FT0(FREG(B11_8)); 1129 gen_op_fmov_frN_FT0(FREG(B11_8));
1080 gen_op_movl_FT0_fpul(); 1130 gen_op_movl_FT0_fpul();
1081 return; 1131 return;
  1132 + case 0xf02d: /* float FPUL,FRn/DRn */
  1133 + if (ctx->fpscr & FPSCR_PR) {
  1134 + if (ctx->opcode & 0x0100)
  1135 + break; /* illegal instruction */
  1136 + gen_op_float_DT();
  1137 + gen_op_fmov_DT0_drN(DREG(B11_8));
  1138 + }
  1139 + else {
  1140 + gen_op_float_FT();
  1141 + gen_op_fmov_FT0_frN(FREG(B11_8));
  1142 + }
  1143 + return;
  1144 + case 0xf03d: /* ftrc FRm/DRm,FPUL */
  1145 + if (ctx->fpscr & FPSCR_PR) {
  1146 + if (ctx->opcode & 0x0100)
  1147 + break; /* illegal instruction */
  1148 + gen_op_fmov_drN_DT0(DREG(B11_8));
  1149 + gen_op_ftrc_DT();
  1150 + }
  1151 + else {
  1152 + gen_op_fmov_frN_FT0(FREG(B11_8));
  1153 + gen_op_ftrc_FT();
  1154 + }
  1155 + return;
  1156 + case 0xf08d: /* fldi0 FRn */
  1157 + if (!(ctx->fpscr & FPSCR_PR)) {
  1158 + gen_op_movl_imm_T0(0);
  1159 + gen_op_fmov_T0_frN(FREG(B11_8));
  1160 + return;
  1161 + }
  1162 + break;
  1163 + case 0xf09d: /* fldi1 FRn */
  1164 + if (!(ctx->fpscr & FPSCR_PR)) {
  1165 + gen_op_movl_imm_T0(0x3f800000);
  1166 + gen_op_fmov_T0_frN(FREG(B11_8));
  1167 + return;
  1168 + }
  1169 + break;
1082 } 1170 }
1083 1171
1084 fprintf(stderr, "unknown instruction 0x%04x at pc 0x%08x\n", 1172 fprintf(stderr, "unknown instruction 0x%04x at pc 0x%08x\n",