Skip to content

Commit

Permalink
target-sparc: Change fpr representation to doubles.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
rth7680 committed Oct 26, 2011
1 parent 45c7b74 commit 30038fd
Show file tree
Hide file tree
Showing 8 changed files with 202 additions and 211 deletions.
35 changes: 24 additions & 11 deletions gdbstub.c
Expand Up @@ -814,7 +814,11 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
#if defined(TARGET_ABI32) || !defined(TARGET_SPARC64)
if (n < 64) {
/* fprs */
GET_REG32(*((uint32_t *)&env->fpr[n - 32]));
if (n & 1) {
GET_REG32(env->fpr[(n - 32) / 2].l.lower);
} else {
GET_REG32(env->fpr[(n - 32) / 2].l.upper);
}
}
/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
switch (n) {
Expand All @@ -831,15 +835,15 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
#else
if (n < 64) {
/* f0-f31 */
GET_REG32(*((uint32_t *)&env->fpr[n - 32]));
if (n & 1) {
GET_REG32(env->fpr[(n - 32) / 2].l.lower);
} else {
GET_REG32(env->fpr[(n - 32) / 2].l.upper);
}
}
if (n < 80) {
/* f32-f62 (double width, even numbers only) */
uint64_t val;

val = (uint64_t)*((uint32_t *)&env->fpr[(n - 64) * 2 + 32]) << 32;
val |= *((uint32_t *)&env->fpr[(n - 64) * 2 + 33]);
GET_REG64(val);
GET_REG64(env->fpr[(n - 32) / 2].ll);
}
switch (n) {
case 80: GET_REGL(env->pc);
Expand Down Expand Up @@ -878,7 +882,12 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
#if defined(TARGET_ABI32) || !defined(TARGET_SPARC64)
else if (n < 64) {
/* fprs */
*((uint32_t *)&env->fpr[n - 32]) = tmp;
/* f0-f31 */
if (n & 1) {
env->fpr[(n - 32) / 2].l.lower = tmp;
} else {
env->fpr[(n - 32) / 2].l.upper = tmp;
}
} else {
/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
switch (n) {
Expand All @@ -896,12 +905,16 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
#else
else if (n < 64) {
/* f0-f31 */
env->fpr[n] = ldfl_p(mem_buf);
tmp = ldl_p(mem_buf);
if (n & 1) {
env->fpr[(n - 32) / 2].l.lower = tmp;
} else {
env->fpr[(n - 32) / 2].l.upper = tmp;
}
return 4;
} else if (n < 80) {
/* f32-f62 (double width, even numbers only) */
*((uint32_t *)&env->fpr[(n - 64) * 2 + 32]) = tmp >> 32;
*((uint32_t *)&env->fpr[(n - 64) * 2 + 33]) = tmp;
env->fpr[(n - 32) / 2].ll = tmp;
} else {
switch (n) {
case 80: env->pc = tmp; break;
Expand Down
28 changes: 16 additions & 12 deletions linux-user/signal.c
Expand Up @@ -2296,12 +2296,14 @@ void sparc64_set_context(CPUSPARCState *env)
*/
err |= __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
{
uint32_t *src, *dst;
src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
dst = env->fpr;
/* XXX: check that the CPU storage is the same as user context */
for (i = 0; i < 64; i++, dst++, src++)
err |= __get_user(*dst, src);
uint32_t *src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
for (i = 0; i < 64; i++, src++) {
if (i & 1) {
err |= __get_user(env->fpr[i/2].l.lower, src);
} else {
err |= __get_user(env->fpr[i/2].l.upper, src);
}
}
}
err |= __get_user(env->fsr,
&(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr));
Expand Down Expand Up @@ -2390,12 +2392,14 @@ void sparc64_get_context(CPUSPARCState *env)
err |= __put_user(i7, &(mcp->mc_i7));

{
uint32_t *src, *dst;
src = env->fpr;
dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
/* XXX: check that the CPU storage is the same as user context */
for (i = 0; i < 64; i++, dst++, src++)
err |= __put_user(*src, dst);
uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
for (i = 0; i < 64; i++, dst++) {
if (i & 1) {
err |= __put_user(env->fpr[i/2].l.lower, dst);
} else {
err |= __put_user(env->fpr[i/2].l.upper, dst);
}
}
}
err |= __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
err |= __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
Expand Down
96 changes: 48 additions & 48 deletions monitor.c
Expand Up @@ -3471,55 +3471,55 @@ static const MonitorDef monitor_defs[] = {
#endif
{ "tbr", offsetof(CPUState, tbr) },
{ "fsr", offsetof(CPUState, fsr) },
{ "f0", offsetof(CPUState, fpr[0]) },
{ "f1", offsetof(CPUState, fpr[1]) },
{ "f2", offsetof(CPUState, fpr[2]) },
{ "f3", offsetof(CPUState, fpr[3]) },
{ "f4", offsetof(CPUState, fpr[4]) },
{ "f5", offsetof(CPUState, fpr[5]) },
{ "f6", offsetof(CPUState, fpr[6]) },
{ "f7", offsetof(CPUState, fpr[7]) },
{ "f8", offsetof(CPUState, fpr[8]) },
{ "f9", offsetof(CPUState, fpr[9]) },
{ "f10", offsetof(CPUState, fpr[10]) },
{ "f11", offsetof(CPUState, fpr[11]) },
{ "f12", offsetof(CPUState, fpr[12]) },
{ "f13", offsetof(CPUState, fpr[13]) },
{ "f14", offsetof(CPUState, fpr[14]) },
{ "f15", offsetof(CPUState, fpr[15]) },
{ "f16", offsetof(CPUState, fpr[16]) },
{ "f17", offsetof(CPUState, fpr[17]) },
{ "f18", offsetof(CPUState, fpr[18]) },
{ "f19", offsetof(CPUState, fpr[19]) },
{ "f20", offsetof(CPUState, fpr[20]) },
{ "f21", offsetof(CPUState, fpr[21]) },
{ "f22", offsetof(CPUState, fpr[22]) },
{ "f23", offsetof(CPUState, fpr[23]) },
{ "f24", offsetof(CPUState, fpr[24]) },
{ "f25", offsetof(CPUState, fpr[25]) },
{ "f26", offsetof(CPUState, fpr[26]) },
{ "f27", offsetof(CPUState, fpr[27]) },
{ "f28", offsetof(CPUState, fpr[28]) },
{ "f29", offsetof(CPUState, fpr[29]) },
{ "f30", offsetof(CPUState, fpr[30]) },
{ "f31", offsetof(CPUState, fpr[31]) },
{ "f0", offsetof(CPUState, fpr[0].l.upper) },
{ "f1", offsetof(CPUState, fpr[0].l.lower) },
{ "f2", offsetof(CPUState, fpr[1].l.upper) },
{ "f3", offsetof(CPUState, fpr[1].l.lower) },
{ "f4", offsetof(CPUState, fpr[2].l.upper) },
{ "f5", offsetof(CPUState, fpr[2].l.lower) },
{ "f6", offsetof(CPUState, fpr[3].l.upper) },
{ "f7", offsetof(CPUState, fpr[3].l.lower) },
{ "f8", offsetof(CPUState, fpr[4].l.upper) },
{ "f9", offsetof(CPUState, fpr[4].l.lower) },
{ "f10", offsetof(CPUState, fpr[5].l.upper) },
{ "f11", offsetof(CPUState, fpr[5].l.lower) },
{ "f12", offsetof(CPUState, fpr[6].l.upper) },
{ "f13", offsetof(CPUState, fpr[6].l.lower) },
{ "f14", offsetof(CPUState, fpr[7].l.upper) },
{ "f15", offsetof(CPUState, fpr[7].l.lower) },
{ "f16", offsetof(CPUState, fpr[8].l.upper) },
{ "f17", offsetof(CPUState, fpr[8].l.lower) },
{ "f18", offsetof(CPUState, fpr[9].l.upper) },
{ "f19", offsetof(CPUState, fpr[9].l.lower) },
{ "f20", offsetof(CPUState, fpr[10].l.upper) },
{ "f21", offsetof(CPUState, fpr[10].l.lower) },
{ "f22", offsetof(CPUState, fpr[11].l.upper) },
{ "f23", offsetof(CPUState, fpr[11].l.lower) },
{ "f24", offsetof(CPUState, fpr[12].l.upper) },
{ "f25", offsetof(CPUState, fpr[12].l.lower) },
{ "f26", offsetof(CPUState, fpr[13].l.upper) },
{ "f27", offsetof(CPUState, fpr[13].l.lower) },
{ "f28", offsetof(CPUState, fpr[14].l.upper) },
{ "f29", offsetof(CPUState, fpr[14].l.lower) },
{ "f30", offsetof(CPUState, fpr[15].l.upper) },
{ "f31", offsetof(CPUState, fpr[15].l.lower) },
#ifdef TARGET_SPARC64
{ "f32", offsetof(CPUState, fpr[32]) },
{ "f34", offsetof(CPUState, fpr[34]) },
{ "f36", offsetof(CPUState, fpr[36]) },
{ "f38", offsetof(CPUState, fpr[38]) },
{ "f40", offsetof(CPUState, fpr[40]) },
{ "f42", offsetof(CPUState, fpr[42]) },
{ "f44", offsetof(CPUState, fpr[44]) },
{ "f46", offsetof(CPUState, fpr[46]) },
{ "f48", offsetof(CPUState, fpr[48]) },
{ "f50", offsetof(CPUState, fpr[50]) },
{ "f52", offsetof(CPUState, fpr[52]) },
{ "f54", offsetof(CPUState, fpr[54]) },
{ "f56", offsetof(CPUState, fpr[56]) },
{ "f58", offsetof(CPUState, fpr[58]) },
{ "f60", offsetof(CPUState, fpr[60]) },
{ "f62", offsetof(CPUState, fpr[62]) },
{ "f32", offsetof(CPUState, fpr[16]) },
{ "f34", offsetof(CPUState, fpr[17]) },
{ "f36", offsetof(CPUState, fpr[18]) },
{ "f38", offsetof(CPUState, fpr[19]) },
{ "f40", offsetof(CPUState, fpr[20]) },
{ "f42", offsetof(CPUState, fpr[21]) },
{ "f44", offsetof(CPUState, fpr[22]) },
{ "f46", offsetof(CPUState, fpr[23]) },
{ "f48", offsetof(CPUState, fpr[24]) },
{ "f50", offsetof(CPUState, fpr[25]) },
{ "f52", offsetof(CPUState, fpr[26]) },
{ "f54", offsetof(CPUState, fpr[27]) },
{ "f56", offsetof(CPUState, fpr[28]) },
{ "f58", offsetof(CPUState, fpr[29]) },
{ "f60", offsetof(CPUState, fpr[30]) },
{ "f62", offsetof(CPUState, fpr[31]) },
{ "asi", offsetof(CPUState, asi) },
{ "pstate", offsetof(CPUState, pstate) },
{ "cansave", offsetof(CPUState, cansave) },
Expand Down
7 changes: 4 additions & 3 deletions target-sparc/cpu.h
Expand Up @@ -3,16 +3,17 @@

#include "config.h"
#include "qemu-common.h"
#include "bswap.h"

#if !defined(TARGET_SPARC64)
#define TARGET_LONG_BITS 32
#define TARGET_FPREGS 32
#define TARGET_DPREGS 16
#define TARGET_PAGE_BITS 12 /* 4k */
#define TARGET_PHYS_ADDR_SPACE_BITS 36
#define TARGET_VIRT_ADDR_SPACE_BITS 32
#else
#define TARGET_LONG_BITS 64
#define TARGET_FPREGS 64
#define TARGET_DPREGS 32
#define TARGET_PAGE_BITS 13 /* 8k */
#define TARGET_PHYS_ADDR_SPACE_BITS 41
# ifdef TARGET_ABI32
Expand Down Expand Up @@ -395,7 +396,7 @@ typedef struct CPUSPARCState {

uint32_t psr; /* processor state register */
target_ulong fsr; /* FPU state register */
float32 fpr[TARGET_FPREGS]; /* floating point registers */
CPU_DoubleU fpr[TARGET_DPREGS]; /* floating point registers */
uint32_t cwp; /* index of current register window (extracted
from PSR) */
#if !defined(TARGET_SPARC64) || defined(TARGET_ABI32)
Expand Down
6 changes: 3 additions & 3 deletions target-sparc/cpu_init.c
Expand Up @@ -813,11 +813,11 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
}
}
cpu_fprintf(f, "\nFloating Point Registers:\n");
for (i = 0; i < TARGET_FPREGS; i++) {
for (i = 0; i < TARGET_DPREGS; i++) {
if ((i & 3) == 0) {
cpu_fprintf(f, "%%f%02d:", i);
cpu_fprintf(f, "%%f%02d:", i * 2);
}
cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
if ((i & 3) == 3) {
cpu_fprintf(f, "\n");
}
Expand Down
71 changes: 30 additions & 41 deletions target-sparc/ldst_helper.c
Expand Up @@ -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);
Expand All @@ -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 */
Expand All @@ -2080,43 +2078,39 @@ 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;
}

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;
}
}

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);
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
}
}
Expand Down

0 comments on commit 30038fd

Please sign in to comment.