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