mirror of
https://github.com/qemu/qemu.git
synced 2024-11-25 11:53:39 +08:00
Fix Sparc64 ldfa, lddfa, stfa, and stdfa instructions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3298 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
ee0b03fd85
commit
3391c81801
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user