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