~jderose/ubuntu/raring/qemu/vde-again

« back to all changes in this revision

Viewing changes to target-arm/op_helper.c

  • Committer: Bazaar Package Importer
  • Author(s): Aurelien Jarno, Aurelien Jarno
  • Date: 2009-03-22 10:13:17 UTC
  • mfrom: (1.2.1 upstream) (6.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20090322101317-iigjtnu5qil35dtb
Tags: 0.10.1-1
[ Aurelien Jarno ]
* New upstream stable release:
  - patches/80_stable-branch.patch: remove.
* debian/control: 
  - Remove depends on proll.
  - Move depends on device-tree-compiler to build-depends.
  - Bump Standards-Version to 3.8.1 (no changes).
* patches/82_qemu-img_decimal.patch: new patch from upstream to make
  qemu-img accept sizes with decimal values (closes: bug#501400).

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 *
16
16
 * You should have received a copy of the GNU Lesser General Public
17
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
 
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
19
19
 */
20
20
#include "exec.h"
 
21
#include "helpers.h"
 
22
 
 
23
#define SIGNBIT (uint32_t)0x80000000
 
24
#define SIGNBIT64 ((uint64_t)1 << 63)
21
25
 
22
26
void raise_exception(int tt)
23
27
{
27
31
 
28
32
/* thread support */
29
33
 
30
 
spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
 
34
static spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
31
35
 
32
36
void cpu_lock(void)
33
37
{
39
43
    spin_unlock(&global_cpu_lock);
40
44
}
41
45
 
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.xregs[ARM_VFP_FPSCR] = (flags << 28)\
76
 
        | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \
77
 
    FORCE_RET();                          \
78
 
}\
79
 
\
80
 
void do_vfp_cmpe##p(void)                   \
81
 
{                                           \
82
 
    uint32_t flags;                       \
83
 
    switch(float ## size ## _compare(FT0##p, FT1##p, &env->vfp.fp_status)) {\
84
 
    case 0: flags = 0x6; break;\
85
 
    case -1: flags = 0x8; break;\
86
 
    case 1: flags = 0x2; break;\
87
 
    default: case 2: flags = 0x3; break;\
88
 
    }\
89
 
    env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28)\
90
 
        | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \
91
 
    FORCE_RET();                          \
92
 
}
93
 
DO_VFP_cmp(s, 32)
94
 
DO_VFP_cmp(d, 64)
95
 
#undef DO_VFP_cmp
96
 
 
97
 
/* Convert host exception flags to vfp form.  */
98
 
static inline int vfp_exceptbits_from_host(int host_bits)
99
 
{
100
 
    int target_bits = 0;
101
 
 
102
 
    if (host_bits & float_flag_invalid)
103
 
        target_bits |= 1;
104
 
    if (host_bits & float_flag_divbyzero)
105
 
        target_bits |= 2;
106
 
    if (host_bits & float_flag_overflow)
107
 
        target_bits |= 4;
108
 
    if (host_bits & float_flag_underflow)
109
 
        target_bits |= 8;
110
 
    if (host_bits & float_flag_inexact)
111
 
        target_bits |= 0x10;
112
 
    return target_bits;
113
 
}
114
 
 
115
 
/* Convert vfp exception flags to target form.  */
116
 
static inline int vfp_exceptbits_to_host(int target_bits)
117
 
{
118
 
    int host_bits = 0;
119
 
 
120
 
    if (target_bits & 1)
121
 
        host_bits |= float_flag_invalid;
122
 
    if (target_bits & 2)
123
 
        host_bits |= float_flag_divbyzero;
124
 
    if (target_bits & 4)
125
 
        host_bits |= float_flag_overflow;
126
 
    if (target_bits & 8)
127
 
        host_bits |= float_flag_underflow;
128
 
    if (target_bits & 0x10)
129
 
        host_bits |= float_flag_inexact;
130
 
    return host_bits;
131
 
}
132
 
 
133
 
void do_vfp_set_fpscr(void)
134
 
{
135
 
    int i;
136
 
    uint32_t changed;
137
 
 
138
 
    changed = env->vfp.xregs[ARM_VFP_FPSCR];
139
 
    env->vfp.xregs[ARM_VFP_FPSCR] = (T0 & 0xffc8ffff);
140
 
    env->vfp.vec_len = (T0 >> 16) & 7;
141
 
    env->vfp.vec_stride = (T0 >> 20) & 3;
142
 
 
143
 
    changed ^= T0;
144
 
    if (changed & (3 << 22)) {
145
 
        i = (T0 >> 22) & 3;
146
 
        switch (i) {
147
 
        case 0:
148
 
            i = float_round_nearest_even;
149
 
            break;
150
 
        case 1:
151
 
            i = float_round_up;
152
 
            break;
153
 
        case 2:
154
 
            i = float_round_down;
155
 
            break;
156
 
        case 3:
157
 
            i = float_round_to_zero;
158
 
            break;
159
 
        }
160
 
        set_float_rounding_mode(i, &env->vfp.fp_status);
161
 
    }
162
 
 
163
 
    i = vfp_exceptbits_to_host((T0 >> 8) & 0x1f);
164
 
    set_float_exception_flags(i, &env->vfp.fp_status);
165
 
    /* XXX: FZ and DN are not implemented.  */
166
 
}
167
 
 
168
 
void do_vfp_get_fpscr(void)
169
 
{
170
 
    int i;
171
 
 
172
 
    T0 = (env->vfp.xregs[ARM_VFP_FPSCR] & 0xffc8ffff) | (env->vfp.vec_len << 16)
173
 
          | (env->vfp.vec_stride << 20);
174
 
    i = get_float_exception_flags(&env->vfp.fp_status);
175
 
    T0 |= vfp_exceptbits_from_host(i);
176
 
}
177
 
 
178
 
float32 helper_recps_f32(float32 a, float32 b)
179
 
{
180
 
    float_status *s = &env->vfp.fp_status;
181
 
    float32 two = int32_to_float32(2, s);
182
 
    return float32_sub(two, float32_mul(a, b, s), s);
183
 
}
184
 
 
185
 
float32 helper_rsqrts_f32(float32 a, float32 b)
186
 
{
187
 
    float_status *s = &env->vfp.fp_status;
188
 
    float32 three = int32_to_float32(3, s);
189
 
    return float32_sub(three, float32_mul(a, b, s), s);
190
 
}
191
 
 
192
 
/* TODO: The architecture specifies the value that the estimate functions
193
 
   should return.  We return the exact reciprocal/root instead.  */
194
 
float32 helper_recpe_f32(float32 a)
195
 
{
196
 
    float_status *s = &env->vfp.fp_status;
197
 
    float32 one = int32_to_float32(1, s);
198
 
    return float32_div(one, a, s);
199
 
}
200
 
 
201
 
float32 helper_rsqrte_f32(float32 a)
202
 
{
203
 
    float_status *s = &env->vfp.fp_status;
204
 
    float32 one = int32_to_float32(1, s);
205
 
    return float32_div(one, float32_sqrt(a, s), s);
206
 
}
207
 
 
208
 
uint32_t helper_recpe_u32(uint32_t a)
209
 
{
210
 
    float_status *s = &env->vfp.fp_status;
211
 
    float32 tmp;
212
 
    tmp = int32_to_float32(a, s);
213
 
    tmp = float32_scalbn(tmp, -32, s);
214
 
    tmp = helper_recpe_f32(tmp);
215
 
    tmp = float32_scalbn(tmp, 31, s);
216
 
    return float32_to_int32(tmp, s);
217
 
}
218
 
 
219
 
uint32_t helper_rsqrte_u32(uint32_t a)
220
 
{
221
 
    float_status *s = &env->vfp.fp_status;
222
 
    float32 tmp;
223
 
    tmp = int32_to_float32(a, s);
224
 
    tmp = float32_scalbn(tmp, -32, s);
225
 
    tmp = helper_rsqrte_f32(tmp);
226
 
    tmp = float32_scalbn(tmp, 31, s);
227
 
    return float32_to_int32(tmp, s);
228
 
}
229
 
 
230
 
void helper_neon_tbl(int rn, int maxindex)
 
46
uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def,
 
47
                          uint32_t rn, uint32_t maxindex)
