xref: /openbmc/qemu/target/s390x/tcg/cc_helper.c (revision 21be74a9)
1c9274b6bSCho, Yu-Chen /*
2c9274b6bSCho, Yu-Chen  *  S/390 condition code helper routines
3c9274b6bSCho, Yu-Chen  *
4c9274b6bSCho, Yu-Chen  *  Copyright (c) 2009 Ulrich Hecht
5c9274b6bSCho, Yu-Chen  *  Copyright (c) 2009 Alexander Graf
6c9274b6bSCho, Yu-Chen  *
7c9274b6bSCho, Yu-Chen  * This library is free software; you can redistribute it and/or
8c9274b6bSCho, Yu-Chen  * modify it under the terms of the GNU Lesser General Public
9c9274b6bSCho, Yu-Chen  * License as published by the Free Software Foundation; either
10c9274b6bSCho, Yu-Chen  * version 2.1 of the License, or (at your option) any later version.
11c9274b6bSCho, Yu-Chen  *
12c9274b6bSCho, Yu-Chen  * This library is distributed in the hope that it will be useful,
13c9274b6bSCho, Yu-Chen  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14c9274b6bSCho, Yu-Chen  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15c9274b6bSCho, Yu-Chen  * Lesser General Public License for more details.
16c9274b6bSCho, Yu-Chen  *
17c9274b6bSCho, Yu-Chen  * You should have received a copy of the GNU Lesser General Public
18c9274b6bSCho, Yu-Chen  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19c9274b6bSCho, Yu-Chen  */
20c9274b6bSCho, Yu-Chen 
21c9274b6bSCho, Yu-Chen #include "qemu/osdep.h"
22c9274b6bSCho, Yu-Chen #include "cpu.h"
23c9274b6bSCho, Yu-Chen #include "s390x-internal.h"
24c9274b6bSCho, Yu-Chen #include "tcg_s390x.h"
25c9274b6bSCho, Yu-Chen #include "exec/exec-all.h"
26c9274b6bSCho, Yu-Chen #include "exec/helper-proto.h"
27c9274b6bSCho, Yu-Chen #include "qemu/host-utils.h"
28c9274b6bSCho, Yu-Chen 
29c9274b6bSCho, Yu-Chen /* #define DEBUG_HELPER */
30c9274b6bSCho, Yu-Chen #ifdef DEBUG_HELPER
31c9274b6bSCho, Yu-Chen #define HELPER_LOG(x...) qemu_log(x)
32c9274b6bSCho, Yu-Chen #else
33c9274b6bSCho, Yu-Chen #define HELPER_LOG(x...)
34c9274b6bSCho, Yu-Chen #endif
35c9274b6bSCho, Yu-Chen 
cc_calc_ltgt_32(int32_t src,int32_t dst)36c9274b6bSCho, Yu-Chen static uint32_t cc_calc_ltgt_32(int32_t src, int32_t dst)
37c9274b6bSCho, Yu-Chen {
38c9274b6bSCho, Yu-Chen     if (src == dst) {
39c9274b6bSCho, Yu-Chen         return 0;
40c9274b6bSCho, Yu-Chen     } else if (src < dst) {
41c9274b6bSCho, Yu-Chen         return 1;
42c9274b6bSCho, Yu-Chen     } else {
43c9274b6bSCho, Yu-Chen         return 2;
44c9274b6bSCho, Yu-Chen     }
45c9274b6bSCho, Yu-Chen }
46c9274b6bSCho, Yu-Chen 
cc_calc_ltgt0_32(int32_t dst)47c9274b6bSCho, Yu-Chen static uint32_t cc_calc_ltgt0_32(int32_t dst)
48c9274b6bSCho, Yu-Chen {
49c9274b6bSCho, Yu-Chen     return cc_calc_ltgt_32(dst, 0);
50c9274b6bSCho, Yu-Chen }
51c9274b6bSCho, Yu-Chen 
cc_calc_ltgt_64(int64_t src,int64_t dst)52c9274b6bSCho, Yu-Chen static uint32_t cc_calc_ltgt_64(int64_t src, int64_t dst)
53c9274b6bSCho, Yu-Chen {
54c9274b6bSCho, Yu-Chen     if (src == dst) {
55c9274b6bSCho, Yu-Chen         return 0;
56c9274b6bSCho, Yu-Chen     } else if (src < dst) {
57c9274b6bSCho, Yu-Chen         return 1;
58c9274b6bSCho, Yu-Chen     } else {
59c9274b6bSCho, Yu-Chen         return 2;
60c9274b6bSCho, Yu-Chen     }
61c9274b6bSCho, Yu-Chen }
62c9274b6bSCho, Yu-Chen 
cc_calc_ltgt0_64(int64_t dst)63c9274b6bSCho, Yu-Chen static uint32_t cc_calc_ltgt0_64(int64_t dst)
64c9274b6bSCho, Yu-Chen {
65c9274b6bSCho, Yu-Chen     return cc_calc_ltgt_64(dst, 0);
66c9274b6bSCho, Yu-Chen }
67c9274b6bSCho, Yu-Chen 
cc_calc_ltugtu_32(uint32_t src,uint32_t dst)68c9274b6bSCho, Yu-Chen static uint32_t cc_calc_ltugtu_32(uint32_t src, uint32_t dst)
69c9274b6bSCho, Yu-Chen {
70c9274b6bSCho, Yu-Chen     if (src == dst) {
71c9274b6bSCho, Yu-Chen         return 0;
72c9274b6bSCho, Yu-Chen     } else if (src < dst) {
73c9274b6bSCho, Yu-Chen         return 1;
74c9274b6bSCho, Yu-Chen     } else {
75c9274b6bSCho, Yu-Chen         return 2;
76c9274b6bSCho, Yu-Chen     }
77c9274b6bSCho, Yu-Chen }
78c9274b6bSCho, Yu-Chen 
cc_calc_ltugtu_64(uint64_t src,uint64_t dst)79c9274b6bSCho, Yu-Chen static uint32_t cc_calc_ltugtu_64(uint64_t src, uint64_t dst)
80c9274b6bSCho, Yu-Chen {
81c9274b6bSCho, Yu-Chen     if (src == dst) {
82c9274b6bSCho, Yu-Chen         return 0;
83c9274b6bSCho, Yu-Chen     } else if (src < dst) {
84c9274b6bSCho, Yu-Chen         return 1;
85c9274b6bSCho, Yu-Chen     } else {
86c9274b6bSCho, Yu-Chen         return 2;
87c9274b6bSCho, Yu-Chen     }
88c9274b6bSCho, Yu-Chen }
89c9274b6bSCho, Yu-Chen 
cc_calc_tm_32(uint32_t val,uint32_t mask)90c9274b6bSCho, Yu-Chen static uint32_t cc_calc_tm_32(uint32_t val, uint32_t mask)
91c9274b6bSCho, Yu-Chen {
92c9274b6bSCho, Yu-Chen     uint32_t r = val & mask;
93c9274b6bSCho, Yu-Chen 
94c9274b6bSCho, Yu-Chen     if (r == 0) {
95c9274b6bSCho, Yu-Chen         return 0;
96c9274b6bSCho, Yu-Chen     } else if (r == mask) {
97c9274b6bSCho, Yu-Chen         return 3;
98c9274b6bSCho, Yu-Chen     } else {
99c9274b6bSCho, Yu-Chen         return 1;
100c9274b6bSCho, Yu-Chen     }
101c9274b6bSCho, Yu-Chen }
102c9274b6bSCho, Yu-Chen 
cc_calc_tm_64(uint64_t val,uint64_t mask)103c9274b6bSCho, Yu-Chen static uint32_t cc_calc_tm_64(uint64_t val, uint64_t mask)
104c9274b6bSCho, Yu-Chen {
105c9274b6bSCho, Yu-Chen     uint64_t r = val & mask;
106c9274b6bSCho, Yu-Chen 
107c9274b6bSCho, Yu-Chen     if (r == 0) {
108c9274b6bSCho, Yu-Chen         return 0;
109c9274b6bSCho, Yu-Chen     } else if (r == mask) {
110c9274b6bSCho, Yu-Chen         return 3;
111c9274b6bSCho, Yu-Chen     } else {
112c9274b6bSCho, Yu-Chen         int top = clz64(mask);
113c9274b6bSCho, Yu-Chen         if ((int64_t)(val << top) < 0) {
114c9274b6bSCho, Yu-Chen             return 2;
115c9274b6bSCho, Yu-Chen         } else {
116c9274b6bSCho, Yu-Chen             return 1;
117c9274b6bSCho, Yu-Chen         }
118c9274b6bSCho, Yu-Chen     }
119c9274b6bSCho, Yu-Chen }
120c9274b6bSCho, Yu-Chen 
cc_calc_nz(uint64_t dst)121c9274b6bSCho, Yu-Chen static uint32_t cc_calc_nz(uint64_t dst)
122c9274b6bSCho, Yu-Chen {
123c9274b6bSCho, Yu-Chen     return !!dst;
124c9274b6bSCho, Yu-Chen }
125c9274b6bSCho, Yu-Chen 
cc_calc_addu(uint64_t carry_out,uint64_t result)126c9274b6bSCho, Yu-Chen static uint32_t cc_calc_addu(uint64_t carry_out, uint64_t result)
127c9274b6bSCho, Yu-Chen {
128c9274b6bSCho, Yu-Chen     g_assert(carry_out <= 1);
129c9274b6bSCho, Yu-Chen     return (result != 0) + 2 * carry_out;
130c9274b6bSCho, Yu-Chen }
131c9274b6bSCho, Yu-Chen 
cc_calc_subu(uint64_t borrow_out,uint64_t result)132c9274b6bSCho, Yu-Chen static uint32_t cc_calc_subu(uint64_t borrow_out, uint64_t result)
133c9274b6bSCho, Yu-Chen {
134c9274b6bSCho, Yu-Chen     return cc_calc_addu(borrow_out + 1, result);
135c9274b6bSCho, Yu-Chen }
136c9274b6bSCho, Yu-Chen 
cc_calc_add_64(int64_t a1,int64_t a2,int64_t ar)137c9274b6bSCho, Yu-Chen static uint32_t cc_calc_add_64(int64_t a1, int64_t a2, int64_t ar)
138c9274b6bSCho, Yu-Chen {
1395a2e67a6SBruno Haible     if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar >= 0)) {
140c9274b6bSCho, Yu-Chen         return 3; /* overflow */
141c9274b6bSCho, Yu-Chen     } else {
142c9274b6bSCho, Yu-Chen         if (ar < 0) {
143c9274b6bSCho, Yu-Chen             return 1;
144c9274b6bSCho, Yu-Chen         } else if (ar > 0) {
145c9274b6bSCho, Yu-Chen             return 2;
146c9274b6bSCho, Yu-Chen         } else {
147c9274b6bSCho, Yu-Chen             return 0;
148c9274b6bSCho, Yu-Chen         }
149c9274b6bSCho, Yu-Chen     }
150c9274b6bSCho, Yu-Chen }
151c9274b6bSCho, Yu-Chen 
cc_calc_sub_64(int64_t a1,int64_t a2,int64_t ar)152c9274b6bSCho, Yu-Chen static uint32_t cc_calc_sub_64(int64_t a1, int64_t a2, int64_t ar)
153c9274b6bSCho, Yu-Chen {
154fc6e0d0fSBruno Haible     if ((a1 >= 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
155c9274b6bSCho, Yu-Chen         return 3; /* overflow */
156c9274b6bSCho, Yu-Chen     } else {
157c9274b6bSCho, Yu-Chen         if (ar < 0) {
158c9274b6bSCho, Yu-Chen             return 1;
159c9274b6bSCho, Yu-Chen         } else if (ar > 0) {
160c9274b6bSCho, Yu-Chen             return 2;
161c9274b6bSCho, Yu-Chen         } else {
162c9274b6bSCho, Yu-Chen             return 0;
163c9274b6bSCho, Yu-Chen         }
164c9274b6bSCho, Yu-Chen     }
165c9274b6bSCho, Yu-Chen }
166c9274b6bSCho, Yu-Chen 
cc_calc_abs_64(int64_t dst)167c9274b6bSCho, Yu-Chen static uint32_t cc_calc_abs_64(int64_t dst)
168c9274b6bSCho, Yu-Chen {
169c9274b6bSCho, Yu-Chen     if ((uint64_t)dst == 0x8000000000000000ULL) {
170c9274b6bSCho, Yu-Chen         return 3;
171c9274b6bSCho, Yu-Chen     } else if (dst) {
172c9274b6bSCho, Yu-Chen         return 2;
173c9274b6bSCho, Yu-Chen     } else {
174c9274b6bSCho, Yu-Chen         return 0;
175c9274b6bSCho, Yu-Chen     }
176c9274b6bSCho, Yu-Chen }
177c9274b6bSCho, Yu-Chen 
cc_calc_nabs_64(int64_t dst)178c9274b6bSCho, Yu-Chen static uint32_t cc_calc_nabs_64(int64_t dst)
179c9274b6bSCho, Yu-Chen {
180c9274b6bSCho, Yu-Chen     return !!dst;
181c9274b6bSCho, Yu-Chen }
182c9274b6bSCho, Yu-Chen 
cc_calc_comp_64(int64_t dst)183c9274b6bSCho, Yu-Chen static uint32_t cc_calc_comp_64(int64_t dst)
184c9274b6bSCho, Yu-Chen {
185c9274b6bSCho, Yu-Chen     if ((uint64_t)dst == 0x8000000000000000ULL) {
186c9274b6bSCho, Yu-Chen         return 3;
187c9274b6bSCho, Yu-Chen     } else if (dst < 0) {
188c9274b6bSCho, Yu-Chen         return 1;
189c9274b6bSCho, Yu-Chen     } else if (dst > 0) {
190c9274b6bSCho, Yu-Chen         return 2;
191c9274b6bSCho, Yu-Chen     } else {
192c9274b6bSCho, Yu-Chen         return 0;
193c9274b6bSCho, Yu-Chen     }
194c9274b6bSCho, Yu-Chen }
195c9274b6bSCho, Yu-Chen 
196c9274b6bSCho, Yu-Chen 
cc_calc_add_32(int32_t a1,int32_t a2,int32_t ar)197c9274b6bSCho, Yu-Chen static uint32_t cc_calc_add_32(int32_t a1, int32_t a2, int32_t ar)
198c9274b6bSCho, Yu-Chen {
1995a2e67a6SBruno Haible     if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar >= 0)) {
200c9274b6bSCho, Yu-Chen         return 3; /* overflow */
201c9274b6bSCho, Yu-Chen     } else {
202c9274b6bSCho, Yu-Chen         if (ar < 0) {
203c9274b6bSCho, Yu-Chen             return 1;
204c9274b6bSCho, Yu-Chen         } else if (ar > 0) {
205c9274b6bSCho, Yu-Chen             return 2;
206c9274b6bSCho, Yu-Chen         } else {
207c9274b6bSCho, Yu-Chen             return 0;
208c9274b6bSCho, Yu-Chen         }
209c9274b6bSCho, Yu-Chen     }
210c9274b6bSCho, Yu-Chen }
211c9274b6bSCho, Yu-Chen 
cc_calc_sub_32(int32_t a1,int32_t a2,int32_t ar)212c9274b6bSCho, Yu-Chen static uint32_t cc_calc_sub_32(int32_t a1, int32_t a2, int32_t ar)
213c9274b6bSCho, Yu-Chen {
214fc6e0d0fSBruno Haible     if ((a1 >= 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
215c9274b6bSCho, Yu-Chen         return 3; /* overflow */
216c9274b6bSCho, Yu-Chen     } else {
217c9274b6bSCho, Yu-Chen         if (ar < 0) {
218c9274b6bSCho, Yu-Chen             return 1;
219c9274b6bSCho, Yu-Chen         } else if (ar > 0) {
220c9274b6bSCho, Yu-Chen             return 2;
221c9274b6bSCho, Yu-Chen         } else {
222c9274b6bSCho, Yu-Chen             return 0;
223c9274b6bSCho, Yu-Chen         }
224c9274b6bSCho, Yu-Chen     }
225c9274b6bSCho, Yu-Chen }
226c9274b6bSCho, Yu-Chen 
cc_calc_abs_32(int32_t dst)227c9274b6bSCho, Yu-Chen static uint32_t cc_calc_abs_32(int32_t dst)
228c9274b6bSCho, Yu-Chen {
229c9274b6bSCho, Yu-Chen     if ((uint32_t)dst == 0x80000000UL) {
230c9274b6bSCho, Yu-Chen         return 3;
231c9274b6bSCho, Yu-Chen     } else if (dst) {
232c9274b6bSCho, Yu-Chen         return 2;
233c9274b6bSCho, Yu-Chen     } else {
234c9274b6bSCho, Yu-Chen         return 0;
235c9274b6bSCho, Yu-Chen     }
236c9274b6bSCho, Yu-Chen }
237c9274b6bSCho, Yu-Chen 
cc_calc_nabs_32(int32_t dst)238c9274b6bSCho, Yu-Chen static uint32_t cc_calc_nabs_32(int32_t dst)
239c9274b6bSCho, Yu-Chen {
240c9274b6bSCho, Yu-Chen     return !!dst;
241c9274b6bSCho, Yu-Chen }
242c9274b6bSCho, Yu-Chen 
cc_calc_comp_32(int32_t dst)243c9274b6bSCho, Yu-Chen static uint32_t cc_calc_comp_32(int32_t dst)
244c9274b6bSCho, Yu-Chen {
245c9274b6bSCho, Yu-Chen     if ((uint32_t)dst == 0x80000000UL) {
246c9274b6bSCho, Yu-Chen         return 3;
247c9274b6bSCho, Yu-Chen     } else if (dst < 0) {
248c9274b6bSCho, Yu-Chen         return 1;
249c9274b6bSCho, Yu-Chen     } else if (dst > 0) {
250c9274b6bSCho, Yu-Chen         return 2;
251c9274b6bSCho, Yu-Chen     } else {
252c9274b6bSCho, Yu-Chen         return 0;
253c9274b6bSCho, Yu-Chen     }
254c9274b6bSCho, Yu-Chen }
255c9274b6bSCho, Yu-Chen 
256c9274b6bSCho, Yu-Chen /* calculate condition code for insert character under mask insn */
cc_calc_icm(uint64_t mask,uint64_t val)257c9274b6bSCho, Yu-Chen static uint32_t cc_calc_icm(uint64_t mask, uint64_t val)
258c9274b6bSCho, Yu-Chen {
259c9274b6bSCho, Yu-Chen     if ((val & mask) == 0) {
260c9274b6bSCho, Yu-Chen         return 0;
261c9274b6bSCho, Yu-Chen     } else {
262c9274b6bSCho, Yu-Chen         int top = clz64(mask);
263c9274b6bSCho, Yu-Chen         if ((int64_t)(val << top) < 0) {
264c9274b6bSCho, Yu-Chen             return 1;
265c9274b6bSCho, Yu-Chen         } else {
266c9274b6bSCho, Yu-Chen             return 2;
267c9274b6bSCho, Yu-Chen         }
268c9274b6bSCho, Yu-Chen     }
269c9274b6bSCho, Yu-Chen }
270c9274b6bSCho, Yu-Chen 
cc_calc_sla(uint64_t src,int shift)2716da170beSIlya Leoshkevich static uint32_t cc_calc_sla(uint64_t src, int shift)
272c9274b6bSCho, Yu-Chen {
273df103c09SIlya Leoshkevich     uint64_t mask = -1ULL << (63 - shift);
274c9274b6bSCho, Yu-Chen     uint64_t sign = 1ULL << 63;
275c9274b6bSCho, Yu-Chen     uint64_t match;
276c9274b6bSCho, Yu-Chen     int64_t r;
277c9274b6bSCho, Yu-Chen 
278c9274b6bSCho, Yu-Chen     /* Check if the sign bit stays the same.  */
279c9274b6bSCho, Yu-Chen     if (src & sign) {
280c9274b6bSCho, Yu-Chen         match = mask;
281c9274b6bSCho, Yu-Chen     } else {
282c9274b6bSCho, Yu-Chen         match = 0;
283c9274b6bSCho, Yu-Chen     }
284c9274b6bSCho, Yu-Chen     if ((src & mask) != match) {
285c9274b6bSCho, Yu-Chen         /* Overflow.  */
286c9274b6bSCho, Yu-Chen         return 3;
287c9274b6bSCho, Yu-Chen     }
288c9274b6bSCho, Yu-Chen 
289c9274b6bSCho, Yu-Chen     r = ((src << shift) & ~sign) | (src & sign);
290c9274b6bSCho, Yu-Chen     if (r == 0) {
291c9274b6bSCho, Yu-Chen         return 0;
292c9274b6bSCho, Yu-Chen     } else if (r < 0) {
293c9274b6bSCho, Yu-Chen         return 1;
294c9274b6bSCho, Yu-Chen     }
295c9274b6bSCho, Yu-Chen     return 2;
296c9274b6bSCho, Yu-Chen }
297c9274b6bSCho, Yu-Chen 
cc_calc_flogr(uint64_t dst)298c9274b6bSCho, Yu-Chen static uint32_t cc_calc_flogr(uint64_t dst)
299c9274b6bSCho, Yu-Chen {
300c9274b6bSCho, Yu-Chen     return dst ? 2 : 0;
301c9274b6bSCho, Yu-Chen }
302c9274b6bSCho, Yu-Chen 
cc_calc_lcbb(uint64_t dst)303c9274b6bSCho, Yu-Chen static uint32_t cc_calc_lcbb(uint64_t dst)
304c9274b6bSCho, Yu-Chen {
305c9274b6bSCho, Yu-Chen     return dst == 16 ? 0 : 3;
306c9274b6bSCho, Yu-Chen }
307c9274b6bSCho, Yu-Chen 
cc_calc_vc(uint64_t low,uint64_t high)308c9274b6bSCho, Yu-Chen static uint32_t cc_calc_vc(uint64_t low, uint64_t high)
309c9274b6bSCho, Yu-Chen {
310c9274b6bSCho, Yu-Chen     if (high == -1ull && low == -1ull) {
311c9274b6bSCho, Yu-Chen         /* all elements match */
312c9274b6bSCho, Yu-Chen         return 0;
313c9274b6bSCho, Yu-Chen     } else if (high == 0 && low == 0) {
314c9274b6bSCho, Yu-Chen         /* no elements match */
315c9274b6bSCho, Yu-Chen         return 3;
316c9274b6bSCho, Yu-Chen     } else {
317c9274b6bSCho, Yu-Chen         /* some elements but not all match */
318c9274b6bSCho, Yu-Chen         return 1;
319c9274b6bSCho, Yu-Chen     }
320c9274b6bSCho, Yu-Chen }
321c9274b6bSCho, Yu-Chen 
cc_calc_muls_32(int64_t res)322c9274b6bSCho, Yu-Chen static uint32_t cc_calc_muls_32(int64_t res)
323c9274b6bSCho, Yu-Chen {
324c9274b6bSCho, Yu-Chen     const int64_t tmp = res >> 31;
325c9274b6bSCho, Yu-Chen 
326c9274b6bSCho, Yu-Chen     if (!res) {
327c9274b6bSCho, Yu-Chen         return 0;
328c9274b6bSCho, Yu-Chen     } else if (tmp && tmp != -1) {
329c9274b6bSCho, Yu-Chen         return 3;
330c9274b6bSCho, Yu-Chen     } else if (res < 0) {
331c9274b6bSCho, Yu-Chen         return 1;
332c9274b6bSCho, Yu-Chen     }
333c9274b6bSCho, Yu-Chen     return 2;
334c9274b6bSCho, Yu-Chen }
335c9274b6bSCho, Yu-Chen 
cc_calc_muls_64(int64_t res_high,uint64_t res_low)336c9274b6bSCho, Yu-Chen static uint64_t cc_calc_muls_64(int64_t res_high, uint64_t res_low)
337c9274b6bSCho, Yu-Chen {
338c9274b6bSCho, Yu-Chen     if (!res_high && !res_low) {
339c9274b6bSCho, Yu-Chen         return 0;
340c9274b6bSCho, Yu-Chen     } else if (res_high + (res_low >> 63) != 0) {
341c9274b6bSCho, Yu-Chen         return 3;
342c9274b6bSCho, Yu-Chen     } else if (res_high < 0) {
343c9274b6bSCho, Yu-Chen         return 1;
344c9274b6bSCho, Yu-Chen     }
345c9274b6bSCho, Yu-Chen     return 2;
346c9274b6bSCho, Yu-Chen }
347c9274b6bSCho, Yu-Chen 
do_calc_cc(CPUS390XState * env,uint32_t cc_op,uint64_t src,uint64_t dst,uint64_t vr)348c9274b6bSCho, Yu-Chen static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
349c9274b6bSCho, Yu-Chen                                   uint64_t src, uint64_t dst, uint64_t vr)
350c9274b6bSCho, Yu-Chen {
351c9274b6bSCho, Yu-Chen     uint32_t r = 0;
352c9274b6bSCho, Yu-Chen 
353c9274b6bSCho, Yu-Chen     switch (cc_op) {
354c9274b6bSCho, Yu-Chen     case CC_OP_CONST0:
355c9274b6bSCho, Yu-Chen     case CC_OP_CONST1:
356c9274b6bSCho, Yu-Chen     case CC_OP_CONST2:
357c9274b6bSCho, Yu-Chen     case CC_OP_CONST3:
358c9274b6bSCho, Yu-Chen         /* cc_op value _is_ cc */
359c9274b6bSCho, Yu-Chen         r = cc_op;
360c9274b6bSCho, Yu-Chen         break;
361c9274b6bSCho, Yu-Chen     case CC_OP_LTGT0_32:
362c9274b6bSCho, Yu-Chen         r = cc_calc_ltgt0_32(dst);
363c9274b6bSCho, Yu-Chen         break;
364c9274b6bSCho, Yu-Chen     case CC_OP_LTGT0_64:
365c9274b6bSCho, Yu-Chen         r =  cc_calc_ltgt0_64(dst);
366c9274b6bSCho, Yu-Chen         break;
367c9274b6bSCho, Yu-Chen     case CC_OP_LTGT_32:
368c9274b6bSCho, Yu-Chen         r =  cc_calc_ltgt_32(src, dst);
369c9274b6bSCho, Yu-Chen         break;
370c9274b6bSCho, Yu-Chen     case CC_OP_LTGT_64:
371c9274b6bSCho, Yu-Chen         r =  cc_calc_ltgt_64(src, dst);
372c9274b6bSCho, Yu-Chen         break;
373c9274b6bSCho, Yu-Chen     case CC_OP_LTUGTU_32:
374c9274b6bSCho, Yu-Chen         r =  cc_calc_ltugtu_32(src, dst);
375c9274b6bSCho, Yu-Chen         break;
376c9274b6bSCho, Yu-Chen     case CC_OP_LTUGTU_64:
377c9274b6bSCho, Yu-Chen         r =  cc_calc_ltugtu_64(src, dst);
378c9274b6bSCho, Yu-Chen         break;
379c9274b6bSCho, Yu-Chen     case CC_OP_TM_32:
380c9274b6bSCho, Yu-Chen         r =  cc_calc_tm_32(src, dst);
381c9274b6bSCho, Yu-Chen         break;
382c9274b6bSCho, Yu-Chen     case CC_OP_TM_64:
383c9274b6bSCho, Yu-Chen         r =  cc_calc_tm_64(src, dst);
384c9274b6bSCho, Yu-Chen         break;
385c9274b6bSCho, Yu-Chen     case CC_OP_NZ:
386c9274b6bSCho, Yu-Chen         r =  cc_calc_nz(dst);
387c9274b6bSCho, Yu-Chen         break;
388c9274b6bSCho, Yu-Chen     case CC_OP_ADDU:
389c9274b6bSCho, Yu-Chen         r = cc_calc_addu(src, dst);
390c9274b6bSCho, Yu-Chen         break;
391c9274b6bSCho, Yu-Chen     case CC_OP_SUBU:
392c9274b6bSCho, Yu-Chen         r = cc_calc_subu(src, dst);
393c9274b6bSCho, Yu-Chen         break;
394c9274b6bSCho, Yu-Chen     case CC_OP_ADD_64:
395c9274b6bSCho, Yu-Chen         r =  cc_calc_add_64(src, dst, vr);
396c9274b6bSCho, Yu-Chen         break;
397c9274b6bSCho, Yu-Chen     case CC_OP_SUB_64:
398c9274b6bSCho, Yu-Chen         r =  cc_calc_sub_64(src, dst, vr);
399c9274b6bSCho, Yu-Chen         break;
400c9274b6bSCho, Yu-Chen     case CC_OP_ABS_64:
401c9274b6bSCho, Yu-Chen         r =  cc_calc_abs_64(dst);
402c9274b6bSCho, Yu-Chen         break;
403c9274b6bSCho, Yu-Chen     case CC_OP_NABS_64:
404c9274b6bSCho, Yu-Chen         r =  cc_calc_nabs_64(dst);
405c9274b6bSCho, Yu-Chen         break;
406c9274b6bSCho, Yu-Chen     case CC_OP_COMP_64:
407c9274b6bSCho, Yu-Chen         r =  cc_calc_comp_64(dst);
408c9274b6bSCho, Yu-Chen         break;
409c9274b6bSCho, Yu-Chen     case CC_OP_MULS_64:
410c9274b6bSCho, Yu-Chen         r = cc_calc_muls_64(src, dst);
411c9274b6bSCho, Yu-Chen         break;
412c9274b6bSCho, Yu-Chen 
413c9274b6bSCho, Yu-Chen     case CC_OP_ADD_32:
414c9274b6bSCho, Yu-Chen         r =  cc_calc_add_32(src, dst, vr);
415c9274b6bSCho, Yu-Chen         break;
416c9274b6bSCho, Yu-Chen     case CC_OP_SUB_32:
417c9274b6bSCho, Yu-Chen         r =  cc_calc_sub_32(src, dst, vr);
418c9274b6bSCho, Yu-Chen         break;
419c9274b6bSCho, Yu-Chen     case CC_OP_ABS_32:
420c9274b6bSCho, Yu-Chen         r =  cc_calc_abs_32(dst);
421c9274b6bSCho, Yu-Chen         break;
422c9274b6bSCho, Yu-Chen     case CC_OP_NABS_32:
423c9274b6bSCho, Yu-Chen         r =  cc_calc_nabs_32(dst);
424c9274b6bSCho, Yu-Chen         break;
425c9274b6bSCho, Yu-Chen     case CC_OP_COMP_32:
426c9274b6bSCho, Yu-Chen         r =  cc_calc_comp_32(dst);
427c9274b6bSCho, Yu-Chen         break;
428c9274b6bSCho, Yu-Chen     case CC_OP_MULS_32:
429c9274b6bSCho, Yu-Chen         r = cc_calc_muls_32(dst);
430c9274b6bSCho, Yu-Chen         break;
431c9274b6bSCho, Yu-Chen 
432c9274b6bSCho, Yu-Chen     case CC_OP_ICM:
433c9274b6bSCho, Yu-Chen         r =  cc_calc_icm(src, dst);
434c9274b6bSCho, Yu-Chen         break;
4356da170beSIlya Leoshkevich     case CC_OP_SLA:
4366da170beSIlya Leoshkevich         r =  cc_calc_sla(src, dst);
437c9274b6bSCho, Yu-Chen         break;
438c9274b6bSCho, Yu-Chen     case CC_OP_FLOGR:
439c9274b6bSCho, Yu-Chen         r = cc_calc_flogr(dst);
440c9274b6bSCho, Yu-Chen         break;
441c9274b6bSCho, Yu-Chen     case CC_OP_LCBB:
442c9274b6bSCho, Yu-Chen         r = cc_calc_lcbb(dst);
443c9274b6bSCho, Yu-Chen         break;
444c9274b6bSCho, Yu-Chen     case CC_OP_VC:
445c9274b6bSCho, Yu-Chen         r = cc_calc_vc(src, dst);
446c9274b6bSCho, Yu-Chen         break;
447c9274b6bSCho, Yu-Chen 
448c9274b6bSCho, Yu-Chen     case CC_OP_NZ_F32:
449c9274b6bSCho, Yu-Chen         r = set_cc_nz_f32(dst);
450c9274b6bSCho, Yu-Chen         break;
451c9274b6bSCho, Yu-Chen     case CC_OP_NZ_F64:
452c9274b6bSCho, Yu-Chen         r = set_cc_nz_f64(dst);
453c9274b6bSCho, Yu-Chen         break;
454c9274b6bSCho, Yu-Chen     case CC_OP_NZ_F128:
455c9274b6bSCho, Yu-Chen         r = set_cc_nz_f128(make_float128(src, dst));
456c9274b6bSCho, Yu-Chen         break;
457c9274b6bSCho, Yu-Chen 
458c9274b6bSCho, Yu-Chen     default:
459c9274b6bSCho, Yu-Chen         cpu_abort(env_cpu(env), "Unknown CC operation: %s\n", cc_name(cc_op));
460c9274b6bSCho, Yu-Chen     }
461c9274b6bSCho, Yu-Chen 
462c9274b6bSCho, Yu-Chen     HELPER_LOG("%s: %15s 0x%016lx 0x%016lx 0x%016lx = %d\n", __func__,
463c9274b6bSCho, Yu-Chen                cc_name(cc_op), src, dst, vr, r);
464c9274b6bSCho, Yu-Chen     return r;
465c9274b6bSCho, Yu-Chen }
466c9274b6bSCho, Yu-Chen 
calc_cc(CPUS390XState * env,uint32_t cc_op,uint64_t src,uint64_t dst,uint64_t vr)467c9274b6bSCho, Yu-Chen uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
468c9274b6bSCho, Yu-Chen                  uint64_t vr)
469c9274b6bSCho, Yu-Chen {
470c9274b6bSCho, Yu-Chen     return do_calc_cc(env, cc_op, src, dst, vr);
471c9274b6bSCho, Yu-Chen }
472c9274b6bSCho, Yu-Chen 
HELPER(calc_cc)473c9274b6bSCho, Yu-Chen uint32_t HELPER(calc_cc)(CPUS390XState *env, uint32_t cc_op, uint64_t src,
474c9274b6bSCho, Yu-Chen                          uint64_t dst, uint64_t vr)
475c9274b6bSCho, Yu-Chen {
476c9274b6bSCho, Yu-Chen     return do_calc_cc(env, cc_op, src, dst, vr);
477c9274b6bSCho, Yu-Chen }
478c9274b6bSCho, Yu-Chen 
479c9274b6bSCho, Yu-Chen #ifndef CONFIG_USER_ONLY
HELPER(load_psw)480c9274b6bSCho, Yu-Chen void HELPER(load_psw)(CPUS390XState *env, uint64_t mask, uint64_t addr)
481c9274b6bSCho, Yu-Chen {
482c9274b6bSCho, Yu-Chen     s390_cpu_set_psw(env, mask, addr);
483c9274b6bSCho, Yu-Chen     cpu_loop_exit(env_cpu(env));
484c9274b6bSCho, Yu-Chen }
485c9274b6bSCho, Yu-Chen 
HELPER(sacf)486c9274b6bSCho, Yu-Chen void HELPER(sacf)(CPUS390XState *env, uint64_t a1)
487c9274b6bSCho, Yu-Chen {
488c9274b6bSCho, Yu-Chen     HELPER_LOG("%s: %16" PRIx64 "\n", __func__, a1);
489c9274b6bSCho, Yu-Chen 
490*21be74a9SThomas Huth     if (!(env->psw.mask & PSW_MASK_DAT)) {
491*21be74a9SThomas Huth         tcg_s390_program_interrupt(env, PGM_SPECIAL_OP, GETPC());
492*21be74a9SThomas Huth     }
493*21be74a9SThomas Huth 
494c9274b6bSCho, Yu-Chen     switch (a1 & 0xf00) {
495c9274b6bSCho, Yu-Chen     case 0x000:
496c9274b6bSCho, Yu-Chen         env->psw.mask &= ~PSW_MASK_ASC;
497c9274b6bSCho, Yu-Chen         env->psw.mask |= PSW_ASC_PRIMARY;
498c9274b6bSCho, Yu-Chen         break;
499c9274b6bSCho, Yu-Chen     case 0x100:
500c9274b6bSCho, Yu-Chen         env->psw.mask &= ~PSW_MASK_ASC;
501c9274b6bSCho, Yu-Chen         env->psw.mask |= PSW_ASC_SECONDARY;
502c9274b6bSCho, Yu-Chen         break;
503c9274b6bSCho, Yu-Chen     case 0x300:
504*21be74a9SThomas Huth         if ((env->psw.mask & PSW_MASK_PSTATE) != 0) {
505*21be74a9SThomas Huth             tcg_s390_program_interrupt(env, PGM_PRIVILEGED, GETPC());
506*21be74a9SThomas Huth         }
507c9274b6bSCho, Yu-Chen         env->psw.mask &= ~PSW_MASK_ASC;
508c9274b6bSCho, Yu-Chen         env->psw.mask |= PSW_ASC_HOME;
509c9274b6bSCho, Yu-Chen         break;
510c9274b6bSCho, Yu-Chen     default:
511c9274b6bSCho, Yu-Chen         HELPER_LOG("unknown sacf mode: %" PRIx64 "\n", a1);
512c9274b6bSCho, Yu-Chen         tcg_s390_program_interrupt(env, PGM_SPECIFICATION, GETPC());
513c9274b6bSCho, Yu-Chen     }
514c9274b6bSCho, Yu-Chen }
515c9274b6bSCho, Yu-Chen #endif
516