Commit 3391c81801c867bc8f4dd6ce32766e4e8345813b

Authored by blueswir1
1 parent ee0b03fd

Fix Sparc64 ldfa, lddfa, stfa, and stdfa instructions


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3298 c046a42c-6fe2-441c-8c8c-71466251a162
target-sparc/exec.h
... ... @@ -51,6 +51,8 @@ void cpu_loop_exit(void);
51 51 void helper_flush(target_ulong addr);
52 52 void helper_ld_asi(int asi, int size, int sign);
53 53 void helper_st_asi(int asi, int size);
  54 +void helper_ldf_asi(int asi, int size, int rd);
  55 +void helper_stf_asi(int asi, int size, int rd);
54 56 void helper_rett(void);
55 57 void helper_ldfsr(void);
56 58 void set_cwp(int new_cwp);
... ...
target-sparc/op.c
... ... @@ -1865,6 +1865,28 @@ void OPPROTO op_st_asi_reg()
1865 1865 helper_st_asi(env->asi, PARAM2);
1866 1866 }
1867 1867  
  1868 +void OPPROTO op_ldf_asi_reg()
  1869 +{
  1870 + T0 += PARAM1;
  1871 + helper_ldf_asi(env->asi, PARAM2, PARAM3);
  1872 +}
  1873 +
  1874 +void OPPROTO op_stf_asi_reg()
  1875 +{
  1876 + T0 += PARAM1;
  1877 + helper_stf_asi(env->asi, PARAM2, PARAM3);
  1878 +}
  1879 +
  1880 +void OPPROTO op_ldf_asi()
  1881 +{
  1882 + helper_ldf_asi(PARAM1, PARAM2, PARAM3);
  1883 +}
  1884 +
  1885 +void OPPROTO op_stf_asi()
  1886 +{
  1887 + helper_stf_asi(PARAM1, PARAM2, PARAM3);
  1888 +}
  1889 +
1868 1890 void OPPROTO op_ldstub_asi_reg() /* XXX: should be atomically */
1869 1891 {
1870 1892 target_ulong tmp;
... ...
target-sparc/op_helper.c
... ... @@ -1126,6 +1126,79 @@ void helper_st_asi(int asi, int size)
1126 1126 }
1127 1127 }
1128 1128 #endif /* CONFIG_USER_ONLY */
  1129 +
  1130 +void helper_ldf_asi(int asi, int size, int rd)
  1131 +{
  1132 + target_ulong tmp_T0 = T0, tmp_T1 = T1;
  1133 + unsigned int i;
  1134 +
  1135 + switch (asi) {
  1136 + case 0xf0: // Block load primary
  1137 + case 0xf1: // Block load secondary
  1138 + case 0xf8: // Block load primary LE
  1139 + case 0xf9: // Block load secondary LE
  1140 + for (i = 0; i < 8; i++) {
  1141 + helper_ld_asi(asi & 0x8f, 8, 0);
  1142 + *((int64_t *)&DT0) = T1;
  1143 + T0 += 8;
  1144 + }
  1145 + T0 = tmp_T0;
  1146 + T1 = tmp_T1;
  1147 +
  1148 + return;
  1149 + default:
  1150 + break;
  1151 + }
  1152 +
  1153 + helper_ld_asi(asi, size, 0);
  1154 + switch(size) {
  1155 + default:
  1156 + case 4:
  1157 + *((uint32_t *)&FT0) = T1;
  1158 + break;
  1159 + case 8:
  1160 + *((int64_t *)&DT0) = T1;
  1161 + break;
  1162 + }
  1163 + T1 = tmp_T1;
  1164 +}
  1165 +
  1166 +void helper_stf_asi(int asi, int size, int rd)
  1167 +{
  1168 + target_ulong tmp_T0 = T0, tmp_T1 = T1;
  1169 + unsigned int i;
  1170 +
  1171 + switch (asi) {
  1172 + case 0xf0: // Block store primary
  1173 + case 0xf1: // Block store secondary
  1174 + case 0xf8: // Block store primary LE
  1175 + case 0xf9: // Block store secondary LE
  1176 + for (i = 0; i < 8; i++) {
  1177 + T1 = *((int64_t *)&DT0);
  1178 + helper_st_asi(asi & 0x8f, 8);
  1179 + T0 += 8;
  1180 + }
  1181 + T0 = tmp_T0;
  1182 + T1 = tmp_T1;
  1183 +
  1184 + return;
  1185 + default:
  1186 + break;
  1187 + }
  1188 +
  1189 + switch(size) {
  1190 + default:
  1191 + case 4:
  1192 + T1 = *((uint32_t *)&FT0);
  1193 + break;
  1194 + case 8:
  1195 + T1 = *((int64_t *)&DT0);
  1196 + break;
  1197 + }
  1198 + helper_st_asi(asi, size);
  1199 + T1 = tmp_T1;
  1200 +}
  1201 +