231
48
{
232
49
    uint32_t val;
233
 
    uint32_t mask;
234
50
    uint32_t tmp;
235
51
    int index;
236
52
    int shift;
237
53
    uint64_t *table;
238
54
    table = (uint64_t *)&env->vfp.regs[rn];
239
55
    val = 0;
240
 
    mask = 0;
241
56
    for (shift = 0; shift < 32; shift += 8) {
242
 
        index = (T1 >> shift) & 0xff;
243
 
        if (index <= maxindex) {
244
 
            tmp = (table[index >> 3] >> (index & 7)) & 0xff;
 
57
        index = (ireg >> shift) & 0xff;
 
58
        if (index < maxindex) {
 
59
            tmp = (table[index >> 3] >> ((index & 7) << 3)) & 0xff;
245
60
            val |= tmp << shift;
246
61
        } else {
247
 
            val |= T0 & (0xff << shift);
 
62
            val |= def & (0xff << shift);
248
63
        }
249
64
    }
250
 
    T0 = val;
 
65
    return val;
251
66
}
252
67
 
253
68
#if !defined(CONFIG_USER_ONLY)
254
69
 
255
70
#define MMUSUFFIX _mmu
256
 
#ifdef __s390__
257
 
# define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
258
 
#else
259
 
# define GETPC() (__builtin_return_address(0))
260
 
#endif
261
71
 
262
72
#define SHIFT 0
263
73
#include "softmmu_template.h"
287
97
    saved_env = env;
288
98
    env = cpu_single_env;
289
99
    ret = cpu_arm_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
290
 
    if (__builtin_expect(ret, 0)) {
 
100
    if (unlikely(ret)) {
291
101
        if (retaddr) {
292
102
            /* now we have a real cpu fault */
293
103
            pc = (unsigned long)retaddr;
303
113
    env = saved_env;
304
114
}
305
115
#endif
 
116
 
 
117
/* FIXME: Pass an axplicit pointer to QF to CPUState, and move saturating
 
118
   instructions into helper.c  */
 
119
uint32_t HELPER(add_setq)(uint32_t a, uint32_t b)
 
120
{
 
121
    uint32_t res = a + b;
 
122
    if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT))
 
123
        env->QF = 1;
 
124
    return res;
 
125
}
 
126
 
 
127
uint32_t HELPER(add_saturate)(uint32_t a, uint32_t b)
 
128
{
 
129
    uint32_t res = a + b;
 
130
    if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT)) {
 
131
        env->QF = 1;
 
132
        res = ~(((int32_t)a >> 31) ^ SIGNBIT);
 
133
    }
 
