OSDN Git Service

VFP register ordering (Paul Brook)
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Thu, 7 Apr 2005 19:42:46 +0000 (19:42 +0000)
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Thu, 7 Apr 2005 19:42:46 +0000 (19:42 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1355 c046a42c-6fe2-441c-8c8c-71466251a162

target-arm/cpu.h
target-arm/translate.c

index cf11c2f..1346175 100644 (file)
@@ -35,9 +35,9 @@
    precision respectively.
    Doing runtime conversions is tricky because VFP registers may contain
    integer values (eg. as the result of a FTOSI instruction).
-   A double precision register load/store must also load/store the
-   corresponding single precision pair, although it is undefined how
  these overlap.  */
+   s<2n> maps to the least significant half of d<n>
+   s<2n+1> maps to the most significant half of d<n>
+ */
 
 typedef struct CPUARMState {
     uint32_t regs[16];
@@ -71,10 +71,7 @@ typedef struct CPUARMState {
                                       memory was written */
     /* VFP coprocessor state.  */
     struct {
-        union {
-            float32 s[32];
-            float64 d[16];
-        } regs;
+        float64 regs[16];
 
         /* We store these fpcsr fields separately for convenience.  */
         int vec_len;
index db38e33..39c28e7 100644 (file)
@@ -385,28 +385,41 @@ VFP_OP(st)
 
 #undef VFP_OP
 
+static inline long
+vfp_reg_offset (int dp, int reg)
+{
+    if (dp)
+        return offsetof(CPUARMState, vfp.regs[reg]);
+    else if (reg & 1) {
+        return offsetof(CPUARMState, vfp.regs[reg >> 1])
+          + offsetof(CPU_DoubleU, l.upper);
+    } else {
+        return offsetof(CPUARMState, vfp.regs[reg >> 1])
+          + offsetof(CPU_DoubleU, l.lower);
+    }
+}
 static inline void gen_mov_F0_vreg(int dp, int reg)
 {
     if (dp)
-        gen_op_vfp_getreg_F0d(offsetof(CPUARMState, vfp.regs.d[reg]));
+        gen_op_vfp_getreg_F0d(vfp_reg_offset(dp, reg));
     else
-        gen_op_vfp_getreg_F0s(offsetof(CPUARMState, vfp.regs.s[reg]));
+        gen_op_vfp_getreg_F0s(vfp_reg_offset(dp, reg));
 }
 
 static inline void gen_mov_F1_vreg(int dp, int reg)
 {
     if (dp)
-        gen_op_vfp_getreg_F1d(offsetof(CPUARMState, vfp.regs.d[reg]));
+        gen_op_vfp_getreg_F1d(vfp_reg_offset(dp, reg));
     else
-        gen_op_vfp_getreg_F1s(offsetof(CPUARMState, vfp.regs.s[reg]));
+        gen_op_vfp_getreg_F1s(vfp_reg_offset(dp, reg));
 }
 
 static inline void gen_mov_vreg_F0(int dp, int reg)
 {
     if (dp)
-        gen_op_vfp_setreg_F0d(offsetof(CPUARMState, vfp.regs.d[reg]));
+        gen_op_vfp_setreg_F0d(vfp_reg_offset(dp, reg));
     else
-        gen_op_vfp_setreg_F0s(offsetof(CPUARMState, vfp.regs.s[reg]));
+        gen_op_vfp_setreg_F0s(vfp_reg_offset(dp, reg));
 }
 
 /* Disassemble a VFP instruction.  Returns nonzero if an error occured
@@ -2120,9 +2133,9 @@ void cpu_dump_state(CPUState *env, FILE *f,
             env->cpsr & (1 << 28) ? 'V' : '-');
 
     for (i = 0; i < 16; i++) {
-        s0.s = env->vfp.regs.s[i * 2];
-        s1.s = env->vfp.regs.s[i * 2 + 1];
-        d.d = env->vfp.regs.d[i];
+        d.d = env->vfp.regs[i];
+        s0.i = d.l.lower;
+        s1.i = d.l.upper;
         cpu_fprintf(f, "s%02d=%08x(%8f) s%02d=%08x(%8f) d%02d=%08x%08x(%8f)\n",
                     i * 2, (int)s0.i, s0.s,
                     i * 2 + 1, (int)s0.i, s0.s,