Revision b7bcbe95

b/Changelog
15 15
  - PC parallel port support (Mark Jonckheere)
16 16
  - initial SPARC64 support (Blue Swirl)
17 17
  - armv5te user mode support (Paul Brook)
18
  - ARM VFP support (Paul Brook)
18 19

  
19 20
version 0.6.1:
20 21

  
b/Makefile.target
259 259
LIBOBJS+= op_helper.o helper.o
260 260
endif
261 261

  
262
ifeq ($(TARGET_BASE_ARCH), arm)
263
LIBOBJS+= op_helper.o
264
endif
265

  
262 266
# NOTE: the disassembler code is only needed for debugging
263 267
LIBOBJS+=disas.o 
264 268
ifeq ($(findstring i386, $(TARGET_ARCH) $(ARCH)),i386)
b/cpu-exec.c
346 346
                cs_base = env->segs[R_CS].base;
347 347
                pc = cs_base + env->eip;
348 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 351
                cs_base = 0;
351 352
                pc = env->regs[15];
352 353
#elif defined(TARGET_SPARC)
......
619 620
#endif
620 621
#elif defined(TARGET_ARM)
621 622
    env->cpsr = compute_cpsr();
623
    /* XXX: Save/restore host fpu exception state?.  */
622 624
#elif defined(TARGET_SPARC)
623 625
#elif defined(TARGET_PPC)
624 626
#else
b/target-arm/cpu.h
29 29
#define EXCP_PREFETCH_ABORT  3
30 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 40
typedef struct CPUARMState {
33 41
    uint32_t regs[16];
34 42
    uint32_t cpsr;
......
50 58
    int interrupt_request;
51 59
    struct TranslationBlock *current_tb;
52 60
    int user_mode_only;
61
    uint32_t address;
53 62

  
54 63
    /* in order to avoid passing too many arguments to the memory
55 64
       write helpers, we store some rarely used information in the CPU
......
58 67
                                   written */
59 68
    unsigned long mem_write_vaddr; /* target virtual addr at which the
60 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 89
    /* user data */
62 90
    void *opaque;
63 91
} CPUARMState;
b/target-arm/exec.h
24 24
register uint32_t T1 asm(AREG2);
25 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 34
#include "cpu.h"
28 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 37
/* Implemented CPSR bits.  */
35 38
#define CACHED_CPSR_BITS 0xf8000000
36 39
static inline int compute_cpsr(void)
......
51 54

  
52 55
int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
53 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);
b/target-arm/op.c
2 2
 *  ARM micro operations
3 3
 * 
4 4
 *  Copyright (c) 2003 Fabrice Bellard
5
 *  Copyright (c) 2005 CodeSourcery, LLC
5 6
 *
6 7
 * This library is free software; you can redistribute it and/or
7 8
 * modify it under the terms of the GNU Lesser General Public
......
857 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
}
b/target-arm/op_helper.c
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
}
b/target-arm/translate.c
2 2
 *  ARM translation
3 3
 * 
4 4
 *  Copyright (c) 2003 Fabrice Bellard
5
 *  Copyright (c) 2005 CodeSourcery, LLC
5 6
 *
6 7
 * This library is free software; you can redistribute it and/or
7 8
 * modify it under the terms of the GNU Lesser General Public
......
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 880
    unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
360 881
    
......
363 884
    
364 885
    cond = insn >> 28;
365 886
    if (cond == 0xf){
887
        /* Unconditional instructions.  */
366 888
        if ((insn & 0x0d70f000) == 0x0550f000)
367 889
            return; /* PLD */
368 890
        else if ((insn & 0x0e000000) == 0x0a000000) {
......
381 903
            gen_op_movl_T0_im(val);
382 904
            gen_bx(s);
383 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 911
        goto illegal_op;
386 912
    }
......
934 1460
                s->is_jmp = DISAS_TB_JUMP;
935 1461
            }
936 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 1479
        case 0xf:
938 1480
            /* swi */
939 1481
            gen_op_movl_T0_im((long)s->pc);
......
1484 2026
        if (env->thumb)
1485 2027
          disas_thumb_insn(dc);
1486 2028
        else
1487
          disas_arm_insn(dc);
2029
          disas_arm_insn(env, dc);
1488 2030
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 
1489 2031
             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
1490 2032
    switch(dc->is_jmp) {
......
1557 2099
                    int flags)
1558 2100
{
1559 2101
    int i;
2102
    struct {
2103
        uint32_t i;
2104
        float s;
2105
    } s0, s1;
2106
    CPU_DoubleU d;
1560 2107

  
1561 2108
    for(i=0;i<16;i++) {
1562 2109
        cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
......
1566 2113
            cpu_fprintf(f, " ");
1567 2114
    }
1568 2115
    cpu_fprintf(f, "PSR=%08x %c%c%c%c\n", 
1569
            env->cpsr, 
2116
             env->cpsr, 
1570 2117
            env->cpsr & (1 << 31) ? 'N' : '-',
1571 2118
            env->cpsr & (1 << 30) ? 'Z' : '-',
1572 2119
            env->cpsr & (1 << 29) ? 'C' : '-',
1573 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 2135
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)

Also available in: Unified diff