Statistics
| Branch: | Revision:

root / target-arm / op_helper.c @ 89344d5a

History | View | Annotate | Download (4.5 kB)

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
#include "exec.h"
21

    
22
void raise_exception(int tt)
23
{
24
    env->exception_index = tt;
25
    cpu_loop_exit();
26
}
27

    
28
/* thread support */
29

    
30
spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
31

    
32
void cpu_lock(void)
33
{
34
    spin_lock(&global_cpu_lock);
35
}
36

    
37
void cpu_unlock(void)
38
{
39
    spin_unlock(&global_cpu_lock);
40
}
41

    
42
/* VFP support.  */
43

    
44
void do_vfp_abss(void)
45
{
46
    FT0s = float32_abs(FT0s);
47
}
48

    
49
void do_vfp_absd(void)
50
{
51
    FT0d = float64_abs(FT0d);
52
}
53

    
54
void do_vfp_sqrts(void)
55
{
56
    FT0s = float32_sqrt(FT0s, &env->vfp.fp_status);
57
}
58

    
59
void do_vfp_sqrtd(void)
60
{
61
    FT0d = float64_sqrt(FT0d, &env->vfp.fp_status);
62
}
63

    
64
/* XXX: check quiet/signaling case */
65
#define DO_VFP_cmp(p, size)               \
66
void do_vfp_cmp##p(void)                  \
67
{                                         \
68
    uint32_t flags;                       \
69
    switch(float ## size ## _compare_quiet(FT0##p, FT1##p, &env->vfp.fp_status)) {\
70
    case 0: flags = 0x6; break;\
71
    case -1: flags = 0x8; break;\
72
    case 1: flags = 0x2; break;\
73
    default: case 2: flags = 0x3; break;\
74
    }\
75
    env->vfp.fpscr = (flags << 28) | (env->vfp.fpscr & 0x0fffffff); \
76
    FORCE_RET();                          \
77
}\
78
\
79
void do_vfp_cmpe##p(void)                   \
80
{                                           \
81
    uint32_t flags;                       \
82
    switch(float ## size ## _compare(FT0##p, FT1##p, &env->vfp.fp_status)) {\
83
    case 0: flags = 0x6; break;\
84
    case -1: flags = 0x8; break;\
85
    case 1: flags = 0x2; break;\
86
    default: case 2: flags = 0x3; break;\
87
    }\
88
    env->vfp.fpscr = (flags << 28) | (env->vfp.fpscr & 0x0fffffff); \
89
    FORCE_RET();                          \
90
}
91
DO_VFP_cmp(s, 32)
92
DO_VFP_cmp(d, 64)
93
#undef DO_VFP_cmp
94

    
95
/* Convert host exception flags to vfp form.  */
96
static inline int vfp_exceptbits_from_host(int host_bits)
97
{
98
    int target_bits = 0;
99

    
100
    if (host_bits & float_flag_invalid)
101
        target_bits |= 1;
102
    if (host_bits & float_flag_divbyzero)
103
        target_bits |= 2;
104
    if (host_bits & float_flag_overflow)
105
        target_bits |= 4;
106
    if (host_bits & float_flag_underflow)
107
        target_bits |= 8;
108
    if (host_bits & float_flag_inexact)
109
        target_bits |= 0x10;
110
    return target_bits;
111
}
112

    
113
/* Convert vfp exception flags to target form.  */
114
static inline int vfp_exceptbits_to_host(int target_bits)
115
{
116
    int host_bits = 0;
117

    
118
    if (target_bits & 1)
119
        host_bits |= float_flag_invalid;
120
    if (target_bits & 2)
121
        host_bits |= float_flag_divbyzero;
122
    if (target_bits & 4)
123
        host_bits |= float_flag_overflow;
124
    if (target_bits & 8)
125
        host_bits |= float_flag_underflow;
126
    if (target_bits & 0x10)
127
        host_bits |= float_flag_inexact;
128
    return host_bits;
129
}
130

    
131
void do_vfp_set_fpscr(void)
132
{
133
    int i;
134
    uint32_t changed;
135

    
136
    changed = env->vfp.fpscr;
137
    env->vfp.fpscr = (T0 & 0xffc8ffff);
138
    env->vfp.vec_len = (T0 >> 16) & 7;
139
    env->vfp.vec_stride = (T0 >> 20) & 3;
140

    
141
    changed ^= T0;
142
    if (changed & (3 << 22)) {
143
        i = (T0 >> 22) & 3;
144
        switch (i) {
145
        case 0:
146
            i = float_round_nearest_even;
147
            break;
148
        case 1:
149
            i = float_round_up;
150
            break;
151
        case 2:
152
            i = float_round_down;
153
            break;
154
        case 3:
155
            i = float_round_to_zero;
156
            break;
157
        }
158
        set_float_rounding_mode(i, &env->vfp.fp_status);
159
    }
160

    
161
    i = vfp_exceptbits_to_host((T0 >> 8) & 0x1f);
162
    set_float_exception_flags(i, &env->vfp.fp_status);
163
    /* XXX: FZ and DN are not implemented.  */
164
}
165

    
166
void do_vfp_get_fpscr(void)
167
{
168
    int i;
169

    
170
    T0 = (env->vfp.fpscr & 0xffc8ffff) | (env->vfp.vec_len << 16)
171
          | (env->vfp.vec_stride << 20);
172
    i = get_float_exception_flags(&env->vfp.fp_status);
173
    T0 |= vfp_exceptbits_from_host(i);
174
}