1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include "qemu/osdep.h"
22#include "cpu.h"
23#include "s390x-internal.h"
24#include "tcg_s390x.h"
25#include "exec/exec-all.h"
26#include "qemu/host-utils.h"
27#include "exec/helper-proto.h"
28
29
30#ifdef DEBUG_HELPER
31#define HELPER_LOG(x...) qemu_log(x)
32#else
33#define HELPER_LOG(x...)
34#endif
35
36
37int64_t HELPER(divs32)(CPUS390XState *env, int64_t a, int64_t b64)
38{
39 int32_t ret, b = b64;
40 int64_t q;
41
42 if (b == 0) {
43 tcg_s390_program_interrupt(env, PGM_FIXPT_DIVIDE, GETPC());
44 }
45
46 ret = q = a / b;
47 env->retxl = a % b;
48
49
50 if (ret != q) {
51 tcg_s390_program_interrupt(env, PGM_FIXPT_DIVIDE, GETPC());
52 }
53
54 return ret;
55}
56
57
58uint64_t HELPER(divu32)(CPUS390XState *env, uint64_t a, uint64_t b64)
59{
60 uint32_t ret, b = b64;
61 uint64_t q;
62
63 if (b == 0) {
64 tcg_s390_program_interrupt(env, PGM_FIXPT_DIVIDE, GETPC());
65 }
66
67 ret = q = a / b;
68 env->retxl = a % b;
69
70
71 if (ret != q) {
72 tcg_s390_program_interrupt(env, PGM_FIXPT_DIVIDE, GETPC());
73 }
74
75 return ret;
76}
77
78
79int64_t HELPER(divs64)(CPUS390XState *env, int64_t a, int64_t b)
80{
81
82 if (b == 0 || (b == -1 && a == (1ll << 63))) {
83 tcg_s390_program_interrupt(env, PGM_FIXPT_DIVIDE, GETPC());
84 }
85 env->retxl = a % b;
86 return a / b;
87}
88
89
90uint64_t HELPER(divu64)(CPUS390XState *env, uint64_t ah, uint64_t al,
91 uint64_t b)
92{
93 uint64_t ret;
94
95 if (b == 0) {
96 tcg_s390_program_interrupt(env, PGM_FIXPT_DIVIDE, GETPC());
97 }
98 if (ah == 0) {
99
100 env->retxl = al % b;
101 ret = al / b;
102 } else {
103
104#ifdef CONFIG_INT128
105 __uint128_t a = ((__uint128_t)ah << 64) | al;
106 __uint128_t q = a / b;
107 env->retxl = a % b;
108 ret = q;
109 if (ret != q) {
110 tcg_s390_program_interrupt(env, PGM_FIXPT_DIVIDE, GETPC());
111 }
112#else
113
114
115 cpu_abort(env_cpu(env), "128 -> 64/64 division not implemented\n");
116#endif
117 }
118 return ret;
119}
120
121uint64_t HELPER(cvd)(int32_t reg)
122{
123
124 uint64_t dec = 0x0c;
125 int64_t bin = reg;
126 int shift;
127
128 if (bin < 0) {
129 bin = -bin;
130 dec = 0x0d;
131 }
132
133 for (shift = 4; (shift < 64) && bin; shift += 4) {
134 dec |= (bin % 10) << shift;
135 bin /= 10;
136 }
137
138 return dec;
139}
140
141uint64_t HELPER(popcnt)(uint64_t val)
142{
143
144 val = (val & 0x5555555555555555ULL) + ((val >> 1) & 0x5555555555555555ULL);
145 val = (val & 0x3333333333333333ULL) + ((val >> 2) & 0x3333333333333333ULL);
146 val = (val + (val >> 4)) & 0x0f0f0f0f0f0f0f0fULL;
147 return val;
148}
149