qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] SH4: convert fmov/fadd to TCG


From: Shin-ichiro KAWASAKI
Subject: [Qemu-devel] [PATCH] SH4: convert fmov/fadd to TCG
Date: Sun, 31 Aug 2008 04:36:17 +0900
User-agent: Thunderbird 2.0.0.16 (Windows/20080708)

This patch converts two SH4 float instructions, 'fmov Rm,Rn' and
'fadd' into TCG.  Before converting other float instructions
into TCG, comments on it will be appreciated.

- TCG variables intorudced for float operation : FT[01], and DT[01].
- I think float registers 'fregs' are not to be mapped for
  TCG variables, because TCG does not support float operations, now.
  Instead of it, float register load/store function introduced.
  For 64 bit operation, they do 32 bit swap with temporary TCG vars.
  I hope that this won't result too much overhead.
- A comment is added to imply that SH-Linux does not run
  'fmov' in 64 bit .

Regards,
Shin-ichiro KAWASAKI


Index: trunk/target-sh4/op.c
===================================================================
--- trunk/target-sh4/op.c       (revision 5116)
+++ trunk/target-sh4/op.c       (working copy)
@@ -230,18 +230,6 @@
     RETURN();
 }
 
-void OPPROTO op_fadd_FT(void)
-{
-    FT0 = float32_add(FT0, FT1, &env->fp_status);
-    RETURN();
-}
-
-void OPPROTO op_fadd_DT(void)
-{
-    DT0 = float64_add(DT0, DT1, &env->fp_status);
-    RETURN();
-}
-
 void OPPROTO op_fsub_FT(void)
 {
     FT0 = float32_sub(FT0, FT1, &env->fp_status);
Index: trunk/target-sh4/helper.h
===================================================================
--- trunk/target-sh4/helper.h   (revision 5116)
+++ trunk/target-sh4/helper.h   (working copy)
@@ -16,3 +16,6 @@
 DEF_HELPER(uint32_t, helper_negc, (uint32_t))
 DEF_HELPER(void, helper_macl, (uint32_t, uint32_t))
 DEF_HELPER(void, helper_macw, (uint32_t, uint32_t))
+
+DEF_HELPER(uint32_t, helper_fadd_FT, (uint32_t, uint32_t, CPUState *))
+DEF_HELPER(uint64_t, helper_fadd_DT, (uint64_t, uint64_t, CPUState *))
Index: trunk/target-sh4/op_helper.c
===================================================================
--- trunk/target-sh4/op_helper.c        (revision 5116)
+++ trunk/target-sh4/op_helper.c        (working copy)
@@ -388,3 +388,15 @@
        env->sr &= ~SR_T;
     *addr = new;
 }
+
+uint32_t helper_fadd_FT(uint32_t t0, uint32_t t1, CPUState * env)
+{
+    float32 ret = float32_add(*(float32*)&t0, *(float32*)&t1, &env->fp_status);
+    return *(uint32_t*)(&ret);
+}
+
+uint64_t helper_fadd_DT(uint64_t t0, uint64_t t1, CPUState * env)
+{
+    float64 ret = float64_add(*(float64*)&t0, *(float64*)&t1, &env->fp_status);
+    return *(uint64_t*)(&ret);
+}
Index: trunk/target-sh4/translate.c
===================================================================
--- trunk/target-sh4/translate.c        (revision 5116)
+++ trunk/target-sh4/translate.c        (working copy)
@@ -69,6 +69,8 @@
 
 /* dyngen register indexes */
 static TCGv cpu_T[2];
+static TCGv cpu_FT[2];
+static TCGv cpu_DT[2];
 
 #include "gen-icount.h"
 
@@ -90,6 +92,14 @@
     cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
     cpu_T[0] = tcg_global_reg_new(TCG_TYPE_I32, TCG_AREG1, "T0");
     cpu_T[1] = tcg_global_reg_new(TCG_TYPE_I32, TCG_AREG2, "T1");
+    cpu_FT[0] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
+                                  offsetof(CPUState, ft0), "FT0");
+    cpu_FT[1] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
+                                  offsetof(CPUState, ft1), "FT1");
+    cpu_DT[0] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
+                                  offsetof(CPUState, dt0), "DT0");
+    cpu_DT[1] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
+                                  offsetof(CPUState, dt1), "DT1");
 
     for (i = 0; i < 24; i++)
         cpu_gregs[i] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
@@ -345,6 +355,42 @@
     tcg_gen_ori_i32(cpu_flags, cpu_flags, flags);
 }
 
