• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- mode: C; c-basic-offset: 3; -*- */
2 
3 /*---------------------------------------------------------------*/
4 /*--- begin                              guest_s390_helpers.c ---*/
5 /*---------------------------------------------------------------*/
6 
7 /*
8    This file is part of Valgrind, a dynamic binary instrumentation
9    framework.
10 
11    Copyright IBM Corp. 2010-2011
12 
13    This program is free software; you can redistribute it and/or
14    modify it under the terms of the GNU General Public License as
15    published by the Free Software Foundation; either version 2 of the
16    License, or (at your option) any later version.
17 
18    This program is distributed in the hope that it will be useful, but
19    WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21    General Public License for more details.
22 
23    You should have received a copy of the GNU General Public License
24    along with this program; if not, write to the Free Software
25    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26    02110-1301, USA.
27 
28    The GNU General Public License is contained in the file COPYING.
29 */
30 
31 /* Contributed by Florian Krohm */
32 
33 #include "libvex_basictypes.h"
34 #include "libvex_emwarn.h"
35 #include "libvex_guest_s390x.h"
36 #include "libvex_ir.h"
37 #include "libvex.h"
38 #include "libvex_s390x_common.h"
39 
40 #include "main_util.h"
41 #include "guest_generic_bb_to_IR.h"
42 #include "guest_s390_defs.h"
43 
44 void
LibVEX_GuestS390X_initialise(VexGuestS390XState * state)45 LibVEX_GuestS390X_initialise(VexGuestS390XState *state)
46 {
47 /*------------------------------------------------------------*/
48 /*--- Initialise ar registers                              ---*/
49 /*------------------------------------------------------------*/
50 
51    state->guest_a0 = 0;
52    state->guest_a1 = 0;
53    state->guest_a2 = 0;
54    state->guest_a3 = 0;
55    state->guest_a4 = 0;
56    state->guest_a5 = 0;
57    state->guest_a6 = 0;
58    state->guest_a7 = 0;
59    state->guest_a8 = 0;
60    state->guest_a9 = 0;
61    state->guest_a10 = 0;
62    state->guest_a11 = 0;
63    state->guest_a12 = 0;
64    state->guest_a13 = 0;
65    state->guest_a14 = 0;
66    state->guest_a15 = 0;
67 
68 /*------------------------------------------------------------*/
69 /*--- Initialise fpr registers                             ---*/
70 /*------------------------------------------------------------*/
71 
72    state->guest_f0 = 0;
73    state->guest_f1 = 0;
74    state->guest_f2 = 0;
75    state->guest_f3 = 0;
76    state->guest_f4 = 0;
77    state->guest_f5 = 0;
78    state->guest_f6 = 0;
79    state->guest_f7 = 0;
80    state->guest_f8 = 0;
81    state->guest_f9 = 0;
82    state->guest_f10 = 0;
83    state->guest_f11 = 0;
84    state->guest_f12 = 0;
85    state->guest_f13 = 0;
86    state->guest_f14 = 0;
87    state->guest_f15 = 0;
88 
89 /*------------------------------------------------------------*/
90 /*--- Initialise gpr registers                             ---*/
91 /*------------------------------------------------------------*/
92 
93    state->guest_r0 = 0;
94    state->guest_r1 = 0;
95    state->guest_r2 = 0;
96    state->guest_r3 = 0;
97    state->guest_r4 = 0;
98    state->guest_r5 = 0;
99    state->guest_r6 = 0;
100    state->guest_r7 = 0;
101    state->guest_r8 = 0;
102    state->guest_r9 = 0;
103    state->guest_r10 = 0;
104    state->guest_r11 = 0;
105    state->guest_r12 = 0;
106    state->guest_r13 = 0;
107    state->guest_r14 = 0;
108    state->guest_r15 = 0;
109 
110 /*------------------------------------------------------------*/
111 /*--- Initialise S390 miscellaneous registers              ---*/
112 /*------------------------------------------------------------*/
113 
114    state->guest_counter = 0;
115    state->guest_fpc = 0;
116    state->guest_IA = 0;
117 
118 /*------------------------------------------------------------*/
119 /*--- Initialise S390 pseudo registers                     ---*/
120 /*------------------------------------------------------------*/
121 
122    state->guest_SYSNO = 0;
123 
124 /*------------------------------------------------------------*/
125 /*--- Initialise generic pseudo registers                  ---*/
126 /*------------------------------------------------------------*/
127 
128    state->guest_NRADDR = 0;
129    state->guest_TISTART = 0;
130    state->guest_TILEN = 0;
131    state->guest_IP_AT_SYSCALL = 0;
132    state->guest_EMWARN = EmWarn_NONE;
133 
134 /*------------------------------------------------------------*/
135 /*--- Initialise thunk                                     ---*/
136 /*------------------------------------------------------------*/
137 
138    state->guest_CC_OP = 0;
139    state->guest_CC_DEP1 = 0;
140    state->guest_CC_DEP2 = 0;
141    state->guest_CC_NDEP = 0;
142 }
143 
144 
145 /* Figure out if any part of the guest state contained in minoff
146    .. maxoff requires precise memory exceptions.  If in doubt return
147    True (but this is generates significantly slower code).  */
148 Bool
guest_s390x_state_requires_precise_mem_exns(Int minoff,Int maxoff)149 guest_s390x_state_requires_precise_mem_exns(Int minoff, Int maxoff)
150 {
151    Int lr_min = S390X_GUEST_OFFSET(guest_LR);
152    Int lr_max = lr_min + 8 - 1;
153    Int sp_min = S390X_GUEST_OFFSET(guest_SP);
154    Int sp_max = sp_min + 8 - 1;
155    Int fp_min = S390X_GUEST_OFFSET(guest_FP);
156    Int fp_max = fp_min + 8 - 1;
157    Int ia_min = S390X_GUEST_OFFSET(guest_IA);
158    Int ia_max = ia_min + 8 - 1;
159 
160    if (maxoff < lr_min || minoff > lr_max) {
161       /* No overlap with LR */
162    } else {
163       return True;
164    }
165 
166    if (maxoff < sp_min || minoff > sp_max) {
167       /* No overlap with SP */
168    } else {
169       return True;
170    }
171 
172    if (maxoff < fp_min || minoff > fp_max) {
173       /* No overlap with FP */
174    } else {
175       return True;
176    }
177 
178    if (maxoff < ia_min || minoff > ia_max) {
179       /* No overlap with IA */
180    } else {
181       return True;
182    }
183 
184    return False;
185 }
186 
187 
188 #define ALWAYSDEFD(field)                             \
189     { S390X_GUEST_OFFSET(field),            \
190       (sizeof ((VexGuestS390XState*)0)->field) }
191 
192 VexGuestLayout s390xGuest_layout = {
193 
194    /* Total size of the guest state, in bytes. */
195    .total_sizeB = sizeof(VexGuestS390XState),
196 
197    /* Describe the stack pointer. */
198    .offset_SP = S390X_GUEST_OFFSET(guest_SP),
199    .sizeof_SP = 8,
200 
201    /* Describe the frame pointer. */
202    .offset_FP = S390X_GUEST_OFFSET(guest_FP),
203    .sizeof_FP = 8,
204 
205    /* Describe the instruction pointer. */
206    .offset_IP = S390X_GUEST_OFFSET(guest_IA),
207    .sizeof_IP = 8,
208 
209    /* Describe any sections to be regarded by Memcheck as
210       'always-defined'. */
211    .n_alwaysDefd = 9,
212 
213    /* Flags thunk: OP and NDEP are always defined, whereas DEP1
214       and DEP2 have to be tracked.  See detailed comment in
215       gdefs.h on meaning of thunk fields. */
216    .alwaysDefd = {
217       /*  0 */ ALWAYSDEFD(guest_CC_OP),     /* generic */
218       /*  1 */ ALWAYSDEFD(guest_CC_NDEP),   /* generic */
219       /*  2 */ ALWAYSDEFD(guest_EMWARN),    /* generic */
220       /*  3 */ ALWAYSDEFD(guest_TISTART),   /* generic */
221       /*  4 */ ALWAYSDEFD(guest_TILEN),     /* generic */
222       /*  5 */ ALWAYSDEFD(guest_IP_AT_SYSCALL), /* generic */
223       /*  6 */ ALWAYSDEFD(guest_IA),        /* control reg */
224       /*  7 */ ALWAYSDEFD(guest_fpc),       /* control reg */
225       /*  8 */ ALWAYSDEFD(guest_counter),   /* internal usage register */
226    }
227 };
228 
229 /*------------------------------------------------------------*/
230 /*--- Dirty helper for invalid opcode 00                   ---*/
231 /*------------------------------------------------------------*/
232 #if defined(VGA_s390x)
233 void
s390x_dirtyhelper_00(VexGuestS390XState * guest_state)234 s390x_dirtyhelper_00(VexGuestS390XState *guest_state)
235 {
236    /* Avoid infinite loop in case SIGILL is caught. See also
237       none/tests/s390x/op_exception.c */
238    guest_state->guest_IA += 2;
239 
240    asm volatile(".hword 0\n");
241 }
242 #else
s390x_dirtyhelper_00(VexGuestS390XState * guest_state)243 void s390x_dirtyhelper_00(VexGuestS390XState *guest_state) { }
244 #endif
245 
246 /*------------------------------------------------------------*/
247 /*--- Dirty helper for EXecute                             ---*/
248 /*------------------------------------------------------------*/
249 void
s390x_dirtyhelper_EX(ULong torun)250 s390x_dirtyhelper_EX(ULong torun)
251 {
252    last_execute_target = torun;
253 }
254 
255 
256 /*------------------------------------------------------------*/
257 /*--- Dirty helper for Clock instructions                  ---*/
258 /*------------------------------------------------------------*/
259 #if defined(VGA_s390x)
s390x_dirtyhelper_STCK(ULong * addr)260 ULong s390x_dirtyhelper_STCK(ULong *addr)
261 {
262    int cc;
263 
264    asm volatile("stck %0\n"
265                 "ipm %1\n"
266                 "srl %1,28\n"
267                 : "+Q" (*addr), "=d" (cc) : : "cc");
268    return cc;
269 }
270 
s390x_dirtyhelper_STCKE(ULong * addr)271 ULong s390x_dirtyhelper_STCKE(ULong *addr)
272 {
273    int cc;
274 
275    asm volatile("stcke %0\n"
276                 "ipm %1\n"
277                 "srl %1,28\n"
278                 : "+Q" (*addr), "=d" (cc) : : "cc");
279    return cc;
280 }
281 
s390x_dirtyhelper_STCKF(ULong * addr)282 ULong s390x_dirtyhelper_STCKF(ULong *addr)
283 {
284    int cc;
285 
286    asm volatile(".insn s,0xb27c0000,%0\n"
287                 "ipm %1\n"
288                 "srl %1,28\n"
289                 : "+Q" (*addr), "=d" (cc) : : "cc");
290    return cc;
291 }
292 #else
s390x_dirtyhelper_STCK(ULong * addr)293 ULong s390x_dirtyhelper_STCK(ULong *addr)  {return 3;}
s390x_dirtyhelper_STCKF(ULong * addr)294 ULong s390x_dirtyhelper_STCKF(ULong *addr) {return 3;}
s390x_dirtyhelper_STCKE(ULong * addr)295 ULong s390x_dirtyhelper_STCKE(ULong *addr) {return 3;}
296 #endif /* VGA_s390x */
297 
298 /*------------------------------------------------------------*/
299 /*--- Dirty helper for Store Facility instruction          ---*/
300 /*------------------------------------------------------------*/
301 #if defined(VGA_s390x)
302 ULong
s390x_dirtyhelper_STFLE(VexGuestS390XState * guest_state,HWord addr)303 s390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, HWord addr)
304 {
305    ULong hoststfle[S390_NUM_FACILITY_DW], cc, num_dw, i;
306    register ULong reg0 asm("0") = guest_state->guest_r0 & 0xF;  /* r0[56:63] */
307 
308    /* We cannot store more than S390_NUM_FACILITY_DW
309       (and it makes not much sense to do so anyhow) */
310    if (reg0 > S390_NUM_FACILITY_DW - 1)
311       reg0 = S390_NUM_FACILITY_DW - 1;
312 
313    num_dw = reg0 + 1;  /* number of double words written */
314 
315    asm volatile(" .insn s,0xb2b00000,%0\n"   /* stfle */
316                 "ipm    %2\n"
317                 "srl    %2,28\n"
318                 : "=m" (hoststfle), "+d"(reg0), "=d"(cc) : : "cc", "memory");
319 
320    /* Update guest register 0  with what STFLE set r0 to */
321    guest_state->guest_r0 = reg0;
322 
323    for (i = 0; i < num_dw; ++i)
324       ((ULong *)addr)[i] = hoststfle[i];
325 
326    return cc;
327 }
328 
329 #else
330 
331 ULong
s390x_dirtyhelper_STFLE(VexGuestS390XState * guest_state,HWord addr)332 s390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, HWord addr)
333 {
334    return 3;
335 }
336 #endif /* VGA_s390x */
337 
338 /*------------------------------------------------------------*/
339 /*--- Helper for condition code.                           ---*/
340 /*------------------------------------------------------------*/
341 
342 #define S390_CC_FOR_BINARY(opcode,cc_dep1,cc_dep2) \
343 ({ \
344    __asm__ volatile ( \
345         opcode " %[op1],%[op2]\n\t" \
346         "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+d"(cc_dep1) \
347                                    : [op2] "d"(cc_dep2) \
348                                    : "cc");\
349    psw >> 28;   /* cc */ \
350 })
351 
352 #define S390_CC_FOR_TERNARY_SUBB(opcode,cc_dep1,cc_dep2,cc_ndep) \
353 ({ \
354    /* Recover the original DEP2 value. See comment near s390_cc_thunk_put3 \
355       for rationale. */ \
356    cc_dep2 = cc_dep2 ^ cc_ndep; \
357    __asm__ volatile ( \
358 	"lghi 0,1\n\t" \
359 	"sr 0,%[op3]\n\t" /* borrow to cc */ \
360         opcode " %[op1],%[op2]\n\t" /* then redo the op */\
361         "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+&d"(cc_dep1) \
362                                    : [op2] "d"(cc_dep2), [op3] "d"(cc_ndep) \
363                                    : "0", "cc");\
364    psw >> 28;   /* cc */ \
365 })
366 
367 #define S390_CC_FOR_TERNARY_ADDC(opcode,cc_dep1,cc_dep2,cc_ndep) \
368 ({ \
369    /* Recover the original DEP2 value. See comment near s390_cc_thunk_put3 \
370       for rationale. */ \
371    cc_dep2 = cc_dep2 ^ cc_ndep; \
372    __asm__ volatile ( \
373 	"lgfr 0,%[op3]\n\t" /* first load cc_ndep */ \
374 	"aghi 0,0\n\t" /* and convert it into a cc */ \
375         opcode " %[op1],%[op2]\n\t" /* then redo the op */\
376         "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+&d"(cc_dep1) \
377                                    : [op2] "d"(cc_dep2), [op3] "d"(cc_ndep) \
378                                    : "0", "cc");\
379    psw >> 28;   /* cc */ \
380 })
381 
382 
383 #define S390_CC_FOR_BFP_RESULT(opcode,cc_dep1) \
384 ({ \
385    __asm__ volatile ( \
386         opcode " 0,%[op]\n\t" \
387         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
388                                    : [op]  "f"(cc_dep1) \
389                                    : "cc", "f0");\
390    psw >> 28;   /* cc */ \
391 })
392 
393 #define S390_CC_FOR_BFP128_RESULT(hi,lo) \
394 ({ \
395    __asm__ volatile ( \
396         "ldr   4,%[high]\n\t" \
397         "ldr   6,%[low]\n\t" \
398         "ltxbr 0,4\n\t" \
399         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
400                                    : [high] "f"(hi), [low] "f"(lo) \
401                                    : "cc", "f0", "f2", "f4", "f6");\
402    psw >> 28;   /* cc */ \
403 })
404 
405 #define S390_CC_FOR_BFP_CONVERT(opcode,cc_dep1) \
406 ({ \
407    __asm__ volatile ( \
408         opcode " 0,0,%[op]\n\t" \
409         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
410                                    : [op]  "f"(cc_dep1) \
411                                    : "cc", "r0");\
412    psw >> 28;   /* cc */ \
413 })
414 
415 #define S390_CC_FOR_BFP128_CONVERT(opcode,hi,lo) \
416 ({ \
417    __asm__ volatile ( \
418         "ldr   4,%[high]\n\t" \
419         "ldr   6,%[low]\n\t" \
420         opcode " 0,0,4\n\t" \
421         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
422                                    : [high] "f"(hi), [low] "f"(lo) \
423                                    : "cc", "r0", "f4", "f6");\
424    psw >> 28;   /* cc */ \
425 })
426 
427 #define S390_CC_FOR_BFP_TDC(opcode,cc_dep1,cc_dep2) \
428 ({ \
429    __asm__ volatile ( \
430         opcode " %[value],0(%[class])\n\t" \
431         "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
432                                    : [value] "f"(cc_dep1), \
433                                      [class] "a"(cc_dep2)  \
434                                    : "cc");\
435    psw >> 28;   /* cc */ \
436 })
437 
438 #define S390_CC_FOR_BFP128_TDC(cc_dep1,cc_dep2,cc_ndep) \
439 ({ \
440    /* Recover the original DEP2 value. See comment near s390_cc_thunk_put1f128Z \
441       for rationale. */ \
442    cc_dep2 = cc_dep2 ^ cc_ndep; \
443    __asm__ volatile ( \
444         "ldr  4,%[high]\n\t" \
445         "ldr  6,%[low]\n\t" \
446         "tcxb 4,0(%[class])\n\t" \
447         "ipm  %[psw]\n\t"          : [psw] "=d"(psw) \
448                                    : [high] "f"(cc_dep1), [low] "f"(cc_dep2), \
449                                      [class] "a"(cc_ndep)  \
450                                    : "cc", "f4", "f6");\
451    psw >> 28;   /* cc */ \
452 })
453 
454 
455 /* Return the value of the condition code from the supplied thunk parameters.
456    This is not the value of the PSW. It is the value of the 2 CC bits within
457    the PSW. The returned value is thusly in the interval [0:3]. */
458 UInt
s390_calculate_cc(ULong cc_op,ULong cc_dep1,ULong cc_dep2,ULong cc_ndep)459 s390_calculate_cc(ULong cc_op, ULong cc_dep1, ULong cc_dep2, ULong cc_ndep)
460 {
461 #if defined(VGA_s390x)
462    UInt psw;
463 
464    switch (cc_op) {
465 
466    case S390_CC_OP_BITWISE:
467       return S390_CC_FOR_BINARY("ogr", cc_dep1, (ULong)0);
468 
469    case S390_CC_OP_SIGNED_COMPARE:
470       return S390_CC_FOR_BINARY("cgr", cc_dep1, cc_dep2);
471 
472    case S390_CC_OP_UNSIGNED_COMPARE:
473       return S390_CC_FOR_BINARY("clgr", cc_dep1, cc_dep2);
474 
475    case S390_CC_OP_SIGNED_ADD_64:
476       return S390_CC_FOR_BINARY("agr", cc_dep1, cc_dep2);
477 
478    case S390_CC_OP_SIGNED_ADD_32:
479       return S390_CC_FOR_BINARY("ar", cc_dep1, cc_dep2);
480 
481    case S390_CC_OP_SIGNED_SUB_64:
482       return S390_CC_FOR_BINARY("sgr", cc_dep1, cc_dep2);
483 
484    case S390_CC_OP_SIGNED_SUB_32:
485       return S390_CC_FOR_BINARY("sr", cc_dep1, cc_dep2);
486 
487    case S390_CC_OP_UNSIGNED_ADD_64:
488       return S390_CC_FOR_BINARY("algr", cc_dep1, cc_dep2);
489 
490    case S390_CC_OP_UNSIGNED_ADD_32:
491       return S390_CC_FOR_BINARY("alr", cc_dep1, cc_dep2);
492 
493    case S390_CC_OP_UNSIGNED_ADDC_64:
494       return S390_CC_FOR_TERNARY_ADDC("alcgr", cc_dep1, cc_dep2, cc_ndep);
495 
496    case S390_CC_OP_UNSIGNED_ADDC_32:
497       return S390_CC_FOR_TERNARY_ADDC("alcr", cc_dep1, cc_dep2, cc_ndep);
498 
499    case S390_CC_OP_UNSIGNED_SUB_64:
500       return S390_CC_FOR_BINARY("slgr", cc_dep1, cc_dep2);
501 
502    case S390_CC_OP_UNSIGNED_SUB_32:
503       return S390_CC_FOR_BINARY("slr", cc_dep1, cc_dep2);
504 
505    case S390_CC_OP_UNSIGNED_SUBB_64:
506       return S390_CC_FOR_TERNARY_SUBB("slbgr", cc_dep1, cc_dep2, cc_ndep);
507 
508    case S390_CC_OP_UNSIGNED_SUBB_32:
509       return S390_CC_FOR_TERNARY_SUBB("slbr", cc_dep1, cc_dep2, cc_ndep);
510 
511    case S390_CC_OP_LOAD_AND_TEST:
512       /* Like signed comparison with 0 */
513       return S390_CC_FOR_BINARY("cgr", cc_dep1, (Long)0);
514 
515    case S390_CC_OP_TEST_AND_SET:
516       /* Shift the sign bit into the LSB. Note, that the tested value is an
517          8-bit value which has been zero-extended to 32/64 bit. */
518       return cc_dep1 >> 7;
519 
520    case S390_CC_OP_LOAD_POSITIVE_32:
521       __asm__ volatile (
522            "lpr  %[result],%[op]\n\t"
523            "ipm  %[psw]\n\t"            : [psw] "=d"(psw), [result] "=d"(cc_dep1)
524                                         : [op] "d"(cc_dep1)
525                                         : "cc");
526       return psw >> 28;   /* cc */
527 
528    case S390_CC_OP_LOAD_POSITIVE_64:
529       __asm__ volatile (
530            "lpgr %[result],%[op]\n\t"
531            "ipm  %[psw]\n\t"            : [psw] "=d"(psw), [result] "=d"(cc_dep1)
532                                         : [op] "d"(cc_dep1)
533                                         : "cc");
534       return psw >> 28;   /* cc */
535 
536    case S390_CC_OP_TEST_UNDER_MASK_8: {
537       UChar value  = cc_dep1;
538       UChar mask   = cc_dep2;
539 
540       __asm__ volatile (
541            "bras %%r2,1f\n\t"             /* %r2 = address of next insn */
542            "tm %[value],0\n\t"            /* this is skipped, then EXecuted */
543            "1: ex %[mask],0(%%r2)\n\t"    /* EXecute TM after modifying mask */
544            "ipm %[psw]\n\t"             : [psw] "=d"(psw)
545                                         : [value] "m"(value), [mask] "a"(mask)
546                                         : "r2", "cc");
547       return psw >> 28;   /* cc */
548    }
549 
550    case S390_CC_OP_TEST_UNDER_MASK_16: {
551       /* Create a TMLL insn with the mask as given by cc_dep2 */
552       UInt insn  = (0xA701 << 16) | cc_dep2;
553       UInt value = cc_dep1;
554 
555       __asm__ volatile (
556            "lr   1,%[value]\n\t"
557            "lhi  2,0x10\n\t"
558            "ex   2,%[insn]\n\t"
559            "ipm  %[psw]\n\t"       : [psw] "=d"(psw)
560                                    : [value] "d"(value), [insn] "m"(insn)
561                                    : "r1", "r2", "cc");
562       return psw >> 28;   /* cc */
563    }
564 
565    case S390_CC_OP_SHIFT_LEFT_32:
566       __asm__ volatile (
567            "sla  %[op],0(%[amount])\n\t"
568            "ipm  %[psw]\n\t"            : [psw] "=d"(psw), [op] "+d"(cc_dep1)
569                                         : [amount] "a"(cc_dep2)
570                                         : "cc");
571       return psw >> 28;   /* cc */
572 
573    case S390_CC_OP_SHIFT_LEFT_64: {
574       Int high = (Int)(cc_dep1 >> 32);
575       Int low  = (Int)(cc_dep1 & 0xFFFFFFFF);
576 
577       __asm__ volatile (
578            "lr   2,%[high]\n\t"
579            "lr   3,%[low]\n\t"
580            "slda 2,0(%[amount])\n\t"
581            "ipm %[psw]\n\t"             : [psw] "=d"(psw), [high] "+d"(high), [low] "+d"(low)
582                                         : [amount] "a"(cc_dep2)
583                                         : "cc", "r2", "r3");
584       return psw >> 28;   /* cc */
585    }
586 
587    case S390_CC_OP_INSERT_CHAR_MASK_32: {
588       Int inserted = 0;
589       Int msb = 0;
590 
591       if (cc_dep2 & 1) {
592          inserted |= cc_dep1 & 0xff;
593          msb = 0x80;
594       }
595       if (cc_dep2 & 2) {
596          inserted |= cc_dep1 & 0xff00;
597          msb = 0x8000;
598       }
599       if (cc_dep2 & 4) {
600          inserted |= cc_dep1 & 0xff0000;
601          msb = 0x800000;
602       }
603       if (cc_dep2 & 8) {
604          inserted |= cc_dep1 & 0xff000000;
605          msb = 0x80000000;
606       }
607 
608       if (inserted & msb)  // MSB is 1
609          return 1;
610       if (inserted > 0)
611          return 2;
612       return 0;
613    }
614 
615    case S390_CC_OP_BFP_RESULT_32:
616       return S390_CC_FOR_BFP_RESULT("ltebr", cc_dep1);
617 
618    case S390_CC_OP_BFP_RESULT_64:
619       return S390_CC_FOR_BFP_RESULT("ltdbr", cc_dep1);
620 
621    case S390_CC_OP_BFP_RESULT_128:
622       return S390_CC_FOR_BFP128_RESULT(cc_dep1, cc_dep2);
623 
624    case S390_CC_OP_BFP_32_TO_INT_32:
625       return S390_CC_FOR_BFP_CONVERT("cfebr", cc_dep1);
626 
627    case S390_CC_OP_BFP_64_TO_INT_32:
628       return S390_CC_FOR_BFP_CONVERT("cfdbr", cc_dep1);
629 
630    case S390_CC_OP_BFP_128_TO_INT_32:
631       return S390_CC_FOR_BFP128_CONVERT("cfxbr", cc_dep1, cc_dep2);
632 
633    case S390_CC_OP_BFP_32_TO_INT_64:
634       return S390_CC_FOR_BFP_CONVERT("cgebr", cc_dep1);
635 
636    case S390_CC_OP_BFP_64_TO_INT_64:
637       return S390_CC_FOR_BFP_CONVERT("cgdbr", cc_dep1);
638 
639    case S390_CC_OP_BFP_128_TO_INT_64:
640       return S390_CC_FOR_BFP128_CONVERT("cgxbr", cc_dep1, cc_dep2);
641 
642    case S390_CC_OP_BFP_TDC_32:
643       return S390_CC_FOR_BFP_TDC("tceb", cc_dep1, cc_dep2);
644 
645    case S390_CC_OP_BFP_TDC_64:
646       return S390_CC_FOR_BFP_TDC("tcdb", cc_dep1, cc_dep2);
647 
648    case S390_CC_OP_BFP_TDC_128:
649       return S390_CC_FOR_BFP128_TDC(cc_dep1, cc_dep2, cc_ndep);
650 
651    case S390_CC_OP_SET:
652       return cc_dep1;
653 
654    default:
655       break;
656    }
657 #endif
658    vpanic("s390_calculate_cc");
659 }
660 
661 
662 UInt
s390_calculate_icc(ULong op,ULong dep1,ULong dep2)663 s390_calculate_icc(ULong op, ULong dep1, ULong dep2)
664 {
665    return s390_calculate_cc(op, dep1, dep2, 0 /* unused */);
666 }
667 
668 
669 /* Note that this does *not* return a Boolean value. The result needs to be
670    explicitly tested against zero. */
671 UInt
s390_calculate_cond(ULong mask,ULong op,ULong dep1,ULong dep2,ULong ndep)672 s390_calculate_cond(ULong mask, ULong op, ULong dep1, ULong dep2, ULong ndep)
673 {
674    UInt cc = s390_calculate_cc(op, dep1, dep2, ndep);
675 
676    return ((mask << cc) & 0x8);
677 }
678 
679 /*------------------------------------------------------------*/
680 /*--- spechelper for performance                           ---*/
681 /*------------------------------------------------------------*/
682 
683 
684 /* Convenience macros */
685 #define unop(op,a1) IRExpr_Unop((op),(a1))
686 #define binop(op,a1,a2) IRExpr_Binop((op),(a1),(a2))
687 #define mkU64(v) IRExpr_Const(IRConst_U64(v))
688 #define mkU32(v) IRExpr_Const(IRConst_U32(v))
689 #define mkU8(v)  IRExpr_Const(IRConst_U8(v))
690 
691 
692 static inline Bool
isC64(IRExpr * expr)693 isC64(IRExpr *expr)
694 {
695    return expr->tag == Iex_Const && expr->Iex.Const.con->tag == Ico_U64;
696 }
697 
698 
699 /* The returned expression is NULL if no specialization was found. In that
700    case the helper function will be called. Otherwise, the expression has
701    type Ity_I32 and a Boolean value. */
702 IRExpr *
guest_s390x_spechelper(HChar * function_name,IRExpr ** args,IRStmt ** precedingStmts,Int n_precedingStmts)703 guest_s390x_spechelper(HChar *function_name, IRExpr **args,
704                        IRStmt **precedingStmts, Int n_precedingStmts)
705 {
706    UInt i, arity = 0;
707 
708    for (i = 0; args[i]; i++)
709       arity++;
710 
711 #  if 0
712    vex_printf("spec request:\n");
713    vex_printf("   %s  ", function_name);
714    for (i = 0; i < arity; i++) {
715       vex_printf("  ");
716       ppIRExpr(args[i]);
717    }
718    vex_printf("\n");
719 #  endif
720 
721    /* --------- Specialising "s390_calculate_cond" --------- */
722 
723    if (vex_streq(function_name, "s390_calculate_cond")) {
724       IRExpr *cond_expr, *cc_op_expr, *cc_dep1, *cc_dep2;
725       ULong cond, cc_op;
726 
727       vassert(arity == 5);
728 
729       cond_expr  = args[0];
730       cc_op_expr = args[1];
731 
732       /* The necessary requirement for all optimizations here is that the
733          condition and the cc_op are constant. So check that upfront. */
734       if (! isC64(cond_expr))  return NULL;
735       if (! isC64(cc_op_expr)) return NULL;
736 
737       cond    = cond_expr->Iex.Const.con->Ico.U64;
738       cc_op   = cc_op_expr->Iex.Const.con->Ico.U64;
739 
740       vassert(cond <= 15);
741 
742       /*
743         +------+---+---+---+---+
744         | cc   | 0 | 1 | 2 | 3 |
745         | cond | 8 | 4 | 2 | 1 |
746         +------+---+---+---+---+
747       */
748       cc_dep1 = args[2];
749       cc_dep2 = args[3];
750 
751       /* S390_CC_OP_SIGNED_COMPARE */
752       if (cc_op == S390_CC_OP_SIGNED_COMPARE) {
753          /*
754             cc == 0  --> cc_dep1 == cc_dep2   (cond == 8)
755             cc == 1  --> cc_dep1 <  cc_dep2   (cond == 4)
756             cc == 2  --> cc_dep1 >  cc_dep2   (cond == 2)
757 
758             Because cc == 3 cannot occur the rightmost bit of cond is
759             a don't care.
760          */
761          if (cond == 8 || cond == 8 + 1) {
762             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
763          }
764          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
765             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
766          }
767          if (cond == 4 || cond == 4 + 1) {
768             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep1, cc_dep2));
769          }
770          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
771             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep1, cc_dep2));
772          }
773          /* cc_dep1 > cc_dep2  ---->  cc_dep2 < cc_dep1 */
774          if (cond == 2 || cond == 2 + 1) {
775             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep2, cc_dep1));
776          }
777          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
778             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep2, cc_dep1));
779          }
780          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
781             return mkU32(1);
782          }
783          /* Remaining case */
784          return mkU32(0);
785       }
786 
787       /* S390_CC_OP_UNSIGNED_COMPARE */
788       if (cc_op == S390_CC_OP_UNSIGNED_COMPARE) {
789          /*
790             cc == 0  --> cc_dep1 == cc_dep2   (cond == 8)
791             cc == 1  --> cc_dep1 <  cc_dep2   (cond == 4)
792             cc == 2  --> cc_dep1 >  cc_dep2   (cond == 2)
793 
794             Because cc == 3 cannot occur the rightmost bit of cond is
795             a don't care.
796          */
797          if (cond == 8 || cond == 8 + 1) {
798             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
799          }
800          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
801             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
802          }
803          if (cond == 4 || cond == 4 + 1) {
804             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
805          }
806          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
807             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
808          }
809          /* cc_dep1 > cc_dep2  ---->  cc_dep2 < cc_dep1 */
810          if (cond == 2 || cond == 2 + 1) {
811             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep2, cc_dep1));
812          }
813          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
814             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
815          }
816          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
817             return mkU32(1);
818          }
819          /* Remaining case */
820          return mkU32(0);
821       }
822 
823       /* S390_CC_OP_LOAD_AND_TEST */
824       if (cc_op == S390_CC_OP_LOAD_AND_TEST) {
825          /*
826             cc == 0  --> cc_dep1 == 0   (cond == 8)
827             cc == 1  --> cc_dep1 <  0   (cond == 4)
828             cc == 2  --> cc_dep1 >  0   (cond == 2)
829 
830             Because cc == 3 cannot occur the rightmost bit of cond is
831             a don't care.
832          */
833          if (cond == 8 || cond == 8 + 1) {
834             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, mkU64(0)));
835          }
836          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
837             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
838          }
839          if (cond == 4 || cond == 4 + 1) {
840             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep1, mkU64(0)));
841          }
842          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
843             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep1, mkU64(0)));
844          }
845          /* cc_dep1 > 0  ---->  0 < cc_dep1 */
846          if (cond == 2 || cond == 2 + 1) {
847             return unop(Iop_1Uto32, binop(Iop_CmpLT64S, mkU64(0), cc_dep1));
848          }
849          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
850             return unop(Iop_1Uto32, binop(Iop_CmpLE64S, mkU64(0), cc_dep1));
851          }
852          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
853             return mkU32(1);
854          }
855          /* Remaining case */
856          return mkU32(0);
857       }
858 
859       /* S390_CC_OP_BITWISE */
860       if (cc_op == S390_CC_OP_BITWISE) {
861          /*
862             cc_dep1 is the result of the boolean operation.
863 
864             cc == 0  --> cc_dep1 == 0   (cond == 8)
865             cc == 1  --> cc_dep1 != 0   (cond == 4)
866 
867             Because cc == 2 and cc == 3 cannot occur the two rightmost bits of
868             cond are don't cares. Therefore:
869 
870             cond == 00xx  -> always false
871             cond == 01xx  -> not equal
872             cond == 10xx  -> equal
873             cond == 11xx  -> always true
874          */
875          if ((cond & (8 + 4)) == 8 + 4) {
876             return mkU32(1);
877          }
878          if (cond & 8) {
879             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, mkU64(0)));
880          }
881          if (cond & 4) {
882             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
883          }
884          /* Remaining case */
885          return mkU32(0);
886       }
887 
888       /* S390_CC_OP_INSERT_CHAR_MASK_32
889          Since the mask comes from an immediate field in the opcode, we
890          expect the mask to be a constant here. That simplifies matters. */
891       if (cc_op == S390_CC_OP_INSERT_CHAR_MASK_32) {
892          ULong mask;
893          UInt imask = 0, shift = 0;
894          IRExpr *word;
895 
896          if (! isC64(cc_dep2)) goto missed;
897 
898          mask = cc_dep2->Iex.Const.con->Ico.U64;
899 
900          /* Extract the 32-bit value from the thunk */
901 
902          word = unop(Iop_64to32, cc_dep1);
903 
904          switch (mask) {
905          case 0:  shift =  0; imask = 0x00000000; break;
906          case 1:  shift = 24; imask = 0x000000FF; break;
907          case 2:  shift = 16; imask = 0x0000FF00; break;
908          case 3:  shift = 16; imask = 0x0000FFFF; break;
909          case 4:  shift =  8; imask = 0x00FF0000; break;
910          case 5:  shift =  8; imask = 0x00FF00FF; break;
911          case 6:  shift =  8; imask = 0x00FFFF00; break;
912          case 7:  shift =  8; imask = 0x00FFFFFF; break;
913          case 8:  shift =  0; imask = 0xFF000000; break;
914          case 9:  shift =  0; imask = 0xFF0000FF; break;
915          case 10: shift =  0; imask = 0xFF00FF00; break;
916          case 11: shift =  0; imask = 0xFF00FFFF; break;
917          case 12: shift =  0; imask = 0xFFFF0000; break;
918          case 13: shift =  0; imask = 0xFFFF00FF; break;
919          case 14: shift =  0; imask = 0xFFFFFF00; break;
920          case 15: shift =  0; imask = 0xFFFFFFFF; break;
921          }
922 
923          /* Select the bits that were inserted */
924          word = binop(Iop_And32, word, mkU32(imask));
925 
926          /* cc == 0  --> all inserted bits zero or mask == 0   (cond == 8)
927             cc == 1  --> leftmost inserted bit is one          (cond == 4)
928             cc == 2  --> leftmost inserted bit is zero and not (cond == 2)
929                          all inserted bits are zero
930 
931             Because cc == 0,1,2 the rightmost bit of the mask is a don't care */
932          if (cond == 8 || cond == 8 + 1) {
933             return unop(Iop_1Uto32, binop(Iop_CmpEQ32, word, mkU32(0)));
934          }
935          if (cond == 4 + 2 || cond == 4 + 2 + 1) {
936             return unop(Iop_1Uto32, binop(Iop_CmpNE32, word, mkU32(0)));
937          }
938 
939          /* Sign extend */
940          if (shift != 0) {
941             word = binop(Iop_Sar32, binop(Iop_Shl32, word, mkU8(shift)),
942                          mkU8(shift));
943          }
944 
945          if (cond == 4 || cond == 4 + 1) {  /* word < 0 */
946             return unop(Iop_1Uto32, binop(Iop_CmpLT32S, word, mkU32(0)));
947          }
948          if (cond == 2 || cond == 2 + 1) {  /* word > 0 */
949             return unop(Iop_1Uto32, binop(Iop_CmpLT32S, mkU32(0), word));
950          }
951          if (cond == 8 + 4 || cond == 8 + 4 + 1) {
952             return unop(Iop_1Uto32, binop(Iop_CmpLE32S, word, mkU32(0)));
953          }
954          if (cond == 8 + 2 || cond == 8 + 2 + 1) {
955             return unop(Iop_1Uto32, binop(Iop_CmpLE32S, mkU32(0), word));
956          }
957          if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
958             return mkU32(1);
959          }
960          /* Remaining case */
961          return mkU32(0);
962       }
963 
964       /* S390_CC_OP_TEST_UNDER_MASK_8
965          Since the mask comes from an immediate field in the opcode, we
966          expect the mask to be a constant here. That simplifies matters. */
967       if (cc_op == S390_CC_OP_TEST_UNDER_MASK_8) {
968          ULong mask16;
969 
970          if (! isC64(cc_dep2)) goto missed;
971 
972          mask16 = cc_dep2->Iex.Const.con->Ico.U64;
973 
974          /* Get rid of the mask16 == 0 case first. Some of the simplifications
975             below (e.g. for OVFL) only hold if mask16 == 0.  */
976          if (mask16 == 0) {   /* cc == 0 */
977             if (cond & 0x8) return mkU32(1);
978             return mkU32(0);
979          }
980 
981          /* cc == 2 is a don't care */
982          if (cond == 8 || cond == 8 + 2) {
983             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
984                                           binop(Iop_And64, cc_dep1, cc_dep2),
985                                           mkU64(0)));
986          }
987          if (cond == 7 || cond == 7 - 2) {
988             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
989                                           binop(Iop_And64, cc_dep1, cc_dep2),
990                                           mkU64(0)));
991          }
992          if (cond == 1 || cond == 1 + 2) {
993             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
994                                           binop(Iop_And64, cc_dep1, cc_dep2),
995                                           cc_dep2));
996          }
997          if (cond == 14 || cond == 14 - 2) {  /* ! OVFL */
998             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
999                                           binop(Iop_And64, cc_dep1, cc_dep2),
1000                                           cc_dep2));
1001          }
1002          goto missed;
1003       }
1004 
1005       /* S390_CC_OP_TEST_UNDER_MASK_16
1006          Since the mask comes from an immediate field in the opcode, we
1007          expect the mask to be a constant here. That simplifies matters. */
1008       if (cc_op == S390_CC_OP_TEST_UNDER_MASK_16) {
1009          ULong mask16;
1010          UInt msb;
1011 
1012          if (! isC64(cc_dep2)) goto missed;
1013 
1014          mask16 = cc_dep2->Iex.Const.con->Ico.U64;
1015 
1016          /* Get rid of the mask16 == 0 case first. Some of the simplifications
1017             below (e.g. for OVFL) only hold if mask16 == 0.  */
1018          if (mask16 == 0) {   /* cc == 0 */
1019             if (cond & 0x8) return mkU32(1);
1020             return mkU32(0);
1021          }
1022 
1023          if (cond == 8) {
1024             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
1025                                           binop(Iop_And64, cc_dep1, cc_dep2),
1026                                           mkU64(0)));
1027          }
1028          if (cond == 7) {
1029             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
1030                                           binop(Iop_And64, cc_dep1, cc_dep2),
1031                                           mkU64(0)));
1032          }
1033          if (cond == 1) {
1034             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
1035                                           binop(Iop_And64, cc_dep1, cc_dep2),
1036                                           mkU64(mask16)));
1037          }
1038          if (cond == 14) {  /* ! OVFL */
1039             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
1040                                           binop(Iop_And64, cc_dep1, cc_dep2),
1041                                           mkU64(mask16)));
1042          }
1043 
1044          /* Find MSB in mask */
1045          msb = 0x8000;
1046          while (msb > mask16)
1047             msb >>= 1;
1048 
1049          if (cond == 2) {  /* cc == 2 */
1050             IRExpr *c1, *c2;
1051 
1052             /* (cc_dep & msb) != 0 && (cc_dep & mask16) != mask16 */
1053             c1 = binop(Iop_CmpNE64,
1054                        binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
1055             c2 = binop(Iop_CmpNE64,
1056                        binop(Iop_And64, cc_dep1, cc_dep2),
1057                        mkU64(mask16));
1058             return binop(Iop_And32, unop(Iop_1Uto32, c1),
1059                          unop(Iop_1Uto32, c2));
1060          }
1061 
1062          if (cond == 4) {  /* cc == 1 */
1063             IRExpr *c1, *c2;
1064 
1065             /* (cc_dep & msb) == 0 && (cc_dep & mask16) != 0 */
1066             c1 = binop(Iop_CmpEQ64,
1067                        binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
1068             c2 = binop(Iop_CmpNE64,
1069                        binop(Iop_And64, cc_dep1, cc_dep2),
1070                        mkU64(0));
1071             return binop(Iop_And32, unop(Iop_1Uto32, c1),
1072                          unop(Iop_1Uto32, c2));
1073          }
1074 
1075          if (cond == 11) {  /* cc == 0,2,3 */
1076             IRExpr *c1, *c2;
1077 
1078             c1 = binop(Iop_CmpNE64,
1079                        binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
1080             c2 = binop(Iop_CmpEQ64,
1081                        binop(Iop_And64, cc_dep1, cc_dep2),
1082                        mkU64(0));
1083             return binop(Iop_Or32, unop(Iop_1Uto32, c1),
1084                          unop(Iop_1Uto32, c2));
1085          }
1086 
1087          if (cond == 3) {  /* cc == 2 || cc == 3 */
1088             return unop(Iop_1Uto32,
1089                         binop(Iop_CmpNE64,
1090                               binop(Iop_And64, cc_dep1, mkU64(msb)),
1091                               mkU64(0)));
1092          }
1093          if (cond == 12) { /* cc == 0 || cc == 1 */
1094             return unop(Iop_1Uto32,
1095                         binop(Iop_CmpEQ64,
1096                               binop(Iop_And64, cc_dep1, mkU64(msb)),
1097                               mkU64(0)));
1098          }
1099          // vex_printf("TUM mask = 0x%llx\n", mask16);
1100          goto missed;
1101       }
1102 
1103       /* S390_CC_OP_UNSIGNED_SUB_64/32 */
1104       if (cc_op == S390_CC_OP_UNSIGNED_SUB_64 ||
1105           cc_op == S390_CC_OP_UNSIGNED_SUB_32) {
1106          /*
1107             cc_dep1, cc_dep2 are the zero extended left and right operands
1108 
1109             cc == 1  --> result != 0, borrow    (cond == 4)
1110             cc == 2  --> result == 0, no borrow (cond == 2)
1111             cc == 3  --> result != 0, no borrow (cond == 1)
1112 
1113             cc = (cc_dep1 == cc_dep2) ? 2
1114                                       : (cc_dep1 > cc_dep2) ? 3 : 1;
1115 
1116             Because cc == 0 cannot occur the leftmost bit of cond is
1117             a don't care.
1118          */
1119          if (cond == 1 || cond == 1 + 8) {  /* cc == 3   op2 < op1 */
1120             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep2, cc_dep1));
1121          }
1122          if (cond == 2 || cond == 2 + 8) {  /* cc == 2 */
1123             return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
1124          }
1125          if (cond == 4 || cond == 4 + 8) {  /* cc == 1 */
1126             return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
1127          }
1128          if (cond == 3 || cond == 3 + 8) {  /* cc == 2 || cc == 3 */
1129             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
1130          }
1131          if (cond == 6 || cond == 6 + 8) {  /* cc == 2 || cc == 1 */
1132             return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
1133          }
1134 
1135          if (cond == 5 || cond == 5 + 8) {  /* cc == 3 || cc == 1 */
1136             return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
1137          }
1138          if (cond == 7 || cond == 7 + 8) {
1139             return mkU32(1);
1140          }
1141          /* Remaining case */
1142          return mkU32(0);
1143       }
1144 
1145       /* S390_CC_OP_UNSIGNED_ADD_64 */
1146       if (cc_op == S390_CC_OP_UNSIGNED_ADD_64) {
1147          /*
1148             cc_dep1, cc_dep2 are the zero extended left and right operands
1149 
1150             cc == 0  --> result == 0, no carry  (cond == 8)
1151             cc == 1  --> result != 0, no carry  (cond == 4)
1152             cc == 2  --> result == 0, carry     (cond == 2)
1153             cc == 3  --> result != 0, carry     (cond == 1)
1154          */
1155          if (cond == 8) { /* cc == 0 */
1156             /* Both inputs are 0 */
1157             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
1158                                           binop(Iop_Or64, cc_dep1, cc_dep2),
1159                                           mkU64(0)));
1160          }
1161          if (cond == 7) { /* cc == 1,2,3 */
1162             /* Not both inputs are 0 */
1163             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
1164                                           binop(Iop_Or64, cc_dep1, cc_dep2),
1165                                           mkU64(0)));
1166          }
1167          if (cond == 8 + 2) {  /* cc == 0,2  -> result is zero */
1168             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
1169                                           binop(Iop_Add64, cc_dep1, cc_dep2),
1170                                           mkU64(0)));
1171          }
1172          if (cond == 4 + 1) {  /* cc == 1,3  -> result is not zero */
1173             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
1174                                           binop(Iop_Add64, cc_dep1, cc_dep2),
1175                                           mkU64(0)));
1176          }
1177          goto missed;
1178       }
1179 
1180       /* S390_CC_OP_UNSIGNED_ADD_32 */
1181       if (cc_op == S390_CC_OP_UNSIGNED_ADD_32) {
1182          /*
1183             cc_dep1, cc_dep2 are the zero extended left and right operands
1184 
1185             cc == 0  --> result == 0, no carry  (cond == 8)
1186             cc == 1  --> result != 0, no carry  (cond == 4)
1187             cc == 2  --> result == 0, carry     (cond == 2)
1188             cc == 3  --> result != 0, carry     (cond == 1)
1189          */
1190          if (cond == 8) { /* cc == 0 */
1191             /* Both inputs are 0 */
1192             return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
1193                                           binop(Iop_Or64, cc_dep1, cc_dep2),
1194                                           mkU64(0)));
1195          }
1196          if (cond == 7) { /* cc == 1,2,3 */
1197             /* Not both inputs are 0 */
1198             return unop(Iop_1Uto32, binop(Iop_CmpNE64,
1199                                           binop(Iop_Or64, cc_dep1, cc_dep2),
1200                                           mkU64(0)));
1201          }
1202          if (cond == 8 + 2) {  /* cc == 0,2  -> result is zero */
1203             return unop(Iop_1Uto32, binop(Iop_CmpEQ32,
1204                                           binop(Iop_Add32,
1205                                                 unop(Iop_64to32, cc_dep1),
1206                                                 unop(Iop_64to32, cc_dep2)),
1207                                           mkU32(0)));
1208          }
1209          if (cond == 4 + 1) {  /* cc == 1,3  -> result is not zero */
1210             return unop(Iop_1Uto32, binop(Iop_CmpNE32,
1211                                           binop(Iop_Add32,
1212                                                 unop(Iop_64to32, cc_dep1),
1213                                                 unop(Iop_64to32, cc_dep2)),
1214                                           mkU32(0)));
1215          }
1216          goto missed;
1217       }
1218 
1219       /* S390_CC_OP_SET */
1220       if (cc_op == S390_CC_OP_SET) {
1221          /* cc_dep1 is the condition code
1222 
1223             Return 1, if ((cond << cc_dep1) & 0x8) != 0 */
1224 
1225         return unop(Iop_1Uto32,
1226                     binop(Iop_CmpNE64,
1227                           binop(Iop_And64,
1228                                 binop(Iop_Shl64, cond_expr,
1229                                       unop(Iop_64to8, cc_dep1)),
1230                                 mkU64(8)),
1231                           mkU64(0)));
1232       }
1233 
1234       /* S390_CC_OP_TEST_AND_SET */
1235       if (cc_op == S390_CC_OP_TEST_AND_SET) {
1236          /* cc_dep1 is the zero-extended loaded value
1237 
1238             cc == 0  --> leftmost bit is zero  (cond == 8)
1239             cc == 1  --> leftmost bit is one   (cond == 4)
1240 
1241             As cc is either 0 or 1, only the two leftmost bits of the mask
1242             are relevant. */
1243          IRExpr *bit = binop(Iop_Shr64, cc_dep1, mkU8(7));
1244 
1245          switch (cond & (8 + 4)) {
1246          case 0:     return mkU32(0);
1247          case 4:     return unop(Iop_1Uto32, binop(Iop_CmpNE64, bit, mkU64(0)));
1248          case 8:     return unop(Iop_1Uto32, binop(Iop_CmpEQ64, bit, mkU64(0)));
1249          case 8 + 4: return mkU32(1);
1250          }
1251          /* not reached */
1252       }
1253 
1254 missed:
1255       ;
1256    }
1257 
1258    return NULL;
1259 }
1260 
1261 /*---------------------------------------------------------------*/
1262 /*--- end                                guest_s390_helpers.c ---*/
1263 /*---------------------------------------------------------------*/
1264