Commit b7bcbe9524c05d5134136cce2d5d2a09c09a4f83

Authored by bellard
1 parent 55754d9e

ARM VFP support (Paul Brook)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1309 c046a42c-6fe2-441c-8c8c-71466251a162
Changelog
@@ -15,6 +15,7 @@ version 0.6.2: @@ -15,6 +15,7 @@ version 0.6.2:
15 - PC parallel port support (Mark Jonckheere) 15 - PC parallel port support (Mark Jonckheere)
16 - initial SPARC64 support (Blue Swirl) 16 - initial SPARC64 support (Blue Swirl)
17 - armv5te user mode support (Paul Brook) 17 - armv5te user mode support (Paul Brook)
  18 + - ARM VFP support (Paul Brook)
18 19
19 version 0.6.1: 20 version 0.6.1:
20 21
Makefile.target
@@ -259,6 +259,10 @@ ifeq ($(TARGET_BASE_ARCH), sparc) @@ -259,6 +259,10 @@ ifeq ($(TARGET_BASE_ARCH), sparc)
259 LIBOBJS+= op_helper.o helper.o 259 LIBOBJS+= op_helper.o helper.o
260 endif 260 endif
261 261
  262 +ifeq ($(TARGET_BASE_ARCH), arm)
  263 +LIBOBJS+= op_helper.o
  264 +endif
  265 +
262 # NOTE: the disassembler code is only needed for debugging 266 # NOTE: the disassembler code is only needed for debugging
263 LIBOBJS+=disas.o 267 LIBOBJS+=disas.o
264 ifeq ($(findstring i386, $(TARGET_ARCH) $(ARCH)),i386) 268 ifeq ($(findstring i386, $(TARGET_ARCH) $(ARCH)),i386)
cpu-exec.c
@@ -346,7 +346,8 @@ int cpu_exec(CPUState *env1) @@ -346,7 +346,8 @@ int cpu_exec(CPUState *env1)
346 cs_base = env->segs[R_CS].base; 346 cs_base = env->segs[R_CS].base;
347 pc = cs_base + env->eip; 347 pc = cs_base + env->eip;
348 #elif defined(TARGET_ARM) 348 #elif defined(TARGET_ARM)
349 - flags = env->thumb; 349 + flags = env->thumb | (env->vfp.vec_len << 1)
  350 + | (env->vfp.vec_stride << 4);
350 cs_base = 0; 351 cs_base = 0;
351 pc = env->regs[15]; 352 pc = env->regs[15];
352 #elif defined(TARGET_SPARC) 353 #elif defined(TARGET_SPARC)
@@ -619,6 +620,7 @@ int cpu_exec(CPUState *env1) @@ -619,6 +620,7 @@ int cpu_exec(CPUState *env1)
619 #endif 620 #endif
620 #elif defined(TARGET_ARM) 621 #elif defined(TARGET_ARM)
621 env->cpsr = compute_cpsr(); 622 env->cpsr = compute_cpsr();
  623 + /* XXX: Save/restore host fpu exception state?. */
622 #elif defined(TARGET_SPARC) 624 #elif defined(TARGET_SPARC)
623 #elif defined(TARGET_PPC) 625 #elif defined(TARGET_PPC)
624 #else 626 #else
target-arm/cpu.h
@@ -29,6 +29,14 @@ @@ -29,6 +29,14 @@
29 #define EXCP_PREFETCH_ABORT 3 29 #define EXCP_PREFETCH_ABORT 3
30 #define EXCP_DATA_ABORT 4 30 #define EXCP_DATA_ABORT 4
31 31
  32 +/* We currently assume float and double are IEEE single and double
  33 + precision respectively.
  34 + Doing runtime conversions is tricky because VFP registers may contain
  35 + integer values (eg. as the result of a FTOSI instruction).
  36 + A double precision register load/store must also load/store the
  37 + corresponding single precision pair, although it is undefined how
  38 + these overlap. */
  39 +
32 typedef struct CPUARMState { 40 typedef struct CPUARMState {
33 uint32_t regs[16]; 41 uint32_t regs[16];
34 uint32_t cpsr; 42 uint32_t cpsr;
@@ -50,6 +58,7 @@ typedef struct CPUARMState { @@ -50,6 +58,7 @@ typedef struct CPUARMState {
50 int interrupt_request; 58 int interrupt_request;
51 struct TranslationBlock *current_tb; 59 struct TranslationBlock *current_tb;
52 int user_mode_only; 60 int user_mode_only;
  61 + uint32_t address;
53 62
54 /* in order to avoid passing too many arguments to the memory 63 /* in order to avoid passing too many arguments to the memory
55 write helpers, we store some rarely used information in the CPU 64 write helpers, we store some rarely used information in the CPU
@@ -58,6 +67,25 @@ typedef struct CPUARMState { @@ -58,6 +67,25 @@ typedef struct CPUARMState {
58 written */ 67 written */
59 unsigned long mem_write_vaddr; /* target virtual addr at which the 68 unsigned long mem_write_vaddr; /* target virtual addr at which the
60 memory was written */ 69 memory was written */
  70 + /* VFP coprocessor state. */
  71 + struct {
  72 + union {
  73 + float s[32];
  74 + double d[16];
  75 + } regs;
  76 +
  77 + /* We store these fpcsr fields separately for convenience. */
  78 + int vec_len;
  79 + int vec_stride;
  80 +
  81 + uint32_t fpscr;
  82 +
  83 + /* Temporary variables if we don't have spare fp regs. */
  84 + float tmp0s, tmp1s;
  85 + double tmp0d, tmp1d;
  86 +
  87 + } vfp;
  88 +
61 /* user data */ 89 /* user data */
62 void *opaque; 90 void *opaque;
63 } CPUARMState; 91 } CPUARMState;
target-arm/exec.h
@@ -24,13 +24,16 @@ register uint32_t T0 asm(AREG1); @@ -24,13 +24,16 @@ register uint32_t T0 asm(AREG1);
24 register uint32_t T1 asm(AREG2); 24 register uint32_t T1 asm(AREG2);
25 register uint32_t T2 asm(AREG3); 25 register uint32_t T2 asm(AREG3);
26 26
  27 +/* TODO: Put these in FP regs on targets that have such things. */
  28 +/* It is ok for FT0s and FT0d to overlap. Likewise FT1s and FT1d. */
  29 +#define FT0s env->vfp.tmp0s
  30 +#define FT1s env->vfp.tmp1s
  31 +#define FT0d env->vfp.tmp0d
  32 +#define FT1d env->vfp.tmp1d
  33 +
27 #include "cpu.h" 34 #include "cpu.h"
28 #include "exec-all.h" 35 #include "exec-all.h"
29 36
30 -void cpu_lock(void);  
31 -void cpu_unlock(void);  
32 -void cpu_loop_exit(void);  
33 -  
34 /* Implemented CPSR bits. */ 37 /* Implemented CPSR bits. */
35 #define CACHED_CPSR_BITS 0xf8000000 38 #define CACHED_CPSR_BITS 0xf8000000
36 static inline int compute_cpsr(void) 39 static inline int compute_cpsr(void)
@@ -51,3 +54,24 @@ static inline void regs_to_env(void) @@ -51,3 +54,24 @@ static inline void regs_to_env(void)
51 54
52 int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw, 55 int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
53 int is_user, int is_softmmu); 56 int is_user, int is_softmmu);
  57 +
  58 +/* In op_helper.c */
  59 +
  60 +void cpu_lock(void);
  61 +void cpu_unlock(void);
  62 +void cpu_loop_exit(void);
  63 +
  64 +void raise_exception(int);
  65 +
  66 +void do_vfp_abss(void);
  67 +void do_vfp_absd(void);
  68 +void do_vfp_negs(void);
  69 +void do_vfp_negd(void);
  70 +void do_vfp_sqrts(void);
  71 +void do_vfp_sqrtd(void);
  72 +void do_vfp_cmps(void);
  73 +void do_vfp_cmpd(void);
  74 +void do_vfp_cmpes(void);
  75 +void do_vfp_cmped(void);
  76 +void do_vfp_set_fpscr(void);
  77 +void do_vfp_get_fpscr(void);
