kvm: Improve upgrade notes when facing unsupported kernels
[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., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 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 static 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) << 3)) & 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     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 = a + b;
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 }