+static inline void gen_ld_frN(TCGv ft, TCGv cpu_env, uint32_t reg)
+{
+    tcg_gen_ld_i32(ft, cpu_env, offsetof(CPUState, fregs[reg]));
+}
+
+static inline void gen_ld_drN(TCGv dt, TCGv cpu_env, uint32_t reg)
+{
+    TCGv tmp = tcg_temp_new(TCG_TYPE_I64);
+               
+    tcg_gen_ld_i64(dt, cpu_env, offsetof(CPUState, fregs[reg]));
+    tcg_gen_shli_i64(tmp, dt, 32);
+    tcg_gen_shri_i64(dt, dt, 32);
+    tcg_gen_or_i64(dt, tmp, dt);
+
+    tcg_temp_free(tmp);
+}
+
+static inline void gen_st_frN(TCGv ft, TCGv cpu_env, uint32_t reg)
+{
+    tcg_gen_st_i32(ft, cpu_env, offsetof(CPUState, fregs[reg]));
+}
+
+static inline void gen_st_drN(TCGv dt, TCGv cpu_env, uint32_t reg)
+{
+    TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64);
+    TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
+               
+    tcg_gen_shli_i64(tmp1, dt, 32);
+    tcg_gen_shri_i64(tmp2, dt, 32);
+    tcg_gen_or_i64(tmp1, tmp1, tmp2);
+    tcg_gen_st_i64(tmp1, cpu_env, offsetof(CPUState, fregs[reg]));
+
+    tcg_temp_free(tmp1);
+    tcg_temp_free(tmp2);
+}
+
 #define B3_0 (ctx->opcode & 0xf)
 #define B6_4 ((ctx->opcode >> 4) & 0x7)
 #define B7_4 ((ctx->opcode >> 4) & 0xf)
@@ -811,12 +857,14 @@
        tcg_gen_xor_i32(cpu_gregs[REG(B11_8)], cpu_gregs[REG(B11_8)], 
cpu_gregs[REG(B7_4)]);
        return;
     case 0xf00c: /* fmov {F,D,X}Rm,{F,D,X}Rn - FPSCR: Nothing */
+        /* 64 bit fmov code is not tested, because SH-Linux seems
+          not to set FPSCR_SZ flag true. */
        if (ctx->fpscr & FPSCR_SZ) {
-           gen_op_fmov_drN_DT0(XREG(B7_4));
-           gen_op_fmov_DT0_drN(XREG(B11_8));
+           gen_ld_drN(cpu_DT[0], cpu_env, XREG(B7_4));
+           gen_st_drN(cpu_DT[1], cpu_env, XREG(B11_8));
        } else {
-           gen_op_fmov_frN_FT0(FREG(B7_4));
-           gen_op_fmov_FT0_frN(FREG(B11_8));
+           gen_ld_frN(cpu_FT[0], cpu_env, FREG(B7_4));
+           gen_st_frN(cpu_FT[0], cpu_env, FREG(B11_8));
        }
        return;
     case 0xf00a: /* fmov {F,D,X}Rm,@Rn - FPSCR: Nothing */
@@ -905,17 +953,22 @@
        if (ctx->fpscr & FPSCR_PR) {
            if (ctx->opcode & 0x0110)
                break; /* illegal instruction */
-           gen_op_fmov_drN_DT1(DREG(B7_4));
-           gen_op_fmov_drN_DT0(DREG(B11_8));
+           gen_ld_drN(cpu_DT[1], cpu_env, DREG(B7_4));
+           gen_ld_drN(cpu_DT[0], cpu_env, DREG(B11_8));
        }
        else {
-           gen_op_fmov_frN_FT1(FREG(B7_4));
-           gen_op_fmov_frN_FT0(FREG(B11_8));
+           gen_ld_frN(cpu_FT[1], cpu_env, FREG(B7_4));
+           gen_ld_frN(cpu_FT[0], cpu_env, FREG(B11_8));
        }
 
        switch (ctx->opcode & 0xf00f) {
        case 0xf000:            /* fadd Rm,Rn */
-           ctx->fpscr & FPSCR_PR ? gen_op_fadd_DT() : gen_op_fadd_FT();
+           if (ctx->fpscr & FPSCR_PR)
+               tcg_gen_helper_1_3(helper_fadd_DT, cpu_DT[0],
+                                  cpu_DT[0], cpu_DT[1], cpu_env);
+           else
+               tcg_gen_helper_1_3(helper_fadd_FT, cpu_FT[0],
+                                  cpu_FT[0], cpu_FT[1], cpu_env);
            break;
        case 0xf001:            /* fsub Rm,Rn */
            ctx->fpscr & FPSCR_PR ? gen_op_fsub_DT() : gen_op_fsub_FT();
@@ -935,10 +988,10 @@
        }
 
        if (ctx->fpscr & FPSCR_PR) {
-           gen_op_fmov_DT0_drN(DREG(B11_8));
+           gen_st_drN(cpu_DT[0], cpu_env, DREG(B11_8));
        }
        else {
-           gen_op_fmov_FT0_frN(FREG(B11_8));
+           gen_st_frN(cpu_FT[0], cpu_env, FREG(B11_8));
        }
        return;
     }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]