summaryrefslogtreecommitdiff
path: root/target-arm
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2005-04-07 19:42:46 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2005-04-07 19:42:46 +0000
commit8e96005d86cba6b2ce177f489463eda602d99238 (patch)
tree755ff27e540b4549d0cbb07849d5ddbf5cb4acf8 /target-arm
parent85d8be6bf2c6823f9d386794defa790618c08986 (diff)
downloadqemu-8e96005d86cba6b2ce177f489463eda602d99238.tar.gz
VFP register ordering (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1355 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-arm')
-rw-r--r--target-arm/cpu.h11
-rw-r--r--target-arm/translate.c31
2 files changed, 26 insertions, 16 deletions
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index cf11c2f94d..1346175134 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -35,9 +35,9 @@
precision respectively.
Doing runtime conversions is tricky because VFP registers may contain
integer values (eg. as the result of a FTOSI instruction).
- A double precision register load/store must also load/store the
- corresponding single precision pair, although it is undefined how
- these overlap. */
+ s<2n> maps to the least significant half of d<n>
+ s<2n+1> maps to the most significant half of d<n>
+ */
typedef struct CPUARMState {
uint32_t regs[16];
@@ -71,10 +71,7 @@ typedef struct CPUARMState {
memory was written */
/* VFP coprocessor state. */
struct {
- union {
- float32 s[32];
- float64 d[16];
- } regs;
+ float64 regs[16];
/* We store these fpcsr fields separately for convenience. */
int vec_len;
diff --git a/target-arm/translate.c b/target-arm/translate.c
index db38e331b6..39c28e754d 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -385,28 +385,41 @@ VFP_OP(st)
#undef VFP_OP
+static inline long
+vfp_reg_offset (int dp, int reg)
+{
+ if (dp)
+ return offsetof(CPUARMState, vfp.regs[reg]);
+ else if (reg & 1) {
+ return offsetof(CPUARMState, vfp.regs[reg >> 1])
+ + offsetof(CPU_DoubleU, l.upper);
+ } else {
+ return offsetof(CPUARMState, vfp.regs[reg >> 1])
+ + offsetof(CPU_DoubleU, l.lower);
+ }
+}
static inline void gen_mov_F0_vreg(int dp, int reg)
{
if (dp)
- gen_op_vfp_getreg_F0d(offsetof(CPUARMState, vfp.regs.d[reg]));
+ gen_op_vfp_getreg_F0d(vfp_reg_offset(dp, reg));
else
- gen_op_vfp_getreg_F0s(offsetof(CPUARMState, vfp.regs.s[reg]));
+ gen_op_vfp_getreg_F0s(vfp_reg_offset(dp, reg));
}
static inline void gen_mov_F1_vreg(int dp, int reg)
{
if (dp)
- gen_op_vfp_getreg_F1d(offsetof(CPUARMState, vfp.regs.d[reg]));
+ gen_op_vfp_getreg_F1d(vfp_reg_offset(dp, reg));
else
- gen_op_vfp_getreg_F1s(offsetof(CPUARMState, vfp.regs.s[reg]));
+ gen_op_vfp_getreg_F1s(vfp_reg_offset(dp, reg));
}
static inline void gen_mov_vreg_F0(int dp, int reg)
{
if (dp)
- gen_op_vfp_setreg_F0d(offsetof(CPUARMState, vfp.regs.d[reg]));
+ gen_op_vfp_setreg_F0d(vfp_reg_offset(dp, reg));
else
- gen_op_vfp_setreg_F0s(offsetof(CPUARMState, vfp.regs.s[reg]));
+ gen_op_vfp_setreg_F0s(vfp_reg_offset(dp, reg));
}
/* Disassemble a VFP instruction. Returns nonzero if an error occured
@@ -2120,9 +2133,9 @@ void cpu_dump_state(CPUState *env, FILE *f,
env->cpsr & (1 << 28) ? 'V' : '-');
for (i = 0; i < 16; i++) {
- s0.s = env->vfp.regs.s[i * 2];
- s1.s = env->vfp.regs.s[i * 2 + 1];
- d.d = env->vfp.regs.d[i];
+ d.d = env->vfp.regs[i];
+ s0.i = d.l.lower;
+ s1.i = d.l.upper;
cpu_fprintf(f, "s%02d=%08x(%8f) s%02d=%08x(%8f) d%02d=%08x%08x(%8f)\n",
i * 2, (int)s0.i, s0.s,
i * 2 + 1, (int)s0.i, s0.s,