Patchwork [09/21] target-sparc: Change fpr representation to doubles.

login
register
mail settings
Submitter Richard Henderson
Date Oct. 18, 2011, 6:50 p.m.
Message ID <1318963843-25100-10-git-send-email-rth@twiddle.net>
Download mbox | patch
Permalink /patch/120488/
State New
Headers show

Comments

Richard Henderson - Oct. 18, 2011, 6:50 p.m.
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>
---
 gdbstub.c                  |   35 +++++++---
 linux-user/signal.c        |   28 +++++----
 monitor.c                  |   96 ++++++++++++++--------------
 target-sparc/cpu.h         |    7 +-
 target-sparc/cpu_init.c    |    6 +-
 target-sparc/ldst_helper.c |   71 +++++++++------------
 target-sparc/machine.c     |   20 ++----
 target-sparc/translate.c   |  146 ++++++++++++++++++++-----------------------
 8 files changed, 199 insertions(+), 210 deletions(-)
Blue Swirl - Oct. 18, 2011, 8:28 p.m.
On Tue, Oct 18, 2011 at 6:50 PM, Richard Henderson <rth@twiddle.net> wrote:
> 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>
> ---
>  gdbstub.c                  |   35 +++++++---
>  linux-user/signal.c        |   28 +++++----
>  monitor.c                  |   96 ++++++++++++++--------------
>  target-sparc/cpu.h         |    7 +-
>  target-sparc/cpu_init.c    |    6 +-
>  target-sparc/ldst_helper.c |   71 +++++++++------------
>  target-sparc/machine.c     |   20 ++----
>  target-sparc/translate.c   |  146 ++++++++++++++++++++-----------------------
>  8 files changed, 199 insertions(+), 210 deletions(-)
>
> diff --git a/gdbstub.c b/gdbstub.c
> index 1d99e19..6c18634 100644
> --- a/gdbstub.c
> +++ b/gdbstub.c
> @@ -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) {
> @@ -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);
> @@ -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) {
> @@ -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;
> diff --git a/linux-user/signal.c b/linux-user/signal.c
> index 89276eb..d68dc94 100644
> --- a/linux-user/signal.c
> +++ b/linux-user/signal.c
> @@ -2299,12 +2299,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));
> @@ -2393,12 +2395,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));
> diff --git a/monitor.c b/monitor.c
> index da13471..02d7e2e 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -3657,55 +3657,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) },
> diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
> index a4419a5..71a890c 100644
> --- a/target-sparc/cpu.h
> +++ b/target-sparc/cpu.h
> @@ -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
> @@ -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)
> diff --git a/target-sparc/cpu_init.c b/target-sparc/cpu_init.c
> index 08b72a9..1118f31 100644
> --- a/target-sparc/cpu_init.c
> +++ b/target-sparc/cpu_init.c
> @@ -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");
>         }
> diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c
> index ec9b5f2..a4254e7 100644
> --- a/target-sparc/ldst_helper.c
> +++ b/target-sparc/ldst_helper.c
> @@ -2057,7 +2057,7 @@ void helper_ldf_asi(CPUState *env, target_ulong addr, int asi, int size,
>                     int rd)
>  {
>     unsigned int i;
> -    CPU_DoubleU u;
> +    target_ulong val;
>
>     helper_check_align(env, addr, 3);
>     addr = asi_address_mask(env, asi, addr);
> @@ -2072,13 +2072,11 @@ void helper_ldf_asi(CPUState *env, target_ulong addr, int asi, int size,
>             return;
>         }
>         helper_check_align(env, addr, 0x3f);
> -        for (i = 0; i < 16; i++) {
> -            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(env, 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(env, 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 */
> @@ -2092,13 +2090,11 @@ void helper_ldf_asi(CPUState *env, target_ulong addr, int asi, int size,
>             return;
>         }
>         helper_check_align(env, addr, 0x3f);
> -        for (i = 0; i < 16; i++) {
> -            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(env, 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(env, addr, asi & 0x19, 8, 0);
>         }
> -
>         return;
> +
>     default:
>         break;
>     }
> @@ -2106,20 +2102,19 @@ void helper_ldf_asi(CPUState *env, target_ulong addr, int asi, int size,
>     switch (size) {
>     default:
>     case 4:
> -        *((uint32_t *)&env->fpr[rd]) = helper_ld_asi(env, addr, asi, size, 0);
> +        val = helper_ld_asi(env, 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(env, 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(env, addr, asi, size, 0);
>         break;
>     case 16:
> -        u.ll = helper_ld_asi(env, 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(env, 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(env, addr, asi, 8, 0);
> +        env->fpr[rd/2 + 1].ll = helper_ld_asi(env, addr + 8, asi, 8, 0);
>         break;
>     }
>  }
> @@ -2128,8 +2123,7 @@ void helper_stf_asi(CPUState *env, 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(env, addr, 3);
>     addr = asi_address_mask(env, asi, addr);
> @@ -2146,10 +2140,8 @@ void helper_stf_asi(CPUState *env, target_ulong addr, int asi, int size,
>             return;
>         }
>         helper_check_align(env, addr, 0x3f);
> -        for (i = 0; i < 16; i++) {
> -            val = *(uint32_t *)&env->fpr[rd++];
> -            helper_st_asi(env, addr, val, asi & 0x8f, 4);
> -            addr += 4;
> +        for (i = 0; i < 8; i++, rd += 2, addr += 8) {
> +            helper_st_asi(env, addr, env->fpr[rd/2].ll, asi & 0x8f, 8);
>         }
>
>         return;
> @@ -2166,10 +2158,8 @@ void helper_stf_asi(CPUState *env, target_ulong addr, int asi, int size,
>             return;
>         }
>         helper_check_align(env, addr, 0x3f);
> -        for (i = 0; i < 16; i++) {
> -            val = *(uint32_t *)&env->fpr[rd++];
> -            helper_st_asi(env, addr, val, asi & 0x19, 4);
> -            addr += 4;
> +        for (i = 0; i < 8; i++, rd += 2, addr += 8) {
> +            helper_st_asi(env, addr, env->fpr[rd/2].ll, asi & 0x19, 8);
>         }
>
>         return;
> @@ -2180,20 +2170,19 @@ void helper_stf_asi(CPUState *env, target_ulong addr, int asi, int size,
>     switch (size) {
>     default:
>     case 4:
> -        helper_st_asi(env, 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(env, 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(env, addr, u.ll, asi, size);
> +        helper_st_asi(env, 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(env, addr, u.ll, asi, 8);
> -        u.l.upper = *(uint32_t *)&env->fpr[rd++];
> -        u.l.lower = *(uint32_t *)&env->fpr[rd++];
> -        helper_st_asi(env, addr + 8, u.ll, asi, 8);
> +        helper_st_asi(env, addr, env->fpr[rd/2].ll, asi, 8);
> +        helper_st_asi(env, addr + 8, env->fpr[rd/2 + 1].ll, asi, 8);
>         break;
>     }
>  }
> diff --git a/target-sparc/machine.c b/target-sparc/machine.c
> index 56ae041..235b088 100644
> --- a/target-sparc/machine.c
> +++ b/target-sparc/machine.c
> @@ -21,13 +21,9 @@ void cpu_save(QEMUFile *f, void *opaque)
>         qemu_put_betls(f, &env->regbase[i]);
>
>     /* FPU */
> -    for(i = 0; i < TARGET_FPREGS; i++) {
> -        union {
> -            float32 f;
> -            uint32_t i;
> -        } u;
> -        u.f = env->fpr[i];
> -        qemu_put_be32(f, u.i);
> +    for (i = 0; i < TARGET_DPREGS; i++) {
> +        qemu_put_be32(f, env->fpr[i].l.upper);
> +        qemu_put_be32(f, env->fpr[i].l.lower);
>     }
>
>     qemu_put_betls(f, &env->pc);
> @@ -128,13 +124,9 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
>         qemu_get_betls(f, &env->regbase[i]);
>
>     /* FPU */
> -    for(i = 0; i < TARGET_FPREGS; i++) {
> -        union {
> -            float32 f;
> -            uint32_t i;
> -        } u;
> -        u.i = qemu_get_be32(f);
> -        env->fpr[i] = u.f;
> +    for (i = 0; i < TARGET_DPREGS; i++) {
> +        env->fpr[i].l.upper = qemu_get_be32(f);
> +        env->fpr[i].l.lower = qemu_get_be32(f);
>     }
>
>     qemu_get_betls(f, &env->pc);
> diff --git a/target-sparc/translate.c b/target-sparc/translate.c
> index f8d3bf2..97a462b 100644
> --- a/target-sparc/translate.c
> +++ b/target-sparc/translate.c
> @@ -68,7 +68,7 @@ static TCGv cpu_tmp0;
>  static TCGv_i32 cpu_tmp32;
>  static TCGv_i64 cpu_tmp64;
>  /* Floating point registers */
> -static TCGv_i32 cpu_fpr[TARGET_FPREGS];
> +static TCGv_i64 cpu_fpr[TARGET_DPREGS];
>
>  static target_ulong gen_opc_npc[OPC_BUF_SIZE];
>  static target_ulong gen_opc_jump_pc[2];
> @@ -87,8 +87,8 @@ typedef struct DisasContext {
>     uint32_t cc_op;  /* current CC operation */
>     struct TranslationBlock *tb;
>     sparc_def_t *def;
> -    TCGv_i64 t64[3];
> -    int n_t64;
> +    TCGv_i32 t32[3];
> +    int n_t32;
>  } DisasContext;
>
>  // This function uses non-native bit order
> @@ -131,12 +131,44 @@ static inline void gen_update_fprs_dirty(int rd)
>  /* floating point registers moves */
>  static TCGv_i32 gen_load_fpr_F(DisasContext *dc, unsigned int src)
>  {
> -    return cpu_fpr[src];
> +#if TCG_TARGET_REG_BITS == 32
> +    if (src & 1) {
> +        return TCGV_LOW(cpu_fpr[src / 2]);
> +    } else {
> +        return TCGV_HIGH(cpu_fpr[src / 2]);
> +    }
> +#else
> +    if (src & 1) {
> +        return MAKE_TCGV_I32(GET_TCGV_I64(cpu_fpr[src / 2]));
> +    } else {
> +        TCGv_i32 ret = tcg_temp_local_new_i32();
> +        TCGv_i64 t = tcg_temp_new_i64();
> +
> +        tcg_gen_shri_i64(t, cpu_fpr[src / 2], 32);
> +        tcg_gen_trunc_i64_i32(ret, t);
> +        tcg_temp_free_i64(t);
> +
> +        dc->t32[dc->n_t32++] = ret;
> +        assert(dc->n_t32 <= ARRAY_SIZE(dc->t32));
> +
> +        return ret;
> +    }
> +#endif
>  }
>
>  static void gen_store_fpr_F(DisasContext *dc, unsigned int dst, TCGv_i32 v)
>  {
> -    tcg_gen_mov_i32(cpu_fpr[dst], v);
> +#if TCG_TARGET_REG_BITS == 32
> +    if (dst & 1) {
> +        tcg_gen_mov_i32(TCGV_LOW(cpu_fpr[dst / 2]), v);
> +    } else {
> +        tcg_gen_mov_i32(TCGV_HIGH(cpu_fpr[dst / 2]), v);
> +    }
> +#else
> +    TCGv_i64 t = MAKE_TCGV_I64(GET_TCGV_I32(v));
> +    tcg_gen_deposit_i64(cpu_fpr[dst / 2], cpu_fpr[dst / 2], t,
> +                        (dst & 1 ? 0 : 32), 32);
> +#endif
>     gen_update_fprs_dirty(dst);
>  }
>
> @@ -147,42 +179,14 @@ static TCGv_i32 gen_dest_fpr_F(void)
>
>  static TCGv_i64 gen_load_fpr_D(DisasContext *dc, unsigned int src)
>  {
> -    TCGv_i64 ret = tcg_temp_new_i64();
>     src = DFPREG(src);
> -
> -#if TCG_TARGET_REG_BITS == 32
> -    tcg_gen_mov_i32(TCGV_HIGH(ret), cpu_fpr[src]);
> -    tcg_gen_mov_i32(TCGV_LOW(ret), cpu_fpr[src + 1]);
> -#else
> -    {
> -        TCGv_i64 t = tcg_temp_new_i64();
> -        tcg_gen_extu_i32_i64(ret, cpu_fpr[src]);
> -        tcg_gen_extu_i32_i64(t, cpu_fpr[src + 1]);
> -        tcg_gen_shli_i64(ret, ret, 32);
> -        tcg_gen_or_i64(ret, ret, t);
> -        tcg_temp_free_i64(t);
> -    }
> -#endif
> -
> -    dc->t64[dc->n_t64++] = ret;
> -    assert(dc->n_t64 <= ARRAY_SIZE(dc->t64));
> -
> -    return ret;
> +    return cpu_fpr[src / 2];
>  }
>
>  static void gen_store_fpr_D(DisasContext *dc, unsigned int dst, TCGv_i64 v)
>  {
>     dst = DFPREG(dst);
> -
> -#if TCG_TARGET_REG_BITS == 32
> -    tcg_gen_mov_i32(cpu__fpu[dst], TCGV_HIGH(v));
> -    tcg_gen_mov_i32(cpu__fpu[dst + 1], TCGV_LOW(v));
> -#else
> -    tcg_gen_trunc_i64_i32(cpu_fpr[dst + 1], v);
> -    tcg_gen_shri_i64(v, v, 32);
> -    tcg_gen_trunc_i64_i32(cpu_fpr[dst], v);
> -#endif
> -
> +    tcg_gen_mov_i64(cpu_fpr[dst / 2], v);
>     gen_update_fprs_dirty(dst);
>  }
>
> @@ -193,50 +197,36 @@ static TCGv_i64 gen_dest_fpr_D(void)
>
>  static void gen_op_load_fpr_QT0(unsigned int src)
>  {
> -    tcg_gen_st_i32(cpu_fpr[src], cpu_env, offsetof(CPUSPARCState, qt0) +
> -                   offsetof(CPU_QuadU, l.upmost));
> -    tcg_gen_st_i32(cpu_fpr[src + 1], cpu_env, offsetof(CPUSPARCState, qt0) +
> -                   offsetof(CPU_QuadU, l.upper));
> -    tcg_gen_st_i32(cpu_fpr[src + 2], cpu_env, offsetof(CPUSPARCState, qt0) +
> -                   offsetof(CPU_QuadU, l.lower));
> -    tcg_gen_st_i32(cpu_fpr[src + 3], cpu_env, offsetof(CPUSPARCState, qt0) +
> -                   offsetof(CPU_QuadU, l.lowest));
> +    tcg_gen_st_i64(cpu_fpr[src / 2], cpu_env, offsetof(CPUSPARCState, qt0) +
> +                   offsetof(CPU_QuadU, ll.upper));
> +    tcg_gen_st_i64(cpu_fpr[src/2 + 1], cpu_env, offsetof(CPUSPARCState, qt0) +
> +                   offsetof(CPU_QuadU, ll.lower));
>  }
>
>  static void gen_op_load_fpr_QT1(unsigned int src)
>  {
> -    tcg_gen_st_i32(cpu_fpr[src], cpu_env, offsetof(CPUSPARCState, qt1) +
> -                   offsetof(CPU_QuadU, l.upmost));
> -    tcg_gen_st_i32(cpu_fpr[src + 1], cpu_env, offsetof(CPUSPARCState, qt1) +
> -                   offsetof(CPU_QuadU, l.upper));
> -    tcg_gen_st_i32(cpu_fpr[src + 2], cpu_env, offsetof(CPUSPARCState, qt1) +
> -                   offsetof(CPU_QuadU, l.lower));
> -    tcg_gen_st_i32(cpu_fpr[src + 3], cpu_env, offsetof(CPUSPARCState, qt1) +
> -                   offsetof(CPU_QuadU, l.lowest));
> +    tcg_gen_st_i64(cpu_fpr[src / 2], cpu_env, offsetof(CPUSPARCState, qt1) +
> +                   offsetof(CPU_QuadU, ll.upper));
> +    tcg_gen_st_i64(cpu_fpr[src/2 + 1], cpu_env, offsetof(CPUSPARCState, qt1) +
> +                   offsetof(CPU_QuadU, ll.lower));
>  }
>
>  static void gen_op_store_QT0_fpr(unsigned int dst)
>  {
> -    tcg_gen_ld_i32(cpu_fpr[dst], cpu_env, offsetof(CPUSPARCState, qt0) +
> -                   offsetof(CPU_QuadU, l.upmost));
> -    tcg_gen_ld_i32(cpu_fpr[dst + 1], cpu_env, offsetof(CPUSPARCState, qt0) +
> -                   offsetof(CPU_QuadU, l.upper));
> -    tcg_gen_ld_i32(cpu_fpr[dst + 2], cpu_env, offsetof(CPUSPARCState, qt0) +
> -                   offsetof(CPU_QuadU, l.lower));
> -    tcg_gen_ld_i32(cpu_fpr[dst + 3], cpu_env, offsetof(CPUSPARCState, qt0) +
> -                   offsetof(CPU_QuadU, l.lowest));
> +    tcg_gen_ld_i64(cpu_fpr[dst / 2], cpu_env, offsetof(CPUSPARCState, qt0) +
> +                   offsetof(CPU_QuadU, ll.upper));
> +    tcg_gen_ld_i64(cpu_fpr[dst/2 + 1], cpu_env, offsetof(CPUSPARCState, qt0) +
> +                   offsetof(CPU_QuadU, ll.lower));
>  }
>
>  #ifdef TARGET_SPARC64
> -static void gen_move_Q(int rd, int rs)
> +static void gen_move_Q(unsigned int rd, unsigned int rs)
>  {
>     rd = QFPREG(rd);
>     rs = QFPREG(rs);
>
> -    tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs]);
> -    tcg_gen_mov_i32(cpu_fpr[rd + 1], cpu_fpr[rs + 1]);
> -    tcg_gen_mov_i32(cpu_fpr[rd + 2], cpu_fpr[rs + 2]);
> -    tcg_gen_mov_i32(cpu_fpr[rd + 3], cpu_fpr[rs + 3]);
> +    tcg_gen_mov_i64(cpu_fpr[rd / 2], cpu_fpr[rs / 2]);
> +    tcg_gen_mov_i64(cpu_fpr[rd / 2 + 1], cpu_fpr[rs / 2 + 1]);
>     gen_update_fprs_dirty(rd);
>  }
>  #endif
> @@ -5008,6 +4998,13 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
>  egress:
>     tcg_temp_free(cpu_tmp1);
>     tcg_temp_free(cpu_tmp2);
> +    if (dc->n_t32 != 0) {
> +        int i;
> +        for (i = dc->n_t32 - 1; i >= 0; --i) {
> +            tcg_temp_free_i32(dc->t32[i]);
> +        }
> +        dc->n_t32 = 0;
> +    }
>  }
>
>  static inline void gen_intermediate_code_internal(TranslationBlock * tb,
> @@ -5109,9 +5106,6 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
>     tcg_temp_free_i64(cpu_tmp64);
>     tcg_temp_free_i32(cpu_tmp32);
>     tcg_temp_free(cpu_tmp0);
> -    for (j = dc->n_t64 - 1; j >= 0; --j) {
> -        tcg_temp_free_i64(dc->t64[j]);
> -    }
>
>     if (tb->cflags & CF_LAST_IO)
>         gen_io_end();
> @@ -5177,15 +5171,11 @@ void gen_intermediate_code_init(CPUSPARCState *env)
>         "g6",
>         "g7",
>     };
> -    static const char * const fregnames[64] = {
> -        "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
> -        "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
> -        "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
> -        "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
> -        "f32", "f33", "f34", "f35", "f36", "f37", "f38", "f39",
> -        "f40", "f41", "f42", "f43", "f44", "f45", "f46", "f47",
> -        "f48", "f49", "f50", "f51", "f52", "f53", "f54", "f55",
> -        "f56", "f57", "f58", "f59", "f60", "f61", "f62", "f63",
> +    static const char * const fregnames[32] = {
> +        "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14",
> +        "f16", "f18", "f20", "f22", "f24", "f26", "f28", "f30",
> +        "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",
> +        "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",

Shouldn't these become "d0" etc?

>     };
>
>     /* init various static tables */
> @@ -5259,8 +5249,8 @@ void gen_intermediate_code_init(CPUSPARCState *env)
>             cpu_gregs[i] = tcg_global_mem_new(TCG_AREG0,
>                                               offsetof(CPUState, gregs[i]),
>                                               gregnames[i]);
> -        for (i = 0; i < TARGET_FPREGS; i++)
> -            cpu_fpr[i] = tcg_global_mem_new_i32(TCG_AREG0,
> +        for (i = 0; i < TARGET_DPREGS; i++)

Please add braces.

> +            cpu_fpr[i] = tcg_global_mem_new_i64(TCG_AREG0,
>                                                 offsetof(CPUState, fpr[i]),
>                                                 fregnames[i]);
>
> --
> 1.7.6.4
>
>
Richard Henderson - Oct. 18, 2011, 10:25 p.m.
On 10/18/2011 01:28 PM, Blue Swirl wrote:
>> > +    static const char * const fregnames[32] = {
>> > +        "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14",
>> > +        "f16", "f18", "f20", "f22", "f24", "f26", "f28", "f30",
>> > +        "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",
>> > +        "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",
> Shouldn't these become "d0" etc?
> 

That's what I had at first, but then after looking at the dumps for
a few additional patches went back and changed it.  My feeling is
that these should match the disassembler, and it always uses f%d.

>> -        for (i = 0; i < TARGET_FPREGS; i++)
>> -            cpu_fpr[i] = tcg_global_mem_new_i32(TCG_AREG0,
>> +        for (i = 0; i < TARGET_DPREGS; i++)
> Please add braces.
> 

Sure.


r~

Patch

diff --git a/gdbstub.c b/gdbstub.c
index 1d99e19..6c18634 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -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) {
@@ -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);
@@ -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) {
@@ -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;
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 89276eb..d68dc94 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -2299,12 +2299,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));
@@ -2393,12 +2395,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));
diff --git a/monitor.c b/monitor.c
index da13471..02d7e2e 100644
--- a/monitor.c
+++ b/monitor.c
@@ -3657,55 +3657,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) },
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index a4419a5..71a890c 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -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
@@ -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)
diff --git a/target-sparc/cpu_init.c b/target-sparc/cpu_init.c
index 08b72a9..1118f31 100644
--- a/target-sparc/cpu_init.c
+++ b/target-sparc/cpu_init.c
@@ -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");
         }
diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c
index ec9b5f2..a4254e7 100644
--- a/target-sparc/ldst_helper.c
+++ b/target-sparc/ldst_helper.c
@@ -2057,7 +2057,7 @@  void helper_ldf_asi(CPUState *env, target_ulong addr, int asi, int size,
                     int rd)
 {
     unsigned int i;
-    CPU_DoubleU u;
+    target_ulong val;
 
     helper_check_align(env, addr, 3);
     addr = asi_address_mask(env, asi, addr);
@@ -2072,13 +2072,11 @@  void helper_ldf_asi(CPUState *env, target_ulong addr, int asi, int size,
             return;
         }
         helper_check_align(env, addr, 0x3f);
-        for (i = 0; i < 16; i++) {
-            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(env, 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(env, 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 */
@@ -2092,13 +2090,11 @@  void helper_ldf_asi(CPUState *env, target_ulong addr, int asi, int size,
             return;
         }
         helper_check_align(env, addr, 0x3f);
-        for (i = 0; i < 16; i++) {
-            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(env, 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(env, addr, asi & 0x19, 8, 0);
         }
-
         return;
+
     default:
         break;
     }
@@ -2106,20 +2102,19 @@  void helper_ldf_asi(CPUState *env, target_ulong addr, int asi, int size,
     switch (size) {
     default:
     case 4:
-        *((uint32_t *)&env->fpr[rd]) = helper_ld_asi(env, addr, asi, size, 0);
+        val = helper_ld_asi(env, 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(env, 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(env, addr, asi, size, 0);
         break;
     case 16:
-        u.ll = helper_ld_asi(env, 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(env, 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(env, addr, asi, 8, 0);
+        env->fpr[rd/2 + 1].ll = helper_ld_asi(env, addr + 8, asi, 8, 0);
         break;
     }
 }
@@ -2128,8 +2123,7 @@  void helper_stf_asi(CPUState *env, 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(env, addr, 3);
     addr = asi_address_mask(env, asi, addr);
@@ -2146,10 +2140,8 @@  void helper_stf_asi(CPUState *env, target_ulong addr, int asi, int size,
             return;
         }
         helper_check_align(env, addr, 0x3f);
-        for (i = 0; i < 16; i++) {
-            val = *(uint32_t *)&env->fpr[rd++];
-            helper_st_asi(env, addr, val, asi & 0x8f, 4);
-            addr += 4;
+        for (i = 0; i < 8; i++, rd += 2, addr += 8) {
+            helper_st_asi(env, addr, env->fpr[rd/2].ll, asi & 0x8f, 8);
         }
 
         return;
@@ -2166,10 +2158,8 @@  void helper_stf_asi(CPUState *env, target_ulong addr, int asi, int size,
             return;
         }
         helper_check_align(env, addr, 0x3f);
-        for (i = 0; i < 16; i++) {
-            val = *(uint32_t *)&env->fpr[rd++];
-            helper_st_asi(env, addr, val, asi & 0x19, 4);
-            addr += 4;
+        for (i = 0; i < 8; i++, rd += 2, addr += 8) {
+            helper_st_asi(env, addr, env->fpr[rd/2].ll, asi & 0x19, 8);
         }
 
         return;
@@ -2180,20 +2170,19 @@  void helper_stf_asi(CPUState *env, target_ulong addr, int asi, int size,
     switch (size) {
     default:
     case 4:
-        helper_st_asi(env, 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(env, 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(env, addr, u.ll, asi, size);
+        helper_st_asi(env, 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(env, addr, u.ll, asi, 8);
-        u.l.upper = *(uint32_t *)&env->fpr[rd++];
-        u.l.lower = *(uint32_t *)&env->fpr[rd++];
-        helper_st_asi(env, addr + 8, u.ll, asi, 8);
+        helper_st_asi(env, addr, env->fpr[rd/2].ll, asi, 8);
+        helper_st_asi(env, addr + 8, env->fpr[rd/2 + 1].ll, asi, 8);
         break;
     }
 }
diff --git a/target-sparc/machine.c b/target-sparc/machine.c
index 56ae041..235b088 100644
--- a/target-sparc/machine.c
+++ b/target-sparc/machine.c
@@ -21,13 +21,9 @@  void cpu_save(QEMUFile *f, void *opaque)
         qemu_put_betls(f, &env->regbase[i]);
 
     /* FPU */
-    for(i = 0; i < TARGET_FPREGS; i++) {
-        union {
-            float32 f;
-            uint32_t i;
-        } u;
-        u.f = env->fpr[i];
-        qemu_put_be32(f, u.i);
+    for (i = 0; i < TARGET_DPREGS; i++) {
+        qemu_put_be32(f, env->fpr[i].l.upper);
+        qemu_put_be32(f, env->fpr[i].l.lower);
     }
 
     qemu_put_betls(f, &env->pc);
@@ -128,13 +124,9 @@  int cpu_load(QEMUFile *f, void *opaque, int version_id)
         qemu_get_betls(f, &env->regbase[i]);
 
     /* FPU */
-    for(i = 0; i < TARGET_FPREGS; i++) {
-        union {
-            float32 f;
-            uint32_t i;
-        } u;
-        u.i = qemu_get_be32(f);
-        env->fpr[i] = u.f;
+    for (i = 0; i < TARGET_DPREGS; i++) {
+        env->fpr[i].l.upper = qemu_get_be32(f);
+        env->fpr[i].l.lower = qemu_get_be32(f);
     }
 
     qemu_get_betls(f, &env->pc);
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index f8d3bf2..97a462b 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -68,7 +68,7 @@  static TCGv cpu_tmp0;
 static TCGv_i32 cpu_tmp32;
 static TCGv_i64 cpu_tmp64;
 /* Floating point registers */
-static TCGv_i32 cpu_fpr[TARGET_FPREGS];
+static TCGv_i64 cpu_fpr[TARGET_DPREGS];
 
 static target_ulong gen_opc_npc[OPC_BUF_SIZE];
 static target_ulong gen_opc_jump_pc[2];
@@ -87,8 +87,8 @@  typedef struct DisasContext {
     uint32_t cc_op;  /* current CC operation */
     struct TranslationBlock *tb;
     sparc_def_t *def;
-    TCGv_i64 t64[3];
-    int n_t64;
+    TCGv_i32 t32[3];
+    int n_t32;
 } DisasContext;
 
 // This function uses non-native bit order
@@ -131,12 +131,44 @@  static inline void gen_update_fprs_dirty(int rd)
 /* floating point registers moves */
 static TCGv_i32 gen_load_fpr_F(DisasContext *dc, unsigned int src)
 {
-    return cpu_fpr[src];
+#if TCG_TARGET_REG_BITS == 32
+    if (src & 1) {
+        return TCGV_LOW(cpu_fpr[src / 2]);
+    } else {
+        return TCGV_HIGH(cpu_fpr[src / 2]);
+    }
+#else
+    if (src & 1) {
+        return MAKE_TCGV_I32(GET_TCGV_I64(cpu_fpr[src / 2]));
+    } else {
+        TCGv_i32 ret = tcg_temp_local_new_i32();
+        TCGv_i64 t = tcg_temp_new_i64();
+
+        tcg_gen_shri_i64(t, cpu_fpr[src / 2], 32);
+        tcg_gen_trunc_i64_i32(ret, t);
+        tcg_temp_free_i64(t);
+
+        dc->t32[dc->n_t32++] = ret;
+        assert(dc->n_t32 <= ARRAY_SIZE(dc->t32));
+
+        return ret;
+    }
+#endif
 }
 
 static void gen_store_fpr_F(DisasContext *dc, unsigned int dst, TCGv_i32 v)
 {
-    tcg_gen_mov_i32(cpu_fpr[dst], v);
+#if TCG_TARGET_REG_BITS == 32
+    if (dst & 1) {
+        tcg_gen_mov_i32(TCGV_LOW(cpu_fpr[dst / 2]), v);
+    } else {
+        tcg_gen_mov_i32(TCGV_HIGH(cpu_fpr[dst / 2]), v);
+    }
+#else
+    TCGv_i64 t = MAKE_TCGV_I64(GET_TCGV_I32(v));
+    tcg_gen_deposit_i64(cpu_fpr[dst / 2], cpu_fpr[dst / 2], t,
+                        (dst & 1 ? 0 : 32), 32);
+#endif
     gen_update_fprs_dirty(dst);
 }
 
@@ -147,42 +179,14 @@  static TCGv_i32 gen_dest_fpr_F(void)
 
 static TCGv_i64 gen_load_fpr_D(DisasContext *dc, unsigned int src)
 {
-    TCGv_i64 ret = tcg_temp_new_i64();
     src = DFPREG(src);
-
-#if TCG_TARGET_REG_BITS == 32
-    tcg_gen_mov_i32(TCGV_HIGH(ret), cpu_fpr[src]);
-    tcg_gen_mov_i32(TCGV_LOW(ret), cpu_fpr[src + 1]);
-#else
-    {
-        TCGv_i64 t = tcg_temp_new_i64();
-        tcg_gen_extu_i32_i64(ret, cpu_fpr[src]);
-        tcg_gen_extu_i32_i64(t, cpu_fpr[src + 1]);
-        tcg_gen_shli_i64(ret, ret, 32);
-        tcg_gen_or_i64(ret, ret, t);
-        tcg_temp_free_i64(t);
-    }
-#endif
-
-    dc->t64[dc->n_t64++] = ret;
-    assert(dc->n_t64 <= ARRAY_SIZE(dc->t64));
-
-    return ret;
+    return cpu_fpr[src / 2];
 }
 
 static void gen_store_fpr_D(DisasContext *dc, unsigned int dst, TCGv_i64 v)
 {
     dst = DFPREG(dst);
-
-#if TCG_TARGET_REG_BITS == 32
-    tcg_gen_mov_i32(cpu__fpu[dst], TCGV_HIGH(v));
-    tcg_gen_mov_i32(cpu__fpu[dst + 1], TCGV_LOW(v));
-#else
-    tcg_gen_trunc_i64_i32(cpu_fpr[dst + 1], v);
-    tcg_gen_shri_i64(v, v, 32);
-    tcg_gen_trunc_i64_i32(cpu_fpr[dst], v);
-#endif
-
+    tcg_gen_mov_i64(cpu_fpr[dst / 2], v);
     gen_update_fprs_dirty(dst);
 }
 
@@ -193,50 +197,36 @@  static TCGv_i64 gen_dest_fpr_D(void)
 
 static void gen_op_load_fpr_QT0(unsigned int src)
 {
-    tcg_gen_st_i32(cpu_fpr[src], cpu_env, offsetof(CPUSPARCState, qt0) +
-                   offsetof(CPU_QuadU, l.upmost));
-    tcg_gen_st_i32(cpu_fpr[src + 1], cpu_env, offsetof(CPUSPARCState, qt0) +
-                   offsetof(CPU_QuadU, l.upper));
-    tcg_gen_st_i32(cpu_fpr[src + 2], cpu_env, offsetof(CPUSPARCState, qt0) +
-                   offsetof(CPU_QuadU, l.lower));
-    tcg_gen_st_i32(cpu_fpr[src + 3], cpu_env, offsetof(CPUSPARCState, qt0) +
-                   offsetof(CPU_QuadU, l.lowest));
+    tcg_gen_st_i64(cpu_fpr[src / 2], cpu_env, offsetof(CPUSPARCState, qt0) +
+                   offsetof(CPU_QuadU, ll.upper));
+    tcg_gen_st_i64(cpu_fpr[src/2 + 1], cpu_env, offsetof(CPUSPARCState, qt0) +
+                   offsetof(CPU_QuadU, ll.lower));
 }
 
 static void gen_op_load_fpr_QT1(unsigned int src)
 {
-    tcg_gen_st_i32(cpu_fpr[src], cpu_env, offsetof(CPUSPARCState, qt1) +
-                   offsetof(CPU_QuadU, l.upmost));
-    tcg_gen_st_i32(cpu_fpr[src + 1], cpu_env, offsetof(CPUSPARCState, qt1) +
-                   offsetof(CPU_QuadU, l.upper));
-    tcg_gen_st_i32(cpu_fpr[src + 2], cpu_env, offsetof(CPUSPARCState, qt1) +
-                   offsetof(CPU_QuadU, l.lower));
-    tcg_gen_st_i32(cpu_fpr[src + 3], cpu_env, offsetof(CPUSPARCState, qt1) +
-                   offsetof(CPU_QuadU, l.lowest));
+    tcg_gen_st_i64(cpu_fpr[src / 2], cpu_env, offsetof(CPUSPARCState, qt1) +
+                   offsetof(CPU_QuadU, ll.upper));
+    tcg_gen_st_i64(cpu_fpr[src/2 + 1], cpu_env, offsetof(CPUSPARCState, qt1) +
+                   offsetof(CPU_QuadU, ll.lower));
 }
 
 static void gen_op_store_QT0_fpr(unsigned int dst)
 {
-    tcg_gen_ld_i32(cpu_fpr[dst], cpu_env, offsetof(CPUSPARCState, qt0) +
-                   offsetof(CPU_QuadU, l.upmost));
-    tcg_gen_ld_i32(cpu_fpr[dst + 1], cpu_env, offsetof(CPUSPARCState, qt0) +
-                   offsetof(CPU_QuadU, l.upper));
-    tcg_gen_ld_i32(cpu_fpr[dst + 2], cpu_env, offsetof(CPUSPARCState, qt0) +
-                   offsetof(CPU_QuadU, l.lower));
-    tcg_gen_ld_i32(cpu_fpr[dst + 3], cpu_env, offsetof(CPUSPARCState, qt0) +
-                   offsetof(CPU_QuadU, l.lowest));
+    tcg_gen_ld_i64(cpu_fpr[dst / 2], cpu_env, offsetof(CPUSPARCState, qt0) +
+                   offsetof(CPU_QuadU, ll.upper));
+    tcg_gen_ld_i64(cpu_fpr[dst/2 + 1], cpu_env, offsetof(CPUSPARCState, qt0) +
+                   offsetof(CPU_QuadU, ll.lower));
 }
 
 #ifdef TARGET_SPARC64
-static void gen_move_Q(int rd, int rs)
+static void gen_move_Q(unsigned int rd, unsigned int rs)
 {
     rd = QFPREG(rd);
     rs = QFPREG(rs);
 
-    tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs]);
-    tcg_gen_mov_i32(cpu_fpr[rd + 1], cpu_fpr[rs + 1]);
-    tcg_gen_mov_i32(cpu_fpr[rd + 2], cpu_fpr[rs + 2]);
-    tcg_gen_mov_i32(cpu_fpr[rd + 3], cpu_fpr[rs + 3]);
+    tcg_gen_mov_i64(cpu_fpr[rd / 2], cpu_fpr[rs / 2]);
+    tcg_gen_mov_i64(cpu_fpr[rd / 2 + 1], cpu_fpr[rs / 2 + 1]);
     gen_update_fprs_dirty(rd);
 }
 #endif
@@ -5008,6 +4998,13 @@  static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
  egress:
     tcg_temp_free(cpu_tmp1);
     tcg_temp_free(cpu_tmp2);
+    if (dc->n_t32 != 0) {
+        int i;
+        for (i = dc->n_t32 - 1; i >= 0; --i) {
+            tcg_temp_free_i32(dc->t32[i]);
+        }
+        dc->n_t32 = 0;
+    }
 }
 
 static inline void gen_intermediate_code_internal(TranslationBlock * tb,
@@ -5109,9 +5106,6 @@  static inline void gen_intermediate_code_internal(TranslationBlock * tb,
     tcg_temp_free_i64(cpu_tmp64);
     tcg_temp_free_i32(cpu_tmp32);
     tcg_temp_free(cpu_tmp0);
-    for (j = dc->n_t64 - 1; j >= 0; --j) {
-        tcg_temp_free_i64(dc->t64[j]);
-    }
 
     if (tb->cflags & CF_LAST_IO)
         gen_io_end();
@@ -5177,15 +5171,11 @@  void gen_intermediate_code_init(CPUSPARCState *env)
         "g6",
         "g7",
     };
-    static const char * const fregnames[64] = {
-        "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
-        "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
-        "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
-        "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
-        "f32", "f33", "f34", "f35", "f36", "f37", "f38", "f39",
-        "f40", "f41", "f42", "f43", "f44", "f45", "f46", "f47",
-        "f48", "f49", "f50", "f51", "f52", "f53", "f54", "f55",
-        "f56", "f57", "f58", "f59", "f60", "f61", "f62", "f63",
+    static const char * const fregnames[32] = {
+        "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14",
+        "f16", "f18", "f20", "f22", "f24", "f26", "f28", "f30",
+        "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",
+        "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",
     };
 
     /* init various static tables */
@@ -5259,8 +5249,8 @@  void gen_intermediate_code_init(CPUSPARCState *env)
             cpu_gregs[i] = tcg_global_mem_new(TCG_AREG0,
                                               offsetof(CPUState, gregs[i]),
                                               gregnames[i]);
-        for (i = 0; i < TARGET_FPREGS; i++)
-            cpu_fpr[i] = tcg_global_mem_new_i32(TCG_AREG0,
+        for (i = 0; i < TARGET_DPREGS; i++)
+            cpu_fpr[i] = tcg_global_mem_new_i64(TCG_AREG0,
                                                 offsetof(CPUState, fpr[i]),
                                                 fregnames[i]);