Commit 3391c81801c867bc8f4dd6ce32766e4e8345813b
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
Showing
4 changed files
with
133 additions
and
6 deletions
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 | ... | ... |