Statistics
| Branch: | Revision:

root / target-arm / op_helper.c @ b7a100da

History | View | Annotate | Download (4.5 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
#include "exec.h"
21 b7bcbe95 bellard
22 b7bcbe95 bellard
void raise_exception(int tt)
23 b7bcbe95 bellard
{
24 b7bcbe95 bellard
    env->exception_index = tt;
25 b7bcbe95 bellard
    cpu_loop_exit();
26 b7bcbe95 bellard
}
27 b7bcbe95 bellard
28 b7bcbe95 bellard
/* thread support */
29 b7bcbe95 bellard
30 b7bcbe95 bellard
spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
31 b7bcbe95 bellard
32 b7bcbe95 bellard
void cpu_lock(void)
33 b7bcbe95 bellard
{
34 b7bcbe95 bellard
    spin_lock(&global_cpu_lock);
35 b7bcbe95 bellard
}
36 b7bcbe95 bellard
37 b7bcbe95 bellard
void cpu_unlock(void)
38 b7bcbe95 bellard
{
39 b7bcbe95 bellard
    spin_unlock(&global_cpu_lock);
40 b7bcbe95 bellard
}
41 b7bcbe95 bellard
42 b7bcbe95 bellard
/* VFP support.  */
43 b7bcbe95 bellard
44 b7bcbe95 bellard
void do_vfp_abss(void)
45 b7bcbe95 bellard
{
46 53cd6637 bellard
    FT0s = float32_abs(FT0s);
47 b7bcbe95 bellard
}
48 b7bcbe95 bellard
49 b7bcbe95 bellard
void do_vfp_absd(void)
50 b7bcbe95 bellard
{
51 53cd6637 bellard
    FT0d = float64_abs(FT0d);
52 b7bcbe95 bellard
}
53 b7bcbe95 bellard
54 b7bcbe95 bellard
void do_vfp_sqrts(void)
55 b7bcbe95 bellard
{
56 53cd6637 bellard
    FT0s = float32_sqrt(FT0s, &env->vfp.fp_status);
57 b7bcbe95 bellard
}
58 b7bcbe95 bellard
59 b7bcbe95 bellard
void do_vfp_sqrtd(void)
60 b7bcbe95 bellard
{
61 53cd6637 bellard
    FT0d = float64_sqrt(FT0d, &env->vfp.fp_status);
62 b7bcbe95 bellard
}
63 b7bcbe95 bellard
64 53cd6637 bellard
/* XXX: check quiet/signaling case */
65 53cd6637 bellard
#define DO_VFP_cmp(p, size)               \
66 b7bcbe95 bellard
void do_vfp_cmp##p(void)                  \
67 b7bcbe95 bellard
{                                         \
68 b7bcbe95 bellard
    uint32_t flags;                       \
69 53cd6637 bellard
    switch(float ## size ## _compare_quiet(FT0##p, FT1##p, &env->vfp.fp_status)) {\
70 53cd6637 bellard
    case 0: flags = 0xc; break;\
71 53cd6637 bellard
    case -1: flags = 0x8; break;\
72 53cd6637 bellard
    case 1: flags = 0x2; break;\
73 53cd6637 bellard
    default: case 2: flags = 0x3; break;\
74 53cd6637 bellard
    }\
75 b7bcbe95 bellard
    env->vfp.fpscr = (flags << 28) | (env->vfp.fpscr & 0x0fffffff); \
76 b7bcbe95 bellard
    FORCE_RET();                          \
77 53cd6637 bellard
}\
78 53cd6637 bellard
\
79 b7bcbe95 bellard
void do_vfp_cmpe##p(void)                   \
80 b7bcbe95 bellard
{                                           \
81 53cd6637 bellard
    uint32_t flags;                       \
82 53cd6637 bellard
    switch(float ## size ## _compare(FT0##p, FT1##p, &env->vfp.fp_status)) {\
83 53cd6637 bellard
    case 0: flags = 0xc; break;\
84 53cd6637 bellard
    case -1: flags = 0x8; break;\
85 53cd6637 bellard
    case 1: flags = 0x2; break;\
86 53cd6637 bellard
    default: case 2: flags = 0x3; break;\
87 53cd6637 bellard
    }\
88 b7bcbe95 bellard
    env->vfp.fpscr = (flags << 28) | (env->vfp.fpscr & 0x0fffffff); \
89 53cd6637 bellard
    FORCE_RET();                          \
90 b7bcbe95 bellard
}
91 53cd6637 bellard
DO_VFP_cmp(s, 32)
92 53cd6637 bellard
DO_VFP_cmp(d, 64)
93 53cd6637 bellard
#undef DO_VFP_cmp
94 b7bcbe95 bellard
95 b7bcbe95 bellard
/* Convert host exception flags to vfp form.  */
96 53cd6637 bellard
static inline int vfp_exceptbits_from_host(int host_bits)
97 b7bcbe95 bellard
{
98 b7bcbe95 bellard
    int target_bits = 0;
99 b7bcbe95 bellard
100 53cd6637 bellard
    if (host_bits & float_flag_invalid)
101 b7bcbe95 bellard
        target_bits |= 1;
102 53cd6637 bellard
    if (host_bits & float_flag_divbyzero)
103 b7bcbe95 bellard
        target_bits |= 2;
104 53cd6637 bellard
    if (host_bits & float_flag_overflow)
105 b7bcbe95 bellard
        target_bits |= 4;
106 53cd6637 bellard
    if (host_bits & float_flag_underflow)
107 b7bcbe95 bellard
        target_bits |= 8;
108 53cd6637 bellard
    if (host_bits & float_flag_inexact)
109 b7bcbe95 bellard
        target_bits |= 0x10;
110 b7bcbe95 bellard
    return target_bits;
111 b7bcbe95 bellard
}
112 b7bcbe95 bellard
113 b7bcbe95 bellard
/* Convert vfp exception flags to target form.  */
114 53cd6637 bellard
static inline int vfp_exceptbits_to_host(int target_bits)
115 b7bcbe95 bellard
{
116 b7bcbe95 bellard
    int host_bits = 0;
117 b7bcbe95 bellard
118 b7bcbe95 bellard
    if (target_bits & 1)
119 53cd6637 bellard
        host_bits |= float_flag_invalid;
120 b7bcbe95 bellard
    if (target_bits & 2)
121 53cd6637 bellard
        host_bits |= float_flag_divbyzero;
122 b7bcbe95 bellard
    if (target_bits & 4)
123 53cd6637 bellard
        host_bits |= float_flag_overflow;
124 b7bcbe95 bellard
    if (target_bits & 8)
125 53cd6637 bellard
        host_bits |= float_flag_underflow;
126 b7bcbe95 bellard
    if (target_bits & 0x10)
127 53cd6637 bellard
        host_bits |= float_flag_inexact;
128 b7bcbe95 bellard
    return host_bits;
129 b7bcbe95 bellard
}
130 b7bcbe95 bellard
131 b7bcbe95 bellard
void do_vfp_set_fpscr(void)
132 b7bcbe95 bellard
{
133 b7bcbe95 bellard
    int i;
134 b7bcbe95 bellard
    uint32_t changed;
135 b7bcbe95 bellard
136 b7bcbe95 bellard
    changed = env->vfp.fpscr;
137 b7bcbe95 bellard
    env->vfp.fpscr = (T0 & 0xffc8ffff);
138 b7bcbe95 bellard
    env->vfp.vec_len = (T0 >> 16) & 7;
139 b7bcbe95 bellard
    env->vfp.vec_stride = (T0 >> 20) & 3;
140 b7bcbe95 bellard
141 b7bcbe95 bellard
    changed ^= T0;
142 b7bcbe95 bellard
    if (changed & (3 << 22)) {
143 b7bcbe95 bellard
        i = (T0 >> 22) & 3;
144 b7bcbe95 bellard
        switch (i) {
145 b7bcbe95 bellard
        case 0:
146 53cd6637 bellard
            i = float_round_nearest_even;
147 b7bcbe95 bellard
            break;
148 b7bcbe95 bellard
        case 1:
149 53cd6637 bellard
            i = float_round_up;
150 b7bcbe95 bellard
            break;
151 b7bcbe95 bellard
        case 2:
152 53cd6637 bellard
            i = float_round_down;
153 b7bcbe95 bellard
            break;
154 b7bcbe95 bellard
        case 3:
155 53cd6637 bellard
            i = float_round_to_zero;
156 b7bcbe95 bellard
            break;
157 b7bcbe95 bellard
        }
158 53cd6637 bellard
        set_float_rounding_mode(i, &env->vfp.fp_status);
159 b7bcbe95 bellard
    }
160 b7bcbe95 bellard
161 53cd6637 bellard
    i = vfp_exceptbits_to_host((T0 >> 8) & 0x1f);
162 53cd6637 bellard
    set_float_exception_flags(i, &env->vfp.fp_status);
163 b7bcbe95 bellard
    /* XXX: FZ and DN are not implemented.  */
164 b7bcbe95 bellard
}
165 b7bcbe95 bellard
166 b7bcbe95 bellard
void do_vfp_get_fpscr(void)
167 b7bcbe95 bellard
{
168 b7bcbe95 bellard
    int i;
169 b7bcbe95 bellard
170 b7bcbe95 bellard
    T0 = (env->vfp.fpscr & 0xffc8ffff) | (env->vfp.vec_len << 16)
171 b7bcbe95 bellard
          | (env->vfp.vec_stride << 20);
172 53cd6637 bellard
    i = get_float_exception_flags(&env->vfp.fp_status);
173 b7bcbe95 bellard
    T0 |= vfp_exceptbits_from_host(i);
174 b7bcbe95 bellard
}