xref: /qemu/target/sparc/helper.c (revision 163fa5ca51e7167330e6135c09eca6120c022b7f)
1e8af50a3Sbellard /*
2163fa5caSBlue Swirl  *  Misc Sparc helpers
3e8af50a3Sbellard  *
483469015Sbellard  *  Copyright (c) 2003-2005 Fabrice Bellard
5e8af50a3Sbellard  *
6e8af50a3Sbellard  * This library is free software; you can redistribute it and/or
7e8af50a3Sbellard  * modify it under the terms of the GNU Lesser General Public
8e8af50a3Sbellard  * License as published by the Free Software Foundation; either
9e8af50a3Sbellard  * version 2 of the License, or (at your option) any later version.
10e8af50a3Sbellard  *
11e8af50a3Sbellard  * This library is distributed in the hope that it will be useful,
12e8af50a3Sbellard  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13e8af50a3Sbellard  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14e8af50a3Sbellard  * Lesser General Public License for more details.
15e8af50a3Sbellard  *
16e8af50a3Sbellard  * You should have received a copy of the GNU Lesser General Public
178167ee88SBlue Swirl  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18e8af50a3Sbellard  */
19ee5bbe38Sbellard 
20ee5bbe38Sbellard #include "cpu.h"
212336c1f1SBlue Swirl #include "host-utils.h"
222336c1f1SBlue Swirl #include "helper.h"
232336c1f1SBlue Swirl #include "sysemu.h"
24e8af50a3Sbellard 
25bc265319SBlue Swirl void helper_raise_exception(CPUState *env, int tt)
26bc265319SBlue Swirl {
27bc265319SBlue Swirl     env->exception_index = tt;
28bc265319SBlue Swirl     cpu_loop_exit(env);
29bc265319SBlue Swirl }
30bc265319SBlue Swirl 
31bc265319SBlue Swirl void helper_debug(CPUState *env)
32bc265319SBlue Swirl {
33bc265319SBlue Swirl     env->exception_index = EXCP_DEBUG;
34bc265319SBlue Swirl     cpu_loop_exit(env);
35bc265319SBlue Swirl }
36bc265319SBlue Swirl 
372336c1f1SBlue Swirl void helper_shutdown(void)
382336c1f1SBlue Swirl {
392336c1f1SBlue Swirl #if !defined(CONFIG_USER_ONLY)
402336c1f1SBlue Swirl     qemu_system_shutdown_request();
412336c1f1SBlue Swirl #endif
422336c1f1SBlue Swirl }
432336c1f1SBlue Swirl 
442336c1f1SBlue Swirl #ifdef TARGET_SPARC64
452336c1f1SBlue Swirl target_ulong helper_popc(target_ulong val)
462336c1f1SBlue Swirl {
472336c1f1SBlue Swirl     return ctpop64(val);
482336c1f1SBlue Swirl }
492336c1f1SBlue Swirl 
502336c1f1SBlue Swirl void helper_tick_set_count(void *opaque, uint64_t count)
512336c1f1SBlue Swirl {
522336c1f1SBlue Swirl #if !defined(CONFIG_USER_ONLY)
532336c1f1SBlue Swirl     cpu_tick_set_count(opaque, count);
542336c1f1SBlue Swirl #endif
552336c1f1SBlue Swirl }
562336c1f1SBlue Swirl 
572336c1f1SBlue Swirl uint64_t helper_tick_get_count(void *opaque)
582336c1f1SBlue Swirl {
592336c1f1SBlue Swirl #if !defined(CONFIG_USER_ONLY)
602336c1f1SBlue Swirl     return cpu_tick_get_count(opaque);
612336c1f1SBlue Swirl #else
622336c1f1SBlue Swirl     return 0;
632336c1f1SBlue Swirl #endif
642336c1f1SBlue Swirl }
652336c1f1SBlue Swirl 
662336c1f1SBlue Swirl void helper_tick_set_limit(void *opaque, uint64_t limit)
672336c1f1SBlue Swirl {
682336c1f1SBlue Swirl #if !defined(CONFIG_USER_ONLY)
692336c1f1SBlue Swirl     cpu_tick_set_limit(opaque, limit);
702336c1f1SBlue Swirl #endif
712336c1f1SBlue Swirl }
722336c1f1SBlue Swirl #endif
737a5e4488SBlue Swirl 
747a5e4488SBlue Swirl static target_ulong helper_udiv_common(CPUState *env, target_ulong a,
757a5e4488SBlue Swirl                                        target_ulong b, int cc)
767a5e4488SBlue Swirl {
777a5e4488SBlue Swirl     int overflow = 0;
787a5e4488SBlue Swirl     uint64_t x0;
797a5e4488SBlue Swirl     uint32_t x1;
807a5e4488SBlue Swirl 
817a5e4488SBlue Swirl     x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
827a5e4488SBlue Swirl     x1 = (b & 0xffffffff);
837a5e4488SBlue Swirl 
847a5e4488SBlue Swirl     if (x1 == 0) {
857a5e4488SBlue Swirl         helper_raise_exception(env, TT_DIV_ZERO);
867a5e4488SBlue Swirl     }
877a5e4488SBlue Swirl 
887a5e4488SBlue Swirl     x0 = x0 / x1;
897a5e4488SBlue Swirl     if (x0 > 0xffffffff) {
907a5e4488SBlue Swirl         x0 = 0xffffffff;
917a5e4488SBlue Swirl         overflow = 1;
927a5e4488SBlue Swirl     }
937a5e4488SBlue Swirl 
947a5e4488SBlue Swirl     if (cc) {
957a5e4488SBlue Swirl         env->cc_dst = x0;
967a5e4488SBlue Swirl         env->cc_src2 = overflow;
977a5e4488SBlue Swirl         env->cc_op = CC_OP_DIV;
987a5e4488SBlue Swirl     }
997a5e4488SBlue Swirl     return x0;
1007a5e4488SBlue Swirl }
1017a5e4488SBlue Swirl 
1027a5e4488SBlue Swirl target_ulong helper_udiv(CPUState *env, target_ulong a, target_ulong b)
1037a5e4488SBlue Swirl {
1047a5e4488SBlue Swirl     return helper_udiv_common(env, a, b, 0);
1057a5e4488SBlue Swirl }
1067a5e4488SBlue Swirl 
1077a5e4488SBlue Swirl target_ulong helper_udiv_cc(CPUState *env, target_ulong a, target_ulong b)
1087a5e4488SBlue Swirl {
1097a5e4488SBlue Swirl     return helper_udiv_common(env, a, b, 1);
1107a5e4488SBlue Swirl }
1117a5e4488SBlue Swirl 
1127a5e4488SBlue Swirl static target_ulong helper_sdiv_common(CPUState *env, target_ulong a,
1137a5e4488SBlue Swirl                                        target_ulong b, int cc)
1147a5e4488SBlue Swirl {
1157a5e4488SBlue Swirl     int overflow = 0;
1167a5e4488SBlue Swirl     int64_t x0;
1177a5e4488SBlue Swirl     int32_t x1;
1187a5e4488SBlue Swirl 
1197a5e4488SBlue Swirl     x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
1207a5e4488SBlue Swirl     x1 = (b & 0xffffffff);
1217a5e4488SBlue Swirl 
1227a5e4488SBlue Swirl     if (x1 == 0) {
1237a5e4488SBlue Swirl         helper_raise_exception(env, TT_DIV_ZERO);
1247a5e4488SBlue Swirl     }
1257a5e4488SBlue Swirl 
1267a5e4488SBlue Swirl     x0 = x0 / x1;
1277a5e4488SBlue Swirl     if ((int32_t) x0 != x0) {
1287a5e4488SBlue Swirl         x0 = x0 < 0 ? 0x80000000 : 0x7fffffff;
1297a5e4488SBlue Swirl         overflow = 1;
1307a5e4488SBlue Swirl     }
1317a5e4488SBlue Swirl 
1327a5e4488SBlue Swirl     if (cc) {
1337a5e4488SBlue Swirl         env->cc_dst = x0;
1347a5e4488SBlue Swirl         env->cc_src2 = overflow;
1357a5e4488SBlue Swirl         env->cc_op = CC_OP_DIV;
1367a5e4488SBlue Swirl     }
1377a5e4488SBlue Swirl     return x0;
1387a5e4488SBlue Swirl }
1397a5e4488SBlue Swirl 
1407a5e4488SBlue Swirl target_ulong helper_sdiv(CPUState *env, target_ulong a, target_ulong b)
1417a5e4488SBlue Swirl {
1427a5e4488SBlue Swirl     return helper_sdiv_common(env, a, b, 0);
1437a5e4488SBlue Swirl }
1447a5e4488SBlue Swirl 
1457a5e4488SBlue Swirl target_ulong helper_sdiv_cc(CPUState *env, target_ulong a, target_ulong b)
1467a5e4488SBlue Swirl {
1477a5e4488SBlue Swirl     return helper_sdiv_common(env, a, b, 1);
1487a5e4488SBlue Swirl }
149