134
    return res;
 
135
}
 
136
 
 
137
uint32_t HELPER(sub_saturate)(uint32_t a, uint32_t b)
 
138
{
 
139
    uint32_t res = a - b;
 
140
    if (((res ^ a) & SIGNBIT) && ((a ^ b) & SIGNBIT)) {
 
141
        env->QF = 1;
 
142
        res = ~(((int32_t)a >> 31) ^ SIGNBIT);
 
143
    }
 
144
    return res;
 
145
}
 
146
 
 
147
uint32_t HELPER(double_saturate)(int32_t val)
 
148
{
 
149
    uint32_t res;
 
150
    if (val >= 0x40000000) {
 
151
        res = ~SIGNBIT;
 
152
        env->QF = 1;
 
153
    } else if (val <= (int32_t)0xc0000000) {
 
154
        res = SIGNBIT;
 
155
        env->QF = 1;
 
156
    } else {
 
157
        res = val << 1;
 
158
    }
 
159
    return res;
 
160
}
 
161
 
 
162
uint32_t HELPER(add_usaturate)(uint32_t a, uint32_t b)
 
163
{
 
164
    uint32_t res = a + b;
 
165
    if (res < a) {
 
166
        env->QF = 1;
 
167
        res = ~0;
 
168
    }
 
169
    return res;
 
170
}
 
171
 
 
172
uint32_t HELPER(sub_usaturate)(uint32_t a, uint32_t b)
 
173
{
 
174
    uint32_t res = a - b;
 
175
    if (res > a) {
 
176
        env->QF = 1;
 
177
        res = 0;
 
178
    }
 
179
    return res;
 
180
}
 
181
 
 
182
/* Signed saturation.  */
 
183
static inline uint32_t do_ssat(int32_t val, int shift)
 
184
{
 
185
    int32_t top;
 
186
    uint32_t mask;
 
187
 
 
188
    top = val >> shift;
 
189
    mask = (1u << shift) - 1;
 
190
    if (top > 0) {
 
191
        env->QF = 1;
 
192
        return mask;
 
193
    } else if (top < -1) {
 
194
        env->QF = 1;
 
195
        return ~mask;
 
196
    }
 
197
    return val;
 
198
}
 
199
 
 
200
/* Unsigned saturation.  */
 
201
static inline uint32_t do_usat(int32_t val, int shift)
 
202
{
 
203
    uint32_t max;
 
204
 
 
205
    max = (1u << shift) - 1;
 
206
    if (val < 0) {
 
207
        env->QF = 1;
 
208
        return 0;
 
209
    } else if (val > max) {
 
210
        env->QF = 1;
 
211
        return max;
 
212
    }
 
213
    return val;
 
214
}
 
