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 | ... | ... |