Statistics
| Branch: | Revision:

root / target-arm / op_helper.c @ 157777ef

History | View | Annotate | Download (5.6 kB)

1 b7bcbe95 bellard
/*
2 b7bcbe95 bellard
 *  ARM helper routines
3 b7bcbe95 bellard
 * 
4 b7bcbe95 bellard
 *  Copyright (c) 2005 CodeSourcery, LLC
5 b7bcbe95 bellard
 *
6 b7bcbe95 bellard
 * This library is free software; you can redistribute it and/or
7 b7bcbe95 bellard
 * modify it under the terms of the GNU Lesser General Public
8 b7bcbe95 bellard
 * License as published by the Free Software Foundation; either
9 b7bcbe95 bellard
 * version 2 of the License, or (at your option) any later version.
10 b7bcbe95 bellard
 *
11 b7bcbe95 bellard
 * This library is distributed in the hope that it will be useful,
12 b7bcbe95 bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 b7bcbe95 bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 b7bcbe95 bellard
 * Lesser General Public License for more details.
15 b7bcbe95 bellard
 *
16 b7bcbe95 bellard
 * You should have received a copy of the GNU Lesser General Public
17 b7bcbe95 bellard
 * License along with this library; if not, write to the Free Software
18 b7bcbe95 bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 b7bcbe95 bellard
 */
20 b7bcbe95 bellard
21 b7bcbe95 bellard
#include <math.h>
22 b7bcbe95 bellard
#include <fenv.h>
23 b7bcbe95 bellard
#include "exec.h"
24 b7bcbe95 bellard
25 b7bcbe95 bellard
/* If the host doesn't define C99 math intrinsics then use the normal
26 b7bcbe95 bellard
   operators.  This may generate excess exceptions, but it's probably
27 b7bcbe95 bellard
   near enough for most things.  */
28 b7bcbe95 bellard
#ifndef isless
29 b7bcbe95 bellard
#define isless(x, y) (x < y)
30 b7bcbe95 bellard
#endif
31 b7bcbe95 bellard
#ifndef isgreater
32 b7bcbe95 bellard
#define isgreater(x, y) (x > y)
33 b7bcbe95 bellard
#endif
34 b7bcbe95 bellard
#ifndef isunordered
35 b7bcbe95 bellard
#define isunordered(x, y) (!((x < y) || (x >= y)))
36 b7bcbe95 bellard
#endif
37 b7bcbe95 bellard
38 b7bcbe95 bellard
void raise_exception(int tt)
39 b7bcbe95 bellard
{
40 b7bcbe95 bellard
    env->exception_index = tt;
41 b7bcbe95 bellard
    cpu_loop_exit();
42 b7bcbe95 bellard
}
43 b7bcbe95 bellard
44 b7bcbe95 bellard
/* thread support */
45 b7bcbe95 bellard
46 b7bcbe95 bellard
spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
47 b7bcbe95 bellard
48 b7bcbe95 bellard
void cpu_lock(void)
49 b7bcbe95 bellard
{
50 b7bcbe95 bellard
    spin_lock(&global_cpu_lock);
51 b7bcbe95 bellard
}
52 b7bcbe95 bellard
53 b7bcbe95 bellard
void cpu_unlock(void)
54 b7bcbe95 bellard
{
55 b7bcbe95 bellard
    spin_unlock(&global_cpu_lock);
56 b7bcbe95 bellard
}
57 b7bcbe95 bellard
58 b7bcbe95 bellard
/* VFP support.  */
59 b7bcbe95 bellard
60 b7bcbe95 bellard
void do_vfp_abss(void)
61 b7bcbe95 bellard
{
62 b7bcbe95 bellard
  FT0s = fabsf(FT0s);
63 b7bcbe95 bellard
}
64 b7bcbe95 bellard
65 b7bcbe95 bellard
void do_vfp_absd(void)
66 b7bcbe95 bellard
{
67 b7bcbe95 bellard
  FT0d = fabs(FT0d);
68 b7bcbe95 bellard
}
69 b7bcbe95 bellard
70 b7bcbe95 bellard
void do_vfp_sqrts(void)
71 b7bcbe95 bellard
{
72 b7bcbe95 bellard
  FT0s = sqrtf(FT0s);
73 b7bcbe95 bellard
}
74 b7bcbe95 bellard
75 b7bcbe95 bellard
void do_vfp_sqrtd(void)
76 b7bcbe95 bellard
{
77 b7bcbe95 bellard
  FT0d = sqrt(FT0d);
78 b7bcbe95 bellard
}
79 b7bcbe95 bellard
80 b7bcbe95 bellard
/* We use an == operator first to generate teh correct floating point
81 b7bcbe95 bellard
   exception.  Subsequent comparisons use the exception-safe macros.  */