215
 
 
216
/* Signed saturate.  */
 
217
uint32_t HELPER(ssat)(uint32_t x, uint32_t shift)
 
218
{
 
219
    return do_ssat(x, shift);
 
220
}
 
221
 
 
222
/* Dual halfword signed saturate.  */
 
223
uint32_t HELPER(ssat16)(uint32_t x, uint32_t shift)
 
224
{
 
225
    uint32_t res;
 
226
 
 
227
    res = (uint16_t)do_ssat((int16_t)x, shift);
 
228
    res |= do_ssat(((int32_t)x) >> 16, shift) << 16;
 
229
    return res;
 
230
}
 
231
 
 
232
/* Unsigned saturate.  */
 
233
uint32_t HELPER(usat)(uint32_t x, uint32_t shift)
 
234
{
 
235
    return do_usat(x, shift);
 
236
}
 
237
 
 
238
/* Dual halfword unsigned saturate.  */
 
239
uint32_t HELPER(usat16)(uint32_t x, uint32_t shift)
 
240
{
 
241
    uint32_t res;
 
242
 
 
243
    res = (uint16_t)do_usat((int16_t)x, shift);
 
244
    res |= do_usat(((int32_t)x) >> 16, shift) << 16;
 
245
    return res;
 
246
}
 
247
 
 
248
void HELPER(wfi)(void)
 
249
{
 
250
    env->exception_index = EXCP_HLT;
 
251
    env->halted = 1;
 
252
    cpu_loop_exit();
 
253
}
 
254
 
 
255
void HELPER(exception)(uint32_t excp)
 
256
{
 
257
    env->exception_index = excp;
 
258
    cpu_loop_exit();
 
259
}
 
260
 
 
261
uint32_t HELPER(cpsr_read)(void)
 
262
{
 
263
    return cpsr_read(env) & ~CPSR_EXEC;
 
264
}
 
265
 
 
266
void HELPER(cpsr_write)(uint32_t val, uint32_t mask)
 
267
{
 
268
    cpsr_write(env, val, mask);
 
269
}
 
270
 
 
271
/* Access to user mode registers from privileged modes.  */
 
272
uint32_t HELPER(get_user_reg)(uint32_t regno)
 
