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