82 b7bcbe95 bellard
#define DO_VFP_cmp(p)                     \
83 b7bcbe95 bellard
void do_vfp_cmp##p(void)                  \
84 b7bcbe95 bellard
{                                         \
85 b7bcbe95 bellard
    uint32_t flags;                       \
86 b7bcbe95 bellard
    if (FT0##p == FT1##p)                 \
87 b7bcbe95 bellard
        flags = 0xc;                      \
88 b7bcbe95 bellard
    else if (isless (FT0##p, FT1##p))     \
89 b7bcbe95 bellard
        flags = 0x8;                      \
90 b7bcbe95 bellard
    else if (isgreater (FT0##p, FT1##p))  \
91 b7bcbe95 bellard
        flags = 0x2;                      \
92 b7bcbe95 bellard
    else /* unordered */                  \
93 b7bcbe95 bellard
        flags = 0x3;                      \
94 b7bcbe95 bellard
    env->vfp.fpscr = (flags << 28) | (env->vfp.fpscr & 0x0fffffff); \
95 b7bcbe95 bellard
    FORCE_RET();                          \
96 b7bcbe95 bellard
}
97 b7bcbe95 bellard
DO_VFP_cmp(s)
98 b7bcbe95 bellard
DO_VFP_cmp(d)
99 b7bcbe95 bellard
#undef DO_VFP_cmp
100 b7bcbe95 bellard
101 b7bcbe95 bellard
/* We use a > operator first to get FP exceptions right.  */
102 b7bcbe95 bellard
#define DO_VFP_cmpe(p)                      \
103 b7bcbe95 bellard
void do_vfp_cmpe##p(void)                   \
104 b7bcbe95 bellard
{                                           \
105 b7bcbe95 bellard
    uint32_t flags;                         \
106 b7bcbe95 bellard
    if (FT0##p > FT1##p)                    \
107 b7bcbe95 bellard
        flags = 0x2;                        \
108 b7bcbe95 bellard
    else if (isless (FT0##p, FT1##p))       \
109 b7bcbe95 bellard
        flags = 0x8;                        \
110 b7bcbe95 bellard
    else if (isunordered (FT0##p, FT1##p))  \
111 b7bcbe95 bellard
        flags = 0x3;                        \
112 b7bcbe95 bellard
    else /* equal */                        \
113 b7bcbe95 bellard
        flags = 0xc;                        \
114 b7bcbe95 bellard
    env->vfp.fpscr = (flags << 28) | (env->vfp.fpscr & 0x0fffffff); \
115 b7bcbe95 bellard
    FORCE_RET();                            \
116 b7bcbe95 bellard
}
117 b7bcbe95 bellard
DO_VFP_cmpe(s)
118 b7bcbe95 bellard
DO_VFP_cmpe(d)
119 b7bcbe95 bellard
#undef DO_VFP_cmpe
120 b7bcbe95 bellard
121 b7bcbe95 bellard
/* Convert host exception flags to vfp form.  */
122 b7bcbe95 bellard
int vfp_exceptbits_from_host(int host_bits)
123 b7bcbe95 bellard
{
124 b7bcbe95 bellard
    int target_bits = 0;
125 b7bcbe95 bellard
126 b7bcbe95 bellard
#ifdef FE_INVALID
127 b7bcbe95 bellard
    if (host_bits & FE_INVALID)
128 b7bcbe95 bellard
        target_bits |= 1;
129 b7bcbe95 bellard
#endif
130 b7bcbe95 bellard
#ifdef FE_DIVBYZERO
131 b7bcbe95 bellard
    if (host_bits & FE_DIVBYZERO)
132 b7bcbe95 bellard
        target_bits |= 2;
133 b7bcbe95 bellard
#endif
134 b7bcbe95 bellard
#ifdef FE_OVERFLOW
135 b7bcbe95 bellard
    if (host_bits & FE_OVERFLOW)
136 b7bcbe95 bellard
        target_bits |= 4;
137 b7bcbe95 bellard
#endif
138 b7bcbe95 bellard
#ifdef FE_UNDERFLOW
139 b7bcbe95 bellard
    if (host_bits & FE_UNDERFLOW)
140 b7bcbe95 bellard
        target_bits |= 8;
141 b7bcbe95 bellard
#endif
142 b7bcbe95 bellard
#ifdef FE_INEXACT
143 b7bcbe95 bellard
    if (host_bits & FE_INEXACT)
144 b7bcbe95 bellard
        target_bits |= 0x10;
145 b7bcbe95 bellard
#endif
146 b7bcbe95 bellard
    /* C doesn't define an inexact exception.  */
147 b7bcbe95 bellard
    return target_bits;
148 b7bcbe95 bellard
}
149 b7bcbe95 bellard
150 b7bcbe95 bellard
/* Convert vfp exception flags to target form.  */
151 b7bcbe95 bellard
int vfp_host_exceptbits_to_host(int target_bits)
152 b7bcbe95 bellard
{
153 b7bcbe95 bellard
    int host_bits = 0;
154 b7bcbe95 bellard
155 b7bcbe95 bellard
#ifdef FE_INVALID
156 b7bcbe95 bellard
    if (target_bits & 1)
157 b7bcbe95 bellard
        host_bits |= FE_INVALID;
158 b7bcbe95 bellard
#endif
159 b7bcbe95 bellard
#ifdef FE_DIVBYZERO
160 b7bcbe95 bellard
    if (target_bits & 2)
161 b7bcbe95 bellard
        host_bits |= FE_DIVBYZERO;
162 b7bcbe95 bellard
#endif
163 b7bcbe95 bellard
#ifdef FE_OVERFLOW
164 b7bcbe95 bellard
    if (target_bits & 4)
165 b7bcbe95 bellard
        host_bits |= FE_OVERFLOW;
166 b7bcbe95 bellard
#endif
167 b7bcbe95 bellard
#ifdef FE_UNDERFLOW
168 b7bcbe95 bellard
    if (target_bits & 8)
169 b7bcbe95 bellard
        host_bits |= FE_UNDERFLOW;
170 b7bcbe95 bellard
#endif
171 b7bcbe95 bellard
#ifdef FE_INEXACT
172 b7bcbe95 bellard
    if (target_bits & 0x10)
173 b7bcbe95 bellard
        host_bits |= FE_INEXACT;
174 b7bcbe95 bellard
#endif
175 b7bcbe95 bellard
    return host_bits;
176 b7bcbe95 bellard
}
177 b7bcbe95 bellard
178 b7bcbe95 bellard
void do_vfp_set_fpscr(void)
179 b7bcbe95 bellard
{
180 b7bcbe95 bellard
    int i;
181 b7bcbe95 bellard
    uint32_t changed;
182 b7bcbe95 bellard
183 b7bcbe95 bellard
    changed = env->vfp.fpscr;
184 b7bcbe95 bellard
    env->vfp.fpscr = (T0 & 0xffc8ffff);
185 b7bcbe95 bellard
    env->vfp.vec_len = (T0 >> 16) & 7;
186 b7bcbe95 bellard
    env->vfp.vec_stride = (T0 >> 20) & 3;
187 b7bcbe95 bellard
188 b7bcbe95 bellard
    changed ^= T0;
189 b7bcbe95 bellard
    if (changed & (3 << 22)) {
190 b7bcbe95 bellard
        i = (T0 >> 22) & 3;
191 b7bcbe95 bellard
        switch (i) {
192 b7bcbe95 bellard
        case 0:
193 b7bcbe95 bellard
            i = FE_TONEAREST;
194 b7bcbe95 bellard
            break;
195 b7bcbe95 bellard
        case 1:
196 b7bcbe95 bellard
            i = FE_UPWARD;
197 b7bcbe95 bellard
            break;
198 b7bcbe95 bellard
        case 2:
199 b7bcbe95 bellard
            i = FE_DOWNWARD;
200 b7bcbe95 bellard
            break;
201 b7bcbe95 bellard
        case 3:
202 b7bcbe95 bellard
            i = FE_TOWARDZERO;
203 b7bcbe95 bellard
            break;
204 b7bcbe95 bellard
        }
205 b7bcbe95 bellard
        fesetround (i);
206 b7bcbe95 bellard
    }
207 b7bcbe95 bellard
208 b7bcbe95 bellard
    /* Clear host exception flags.  */
209 b7bcbe95 bellard
    feclearexcept(FE_ALL_EXCEPT);
210 b7bcbe95 bellard
211 b7bcbe95 bellard
#ifdef feenableexcept
212 b7bcbe95 bellard
    if (changed & 0x1f00) {
213 b7bcbe95 bellard
        i = vfp_exceptbits_to_host((T0 >> 8) & 0x1f);
214 b7bcbe95 bellard
        feenableexcept (i);
215 b7bcbe95 bellard
        fedisableexcept (FE_ALL_EXCEPT & ~i);
216 b7bcbe95 bellard
    }
217 b7bcbe95 bellard
#endif
218 b7bcbe95 bellard
    /* XXX: FZ and DN are not implemented.  */
219 b7bcbe95 bellard
}
220 b7bcbe95 bellard
221 b7bcbe95 bellard
void do_vfp_get_fpscr(void)
222 b7bcbe95 bellard
{
223 b7bcbe95 bellard
    int i;
224 b7bcbe95 bellard
225 b7bcbe95 bellard
    T0 = (env->vfp.fpscr & 0xffc8ffff) | (env->vfp.vec_len << 16)
226 b7bcbe95 bellard
          | (env->vfp.vec_stride << 20);
227 b7bcbe95 bellard
    i = fetestexcept(FE_ALL_EXCEPT);
228 b7bcbe95 bellard
    T0 |= vfp_exceptbits_from_host(i);
229 b7bcbe95 bellard
}