target-arm/op.c
@@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
2 * ARM micro operations 2 * ARM micro operations
3 * 3 *
4 * Copyright (c) 2003 Fabrice Bellard 4 * Copyright (c) 2003 Fabrice Bellard
  5 + * Copyright (c) 2005 CodeSourcery, LLC
5 * 6 *
6 * This library is free software; you can redistribute it and/or 7 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public 8 * modify it under the terms of the GNU Lesser General Public
@@ -857,17 +858,259 @@ void OPPROTO op_undef_insn(void) @@ -857,17 +858,259 @@ void OPPROTO op_undef_insn(void)
857 cpu_loop_exit(); 858 cpu_loop_exit();
858 } 859 }
859 860
860 -/* thread support */ 861 +/* VFP support. We follow the convention used for VFP instrunctions:
  862 + Single precition routines have a "s" suffix, double precision a
  863 + "d" suffix. */
861 864
862 -spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED; 865 +#define VFP_OP(name, p) void OPPROTO op_vfp_##name##p(void)
863 866
864 -void cpu_lock(void) 867 +#define VFP_BINOP(name, op) \
  868 +VFP_OP(name, s) \
  869 +{ \
  870 + FT0s = FT0s op FT1s; \
  871 +} \
  872 +VFP_OP(name, d) \
  873 +{ \
  874 + FT0d = FT0d op FT1d; \
  875 +}
  876 +VFP_BINOP(add, +)
  877 +VFP_BINOP(sub, -)
  878 +VFP_BINOP(mul, *)
  879 +VFP_BINOP(div, /)
  880 +#undef VFP_BINOP
  881 +
  882 +#define VFP_HELPER(name) \
  883 +VFP_OP(name, s) \
  884 +{ \
  885 + do_vfp_##name##s(); \
  886 +} \
  887 +VFP_OP(name, d) \
  888 +{ \
  889 + do_vfp_##name##d(); \
  890 +}
  891 +VFP_HELPER(abs)
  892 +VFP_HELPER(sqrt)
  893 +VFP_HELPER(cmp)
  894 +VFP_HELPER(cmpe)
  895 +#undef VFP_HELPER
  896 +
  897 +/* XXX: Will this do the right thing for NANs. Should invert the signbit
  898 + without looking at the rest of the value. */
  899 +VFP_OP(neg, s)
  900 +{
  901 + FT0s = -FT0s;
  902 +}
  903 +
  904 +VFP_OP(neg, d)
  905 +{
  906 + FT0d = -FT0d;
  907 +}
  908 +
  909 +VFP_OP(F1_ld0, s)
  910 +{
  911 + FT1s = 0.0f;
  912 +}
  913 +
  914 +VFP_OP(F1_ld0, d)
  915 +{
  916 + FT1d = 0.0;
  917 +}
  918 +
  919 +/* Helper routines to perform bitwise copies between float and int. */
  920 +static inline float vfp_itos(uint32_t i)
  921 +{
  922 + union {
  923 + uint32_t i;
  924 + float s;
  925 + } v;
  926 +
  927 + v.i = i;
  928 + return v.s;
  929 +}
  930 +
  931 +static inline uint32_t vfp_stoi(float s)
  932 +{
  933 + union {
  934 + uint32_t i;
  935 + float s;
  936 + } v;
  937 +
  938 + v.s = s;
  939 + return v.i;
  940 +}
  941 +
  942 +/* Integer to float conversion. */
  943 +VFP_OP(uito, s)
  944 +{
  945 + FT0s = (float)(uint32_t)vfp_stoi(FT0s);
  946 +}
  947 +
  948 +VFP_OP(uito, d)
  949 +{
  950 + FT0d = (double)(uint32_t)vfp_stoi(FT0s);
  951 +}
  952 +
  953 +VFP_OP(sito, s)
  954 +{
  955 + FT0s = (float)(int32_t)vfp_stoi(FT0s);
  956 +}
  957 +
  958 +VFP_OP(sito, d)
  959 +{
  960 + FT0d = (double)(int32_t)vfp_stoi(FT0s);
  961 +}
  962 +
  963 +/* Float to integer conversion. */
  964 +VFP_OP(toui, s)
  965 +{
  966 + FT0s = vfp_itos((uint32_t)FT0s);
  967 +}
  968 +
  969 +VFP_OP(toui, d)
  970 +{
  971 + FT0s = vfp_itos((uint32_t)FT0d);
  972 +}
  973 +
  974 +VFP_OP(tosi, s)
  975 +{
  976 + FT0s = vfp_itos((int32_t)FT0s);
  977 +}
  978 +
  979 +VFP_OP(tosi, d)
  980 +{
  981 + FT0s = vfp_itos((int32_t)FT0d);
  982 +}
  983 +
  984 +/* TODO: Set rounding mode properly. */
  985 +VFP_OP(touiz, s)
  986 +{
  987 + FT0s = vfp_itos((uint32_t)FT0s);
  988 +}
  989 +
  990 +VFP_OP(touiz, d)
  991 +{
  992 + FT0s = vfp_itos((uint32_t)FT0d);
  993 +}
  994 +
  995 +VFP_OP(tosiz, s)
  996 +{
  997 + FT0s = vfp_itos((int32_t)FT0s);
  998 +}
  999 +
  1000 +VFP_OP(tosiz, d)
