Fix Sparc64 ldfa, lddfa, stfa, and stdfa instructions
authorblueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 30 Sep 2007 19:38:12 +0000 (19:38 +0000)
committerblueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 30 Sep 2007 19:38:12 +0000 (19:38 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3298 c046a42c-6fe2-441c-8c8c-71466251a162

target-sparc/exec.h
target-sparc/op.c
target-sparc/op_helper.c
target-sparc/translate.c

index 35f4b5f..063e2ee 100644 (file)
@@ -51,6 +51,8 @@ void cpu_loop_exit(void);
 void helper_flush(target_ulong addr);
 void helper_ld_asi(int asi, int size, int sign);
 void helper_st_asi(int asi, int size);
+void helper_ldf_asi(int asi, int size, int rd);
+void helper_stf_asi(int asi, int size, int rd);
 void helper_rett(void);
 void helper_ldfsr(void);
 void set_cwp(int new_cwp);
index bb084ee..613bcb0 100644 (file)
@@ -1865,6 +1865,28 @@ void OPPROTO op_st_asi_reg()
     helper_st_asi(env->asi, PARAM2);
 }
 
+void OPPROTO op_ldf_asi_reg()
+{
+    T0 += PARAM1;
+    helper_ldf_asi(env->asi, PARAM2, PARAM3);
+}
+
+void OPPROTO op_stf_asi_reg()
+{
+    T0 += PARAM1;
+    helper_stf_asi(env->asi, PARAM2, PARAM3);
+}
+
+void OPPROTO op_ldf_asi()
+{
+    helper_ldf_asi(PARAM1, PARAM2, PARAM3);
+}
+
+void OPPROTO op_stf_asi()
+{
+    helper_stf_asi(PARAM1, PARAM2, PARAM3);
+}
+
 void OPPROTO op_ldstub_asi_reg()             /* XXX: should be atomically */
 {
     target_ulong tmp;
index eea4a63..fa51cde 100644 (file)
@@ -1126,6 +1126,79 @@ void helper_st_asi(int asi, int size)
     }
 }
 #endif /* CONFIG_USER_ONLY */
+
+void helper_ldf_asi(int asi, int size, int rd)
+{
+    target_ulong tmp_T0 = T0, tmp_T1 = T1;
+    unsigned int i;
+
+    switch (asi) {
+    case 0xf0: // Block load primary
+    case 0xf1: // Block load secondary
+    case 0xf8: // Block load primary LE
+    case 0xf9: // Block load secondary LE
+        for (i = 0; i < 8; i++) {
+            helper_ld_asi(asi & 0x8f, 8, 0);
+            *((int64_t *)&DT0) = T1;
+            T0 += 8;
+        }
+        T0 = tmp_T0;
+        T1 = tmp_T1;
+
+        return;
+    default:
+        break;
+    }
+
+    helper_ld_asi(asi, size, 0);
+    switch(size) {
+    default:
+    case 4:
+        *((uint32_t *)&FT0) = T1;
+        break;
+    case 8:
+        *((int64_t *)&DT0) = T1;
+        break;
+    }
+    T1 = tmp_T1;
+}
+
+void helper_stf_asi(int asi, int size, int rd)
+{
+    target_ulong tmp_T0 = T0, tmp_T1 = T1;
+    unsigned int i;
+
+    switch (asi) {
+    case 0xf0: // Block store primary
+    case 0xf1: // Block store secondary
+    case 0xf8: // Block store primary LE
+    case 0xf9: // Block store secondary LE
+        for (i = 0; i < 8; i++) {
+            T1 = *((int64_t *)&DT0);
+            helper_st_asi(asi & 0x8f, 8);
+            T0 += 8;
+        }
+        T0 = tmp_T0;
+        T1 = tmp_T1;
+
+        return;
+    default:
+        break;
+    }
+
+    switch(size) {
+    default:
+    case 4:
+        T1 = *((uint32_t *)&FT0);
+        break;
+    case 8:
+        T1 = *((int64_t *)&DT0);
+        break;
+    }
+    helper_st_asi(asi, size);
+    T1 = tmp_T1;
+}
+
 #endif /* TARGET_SPARC64 */
 
 #ifndef TARGET_SPARC64
index 0cffa9e..94503be 100644 (file)
@@ -427,6 +427,34 @@ static inline void gen_st_asi(int insn, int size)
     }
 }
 
+static inline void gen_ldf_asi(int insn, int size)
+{
+    int asi, offset, rd;
+
+    rd = GET_FIELD(insn, 2, 6);
+    if (IS_IMM) {
+        offset = GET_FIELD(insn, 25, 31);
+        gen_op_ldf_asi_reg(offset, size, rd);
+    } else {
+        asi = GET_FIELD(insn, 19, 26);
+        gen_op_ldf_asi(asi, size, rd);
+    }
+}
+
+static inline void gen_stf_asi(int insn, int size)
+{
+    int asi, offset, rd;
+
+    rd = GET_FIELD(insn, 2, 6);
+    if (IS_IMM) {
+        offset = GET_FIELD(insn, 25, 31);
+        gen_op_stf_asi_reg(offset, size, rd);
+    } else {
+        asi = GET_FIELD(insn, 19, 26);
+        gen_op_stf_asi(asi, size, rd);
+    }
+}
+
 static inline void gen_swap_asi(int insn)
 {
     int asi, offset;
@@ -3069,11 +3097,11 @@ static void disas_sparc_insn(DisasContext * dc)
 #ifdef CONFIG_USER_ONLY
                     gen_op_check_align_T0_3();
 #endif
-                    gen_ld_asi(insn, 8, 0); // XXX
+                    gen_ldf_asi(insn, 4);
                     goto skip_move;
                 case 0x33: /* V9 lddfa */
-                    gen_op_check_align_T0_7();
-                    gen_ld_asi(insn, 8, 0); // XXX
+                    gen_op_check_align_T0_3();
+                    gen_ldf_asi(insn, 8);
                     goto skip_move;
                 case 0x3d: /* V9 prefetcha, no effect */
                     goto skip_move;
@@ -3245,11 +3273,13 @@ static void disas_sparc_insn(DisasContext * dc)
 #ifdef CONFIG_USER_ONLY
                     gen_op_check_align_T0_3();
 #endif
-                    gen_st_asi(insn, 0); // XXX
+                    gen_op_load_fpr_FT0(rd);
+                    gen_stf_asi(insn, 4);
                     break;
                 case 0x37: /* V9 stdfa */
-                    gen_op_check_align_T0_7();
-                    gen_st_asi(insn, 0); // XXX
+                    gen_op_check_align_T0_3();
+                    gen_op_load_fpr_DT0(DFPREG(rd));
+                    gen_stf_asi(insn, 8);
                     break;
                 case 0x3c: /* V9 casa */
 #ifdef CONFIG_USER_ONLY