1129 1202 #endif /* TARGET_SPARC64 */
1130 1203  
1131 1204 #ifndef TARGET_SPARC64
... ...
target-sparc/translate.c
... ... @@ -427,6 +427,34 @@ static inline void gen_st_asi(int insn, int size)
427 427 }
428 428 }
429 429  
  430 +static inline void gen_ldf_asi(int insn, int size)
  431 +{
  432 + int asi, offset, rd;
  433 +
  434 + rd = GET_FIELD(insn, 2, 6);
  435 + if (IS_IMM) {
  436 + offset = GET_FIELD(insn, 25, 31);
  437 + gen_op_ldf_asi_reg(offset, size, rd);
  438 + } else {
  439 + asi = GET_FIELD(insn, 19, 26);
  440 + gen_op_ldf_asi(asi, size, rd);
  441 + }
  442 +}
  443 +
  444 +static inline void gen_stf_asi(int insn, int size)
  445 +{
  446 + int asi, offset, rd;
  447 +
  448 + rd = GET_FIELD(insn, 2, 6);
  449 + if (IS_IMM) {
  450 + offset = GET_FIELD(insn, 25, 31);
  451 + gen_op_stf_asi_reg(offset, size, rd);
  452 + } else {
  453 + asi = GET_FIELD(insn, 19, 26);
  454 + gen_op_stf_asi(asi, size, rd);
  455 + }
  456 +}
  457 +
430 458 static inline void gen_swap_asi(int insn)
431 459 {
432 460 int asi, offset;
... ... @@ -3069,11 +3097,11 @@ static void disas_sparc_insn(DisasContext * dc)
3069 3097 #ifdef CONFIG_USER_ONLY
3070 3098 gen_op_check_align_T0_3();
3071 3099 #endif
3072   - gen_ld_asi(insn, 8, 0); // XXX
  3100 + gen_ldf_asi(insn, 4);
3073 3101 goto skip_move;
3074 3102 case 0x33: /* V9 lddfa */
3075   - gen_op_check_align_T0_7();
3076   - gen_ld_asi(insn, 8, 0); // XXX
  3103 + gen_op_check_align_T0_3();
  3104 + gen_ldf_asi(insn, 8);
3077 3105 goto skip_move;
3078 3106 case 0x3d: /* V9 prefetcha, no effect */
3079 3107 goto skip_move;
... ... @@ -3245,11 +3273,13 @@ static void disas_sparc_insn(DisasContext * dc)
3245 3273 #ifdef CONFIG_USER_ONLY
3246 3274 gen_op_check_align_T0_3();
3247 3275 #endif
3248   - gen_st_asi(insn, 0); // XXX
  3276 + gen_op_load_fpr_FT0(rd);
  3277 + gen_stf_asi(insn, 4);
3249 3278 break;
3250 3279 case 0x37: /* V9 stdfa */
3251   - gen_op_check_align_T0_7();
3252   - gen_st_asi(insn, 0); // XXX
  3280 + gen_op_check_align_T0_3();
  3281 + gen_op_load_fpr_DT0(DFPREG(rd));
  3282 + gen_stf_asi(insn, 8);
3253 3283 break;
3254 3284 case 0x3c: /* V9 casa */
3255 3285 #ifdef CONFIG_USER_ONLY
... ...