865 { 1001 {
866 - spin_lock(&global_cpu_lock); 1002 + FT0s = vfp_itos((int32_t)FT0d);
867 } 1003 }
868 1004
869 -void cpu_unlock(void) 1005 +/* floating point conversion */
  1006 +VFP_OP(fcvtd, s)
870 { 1007 {
871 - spin_unlock(&global_cpu_lock); 1008 + FT0d = (double)FT0s;
872 } 1009 }
873 1010
  1011 +VFP_OP(fcvts, d)
  1012 +{
  1013 + FT0s = (float)FT0d;
  1014 +}
  1015 +
  1016 +/* Get and Put values from registers. */
  1017 +VFP_OP(getreg_F0, d)
  1018 +{
  1019 + FT0d = *(double *)((char *) env + PARAM1);
  1020 +}
  1021 +
  1022 +VFP_OP(getreg_F0, s)
  1023 +{
  1024 + FT0s = *(float *)((char *) env + PARAM1);
  1025 +}
  1026 +
  1027 +VFP_OP(getreg_F1, d)
  1028 +{
  1029 + FT1d = *(double *)((char *) env + PARAM1);
  1030 +}
  1031 +
  1032 +VFP_OP(getreg_F1, s)
  1033 +{
  1034 + FT1s = *(float *)((char *) env + PARAM1);
  1035 +}
  1036 +
  1037 +VFP_OP(setreg_F0, d)
  1038 +{
  1039 + *(double *)((char *) env + PARAM1) = FT0d;
  1040 +}
  1041 +
  1042 +VFP_OP(setreg_F0, s)
  1043 +{
  1044 + *(float *)((char *) env + PARAM1) = FT0s;
  1045 +}
  1046 +
  1047 +VFP_OP(foobar, d)
  1048 +{
  1049 + FT0d = env->vfp.regs.s[3];
  1050 +}
  1051 +
  1052 +void OPPROTO op_vfp_movl_T0_fpscr(void)
  1053 +{
  1054 + do_vfp_get_fpscr ();
  1055 +}
  1056 +
  1057 +void OPPROTO op_vfp_movl_T0_fpscr_flags(void)
  1058 +{
  1059 + T0 = env->vfp.fpscr & (0xf << 28);
  1060 +}
  1061 +
  1062 +void OPPROTO op_vfp_movl_fpscr_T0(void)
  1063 +{
  1064 + do_vfp_set_fpscr();
  1065 +}
  1066 +
  1067 +/* Move between FT0s to T0 */
  1068 +void OPPROTO op_vfp_mrs(void)
  1069 +{
  1070 + T0 = vfp_stoi(FT0s);
  1071 +}
  1072 +
  1073 +void OPPROTO op_vfp_msr(void)
  1074 +{
  1075 + FT0s = vfp_itos(T0);
  1076 +}
  1077 +
  1078 +/* Move between FT0d and {T0,T1} */
  1079 +void OPPROTO op_vfp_mrrd(void)
  1080 +{
  1081 + CPU_DoubleU u;
  1082 +
  1083 + u.d = FT0d;
  1084 + T0 = u.l.lower;
  1085 + T1 = u.l.upper;
  1086 +}
  1087 +
  1088 +void OPPROTO op_vfp_mdrr(void)
  1089 +{
  1090 + CPU_DoubleU u;
  1091 +
  1092 + u.l.lower = T0;
  1093 + u.l.upper = T1;
  1094 + FT0d = u.d;
  1095 +}
  1096 +
  1097 +/* Floating point load/store. Address is in T1 */
  1098 +void OPPROTO op_vfp_lds(void)
  1099 +{
  1100 + FT0s = ldfl((void *)T1);
  1101 +}
  1102 +
  1103 +void OPPROTO op_vfp_ldd(void)
  1104 +{
  1105 + FT0d = ldfq((void *)T1);
  1106 +}
  1107 +
  1108 +void OPPROTO op_vfp_sts(void)
  1109 +{
  1110 + stfl((void *)T1, FT0s);
  1111 +}
  1112 +
  1113 +void OPPROTO op_vfp_std(void)
  1114 +{
  1115 + stfq((void *)T1, FT0d);
  1116 +}
