1 /* -*- mode: C; c-basic-offset: 3; -*- */
3 /*---------------------------------------------------------------*/
4 /*--- begin guest_s390_helpers.c ---*/
5 /*---------------------------------------------------------------*/
8 This file is part of Valgrind, a dynamic binary instrumentation
11 Copyright IBM Corp. 2010-2011
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.
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.
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
28 The GNU General Public License is contained in the file COPYING.
31 /* Contributed by Florian Krohm */
33 #include "libvex_basictypes.h"
34 #include "libvex_emwarn.h"
35 #include "libvex_guest_s390x.h"
36 #include "libvex_ir.h"
39 #include "main_util.h"
40 #include "guest_generic_bb_to_IR.h"
41 #include "guest_s390_defs.h"
44 LibVEX_GuestS390X_initialise(VexGuestS390XState *state)
46 /*------------------------------------------------------------*/
47 /*--- Initialise ar registers ---*/
48 /*------------------------------------------------------------*/
67 /*------------------------------------------------------------*/
68 /*--- Initialise fpr registers ---*/
69 /*------------------------------------------------------------*/
88 /*------------------------------------------------------------*/
89 /*--- Initialise gpr registers ---*/
90 /*------------------------------------------------------------*/
102 state->guest_r10 = 0;
103 state->guest_r11 = 0;
104 state->guest_r12 = 0;
105 state->guest_r13 = 0;
106 state->guest_r14 = 0;
107 state->guest_r15 = 0;
109 /*------------------------------------------------------------*/
110 /*--- Initialise S390 miscellaneous registers ---*/
111 /*------------------------------------------------------------*/
113 state->guest_counter = 0;
114 state->guest_fpc = 0;
117 /*------------------------------------------------------------*/
118 /*--- Initialise S390 pseudo registers ---*/
119 /*------------------------------------------------------------*/
121 state->guest_SYSNO = 0;
123 /*------------------------------------------------------------*/
124 /*--- Initialise generic pseudo registers ---*/
125 /*------------------------------------------------------------*/
127 state->guest_NRADDR = 0;
128 state->guest_TISTART = 0;
129 state->guest_TILEN = 0;
130 state->guest_IP_AT_SYSCALL = 0;
131 state->guest_EMWARN = EmWarn_NONE;
133 /*------------------------------------------------------------*/
134 /*--- Initialise thunk ---*/
135 /*------------------------------------------------------------*/
137 state->guest_CC_OP = 0;
138 state->guest_CC_DEP1 = 0;
139 state->guest_CC_DEP2 = 0;
140 state->guest_CC_NDEP = 0;
144 /* Figure out if any part of the guest state contained in minoff
145 .. maxoff requires precise memory exceptions. If in doubt return
146 True (but this is generates significantly slower code). */
148 guest_s390x_state_requires_precise_mem_exns(Int minoff, Int maxoff)
150 Int lr_min = offsetof(VexGuestS390XState, guest_LR);
151 Int lr_max = lr_min + 8 - 1;
152 Int sp_min = offsetof(VexGuestS390XState, guest_SP);
153 Int sp_max = sp_min + 8 - 1;
154 Int fp_min = offsetof(VexGuestS390XState, guest_FP);
155 Int fp_max = fp_min + 8 - 1;
156 Int ia_min = offsetof(VexGuestS390XState, guest_IA);
157 Int ia_max = ia_min + 8 - 1;
159 if (maxoff < lr_min || minoff > lr_max) {
160 /* No overlap with LR */
165 if (maxoff < sp_min || minoff > sp_max) {
166 /* No overlap with SP */
171 if (maxoff < fp_min || minoff > fp_max) {
172 /* No overlap with FP */
177 if (maxoff < ia_min || minoff > ia_max) {
178 /* No overlap with IA */
187 #define ALWAYSDEFD(field) \
188 { offsetof(VexGuestS390XState, field), \
189 (sizeof ((VexGuestS390XState*)0)->field) }
191 VexGuestLayout s390xGuest_layout = {
193 /* Total size of the guest state, in bytes. */
194 .total_sizeB = sizeof(VexGuestS390XState),
196 /* Describe the stack pointer. */
197 .offset_SP = offsetof(VexGuestS390XState, guest_SP),
200 /* Describe the frame pointer. */
201 .offset_FP = offsetof(VexGuestS390XState, guest_FP),
204 /* Describe the instruction pointer. */
205 .offset_IP = offsetof(VexGuestS390XState, guest_IA),
208 /* Describe any sections to be regarded by Memcheck as
212 /* Flags thunk: OP and NDEP are always defined, whereas DEP1
213 and DEP2 have to be tracked. See detailed comment in
214 gdefs.h on meaning of thunk fields. */
216 /* 0 */ ALWAYSDEFD(guest_CC_OP), /* generic */
217 /* 1 */ ALWAYSDEFD(guest_CC_NDEP), /* generic */
218 /* 2 */ ALWAYSDEFD(guest_EMWARN), /* generic */
219 /* 3 */ ALWAYSDEFD(guest_TISTART), /* generic */
220 /* 4 */ ALWAYSDEFD(guest_TILEN), /* generic */
221 /* 5 */ ALWAYSDEFD(guest_IP_AT_SYSCALL), /* generic */
222 /* 6 */ ALWAYSDEFD(guest_IA), /* control reg */
223 /* 7 */ ALWAYSDEFD(guest_fpc), /* control reg */
224 /* 8 */ ALWAYSDEFD(guest_counter), /* internal usage register */
228 /*------------------------------------------------------------*/
229 /*--- Dirty helper for EXecute ---*/
230 /*------------------------------------------------------------*/
232 s390x_dirtyhelper_EX(ULong torun)
234 last_execute_target = torun;
238 /*------------------------------------------------------------*/
239 /*--- Dirty helper for Clock instructions ---*/
240 /*------------------------------------------------------------*/
241 #if defined(VGA_s390x)
242 ULong s390x_dirtyhelper_STCK(ULong *addr)
246 asm volatile("stck %0\n"
249 : "+Q" (*addr), "=d" (cc) : : "cc");
253 ULong s390x_dirtyhelper_STCKE(ULong *addr)
257 asm volatile("stcke %0\n"
260 : "+Q" (*addr), "=d" (cc) : : "cc");
264 ULong s390x_dirtyhelper_STCKF(ULong *addr)
268 asm volatile(".insn s,0xb27c0000,%0\n"
271 : "+Q" (*addr), "=d" (cc) : : "cc");
275 ULong s390x_dirtyhelper_STCK(ULong *addr) {return 3;}
276 ULong s390x_dirtyhelper_STCKF(ULong *addr) {return 3;}
277 ULong s390x_dirtyhelper_STCKE(ULong *addr) {return 3;}
278 #endif /* VGA_s390x */
280 /*------------------------------------------------------------*/
281 /*--- Helper for condition code. ---*/
282 /*------------------------------------------------------------*/
284 #define S390_CC_FOR_BINARY(opcode,cc_dep1,cc_dep2) \
287 opcode " %[op1],%[op2]\n\t" \
288 "ipm %[psw]\n\t" : [psw] "=d"(psw), [op1] "+d"(cc_dep1) \
289 : [op2] "d"(cc_dep2) \
291 psw >> 28; /* cc */ \
294 #define S390_CC_FOR_TERNARY_SUBB(opcode,cc_dep1,cc_dep2,cc_ndep) \
296 /* Recover the original DEP2 value. See comment near s390_cc_thunk_put3 \
298 cc_dep2 = cc_dep2 ^ cc_ndep; \
301 "sr 0,%[op3]\n\t" /* borrow to cc */ \
302 opcode " %[op1],%[op2]\n\t" /* then redo the op */\
303 "ipm %[psw]\n\t" : [psw] "=d"(psw), [op1] "+&d"(cc_dep1) \
304 : [op2] "d"(cc_dep2), [op3] "d"(cc_ndep) \
306 psw >> 28; /* cc */ \
309 #define S390_CC_FOR_TERNARY_ADDC(opcode,cc_dep1,cc_dep2,cc_ndep) \
311 /* Recover the original DEP2 value. See comment near s390_cc_thunk_put3 \
313 cc_dep2 = cc_dep2 ^ cc_ndep; \
315 "lgfr 0,%[op3]\n\t" /* first load cc_ndep */ \
316 "aghi 0,0\n\t" /* and convert it into a cc */ \
317 opcode " %[op1],%[op2]\n\t" /* then redo the op */\
318 "ipm %[psw]\n\t" : [psw] "=d"(psw), [op1] "+&d"(cc_dep1) \
319 : [op2] "d"(cc_dep2), [op3] "d"(cc_ndep) \
321 psw >> 28; /* cc */ \
325 #define S390_CC_FOR_BFP_RESULT(opcode,cc_dep1) \
328 opcode " 0,%[op]\n\t" \
329 "ipm %[psw]\n\t" : [psw] "=d"(psw) \
330 : [op] "f"(cc_dep1) \
332 psw >> 28; /* cc */ \
335 #define S390_CC_FOR_BFP128_RESULT(hi,lo) \
338 "ldr 4,%[high]\n\t" \
341 "ipm %[psw]\n\t" : [psw] "=d"(psw) \
342 : [high] "f"(hi), [low] "f"(lo) \
343 : "cc", "f0", "f2", "f4", "f6");\
344 psw >> 28; /* cc */ \
347 #define S390_CC_FOR_BFP_CONVERT(opcode,cc_dep1) \
350 opcode " 0,0,%[op]\n\t" \
351 "ipm %[psw]\n\t" : [psw] "=d"(psw) \
352 : [op] "f"(cc_dep1) \
354 psw >> 28; /* cc */ \
357 #define S390_CC_FOR_BFP128_CONVERT(opcode,hi,lo) \
360 "ldr 4,%[high]\n\t" \
362 opcode " 0,0,4\n\t" \
363 "ipm %[psw]\n\t" : [psw] "=d"(psw) \
364 : [high] "f"(hi), [low] "f"(lo) \
365 : "cc", "r0", "f4", "f6");\
366 psw >> 28; /* cc */ \
369 #define S390_CC_FOR_BFP_TDC(opcode,cc_dep1,cc_dep2) \
372 opcode " %[value],0(%[class])\n\t" \
373 "ipm %[psw]\n\t" : [psw] "=d"(psw) \
374 : [value] "f"(cc_dep1), \
375 [class] "a"(cc_dep2) \
377 psw >> 28; /* cc */ \
380 #define S390_CC_FOR_BFP128_TDC(cc_dep1,cc_dep2,cc_ndep) \
382 /* Recover the original DEP2 value. See comment near s390_cc_thunk_put1f128Z \
384 cc_dep2 = cc_dep2 ^ cc_ndep; \
386 "ldr 4,%[high]\n\t" \
388 "tcxb 4,0(%[class])\n\t" \
389 "ipm %[psw]\n\t" : [psw] "=d"(psw) \
390 : [high] "f"(cc_dep1), [low] "f"(cc_dep2), \
391 [class] "a"(cc_ndep) \
392 : "cc", "f4", "f6");\
393 psw >> 28; /* cc */ \
397 /* Return the value of the condition code from the supplied thunk parameters.
398 This is not the value of the PSW. It is the value of the 2 CC bits within
399 the PSW. The returned value is thusly in the interval [0:3]. */
401 s390_calculate_cc(ULong cc_op, ULong cc_dep1, ULong cc_dep2, ULong cc_ndep)
403 #if defined(VGA_s390x)
408 case S390_CC_OP_BITWISE:
409 return S390_CC_FOR_BINARY("ogr", cc_dep1, (ULong)0);
411 case S390_CC_OP_SIGNED_COMPARE:
412 return S390_CC_FOR_BINARY("cgr", cc_dep1, cc_dep2);
414 case S390_CC_OP_UNSIGNED_COMPARE:
415 return S390_CC_FOR_BINARY("clgr", cc_dep1, cc_dep2);
417 case S390_CC_OP_SIGNED_ADD_64:
418 return S390_CC_FOR_BINARY("agr", cc_dep1, cc_dep2);
420 case S390_CC_OP_SIGNED_ADD_32:
421 return S390_CC_FOR_BINARY("ar", cc_dep1, cc_dep2);
423 case S390_CC_OP_SIGNED_SUB_64:
424 return S390_CC_FOR_BINARY("sgr", cc_dep1, cc_dep2);
426 case S390_CC_OP_SIGNED_SUB_32:
427 return S390_CC_FOR_BINARY("sr", cc_dep1, cc_dep2);
429 case S390_CC_OP_UNSIGNED_ADD_64:
430 return S390_CC_FOR_BINARY("algr", cc_dep1, cc_dep2);
432 case S390_CC_OP_UNSIGNED_ADD_32:
433 return S390_CC_FOR_BINARY("alr", cc_dep1, cc_dep2);
435 case S390_CC_OP_UNSIGNED_ADDC_64:
436 return S390_CC_FOR_TERNARY_ADDC("alcgr", cc_dep1, cc_dep2, cc_ndep);
438 case S390_CC_OP_UNSIGNED_ADDC_32:
439 return S390_CC_FOR_TERNARY_ADDC("alcr", cc_dep1, cc_dep2, cc_ndep);
441 case S390_CC_OP_UNSIGNED_SUB_64:
442 return S390_CC_FOR_BINARY("slgr", cc_dep1, cc_dep2);
444 case S390_CC_OP_UNSIGNED_SUB_32:
445 return S390_CC_FOR_BINARY("slr", cc_dep1, cc_dep2);
447 case S390_CC_OP_UNSIGNED_SUBB_64:
448 return S390_CC_FOR_TERNARY_SUBB("slbgr", cc_dep1, cc_dep2, cc_ndep);
450 case S390_CC_OP_UNSIGNED_SUBB_32:
451 return S390_CC_FOR_TERNARY_SUBB("slbr", cc_dep1, cc_dep2, cc_ndep);
453 case S390_CC_OP_LOAD_AND_TEST:
454 /* Like signed comparison with 0 */
455 return S390_CC_FOR_BINARY("cgr", cc_dep1, (Long)0);
457 case S390_CC_OP_TEST_AND_SET:
458 /* Shift the sign bit into the LSB. Note, that the tested value is an
459 8-bit value which has been zero-extended to 32/64 bit. */
462 case S390_CC_OP_LOAD_POSITIVE_32:
464 "lpr %[result],%[op]\n\t"
465 "ipm %[psw]\n\t" : [psw] "=d"(psw), [result] "=d"(cc_dep1)
468 return psw >> 28; /* cc */
470 case S390_CC_OP_LOAD_POSITIVE_64:
472 "lpgr %[result],%[op]\n\t"
473 "ipm %[psw]\n\t" : [psw] "=d"(psw), [result] "=d"(cc_dep1)
476 return psw >> 28; /* cc */
478 case S390_CC_OP_TEST_UNDER_MASK_8: {
479 UChar value = cc_dep1;
480 UChar mask = cc_dep2;
483 "bras %%r2,1f\n\t" /* %r2 = address of next insn */
484 "tm %[value],0\n\t" /* this is skipped, then EXecuted */
485 "1: ex %[mask],0(%%r2)\n\t" /* EXecute TM after modifying mask */
486 "ipm %[psw]\n\t" : [psw] "=d"(psw)
487 : [value] "m"(value), [mask] "a"(mask)
489 return psw >> 28; /* cc */
492 case S390_CC_OP_TEST_UNDER_MASK_16: {
493 /* Create a TMLL insn with the mask as given by cc_dep2 */
494 UInt insn = (0xA701 << 16) | cc_dep2;
495 UInt value = cc_dep1;
501 "ipm %[psw]\n\t" : [psw] "=d"(psw)
502 : [value] "d"(value), [insn] "m"(insn)
504 return psw >> 28; /* cc */
507 case S390_CC_OP_SHIFT_LEFT_32:
509 "sla %[op],0(%[amount])\n\t"
510 "ipm %[psw]\n\t" : [psw] "=d"(psw), [op] "+d"(cc_dep1)
511 : [amount] "a"(cc_dep2)
513 return psw >> 28; /* cc */
515 case S390_CC_OP_SHIFT_LEFT_64: {
516 Int high = (Int)(cc_dep1 >> 32);
517 Int low = (Int)(cc_dep1 & 0xFFFFFFFF);
522 "slda 2,0(%[amount])\n\t"
523 "ipm %[psw]\n\t" : [psw] "=d"(psw), [high] "+d"(high), [low] "+d"(low)
524 : [amount] "a"(cc_dep2)
526 return psw >> 28; /* cc */
529 case S390_CC_OP_INSERT_CHAR_MASK_32: {
534 inserted |= cc_dep1 & 0xff;
538 inserted |= cc_dep1 & 0xff00;
542 inserted |= cc_dep1 & 0xff0000;
546 inserted |= cc_dep1 & 0xff000000;
550 if (inserted & msb) // MSB is 1
557 case S390_CC_OP_BFP_RESULT_32:
558 return S390_CC_FOR_BFP_RESULT("ltebr", cc_dep1);
560 case S390_CC_OP_BFP_RESULT_64:
561 return S390_CC_FOR_BFP_RESULT("ltdbr", cc_dep1);
563 case S390_CC_OP_BFP_RESULT_128:
564 return S390_CC_FOR_BFP128_RESULT(cc_dep1, cc_dep2);
566 case S390_CC_OP_BFP_32_TO_INT_32:
567 return S390_CC_FOR_BFP_CONVERT("cfebr", cc_dep1);
569 case S390_CC_OP_BFP_64_TO_INT_32:
570 return S390_CC_FOR_BFP_CONVERT("cfdbr", cc_dep1);
572 case S390_CC_OP_BFP_128_TO_INT_32:
573 return S390_CC_FOR_BFP128_CONVERT("cfxbr", cc_dep1, cc_dep2);
575 case S390_CC_OP_BFP_32_TO_INT_64:
576 return S390_CC_FOR_BFP_CONVERT("cgebr", cc_dep1);
578 case S390_CC_OP_BFP_64_TO_INT_64:
579 return S390_CC_FOR_BFP_CONVERT("cgdbr", cc_dep1);
581 case S390_CC_OP_BFP_128_TO_INT_64:
582 return S390_CC_FOR_BFP128_CONVERT("cgxbr", cc_dep1, cc_dep2);
584 case S390_CC_OP_BFP_TDC_32:
585 return S390_CC_FOR_BFP_TDC("tceb", cc_dep1, cc_dep2);
587 case S390_CC_OP_BFP_TDC_64:
588 return S390_CC_FOR_BFP_TDC("tcdb", cc_dep1, cc_dep2);
590 case S390_CC_OP_BFP_TDC_128:
591 return S390_CC_FOR_BFP128_TDC(cc_dep1, cc_dep2, cc_ndep);
600 vpanic("s390_calculate_cc");
605 s390_calculate_icc(ULong op, ULong dep1, ULong dep2)
607 return s390_calculate_cc(op, dep1, dep2, 0 /* unused */);
611 /* Note that this does *not* return a Boolean value. The result needs to be
612 explicitly tested against zero. */
614 s390_calculate_cond(ULong mask, ULong op, ULong dep1, ULong dep2, ULong ndep)
616 UInt cc = s390_calculate_cc(op, dep1, dep2, ndep);
618 return ((mask << cc) & 0x8);
621 /*------------------------------------------------------------*/
622 /*--- spechelper for performance ---*/
623 /*------------------------------------------------------------*/
626 /* Convenience macros */
627 #define unop(op,a1) IRExpr_Unop((op),(a1))
628 #define binop(op,a1,a2) IRExpr_Binop((op),(a1),(a2))
629 #define mkU64(v) IRExpr_Const(IRConst_U64(v))
630 #define mkU32(v) IRExpr_Const(IRConst_U32(v))
631 #define mkU8(v) IRExpr_Const(IRConst_U8(v))
637 return expr->tag == Iex_Const && expr->Iex.Const.con->tag == Ico_U64;
641 /* The returned expression is NULL if no specialization was found. In that
642 case the helper function will be called. Otherwise, the expression has
643 type Ity_I32 and a Boolean value. */
645 guest_s390x_spechelper(HChar *function_name, IRExpr **args,
646 IRStmt **precedingStmts, Int n_precedingStmts)
650 for (i = 0; args[i]; i++)
654 vex_printf("spec request:\n");
655 vex_printf(" %s ", function_name);
656 for (i = 0; i < arity; i++) {
663 /* --------- Specialising "s390_calculate_cond" --------- */
665 if (vex_streq(function_name, "s390_calculate_cond")) {
666 IRExpr *cond_expr, *cc_op_expr, *cc_dep1, *cc_dep2;
672 cc_op_expr = args[1];
674 /* The necessary requirement for all optimizations here is that the
675 condition and the cc_op are constant. So check that upfront. */
676 if (! isC64(cond_expr)) return NULL;
677 if (! isC64(cc_op_expr)) return NULL;
679 cond = cond_expr->Iex.Const.con->Ico.U64;
680 cc_op = cc_op_expr->Iex.Const.con->Ico.U64;
685 +------+---+---+---+---+
686 | cc | 0 | 1 | 2 | 3 |
687 | cond | 8 | 4 | 2 | 1 |
688 +------+---+---+---+---+
693 /* S390_CC_OP_SIGNED_COMPARE */
694 if (cc_op == S390_CC_OP_SIGNED_COMPARE) {
696 cc == 0 --> cc_dep1 == cc_dep2 (cond == 8)
697 cc == 1 --> cc_dep1 < cc_dep2 (cond == 4)
698 cc == 2 --> cc_dep1 > cc_dep2 (cond == 2)
700 Because cc == 3 cannot occur the rightmost bit of cond is
703 if (cond == 8 || cond == 8 + 1) {
704 return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
706 if (cond == 4 + 2 || cond == 4 + 2 + 1) {
707 return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
709 if (cond == 4 || cond == 4 + 1) {
710 return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep1, cc_dep2));
712 if (cond == 8 + 4 || cond == 8 + 4 + 1) {
713 return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep1, cc_dep2));
715 /* cc_dep1 > cc_dep2 ----> cc_dep2 < cc_dep1 */
716 if (cond == 2 || cond == 2 + 1) {
717 return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep2, cc_dep1));
719 if (cond == 8 + 2 || cond == 8 + 2 + 1) {
720 return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep2, cc_dep1));
722 if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
729 /* S390_CC_OP_UNSIGNED_COMPARE */
730 if (cc_op == S390_CC_OP_UNSIGNED_COMPARE) {
732 cc == 0 --> cc_dep1 == cc_dep2 (cond == 8)
733 cc == 1 --> cc_dep1 < cc_dep2 (cond == 4)
734 cc == 2 --> cc_dep1 > cc_dep2 (cond == 2)
736 Because cc == 3 cannot occur the rightmost bit of cond is
739 if (cond == 8 || cond == 8 + 1) {
740 return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
742 if (cond == 4 + 2 || cond == 4 + 2 + 1) {
743 return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
745 if (cond == 4 || cond == 4 + 1) {
746 return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
748 if (cond == 8 + 4 || cond == 8 + 4 + 1) {
749 return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
751 /* cc_dep1 > cc_dep2 ----> cc_dep2 < cc_dep1 */
752 if (cond == 2 || cond == 2 + 1) {
753 return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep2, cc_dep1));
755 if (cond == 8 + 2 || cond == 8 + 2 + 1) {
756 return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
758 if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
765 /* S390_CC_OP_LOAD_AND_TEST */
766 if (cc_op == S390_CC_OP_LOAD_AND_TEST) {
768 cc == 0 --> cc_dep1 == 0 (cond == 8)
769 cc == 1 --> cc_dep1 < 0 (cond == 4)
770 cc == 2 --> cc_dep1 > 0 (cond == 2)
772 Because cc == 3 cannot occur the rightmost bit of cond is
775 if (cond == 8 || cond == 8 + 1) {
776 return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, mkU64(0)));
778 if (cond == 4 + 2 || cond == 4 + 2 + 1) {
779 return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
781 if (cond == 4 || cond == 4 + 1) {
782 return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep1, mkU64(0)));
784 if (cond == 8 + 4 || cond == 8 + 4 + 1) {
785 return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep1, mkU64(0)));
787 /* cc_dep1 > 0 ----> 0 < cc_dep1 */
788 if (cond == 2 || cond == 2 + 1) {
789 return unop(Iop_1Uto32, binop(Iop_CmpLT64S, mkU64(0), cc_dep1));
791 if (cond == 8 + 2 || cond == 8 + 2 + 1) {
792 return unop(Iop_1Uto32, binop(Iop_CmpLE64S, mkU64(0), cc_dep1));
794 if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
801 /* S390_CC_OP_BITWISE */
802 if (cc_op == S390_CC_OP_BITWISE) {
804 cc_dep1 is the result of the boolean operation.
806 cc == 0 --> cc_dep1 == 0 (cond == 8)
807 cc == 1 --> cc_dep1 != 0 (cond == 4)
809 Because cc == 2 and cc == 3 cannot occur the two rightmost bits of
810 cond are don't cares. Therefore:
812 cond == 00xx -> always false
813 cond == 01xx -> not equal
814 cond == 10xx -> equal
815 cond == 11xx -> always true
817 if ((cond & (8 + 4)) == 8 + 4) {
821 return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, mkU64(0)));
824 return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
830 /* S390_CC_OP_INSERT_CHAR_MASK_32
831 Since the mask comes from an immediate field in the opcode, we
832 expect the mask to be a constant here. That simplifies matters. */
833 if (cc_op == S390_CC_OP_INSERT_CHAR_MASK_32) {
835 UInt imask = 0, shift = 0;
838 if (! isC64(cc_dep2)) goto missed;
840 mask = cc_dep2->Iex.Const.con->Ico.U64;
842 /* Extract the 32-bit value from the thunk */
844 word = unop(Iop_64to32, cc_dep1);
847 case 0: shift = 0; imask = 0x00000000; break;
848 case 1: shift = 24; imask = 0x000000FF; break;
849 case 2: shift = 16; imask = 0x0000FF00; break;
850 case 3: shift = 16; imask = 0x0000FFFF; break;
851 case 4: shift = 8; imask = 0x00FF0000; break;
852 case 5: shift = 8; imask = 0x00FF00FF; break;
853 case 6: shift = 8; imask = 0x00FFFF00; break;
854 case 7: shift = 8; imask = 0x00FFFFFF; break;
855 case 8: shift = 0; imask = 0xFF000000; break;
856 case 9: shift = 0; imask = 0xFF0000FF; break;
857 case 10: shift = 0; imask = 0xFF00FF00; break;
858 case 11: shift = 0; imask = 0xFF00FFFF; break;
859 case 12: shift = 0; imask = 0xFFFF0000; break;
860 case 13: shift = 0; imask = 0xFFFF00FF; break;
861 case 14: shift = 0; imask = 0xFFFFFF00; break;
862 case 15: shift = 0; imask = 0xFFFFFFFF; break;
865 /* Select the bits that were inserted */
866 word = binop(Iop_And32, word, mkU32(imask));
868 /* cc == 0 --> all inserted bits zero or mask == 0 (cond == 8)
869 cc == 1 --> leftmost inserted bit is one (cond == 4)
870 cc == 2 --> leftmost inserted bit is zero and not (cond == 2)
871 all inserted bits are zero
873 Because cc == 0,1,2 the rightmost bit of the mask is a don't care */
874 if (cond == 8 || cond == 8 + 1) {
875 return unop(Iop_1Uto32, binop(Iop_CmpEQ32, word, mkU32(0)));
877 if (cond == 4 + 2 || cond == 4 + 2 + 1) {
878 return unop(Iop_1Uto32, binop(Iop_CmpNE32, word, mkU32(0)));
883 word = binop(Iop_Sar32, binop(Iop_Shl32, word, mkU8(shift)),
887 if (cond == 4 || cond == 4 + 1) { /* word < 0 */
888 return unop(Iop_1Uto32, binop(Iop_CmpLT32S, word, mkU32(0)));
890 if (cond == 2 || cond == 2 + 1) { /* word > 0 */
891 return unop(Iop_1Uto32, binop(Iop_CmpLT32S, mkU32(0), word));
893 if (cond == 8 + 4 || cond == 8 + 4 + 1) {
894 return unop(Iop_1Uto32, binop(Iop_CmpLE32S, word, mkU32(0)));
896 if (cond == 8 + 2 || cond == 8 + 2 + 1) {
897 return unop(Iop_1Uto32, binop(Iop_CmpLE32S, mkU32(0), word));
899 if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
906 /* S390_CC_OP_TEST_UNDER_MASK_8
907 Since the mask comes from an immediate field in the opcode, we
908 expect the mask to be a constant here. That simplifies matters. */
909 if (cc_op == S390_CC_OP_TEST_UNDER_MASK_8) {
912 if (! isC64(cc_dep2)) goto missed;
914 mask16 = cc_dep2->Iex.Const.con->Ico.U64;
916 /* Get rid of the mask16 == 0 case first. Some of the simplifications
917 below (e.g. for OVFL) only hold if mask16 == 0. */
918 if (mask16 == 0) { /* cc == 0 */
919 if (cond & 0x8) return mkU32(1);
923 /* cc == 2 is a don't care */
924 if (cond == 8 || cond == 8 + 2) {
925 return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
926 binop(Iop_And64, cc_dep1, cc_dep2),
929 if (cond == 7 || cond == 7 - 2) {
930 return unop(Iop_1Uto32, binop(Iop_CmpNE64,
931 binop(Iop_And64, cc_dep1, cc_dep2),
934 if (cond == 1 || cond == 1 + 2) {
935 return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
936 binop(Iop_And64, cc_dep1, cc_dep2),
939 if (cond == 14 || cond == 14 - 2) { /* ! OVFL */
940 return unop(Iop_1Uto32, binop(Iop_CmpNE64,
941 binop(Iop_And64, cc_dep1, cc_dep2),
947 /* S390_CC_OP_TEST_UNDER_MASK_16
948 Since the mask comes from an immediate field in the opcode, we
949 expect the mask to be a constant here. That simplifies matters. */
950 if (cc_op == S390_CC_OP_TEST_UNDER_MASK_16) {
954 if (! isC64(cc_dep2)) goto missed;
956 mask16 = cc_dep2->Iex.Const.con->Ico.U64;
958 /* Get rid of the mask16 == 0 case first. Some of the simplifications
959 below (e.g. for OVFL) only hold if mask16 == 0. */
960 if (mask16 == 0) { /* cc == 0 */
961 if (cond & 0x8) return mkU32(1);
966 return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
967 binop(Iop_And64, cc_dep1, cc_dep2),
971 return unop(Iop_1Uto32, binop(Iop_CmpNE64,
972 binop(Iop_And64, cc_dep1, cc_dep2),
976 return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
977 binop(Iop_And64, cc_dep1, cc_dep2),
980 if (cond == 14) { /* ! OVFL */
981 return unop(Iop_1Uto32, binop(Iop_CmpNE64,
982 binop(Iop_And64, cc_dep1, cc_dep2),
986 /* Find MSB in mask */
991 if (cond == 2) { /* cc == 2 */
994 /* (cc_dep & msb) != 0 && (cc_dep & mask16) != mask16 */
995 c1 = binop(Iop_CmpNE64,
996 binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
997 c2 = binop(Iop_CmpNE64,
998 binop(Iop_And64, cc_dep1, cc_dep2),
1000 return binop(Iop_And32, unop(Iop_1Uto32, c1),
1001 unop(Iop_1Uto32, c2));
1004 if (cond == 4) { /* cc == 1 */
1007 /* (cc_dep & msb) == 0 && (cc_dep & mask16) != 0 */
1008 c1 = binop(Iop_CmpEQ64,
1009 binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
1010 c2 = binop(Iop_CmpNE64,
1011 binop(Iop_And64, cc_dep1, cc_dep2),
1013 return binop(Iop_And32, unop(Iop_1Uto32, c1),
1014 unop(Iop_1Uto32, c2));
1017 if (cond == 11) { /* cc == 0,2,3 */
1020 c1 = binop(Iop_CmpNE64,
1021 binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
1022 c2 = binop(Iop_CmpEQ64,
1023 binop(Iop_And64, cc_dep1, cc_dep2),
1025 return binop(Iop_Or32, unop(Iop_1Uto32, c1),
1026 unop(Iop_1Uto32, c2));
1029 if (cond == 3) { /* cc == 2 || cc == 3 */
1030 return unop(Iop_1Uto32,
1032 binop(Iop_And64, cc_dep1, mkU64(msb)),
1035 if (cond == 12) { /* cc == 0 || cc == 1 */
1036 return unop(Iop_1Uto32,
1038 binop(Iop_And64, cc_dep1, mkU64(msb)),
1041 // vex_printf("TUM mask = 0x%llx\n", mask16);
1045 /* S390_CC_OP_UNSIGNED_SUB_64/32 */
1046 if (cc_op == S390_CC_OP_UNSIGNED_SUB_64 ||
1047 cc_op == S390_CC_OP_UNSIGNED_SUB_32) {
1049 cc_dep1, cc_dep2 are the zero extended left and right operands
1051 cc == 1 --> result != 0, borrow (cond == 4)
1052 cc == 2 --> result == 0, no borrow (cond == 2)
1053 cc == 3 --> result != 0, no borrow (cond == 1)
1055 cc = (cc_dep1 == cc_dep2) ? 2
1056 : (cc_dep1 > cc_dep2) ? 3 : 1;
1058 Because cc == 0 cannot occur the leftmost bit of cond is
1061 if (cond == 1 || cond == 1 + 8) { /* cc == 3 op2 < op1 */
1062 return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep2, cc_dep1));
1064 if (cond == 2 || cond == 2 + 8) { /* cc == 2 */
1065 return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
1067 if (cond == 4 || cond == 4 + 8) { /* cc == 1 */
1068 return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
1070 if (cond == 3 || cond == 3 + 8) { /* cc == 2 || cc == 3 */
1071 return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
1073 if (cond == 6 || cond == 6 + 8) { /* cc == 2 || cc == 1 */
1074 return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
1077 if (cond == 5 || cond == 5 + 8) { /* cc == 3 || cc == 1 */
1078 return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
1080 if (cond == 7 || cond == 7 + 8) {
1083 /* Remaining case */
1087 /* S390_CC_OP_UNSIGNED_ADD_64 */
1088 if (cc_op == S390_CC_OP_UNSIGNED_ADD_64) {
1090 cc_dep1, cc_dep2 are the zero extended left and right operands
1092 cc == 0 --> result == 0, no carry (cond == 8)
1093 cc == 1 --> result != 0, no carry (cond == 4)
1094 cc == 2 --> result == 0, carry (cond == 2)
1095 cc == 3 --> result != 0, carry (cond == 1)
1097 if (cond == 8) { /* cc == 0 */
1098 /* Both inputs are 0 */
1099 return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
1100 binop(Iop_Or64, cc_dep1, cc_dep2),
1103 if (cond == 7) { /* cc == 1,2,3 */
1104 /* Not both inputs are 0 */
1105 return unop(Iop_1Uto32, binop(Iop_CmpNE64,
1106 binop(Iop_Or64, cc_dep1, cc_dep2),
1109 if (cond == 8 + 2) { /* cc == 0,2 -> result is zero */
1110 return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
1111 binop(Iop_Add64, cc_dep1, cc_dep2),
1114 if (cond == 4 + 1) { /* cc == 1,3 -> result is not zero */
1115 return unop(Iop_1Uto32, binop(Iop_CmpNE64,
1116 binop(Iop_Add64, cc_dep1, cc_dep2),
1122 /* S390_CC_OP_UNSIGNED_ADD_32 */
1123 if (cc_op == S390_CC_OP_UNSIGNED_ADD_32) {
1125 cc_dep1, cc_dep2 are the zero extended left and right operands
1127 cc == 0 --> result == 0, no carry (cond == 8)
1128 cc == 1 --> result != 0, no carry (cond == 4)
1129 cc == 2 --> result == 0, carry (cond == 2)
1130 cc == 3 --> result != 0, carry (cond == 1)
1132 if (cond == 8) { /* cc == 0 */
1133 /* Both inputs are 0 */
1134 return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
1135 binop(Iop_Or64, cc_dep1, cc_dep2),
1138 if (cond == 7) { /* cc == 1,2,3 */
1139 /* Not both inputs are 0 */
1140 return unop(Iop_1Uto32, binop(Iop_CmpNE64,
1141 binop(Iop_Or64, cc_dep1, cc_dep2),
1144 if (cond == 8 + 2) { /* cc == 0,2 -> result is zero */
1145 return unop(Iop_1Uto32, binop(Iop_CmpEQ32,
1147 unop(Iop_64to32, cc_dep1),
1148 unop(Iop_64to32, cc_dep2)),
1151 if (cond == 4 + 1) { /* cc == 1,3 -> result is not zero */
1152 return unop(Iop_1Uto32, binop(Iop_CmpNE32,
1154 unop(Iop_64to32, cc_dep1),
1155 unop(Iop_64to32, cc_dep2)),
1161 /* S390_CC_OP_SET */
1162 if (cc_op == S390_CC_OP_SET) {
1163 /* cc_dep1 is the condition code
1165 Return 1, if ((cond << cc_dep1) & 0x8) != 0 */
1167 return unop(Iop_1Uto32,
1170 binop(Iop_Shl64, cond_expr,
1171 unop(Iop_64to8, cc_dep1)),
1176 /* S390_CC_OP_TEST_AND_SET */
1177 if (cc_op == S390_CC_OP_TEST_AND_SET) {
1178 /* cc_dep1 is the zero-extended loaded value
1180 cc == 0 --> leftmost bit is zero (cond == 8)
1181 cc == 1 --> leftmost bit is one (cond == 4)
1183 As cc is either 0 or 1, only the two leftmost bits of the mask
1185 IRExpr *bit = binop(Iop_Shr64, cc_dep1, mkU8(7));
1187 switch (cond & (8 + 4)) {
1188 case 0: return mkU32(0);
1189 case 4: return unop(Iop_1Uto32, binop(Iop_CmpNE64, bit, mkU64(0)));
1190 case 8: return unop(Iop_1Uto32, binop(Iop_CmpEQ64, bit, mkU64(0)));
1191 case 8 + 4: return mkU32(1);
1203 /*---------------------------------------------------------------*/
1204 /*--- end guest_s390_helpers.c ---*/
1205 /*---------------------------------------------------------------*/