273
{
 
274
    uint32_t val;
 
275
 
 
276
    if (regno == 13) {
 
277
        val = env->banked_r13[0];
 
278
    } else if (regno == 14) {
 
279
        val = env->banked_r14[0];
 
280
    } else if (regno >= 8
 
281
               && (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) {
 
282
        val = env->usr_regs[regno - 8];
 
283
    } else {
 
284
        val = env->regs[regno];
 
285
    }
 
286
    return val;
 
287
}
 
288
 
 
289
void HELPER(set_user_reg)(uint32_t regno, uint32_t val)
 
290
{
 
291
    if (regno == 13) {
 
292
        env->banked_r13[0] = val;
 
293
    } else if (regno == 14) {
 
294
        env->banked_r14[0] = val;
 
295
    } else if (regno >= 8
 
296
               && (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) {
 
297
        env->usr_regs[regno - 8] = val;
 
298
    } else {
 
299
        env->regs[regno] = val;
 
300
    }
 
301
}
 
302
 
 
303
/* ??? Flag setting arithmetic is awkward because we need to do comparisons.
 
304
   The only way to do that in TCG is a conditional branch, which clobbers
 
305
   all our temporaries.  For now implement these as helper functions.  */
 
306
 
 
307
uint32_t HELPER (add_cc)(uint32_t a, uint32_t b)
 
308
{
 
309
    uint32_t result;
 
310
    result = T0 + T1;
 
311
    env->NF = env->ZF = result;
 
312
    env->CF = result < a;
 
313
    env->VF = (a ^ b ^ -1) & (a ^ result);
 
314
    return result;
 
315
}
 
316
 
 
317
uint32_t HELPER(adc_cc)(uint32_t a, uint32_t b)
 
318
{
 
319
    uint32_t result;
 
320
    if (!env->CF) {
 
321
        result = a + b;
 
322
        env->CF = result < a;
 
323
    } else {
 
324
        result = a + b + 1;
 
325
        env->CF = result <= a;
 
326
    }
 
327
    env->VF = (a ^ b ^ -1) & (a ^ result);
 
328
    env->NF = env->ZF = result;
 
329
    return result;
 
330
}
 
331
 
 
332
uint32_t HELPER(sub_cc)(uint32_t a, uint32_t b)
 
333
{
 
334
    uint32_t result;
 
335
    result = a - b;
 
336
    env->NF = env->ZF = result;
 
337
    env->CF = a >= b;
 
338
    env->VF = (a ^ b) & (a ^ result);
 
339
    return result;
 
340
}
 
341
 
 
342
uint32_t HELPER(sbc_cc)(uint32_t a, uint32_t b)
 
343
{
 
344
    uint32_t result;
 
345
    if (!env->CF) {
 
346
        result = a - b - 1;
 
347
        env->CF = a > b;
 
348
    } else {
 
349
        result = a - b;
 
350
        env->CF = a >= b;
 
351
    }
 
352
    env->VF = (a ^ b) & (a ^ result);
 
353
    env->NF = env->ZF = result;
 
354
    return result;
 
355
}
 
356
 
 
357
/* Similarly for variable shift instructions.  */
 
358
 
 
359
uint32_t HELPER(shl)(uint32_t x, uint32_t i)
 
360
{
 
361
    int shift = i & 0xff;
 
362
    if (shift >= 32)
 
363
        return 0;
 
364
    return x << shift;
 
365
}
 
366
 
 
367
uint32_t HELPER(shr)(uint32_t x, uint32_t i)
 
368
{
 
369
    int shift = i & 0xff;
 
370
    if (shift >= 32)
 
371
        return 0;
 
372
    return (uint32_t)x >> shift;
 
373
}
 
374
 
 
375
uint32_t HELPER(sar)(uint32_t x, uint32_t i)
 
376
{
 
377
    int shift = i & 0xff;
 
378
    if (shift >= 32)
 
379
        shift = 31;
 
380
    return (int32_t)x >> shift;
 
381
}
 
382
 
 
383
uint32_t HELPER(ror)(uint32_t x, uint32_t i)
 
384
{
 
385
    int shift = i & 0xff;
 
386
    if (shift == 0)
 
387
        return x;
 
388
    return (x >> shift) | (x << (32 - shift));
 
389
}
 
390
 
 
391
uint32_t HELPER(shl_cc)(uint32_t x, uint32_t i)
 
392
{
 
393
    int shift = i & 0xff;
 
394
    if (shift >= 32) {
 
395
        if (shift == 32)
 
396
            env->CF = x & 1;
 
397
        else
 
398
            env->CF = 0;
 
399
        return 0;
 
400
    } else if (shift != 0) {
 
401
        env->CF = (x >> (32 - shift)) & 1;
 
402
        return x << shift;
 
403
    }
 
404
    return x;
 
405
}
 
406
 
 
407
uint32_t HELPER(shr_cc)(uint32_t x, uint32_t i)
 
408
{
 
409
    int shift = i & 0xff;
 
410
    if (shift >= 32) {
 
411
        if (shift == 32)
 
412
            env->CF = (x >> 31) & 1;
 
413
        else
 
414
            env->CF = 0;
 
415
        return 0;
 
416
    } else if (shift != 0) {
 
417
        env->CF = (x >> (shift - 1)) & 1;
 
418
        return x >> shift;
 
419
    }
 
420
    return x;
 
421
}
 
422
 
 
423
uint32_t HELPER(sar_cc)(uint32_t x, uint32_t i)
 
424
{
 
425
    int shift = i & 0xff;
 
426
    if (shift >= 32) {
 
427
        env->CF = (x >> 31) & 1;
 
428
        return (int32_t)x >> 31;
 
429
    } else if (shift != 0) {
 
430
        env->CF = (x >> (shift - 1)) & 1;
 
431
        return (int32_t)x >> shift;
 
432
    }
 
433
    return x;
 
434
}
 
435
 
 
436
uint32_t HELPER(ror_cc)(uint32_t x, uint32_t i)
 
437
{
 
438
    int shift1, shift;
 
439
    shift1 = i & 0xff;
 
440
    shift = shift1 & 0x1f;
 
441
    if (shift == 0) {
 
442
        if (shift1 != 0)
 
443
            env->CF = (x >> 31) & 1;
 
444
        return x;
 
445
    } else {
 
446
        env->CF = (x >> (shift - 1)) & 1;
 
447
        return ((uint32_t)x >> shift) | (x << (32 - shift));
 
448
    }
 
449
}
 
450
 
 
451
uint64_t HELPER(neon_add_saturate_s64)(uint64_t src1, uint64_t src2)
 
452
{
 
453
    uint64_t res;
 
454
 
 
455
    res = src1 + src2;
 
456
    if (((res ^ src1) & SIGNBIT64) && !((src1 ^ src2) & SIGNBIT64)) {
 
457
        env->QF = 1;
 
458
        res = ((int64_t)src1 >> 63) ^ ~SIGNBIT64;
 
459
    }
 
460
    return res;
 
461
}
 
462
 
 
463
uint64_t HELPER(neon_add_saturate_u64)(uint64_t src1, uint64_t src2)
 
464
{
 
465
    uint64_t res;
 
466
 
 
467
    res = src1 + src2;
 
468
    if (res < src1) {
 
469
        env->QF = 1;
 
470
        res = ~(uint64_t)0;
 
471
    }
 
472
    return res;
 
473
}
 
474
 
 
475
uint64_t HELPER(neon_sub_saturate_s64)(uint64_t src1, uint64_t src2)
 
476
{
 
477
    uint64_t res;
 
478
 
 
479
    res = src1 - src2;
 
480
    if (((res ^ src1) & SIGNBIT64) && ((src1 ^ src2) & SIGNBIT64)) {
 
481
        env->QF = 1;
 
482
        res = ((int64_t)src1 >> 63) ^ ~SIGNBIT64;
 
483
    }
 
484
    return res;
 
485
}
 
486
 
 
487
uint64_t HELPER(neon_sub_saturate_u64)(uint64_t src1, uint64_t src2)
 
488
{
 
489
    uint64_t res;
 
490
 
 
491
    if (src1 < src2) {
 
492
        env->QF = 1;
 
493
        res = 0;
 
494
    } else {
 
495
        res = src1 - src2;
 
496
    }
 
497
    return res;
 
498
}
 
499
 
 
500
/* These need to return a pair of value, so still use T0/T1.  */
 
501
/* Transpose.  Argument order is rather strange to avoid special casing
 
502
   the tranlation code.
 
503
   On input T0 = rm, T1 = rd.  On output T0 = rd, T1 = rm  */
 
504
void HELPER(neon_trn_u8)(void)
 
505
{
 
506
    uint32_t rd;
 
507
    uint32_t rm;
 
508
    rd = ((T0 & 0x00ff00ff) << 8) | (T1 & 0x00ff00ff);
 
509
    rm = ((T1 & 0xff00ff00) >> 8) | (T0 & 0xff00ff00);
 
510
    T0 = rd;
 
511
    T1 = rm;
 
512
}
 
513
 
 
514
void HELPER(neon_trn_u16)(void)
 
515
{
 
516
    uint32_t rd;
 
517
    uint32_t rm;
 
518
    rd = (T0 << 16) | (T1 & 0xffff);
 
519
    rm = (T1 >> 16) | (T0 & 0xffff0000);
 
520
    T0 = rd;
 
521
    T1 = rm;
 
522
}
 
523
 
 
524
/* Worker routines for zip and unzip.  */
 
525
void HELPER(neon_unzip_u8)(void)
 
526
{
 
527
    uint32_t rd;
 
528
    uint32_t rm;
 
529
    rd = (T0 & 0xff) | ((T0 >> 8) & 0xff00)
 
530
         | ((T1 << 16) & 0xff0000) | ((T1 << 8) & 0xff000000);
 
531
    rm = ((T0 >> 8) & 0xff) | ((T0 >> 16) & 0xff00)
 
532
         | ((T1 << 8) & 0xff0000) | (T1 & 0xff000000);
 
533
    T0 = rd;
 
534
    T1 = rm;
 
535
}
 
536
 
 
537
void HELPER(neon_zip_u8)(void)
 
538
{
 
539
    uint32_t rd;
 
540
    uint32_t rm;
 
541
    rd = (T0 & 0xff) | ((T1 << 8) & 0xff00)
 
542
         | ((T0 << 16) & 0xff0000) | ((T1 << 24) & 0xff000000);
 
543
    rm = ((T0 >> 16) & 0xff) | ((T1 >> 8) & 0xff00)
 
544
         | ((T0 >> 8) & 0xff0000) | (T1 & 0xff000000);
 
545
    T0 = rd;
 
546
    T1 = rm;
 
547
}
 
548
 
 
549
void HELPER(neon_zip_u16)(void)
 
550
{
 
551
    uint32_t tmp;
 
552
 
 
553
    tmp = (T0 & 0xffff) | (T1 << 16);
 
554
    T1 = (T1 & 0xffff0000) | (T0 >> 16);
 
555
    T0 = tmp;
 
556
}