diff options
author | Richard Henderson <rth@twiddle.net> | 2011-10-17 10:42:49 -0700 |
---|---|---|
committer | Richard Henderson <rth@twiddle.net> | 2011-10-26 13:55:26 -0700 |
commit | 30038fd81808f7c3bca92be2369e74c8ca7b3d69 (patch) | |
tree | bf718259c3d5bcc3e4f8605dbe9828c739be345d /target-sparc/ldst_helper.c | |
parent | 45c7b743cda3e87e528516ac1dd039d5932433a3 (diff) |
target-sparc: Change fpr representation to doubles.
This allows a more efficient representation for 64-bit hosts.
It should be about the same for 32-bit hosts, as we can still
access the individual pieces of the double.
Signed-off-by: Richard Henderson <rth@twiddle.net>
Diffstat (limited to 'target-sparc/ldst_helper.c')
-rw-r--r-- | target-sparc/ldst_helper.c | 71 |
1 files changed, 30 insertions, 41 deletions
diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c index 80e540818..b59707ecd 100644 --- a/target-sparc/ldst_helper.c +++ b/target-sparc/ldst_helper.c @@ -2045,7 +2045,7 @@ void helper_ldda_asi(target_ulong addr, int asi, int rd) void helper_ldf_asi(target_ulong addr, int asi, int size, int rd) { unsigned int i; - CPU_DoubleU u; + target_ulong val; helper_check_align(addr, 3); addr = asi_address_mask(env, asi, addr); @@ -2060,13 +2060,11 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd) return; } helper_check_align(addr, 0x3f); - for (i = 0; i < 16; i++) { - *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4, - 0); - addr += 4; + for (i = 0; i < 8; i++, rd += 2, addr += 8) { + env->fpr[rd/2].ll = helper_ld_asi(addr, asi & 0x8f, 8, 0); } - return; + case 0x16: /* UA2007 Block load primary, user privilege */ case 0x17: /* UA2007 Block load secondary, user privilege */ case 0x1e: /* UA2007 Block load primary LE, user privilege */ @@ -2080,13 +2078,11 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd) return; } helper_check_align(addr, 0x3f); - for (i = 0; i < 16; i++) { - *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x19, 4, - 0); - addr += 4; + for (i = 0; i < 8; i++, rd += 2, addr += 4) { + env->fpr[rd/2].ll = helper_ld_asi(addr, asi & 0x19, 8, 0); } - return; + default: break; } @@ -2094,20 +2090,19 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd) switch (size) { default: case 4: - *((uint32_t *)&env->fpr[rd]) = helper_ld_asi(addr, asi, size, 0); + val = helper_ld_asi(addr, asi, size, 0); + if (rd & 1) { + env->fpr[rd/2].l.lower = val; + } else { + env->fpr[rd/2].l.upper = val; + } break; case 8: - u.ll = helper_ld_asi(addr, asi, size, 0); - *((uint32_t *)&env->fpr[rd++]) = u.l.upper; - *((uint32_t *)&env->fpr[rd++]) = u.l.lower; + env->fpr[rd/2].ll = helper_ld_asi(addr, asi, size, 0); break; case 16: - u.ll = helper_ld_asi(addr, asi, 8, 0); - *((uint32_t *)&env->fpr[rd++]) = u.l.upper; - *((uint32_t *)&env->fpr[rd++]) = u.l.lower; - u.ll = helper_ld_asi(addr + 8, asi, 8, 0); - *((uint32_t *)&env->fpr[rd++]) = u.l.upper; - *((uint32_t *)&env->fpr[rd++]) = u.l.lower; + env->fpr[rd/2].ll = helper_ld_asi(addr, asi, 8, 0); + env->fpr[rd/2 + 1].ll = helper_ld_asi(addr + 8, asi, 8, 0); break; } } @@ -2115,8 +2110,7 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd) void helper_stf_asi(target_ulong addr, int asi, int size, int rd) { unsigned int i; - target_ulong val = 0; - CPU_DoubleU u; + target_ulong val; helper_check_align(addr, 3); addr = asi_address_mask(env, asi, addr); @@ -2133,10 +2127,8 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd) return; } helper_check_align(addr, 0x3f); - for (i = 0; i < 16; i++) { - val = *(uint32_t *)&env->fpr[rd++]; - helper_st_asi(addr, val, asi & 0x8f, 4); - addr += 4; + for (i = 0; i < 8; i++, rd += 2, addr += 8) { + helper_st_asi(addr, env->fpr[rd/2].ll, asi & 0x8f, 8); } return; @@ -2153,10 +2145,8 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd) return; } helper_check_align(addr, 0x3f); - for (i = 0; i < 16; i++) { - val = *(uint32_t *)&env->fpr[rd++]; - helper_st_asi(addr, val, asi & 0x19, 4); - addr += 4; + for (i = 0; i < 8; i++, rd += 2, addr += 8) { + helper_st_asi(addr, env->fpr[rd/2].ll, asi & 0x19, 8); } return; @@ -2167,20 +2157,19 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd) switch (size) { default: case 4: - helper_st_asi(addr, *(uint32_t *)&env->fpr[rd], asi, size); + if (rd & 1) { + val = env->fpr[rd/2].l.lower; + } else { + val = env->fpr[rd/2].l.upper; + } + helper_st_asi(addr, val, asi, size); break; case 8: - u.l.upper = *(uint32_t *)&env->fpr[rd++]; - u.l.lower = *(uint32_t *)&env->fpr[rd++]; - helper_st_asi(addr, u.ll, asi, size); + helper_st_asi(addr, env->fpr[rd/2].ll, asi, size); break; case 16: - u.l.upper = *(uint32_t *)&env->fpr[rd++]; - u.l.lower = *(uint32_t *)&env->fpr[rd++]; - helper_st_asi(addr, u.ll, asi, 8); - u.l.upper = *(uint32_t *)&env->fpr[rd++]; - u.l.lower = *(uint32_t *)&env->fpr[rd++]; - helper_st_asi(addr + 8, u.ll, asi, 8); + helper_st_asi(addr, env->fpr[rd/2].ll, asi, 8); + helper_st_asi(addr + 8, env->fpr[rd/2 + 1].ll, asi, 8); break; } } |