Revision 4373f3ce target-arm/op_helper.c

b/target-arm/op_helper.c
40 40
    spin_unlock(&global_cpu_lock);
41 41
}
42 42

  
43
/* VFP support.  */
44

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

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

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

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

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

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

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

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

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

  
134
void do_vfp_set_fpscr(void)
135
{
136
    int i;
137
    uint32_t changed;
138

  
139
    changed = env->vfp.xregs[ARM_VFP_FPSCR];
140
    env->vfp.xregs[ARM_VFP_FPSCR] = (T0 & 0xffc8ffff);
141
    env->vfp.vec_len = (T0 >> 16) & 7;
142
    env->vfp.vec_stride = (T0 >> 20) & 3;
143

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

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

  
169
void do_vfp_get_fpscr(void)
170
{
171
    int i;
172

  
173
    T0 = (env->vfp.xregs[ARM_VFP_FPSCR] & 0xffc8ffff) | (env->vfp.vec_len << 16)
174
          | (env->vfp.vec_stride << 20);
175
    i = get_float_exception_flags(&env->vfp.fp_status);
176
    T0 |= vfp_exceptbits_from_host(i);
177
}
178

  
179
float32 helper_recps_f32(float32 a, float32 b)
180
{
181
    float_status *s = &env->vfp.fp_status;
182
    float32 two = int32_to_float32(2, s);
183
    return float32_sub(two, float32_mul(a, b, s), s);
184
}
185

  
186
float32 helper_rsqrts_f32(float32 a, float32 b)
187
{
188
    float_status *s = &env->vfp.fp_status;
189
    float32 three = int32_to_float32(3, s);
190
    return float32_sub(three, float32_mul(a, b, s), s);
191
}
192

  
193
/* TODO: The architecture specifies the value that the estimate functions
194
   should return.  We return the exact reciprocal/root instead.  */
195
float32 helper_recpe_f32(float32 a)
196
{
197
    float_status *s = &env->vfp.fp_status;
198
    float32 one = int32_to_float32(1, s);
199
    return float32_div(one, a, s);
200
}
201

  
202
float32 helper_rsqrte_f32(float32 a)
203
{
204
    float_status *s = &env->vfp.fp_status;
205
    float32 one = int32_to_float32(1, s);
206
    return float32_div(one, float32_sqrt(a, s), s);
207
}
208

  
209
uint32_t helper_recpe_u32(uint32_t a)
210
{
211
    float_status *s = &env->vfp.fp_status;
212
    float32 tmp;
213
    tmp = int32_to_float32(a, s);
214
    tmp = float32_scalbn(tmp, -32, s);
215
    tmp = helper_recpe_f32(tmp);
216
    tmp = float32_scalbn(tmp, 31, s);
217
    return float32_to_int32(tmp, s);
218
}
219

  
220
uint32_t helper_rsqrte_u32(uint32_t a)
221
{
222
    float_status *s = &env->vfp.fp_status;
223
    float32 tmp;
224
    tmp = int32_to_float32(a, s);
225
    tmp = float32_scalbn(tmp, -32, s);
226
    tmp = helper_rsqrte_f32(tmp);
227
    tmp = float32_scalbn(tmp, 31, s);
228
    return float32_to_int32(tmp, s);
229
}
230

  
231 43
void helper_neon_tbl(int rn, int maxindex)
232 44
{
233 45
    uint32_t val;

Also available in: Unified diff