target-arm/op_helper.c 0 โ†’ 100644
  1 +/*
  2 + * ARM helper routines
  3 + *
  4 + * Copyright (c) 2005 CodeSourcery, LLC
  5 + *
  6 + * This library is free software; you can redistribute it and/or
  7 + * modify it under the terms of the GNU Lesser General Public
  8 + * License as published by the Free Software Foundation; either
  9 + * version 2 of the License, or (at your option) any later version.
  10 + *
  11 + * This library is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14 + * Lesser General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU Lesser General Public
  17 + * License along with this library; if not, write to the Free Software
  18 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19 + */
  20 +
  21 +#include <math.h>
  22 +#include <fenv.h>
  23 +#include "exec.h"
  24 +
  25 +/* If the host doesn't define C99 math intrinsics then use the normal
  26 + operators. This may generate excess exceptions, but it's probably
  27 + near enough for most things. */
  28 +#ifndef isless
  29 +#define isless(x, y) (x < y)
  30 +#endif
  31 +#ifndef isgreater
  32 +#define isgreater(x, y) (x > y)
  33 +#endif
  34 +#ifndef isunordered
  35 +#define isunordered(x, y) (!((x < y) || (x >= y)))
  36 +#endif
  37 +
  38 +void raise_exception(int tt)
  39 +{
  40 + env->exception_index = tt;
  41 + cpu_loop_exit();
  42 +}
  43 +
  44 +/* thread support */
  45 +
  46 +spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
  47 +
  48 +void cpu_lock(void)
  49 +{
  50 + spin_lock(&global_cpu_lock);
  51 +}
  52 +
  53 +void cpu_unlock(void)
  54 +{
  55 + spin_unlock(&global_cpu_lock);
  56 +}
  57 +
  58 +/* VFP support. */
  59 +
  60 +void do_vfp_abss(void)
  61 +{
  62 + FT0s = fabsf(FT0s);
  63 +}
  64 +
  65 +void do_vfp_absd(void)
  66 +{
  67 + FT0d = fabs(FT0d);
  68 +}
  69 +
  70 +void do_vfp_sqrts(void)
  71 +{
  72 + FT0s = sqrtf(FT0s);
  73 +}
  74 +
  75 +void do_vfp_sqrtd(void)
  76 +{
  77 + FT0d = sqrt(FT0d);
  78 +}
  79 +
  80 +/* We use an == operator first to generate teh correct floating point
  81 + exception. Subsequent comparisons use the exception-safe macros. */
  82 +#define DO_VFP_cmp(p) \
  83 +void do_vfp_cmp##p(void) \
  84 +{ \
  85 + uint32_t flags; \
  86 + if (FT0##p == FT1##p) \
  87 + flags = 0xc; \
  88 + else if (isless (FT0##p, FT1##p)) \
  89 + flags = 0x8; \
  90 + else if (isgreater (FT0##p, FT1##p)) \
  91 + flags = 0x2; \
  92 + else /* unordered */ \
  93 + flags = 0x3; \
  94 + env->vfp.fpscr = (flags << 28) | (env->vfp.fpscr & 0x0fffffff); \
  95 + FORCE_RET(); \
  96 +}
  97 +DO_VFP_cmp(s)
  98 +DO_VFP_cmp(d)
  99 +#undef DO_VFP_cmp
  100 +
  101 +/* We use a > operator first to get FP exceptions right. */
  102 +#define DO_VFP_cmpe(p) \
  103 +void do_vfp_cmpe##p(void) \
  104 +{ \
  105 + uint32_t flags; \
  106 + if (FT0##p > FT1##p) \
  107 + flags = 0x2; \
  108 + else if (isless (FT0##p, FT1##p)) \
  109 + flags = 0x8; \
  110 + else if (isunordered (FT0##p, FT1##p)) \
  111 + flags = 0x3; \
  112 + else /* equal */ \
  113 + flags = 0xc; \
  114 + env->vfp.fpscr = (flags << 28) | (env->vfp.fpscr & 0x0fffffff); \
  115 + FORCE_RET(); \
  116 +}
  117 +DO_VFP_cmpe(s)
  118 +DO_VFP_cmpe(d)
  119 +#undef DO_VFP_cmpe
  120 +
  121 +/* Convert host exception flags to vfp form. */
  122 +int vfp_exceptbits_from_host(int host_bits)
  123 +{
  124 + int target_bits = 0;
  125 +
  126 +#ifdef FE_INVALID
  127 + if (host_bits & FE_INVALID)
  128 + target_bits |= 1;
  129 +#endif
  130 +#ifdef FE_DIVBYZERO
  131 + if (host_bits & FE_DIVBYZERO)
  132 + target_bits |= 2;
  133 +#endif
  134 +#ifdef FE_OVERFLOW
  135 + if (host_bits & FE_OVERFLOW)
  136 + target_bits |= 4;
  137 +#endif
  138 +#ifdef FE_UNDERFLOW
  139 + if (host_bits & FE_UNDERFLOW)
  140 + target_bits |= 8;
  141 +#endif
  142 +#ifdef FE_INEXACT
  143 + if (host_bits & FE_INEXACT)
  144 + target_bits |= 0x10;
  145 +#endif
  146 + /* C doesn't define an inexact exception. */
  147 + return target_bits;
  148 +}
  149 +
  150 +/* Convert vfp exception flags to target form. */
  151 +int vfp_host_exceptbits_to_host(int target_bits)
  152 +{
  153 + int host_bits = 0;
  154 +
  155 +#ifdef FE_INVALID
  156 + if (target_bits & 1)
  157 + host_bits |= FE_INVALID;
  158 +#endif
  159 +#ifdef FE_DIVBYZERO
  160 + if (target_bits & 2)
  161 + host_bits |= FE_DIVBYZERO;
  162 +#endif
  163 +#ifdef FE_OVERFLOW
  164 + if (target_bits & 4)
  165 + host_bits |= FE_OVERFLOW;
  166 +#endif
  167 +#ifdef FE_UNDERFLOW
  168 + if (target_bits & 8)
  169 + host_bits |= FE_UNDERFLOW;
  170 +#endif
  171 +#ifdef FE_INEXACT
  172 + if (target_bits & 0x10)
  173 + host_bits |= FE_INEXACT;
  174 +#endif
  175 + return host_bits;
  176 +}
  177 +
  178 +void do_vfp_set_fpscr(void)
  179 +{
  180 + int i;
  181 + uint32_t changed;
  182 +
  183 + changed = env->vfp.fpscr;
  184 + env->vfp.fpscr = (T0 & 0xffc8ffff);
  185 + env->vfp.vec_len = (T0 >> 16) & 7;
  186 + env->vfp.vec_stride = (T0 >> 20) & 3;
  187 +
  188 + changed ^= T0;
  189 + if (changed & (3 << 22)) {
  190 + i = (T0 >> 22) & 3;
  191 + switch (i) {
  192 + case 0:
  193 + i = FE_TONEAREST;
  194 + break;
  195 + case 1:
  196 + i = FE_UPWARD;
  197 + break;
  198 + case 2:
  199 + i = FE_DOWNWARD;
  200 + break;
  201 + case 3:
  202 + i = FE_TOWARDZERO;
  203 + break;
  204 + }
  205 + fesetround (i);
  206 + }
  207 +
  208 + /* Clear host exception flags. */
  209 + feclearexcept(FE_ALL_EXCEPT);
  210 +
  211 +#ifdef feenableexcept
  212 + if (changed & 0x1f00) {
  213 + i = vfp_exceptbits_to_host((T0 >> 8) & 0x1f);
  214 + feenableexcept (i);
  215 + fedisableexcept (FE_ALL_EXCEPT & ~i);
  216 + }
  217 +#endif
  218 + /* XXX: FZ and DN are not implemented. */
  219 +}
  220 +
  221 +void do_vfp_get_fpscr(void)
  222 +{
  223 + int i;
  224 +
  225 + T0 = (env->vfp.fpscr & 0xffc8ffff) | (env->vfp.vec_len << 16)
  226 + | (env->vfp.vec_stride << 20);
  227 + i = fetestexcept(FE_ALL_EXCEPT);
  228 + T0 |= vfp_exceptbits_from_host(i);
  229 +}
target-arm/translate.c
@@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
2 * ARM translation 2 * ARM translation
3 * 3 *
4 * Copyright (c) 2003 Fabrice Bellard 4 * Copyright (c) 2003 Fabrice Bellard
  5 + * Copyright (c) 2005 CodeSourcery, LLC
5 * 6 *
6 * This library is free software; you can redistribute it and/or 7 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public 8 * modify it under the terms of the GNU Lesser General Public
@@ -354,7 +355,527 @@ static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn) @@ -354,7 +355,527 @@ static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn)
354 } 355 }
355 } 356 }
356 357
357 -static void disas_arm_insn(DisasContext *s) 358 +#define VFP_OP(name) \
  359 +static inline void gen_vfp_##name(int dp) \
  360 +{ \
  361 + if (dp) \
  362 + gen_op_vfp_##name##d(); \
  363 + else \
  364 + gen_op_vfp_##name##s(); \
  365 +}
  366 +
  367 +VFP_OP(add)
  368 +VFP_OP(sub)
  369 +VFP_OP(mul)
  370 +VFP_OP(div)
  371 +VFP_OP(neg)
  372 +VFP_OP(abs)
  373 +VFP_OP(sqrt)
  374 +VFP_OP(cmp)
  375 +VFP_OP(cmpe)
  376 +VFP_OP(F1_ld0)
  377 +VFP_OP(uito)
  378 +VFP_OP(sito)
  379 +VFP_OP(toui)
  380 +VFP_OP(touiz)
  381 +VFP_OP(tosi)
  382 +VFP_OP(tosiz)
  383 +VFP_OP(ld)
  384 +VFP_OP(st)
  385 +
  386 +#undef VFP_OP
  387 +
  388 +static inline void gen_mov_F0_vreg(int dp, int reg)
  389 +{
  390 + if (dp)
  391 + gen_op_vfp_getreg_F0d(offsetof(CPUARMState, vfp.regs.d[reg]));
  392 + else
  393 + gen_op_vfp_getreg_F0s(offsetof(CPUARMState, vfp.regs.s[reg]));
  394 +}
  395 +
  396 +static inline void gen_mov_F1_vreg(int dp, int reg)
  397 +{
  398 + if (dp)
  399 + gen_op_vfp_getreg_F1d(offsetof(CPUARMState, vfp.regs.d[reg]));
  400 + else
  401 + gen_op_vfp_getreg_F1s(offsetof(CPUARMState, vfp.regs.s[reg]));
  402 +}
  403 +
  404 +static inline void gen_mov_vreg_F0(int dp, int reg)
  405 +{
  406 + if (dp)
  407 + gen_op_vfp_setreg_F0d(offsetof(CPUARMState, vfp.regs.d[reg]));
  408 + else
  409 + gen_op_vfp_setreg_F0s(offsetof(CPUARMState, vfp.regs.s[reg]));
  410 +}
  411 +
  412 +/* Disassemble a VFP instruction. Returns nonzero if an error occured
  413 + (ie. an undefined instruction). */
  414 +static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
  415 +{
  416 + uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
  417 + int dp, veclen;
  418 +
  419 + dp = ((insn & 0xf00) == 0xb00);
  420 + switch ((insn >> 24) & 0xf) {
  421 + case 0xe:
  422 + if (insn & (1 << 4)) {
  423 + /* single register transfer */
  424 + if ((insn & 0x6f) != 0x00)
  425 + return 1;
  426 + rd = (insn >> 12) & 0xf;
  427 + if (dp) {
  428 + if (insn & 0x80)
  429 + return 1;
  430 + rn = (insn >> 16) & 0xf;
  431 + /* Get the existing value even for arm->vfp moves because
  432 + we only set half the register. */
  433 + gen_mov_F0_vreg(1, rn);
  434 + gen_op_vfp_mrrd();
  435 + if (insn & (1 << 20)) {
  436 + /* vfp->arm */
  437 + if (insn & (1 << 21))
  438 + gen_movl_reg_T1(s, rd);
  439 + else
  440 + gen_movl_reg_T0(s, rd);
  441 + } else {
  442 + /* arm->vfp */
  443 + if (insn & (1 << 21))
  444 + gen_movl_T1_reg(s, rd);
  445 + else
  446 + gen_movl_T0_reg(s, rd);
  447 + gen_op_vfp_mdrr();
  448 + gen_mov_vreg_F0(dp, rn);
  449 + }
  450 + } else {
  451 + rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
  452 + if (insn & (1 << 20)) {
  453 + /* vfp->arm */
  454 + if (insn & (1 << 21)) {
  455 + /* system register */
  456 + switch (rn) {
  457 + case 0: /* fpsid */
  458 + n = 0x0091A0000;
  459 + break;
  460 + case 2: /* fpscr */
  461 + if (rd == 15)
  462 + gen_op_vfp_movl_T0_fpscr_flags();
  463 + else
  464 + gen_op_vfp_movl_T0_fpscr();
  465 + break;
  466 + default:
  467 + return 1;
  468 + }
  469 + } else {
  470 + gen_mov_F0_vreg(0, rn);
  471 + gen_op_vfp_mrs();
  472 + }
  473 + if (rd == 15) {
  474 + /* This will only set the 4 flag bits */
  475 + gen_op_movl_psr_T0();
  476 + } else
  477 + gen_movl_reg_T0(s, rd);
  478 + } else {
  479 + /* arm->vfp */
  480 + gen_movl_T0_reg(s, rd);
  481 + if (insn & (1 << 21)) {
  482 + /* system register */
  483 + switch (rn) {
  484 + case 0: /* fpsid */
  485 + /* Writes are ignored. */
  486 + break;
  487 + case 2: /* fpscr */
  488 + gen_op_vfp_movl_fpscr_T0();
  489 + /* This could change vector settings, so jump to
  490 + the next instuction. */
  491 + gen_op_movl_T0_im(s->pc);
  492 + gen_movl_reg_T0(s, 15);
  493 + s->is_jmp = DISAS_UPDATE;
  494 + break;
  495 + default:
  496 + return 1;
  497 + }
  498 + } else {
  499 + gen_op_vfp_msr();
  500 + gen_mov_vreg_F0(0, rn);
  501 + }
  502 + }
  503 + }
  504 + } else {
  505 + /* data processing */
  506 + /* The opcode is in bits 23, 21, 20 and 6. */
  507 + op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
  508 + if (dp) {
  509 + if (op == 15) {
  510 + /* rn is opcode */
  511 + rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
  512 + } else {
  513 + /* rn is register number */
  514 + if (insn & (1 << 7))
  515 + return 1;
  516 + rn = (insn >> 16) & 0xf;
  517 + }
  518 +
  519 + if (op == 15 && (rn == 15 || rn > 17)) {
  520 + /* Integer or single precision destination. */
  521 + rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
  522 + } else {
  523 + if (insn & (1 << 22))
  524 + return 1;
  525 + rd = (insn >> 12) & 0xf;
  526 + }
  527 +
  528 + if (op == 15 && (rn == 16 || rn == 17)) {
  529 + /* Integer source. */
  530 + rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
  531 + } else {
  532 + if (insn & (1 << 5))
  533 + return 1;
  534 + rm = insn & 0xf;
  535 + }
  536 + } else {
  537 + rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
  538 + if (op == 15 && rn == 15) {
  539 + /* Double precision destination. */
  540 + if (insn & (1 << 22))
  541 + return 1;
  542 + rd = (insn >> 12) & 0xf;
  543 + } else
  544 + rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
  545 + rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
  546 + }
  547 +
  548 + veclen = env->vfp.vec_len;
  549 + if (op == 15 && rn > 3)
  550 + veclen = 0;
  551 +
  552 + /* Shut up compiler warnings. */
  553 + delta_m = 0;
  554 + delta_d = 0;
  555 + bank_mask = 0;
  556 +
  557 + if (veclen > 0) {
  558 + if (dp)
  559 + bank_mask = 0xc;
  560 + else
  561 + bank_mask = 0x18;
  562 +
  563 + /* Figure out what type of vector operation this is. */
  564 + if ((rd & bank_mask) == 0) {
  565 + /* scalar */
  566 + veclen = 0;
  567 + } else {
  568 + if (dp)
  569 + delta_d = (env->vfp.vec_stride >> 1) + 1;
  570 + else
  571 + delta_d = env->vfp.vec_stride + 1;
  572 +
  573 + if ((rm & bank_mask) == 0) {
  574 + /* mixed scalar/vector */
  575 + delta_m = 0;
  576 + } else {
  577 + /* vector */
  578 + delta_m = delta_d;
  579 + }
  580 + }
  581 + }
  582 +
  583 + /* Load the initial operands. */
  584 + if (op == 15) {
  585 + switch (rn) {
  586 + case 16:
  587 + case 17:
  588 + /* Integer source */
  589 + gen_mov_F0_vreg(0, rm);
  590 + break;
  591 + case 8:
  592 + case 9:
  593 + /* Compare */
  594 + gen_mov_F0_vreg(dp, rd);
  595 + gen_mov_F1_vreg(dp, rm);
  596 + break;
  597 + case 10:
  598 + case 11:
  599 + /* Compare with zero */
  600 + gen_mov_F0_vreg(dp, rd);
  601 + gen_vfp_F1_ld0(dp);
  602 + break;
  603 + default:
  604 + /* One source operand. */
  605 + gen_mov_F0_vreg(dp, rm);
  606 + }
  607 + } else {
  608 + /* Two source operands. */
  609 + gen_mov_F0_vreg(dp, rn);
  610 + gen_mov_F1_vreg(dp, rm);
  611 + }
  612 +
  613 + for (;;) {
  614 + /* Perform the calculation. */
  615 + switch (op) {
  616 + case 0: /* mac: fd + (fn * fm) */
  617 + gen_vfp_mul(dp);
  618 + gen_mov_F1_vreg(dp, rd);
  619 + gen_vfp_add(dp);
  620 + break;
  621 + case 1: /* nmac: fd - (fn * fm) */
  622 + gen_vfp_mul(dp);
  623 + gen_vfp_neg(dp);
  624 + gen_mov_F1_vreg(dp, rd);
  625 + gen_vfp_add(dp);
  626 + break;
  627 + case 2: /* msc: -fd + (fn * fm) */
  628 + gen_vfp_mul(dp);
  629 + gen_mov_F1_vreg(dp, rd);
  630 + gen_vfp_sub(dp);
  631 + break;
  632 + case 3: /* nmsc: -fd - (fn * fm) */
  633 + gen_vfp_mul(dp);
  634 + gen_mov_F1_vreg(dp, rd);
  635 + gen_vfp_add(dp);
  636 + gen_vfp_neg(dp);
  637 + break;
  638 + case 4: /* mul: fn * fm */
  639 + gen_vfp_mul(dp);
  640 + break;
  641 + case 5: /* nmul: -(fn * fm) */
  642 + gen_vfp_mul(dp);
  643 + gen_vfp_neg(dp);
  644 + break;
  645 + case 6: /* add: fn + fm */
  646 + gen_vfp_add(dp);
  647 + break;
  648 + case 7: /* sub: fn - fm */
  649 + gen_vfp_sub(dp);
  650 + break;
  651 + case 8: /* div: fn / fm */
  652 + gen_vfp_div(dp);
  653 + break;
  654 + case 15: /* extension space */
  655 + switch (rn) {
  656 + case 0: /* cpy */
  657 + /* no-op */
  658 + break;
  659 + case 1: /* abs */
  660 + gen_vfp_abs(dp);
  661 + break;
  662 + case 2: /* neg */
  663 + gen_vfp_neg(dp);
  664 + break;
  665 + case 3: /* sqrt */
  666 + gen_vfp_sqrt(dp);
  667 + break;
  668 + case 8: /* cmp */
  669 + gen_vfp_cmp(dp);
  670 + break;
  671 + case 9: /* cmpe */
  672 + gen_vfp_cmpe(dp);
  673 + break;
  674 + case 10: /* cmpz */
  675 + gen_vfp_cmp(dp);
  676 + break;
  677 + case 11: /* cmpez */
  678 + gen_vfp_F1_ld0(dp);
  679 + gen_vfp_cmpe(dp);
  680 + break;
  681 + case 15: /* single<->double conversion */
  682 + if (dp)
  683 + gen_op_vfp_fcvtsd();
  684 + else
  685 + gen_op_vfp_fcvtds();
  686 + break;
  687 + case 16: /* fuito */
  688 + gen_vfp_uito(dp);
  689 + break;
  690 + case 17: /* fsito */
  691 + gen_vfp_sito(dp);
  692 + break;
  693 + case 24: /* ftoui */
  694 + gen_vfp_toui(dp);
  695 + break;
  696 + case 25: /* ftouiz */
  697 + gen_vfp_touiz(dp);
  698 + break;
  699 + case 26: /* ftosi */
  700 + gen_vfp_tosi(dp);
  701 + break;
  702 + case 27: /* ftosiz */
  703 + gen_vfp_tosiz(dp);
  704 + break;
  705 + default: /* undefined */
  706 + printf ("rn:%d\n", rn);
  707 + return 1;
  708 + }
  709 + break;
  710 + default: /* undefined */
  711 + printf ("op:%d\n", op);
  712 + return 1;
  713 + }
  714 +
  715 + /* Write back the result. */
  716 + if (op == 15 && (rn >= 8 && rn <= 11))
  717 + ; /* Comparison, do nothing. */
  718 + else if (op == 15 && rn > 17)
  719 + /* Integer result. */
  720 + gen_mov_vreg_F0(0, rd);
  721 + else if (op == 15 && rn == 15)
  722 + /* conversion */
  723 + gen_mov_vreg_F0(!dp, rd);
  724 + else
  725 + gen_mov_vreg_F0(dp, rd);
  726 +
  727 + /* break out of the loop if we have finished */
  728 + if (veclen == 0)
  729 + break;
  730 +
  731 + if (op == 15 && delta_m == 0) {
  732 + /* single source one-many */
  733 + while (veclen--) {
  734 + rd = ((rd + delta_d) & (bank_mask - 1))
  735 + | (rd & bank_mask);
  736 + gen_mov_vreg_F0(dp, rd);
  737 + }
  738 + break;
  739 + }
  740 + /* Setup the next operands. */
  741 + veclen--;
  742 + rd = ((rd + delta_d) & (bank_mask - 1))
  743 + | (rd & bank_mask);
  744 +
  745 + if (op == 15) {
  746 + /* One source operand. */
  747 + rm = ((rm + delta_m) & (bank_mask - 1))
  748 + | (rm & bank_mask);
  749 + gen_mov_F0_vreg(dp, rm);
  750 + } else {
  751 + /* Two source operands. */
  752 + rn = ((rn + delta_d) & (bank_mask - 1))
  753 + | (rn & bank_mask);
  754 + gen_mov_F0_vreg(dp, rn);
  755 + if (delta_m) {
  756 + rm = ((rm + delta_m) & (bank_mask - 1))
  757 + | (rm & bank_mask);
  758 + gen_mov_F1_vreg(dp, rm);
  759 + }
  760 + }
  761 + }
  762 + }
  763 + break;
  764 + case 0xc:
  765 + case 0xd:
  766 + if (dp && (insn & (1 << 22))) {
  767 + /* two-register transfer */
  768 + rn = (insn >> 16) & 0xf;
  769 + rd = (insn >> 12) & 0xf;
  770 + if (dp) {
  771 + if (insn & (1 << 5))
  772 + return 1;
  773 + rm = insn & 0xf;
  774 + } else
  775 + rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
  776 +
  777 + if (insn & (1 << 20)) {
  778 + /* vfp->arm */
  779 + if (dp) {
  780 + gen_mov_F0_vreg(1, rm);
  781 + gen_op_vfp_mrrd();
  782 + gen_movl_reg_T0(s, rd);
  783 + gen_movl_reg_T1(s, rn);
  784 + } else {
  785 + gen_mov_F0_vreg(0, rm);
  786 + gen_op_vfp_mrs();
  787 + gen_movl_reg_T0(s, rn);
  788 + gen_mov_F0_vreg(0, rm + 1);
  789 + gen_op_vfp_mrs();
  790 + gen_movl_reg_T0(s, rd);
  791 + }
  792 + } else {
  793 + /* arm->vfp */
  794 + if (dp) {
  795 + gen_movl_T0_reg(s, rd);
  796 + gen_movl_T1_reg(s, rn);
  797 + gen_op_vfp_mdrr();
  798 + gen_mov_vreg_F0(1, rm);
  799 + } else {
  800 + gen_movl_T0_reg(s, rn);
  801 + gen_op_vfp_msr();
  802 + gen_mov_vreg_F0(0, rm);
  803 + gen_movl_T0_reg(s, rd);
  804 + gen_op_vfp_msr();
  805 + gen_mov_vreg_F0(0, rm + 1);
  806 + }
  807 + }
  808 + } else {
  809 + /* Load/store */
  810 + rn = (insn >> 16) & 0xf;
  811 + if (dp)
  812 + rd = (insn >> 12) & 0xf;
  813 + else
  814 + rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
  815 + gen_movl_T1_reg(s, rn);
  816 + if ((insn & 0x01200000) == 0x01000000) {
  817 + /* Single load/store */
  818 + offset = (insn & 0xff) << 2;
  819 + if ((insn & (1 << 23)) == 0)
  820 + offset = -offset;
  821 + gen_op_addl_T1_im(offset);
  822 + if (insn & (1 << 20)) {
  823 + gen_vfp_ld(dp);
  824 + gen_mov_vreg_F0(dp, rd);
  825 + } else {
  826 + gen_mov_F0_vreg(dp, rd);
  827 + gen_vfp_st(dp);
  828 + }
  829 + } else {
  830 + /* load/store multiple */
  831 + if (dp)
  832 + n = (insn >> 1) & 0x7f;
  833 + else
  834 + n = insn & 0xff;
  835 +
  836 + if (insn & (1 << 24)) /* pre-decrement */
  837 + gen_op_addl_T1_im(-((insn & 0xff) << 2));
  838 +
  839 + if (dp)
  840 + offset = 8;
  841 + else
  842 + offset = 4;
  843 + for (i = 0; i < n; i++) {
  844 + if (insn & (1 << 20)) {
  845 + /* load */
  846 + gen_vfp_ld(dp);
  847 + gen_mov_vreg_F0(dp, rd + i);
  848 + } else {
  849 + /* store */
  850 + gen_mov_F0_vreg(dp, rd + i);
  851 + gen_vfp_st(dp);
  852 + }
  853 + gen_op_addl_T1_im(offset);
  854 + }
  855 + if (insn & (1 << 21)) {
  856 + /* writeback */
  857 + if (insn & (1 << 24))
  858 + offset = -offset * n;
  859 + else if (dp && (insn & 1))
  860 + offset = 4;
  861 + else
  862 + offset = 0;
  863 +
  864 + if (offset != 0)
  865 + gen_op_addl_T1_im(offset);
  866 + gen_movl_reg_T1(s, rn);
  867 + }
  868 + }
  869 + }
  870 + break;
  871 + default:
  872 + /* Should never happen. */
  873 + return 1;
  874 + }
  875 + return 0;
  876 +}
  877 +
  878 +static void disas_arm_insn(CPUState * env, DisasContext *s)
358 { 879 {
359 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh; 880 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
360 881
@@ -363,6 +884,7 @@ static void disas_arm_insn(DisasContext *s) @@ -363,6 +884,7 @@ static void disas_arm_insn(DisasContext *s)
363 884
364 cond = insn >> 28; 885 cond = insn >> 28;
365 if (cond == 0xf){ 886 if (cond == 0xf){
  887 + /* Unconditional instructions. */
366 if ((insn & 0x0d70f000) == 0x0550f000) 888 if ((insn & 0x0d70f000) == 0x0550f000)
367 return; /* PLD */ 889 return; /* PLD */
368 else if ((insn & 0x0e000000) == 0x0a000000) { 890 else if ((insn & 0x0e000000) == 0x0a000000) {
@@ -381,6 +903,10 @@ static void disas_arm_insn(DisasContext *s) @@ -381,6 +903,10 @@ static void disas_arm_insn(DisasContext *s)
381 gen_op_movl_T0_im(val); 903 gen_op_movl_T0_im(val);
382 gen_bx(s); 904 gen_bx(s);
383 return; 905 return;
  906 + } else if ((insn & 0x0fe00000) == 0x0c400000) {
  907 + /* Coprocessor double register transfer. */
  908 + } else if ((insn & 0x0f000010) == 0x0e000010) {
  909 + /* Additional coprocessor register transfer. */
384 } 910 }
385 goto illegal_op; 911 goto illegal_op;
386 } 912 }
@@ -934,6 +1460,22 @@ static void disas_arm_insn(DisasContext *s) @@ -934,6 +1460,22 @@ static void disas_arm_insn(DisasContext *s)
934 s->is_jmp = DISAS_TB_JUMP; 1460 s->is_jmp = DISAS_TB_JUMP;
935 } 1461 }
936 break; 1462 break;
  1463 + case 0xc:
  1464 + case 0xd:
  1465 + case 0xe:
  1466 + /* Coprocessor. */
  1467 + op1 = (insn >> 8) & 0xf;
  1468 + switch (op1) {
  1469 + case 10:
  1470 + case 11:
  1471 + if (disas_vfp_insn (env, s, insn))
  1472 + goto illegal_op;
  1473 + break;
  1474 + default:
  1475 + /* unknown coprocessor. */
  1476 + goto illegal_op;
  1477 + }
  1478 + break;
937 case 0xf: 1479 case 0xf:
938 /* swi */ 1480 /* swi */
939 gen_op_movl_T0_im((long)s->pc); 1481 gen_op_movl_T0_im((long)s->pc);
@@ -1484,7 +2026,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, @@ -1484,7 +2026,7 @@ static inline int gen_intermediate_code_internal(CPUState *env,
1484 if (env->thumb) 2026 if (env->thumb)
1485 disas_thumb_insn(dc); 2027 disas_thumb_insn(dc);
1486 else 2028 else
1487 - disas_arm_insn(dc); 2029 + disas_arm_insn(env, dc);
1488 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 2030 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
1489 (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32)); 2031 (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
1490 switch(dc->is_jmp) { 2032 switch(dc->is_jmp) {
@@ -1557,6 +2099,11 @@ void cpu_dump_state(CPUState *env, FILE *f, @@ -1557,6 +2099,11 @@ void cpu_dump_state(CPUState *env, FILE *f,
1557 int flags) 2099 int flags)
1558 { 2100 {
1559 int i; 2101 int i;
  2102 + struct {
  2103 + uint32_t i;
  2104 + float s;
  2105 + } s0, s1;
  2106 + CPU_DoubleU d;
1560 2107
1561 for(i=0;i<16;i++) { 2108 for(i=0;i<16;i++) {
1562 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]); 2109 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
@@ -1566,11 +2113,23 @@ void cpu_dump_state(CPUState *env, FILE *f, @@ -1566,11 +2113,23 @@ void cpu_dump_state(CPUState *env, FILE *f,
1566 cpu_fprintf(f, " "); 2113 cpu_fprintf(f, " ");
1567 } 2114 }
1568 cpu_fprintf(f, "PSR=%08x %c%c%c%c\n", 2115 cpu_fprintf(f, "PSR=%08x %c%c%c%c\n",
1569 - env->cpsr, 2116 + env->cpsr,
1570 env->cpsr & (1 << 31) ? 'N' : '-', 2117 env->cpsr & (1 << 31) ? 'N' : '-',
1571 env->cpsr & (1 << 30) ? 'Z' : '-', 2118 env->cpsr & (1 << 30) ? 'Z' : '-',
1572 env->cpsr & (1 << 29) ? 'C' : '-', 2119 env->cpsr & (1 << 29) ? 'C' : '-',
1573 env->cpsr & (1 << 28) ? 'V' : '-'); 2120 env->cpsr & (1 << 28) ? 'V' : '-');
  2121 +
  2122 + for (i = 0; i < 16; i++) {
  2123 + s0.s = env->vfp.regs.s[i * 2];
  2124 + s1.s = env->vfp.regs.s[i * 2 + 1];
  2125 + d.d = env->vfp.regs.d[i];
  2126 + cpu_fprintf(f, "s%02d=%08x(%8f) s%02d=%08x(%8f) d%02d=%08x%08x(%8f)\n",
  2127 + i * 2, (int)s0.i, s0.s,
  2128 + i * 2 + 1, (int)s0.i, s0.s,
  2129 + i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
  2130 + d.d);
  2131 + cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.fpscr);
  2132 + }
1574 } 2133 }
1575 2134
1576 target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr) 2135 target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)