host_s390_isel.c revision 663860b1408516d02ebfcb3a9999a134e6cfb223
1/* -*- mode: C; c-basic-offset: 3; -*- */
2
3/*---------------------------------------------------------------*/
4/*--- begin                                  host_s390_isel.c ---*/
5/*---------------------------------------------------------------*/
6
7/*
8   This file is part of Valgrind, a dynamic binary instrumentation
9   framework.
10
11   Copyright IBM Corp. 2010-2012
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_ir.h"
35#include "libvex.h"
36#include "libvex_s390x_common.h"
37
38#include "main_util.h"
39#include "main_globals.h"
40#include "guest_s390_defs.h"   /* guest_s390x_state_requires_precise_mem_exns */
41#include "host_generic_regs.h"
42#include "host_s390_defs.h"
43
44/*---------------------------------------------------------*/
45/*--- ISelEnv                                           ---*/
46/*---------------------------------------------------------*/
47
48/* This carries around:
49
50   - A mapping from IRTemp to IRType, giving the type of any IRTemp we
51     might encounter.  This is computed before insn selection starts,
52     and does not change.
53
54   - A mapping from IRTemp to HReg.  This tells the insn selector
55     which virtual register(s) are associated with each IRTemp
56      temporary.  This is computed before insn selection starts, and
57      does not change.  We expect this mapping to map precisely the
58      same set of IRTemps as the type mapping does.
59
60         - vregmap   holds the primary register for the IRTemp.
61         - vregmapHI holds the secondary register for the IRTemp,
62              if any is needed.  That's only for Ity_I64 temps
63              in 32 bit mode or Ity_I128 temps in 64-bit mode.
64
65    - The code array, that is, the insns selected so far.
66
67    - A counter, for generating new virtual registers.
68
69    - The host subarchitecture we are selecting insns for.
70      This is set at the start and does not change.
71
72   - A Bool for indicating whether we may generate chain-me
73     instructions for control flow transfers, or whether we must use
74     XAssisted.
75
76   - The maximum guest address of any guest insn in this block.
77     Actually, the address of the highest-addressed byte from any insn
78     in this block.  Is set at the start and does not change.  This is
79     used for detecting jumps which are definitely forward-edges from
80     this block, and therefore can be made (chained) to the fast entry
81     point of the destination, thereby avoiding the destination's
82     event check.
83
84    - A flag to indicate whether the guest IA has been assigned to.
85
86    - Values of certain guest registers which are often assigned constants.
87*/
88
89/* Symbolic names for guest registers whose value we're tracking */
90enum {
91   GUEST_IA,
92   GUEST_CC_OP,
93   GUEST_CC_DEP1,
94   GUEST_CC_DEP2,
95   GUEST_CC_NDEP,
96   GUEST_SYSNO,
97   GUEST_COUNTER,
98   GUEST_UNKNOWN    /* must be the last entry */
99};
100
101/* Number of registers we're tracking. */
102#define NUM_TRACKED_REGS GUEST_UNKNOWN
103
104
105typedef struct {
106   IRTypeEnv   *type_env;
107
108   HInstrArray *code;
109   HReg        *vregmap;
110   HReg        *vregmapHI;
111   UInt         n_vregmap;
112   UInt         vreg_ctr;
113   UInt         hwcaps;
114
115   ULong        old_value[NUM_TRACKED_REGS];
116
117   /* The next two are for translation chaining */
118   Addr64       max_ga;
119   Bool         chaining_allowed;
120
121   Bool         first_IA_assignment;
122   Bool         old_value_valid[NUM_TRACKED_REGS];
123} ISelEnv;
124
125
126/* Forward declarations */
127static HReg          s390_isel_int_expr(ISelEnv *, IRExpr *);
128static s390_amode   *s390_isel_amode(ISelEnv *, IRExpr *);
129static s390_cc_t     s390_isel_cc(ISelEnv *, IRExpr *);
130static s390_opnd_RMI s390_isel_int_expr_RMI(ISelEnv *, IRExpr *);
131static void          s390_isel_int128_expr(HReg *, HReg *, ISelEnv *, IRExpr *);
132static HReg          s390_isel_float_expr(ISelEnv *, IRExpr *);
133static void          s390_isel_float128_expr(HReg *, HReg *, ISelEnv *, IRExpr *);
134
135
136static Int
137get_guest_reg(Int offset)
138{
139   switch (offset) {
140   case S390X_GUEST_OFFSET(guest_IA):        return GUEST_IA;
141   case S390X_GUEST_OFFSET(guest_CC_OP):     return GUEST_CC_OP;
142   case S390X_GUEST_OFFSET(guest_CC_DEP1):   return GUEST_CC_DEP1;
143   case S390X_GUEST_OFFSET(guest_CC_DEP2):   return GUEST_CC_DEP2;
144   case S390X_GUEST_OFFSET(guest_CC_NDEP):   return GUEST_CC_NDEP;
145   case S390X_GUEST_OFFSET(guest_SYSNO):     return GUEST_SYSNO;
146   case S390X_GUEST_OFFSET(guest_counter):   return GUEST_COUNTER;
147
148      /* Also make sure there is never a partial write to one of
149         these registers. That would complicate matters. */
150   case S390X_GUEST_OFFSET(guest_IA)+1      ... S390X_GUEST_OFFSET(guest_IA)+7:
151   case S390X_GUEST_OFFSET(guest_CC_OP)+1   ... S390X_GUEST_OFFSET(guest_CC_OP)+7:
152   case S390X_GUEST_OFFSET(guest_CC_DEP1)+1 ... S390X_GUEST_OFFSET(guest_CC_DEP1)+7:
153   case S390X_GUEST_OFFSET(guest_CC_DEP2)+1 ... S390X_GUEST_OFFSET(guest_CC_DEP2)+7:
154   case S390X_GUEST_OFFSET(guest_CC_NDEP)+1 ... S390X_GUEST_OFFSET(guest_CC_NDEP)+7:
155   case S390X_GUEST_OFFSET(guest_SYSNO)+1   ... S390X_GUEST_OFFSET(guest_SYSNO)+7:
156      /* counter is used both as 4-byte and as 8-byte entity */
157   case S390X_GUEST_OFFSET(guest_counter)+1 ... S390X_GUEST_OFFSET(guest_counter)+3:
158   case S390X_GUEST_OFFSET(guest_counter)+5 ... S390X_GUEST_OFFSET(guest_counter)+7:
159      vpanic("partial update of this guest state register is not allowed");
160      break;
161
162   default: break;
163   }
164
165   return GUEST_UNKNOWN;
166}
167
168/* Add an instruction */
169static void
170addInstr(ISelEnv *env, s390_insn *insn)
171{
172   addHInstr(env->code, insn);
173
174   if (vex_traceflags & VEX_TRACE_VCODE) {
175      vex_printf("%s\n", s390_insn_as_string(insn));
176   }
177}
178
179
180static __inline__ IRExpr *
181mkU64(ULong value)
182{
183   return IRExpr_Const(IRConst_U64(value));
184}
185
186
187/*---------------------------------------------------------*/
188/*--- Registers                                         ---*/
189/*---------------------------------------------------------*/
190
191/* Return the virtual register to which a given IRTemp is mapped. */
192static HReg
193lookupIRTemp(ISelEnv *env, IRTemp tmp)
194{
195   vassert(tmp < env->n_vregmap);
196   vassert(env->vregmap[tmp] != INVALID_HREG);
197
198   return env->vregmap[tmp];
199}
200
201
202/* Return the two virtual registers to which the IRTemp is mapped. */
203static void
204lookupIRTemp128(HReg *hi, HReg *lo, ISelEnv *env, IRTemp tmp)
205{
206   vassert(tmp < env->n_vregmap);
207   vassert(env->vregmapHI[tmp] != INVALID_HREG);
208
209   *lo = env->vregmap[tmp];
210   *hi = env->vregmapHI[tmp];
211}
212
213
214/* Allocate a new integer register */
215static HReg
216newVRegI(ISelEnv *env)
217{
218   HReg reg = mkHReg(env->vreg_ctr, HRcInt64, True /* virtual */ );
219   env->vreg_ctr++;
220
221   return reg;
222}
223
224
225/* Allocate a new floating point register */
226static HReg
227newVRegF(ISelEnv *env)
228{
229   HReg reg = mkHReg(env->vreg_ctr, HRcFlt64, True /* virtual */ );
230
231   env->vreg_ctr++;
232
233   return reg;
234}
235
236
237/* Construct a non-virtual general purpose register */
238static __inline__ HReg
239make_gpr(UInt regno)
240{
241   return mkHReg(regno, HRcInt64, False /* virtual */ );
242}
243
244
245/* Construct a non-virtual floating point register */
246static __inline__ HReg
247make_fpr(UInt regno)
248{
249   return mkHReg(regno, HRcFlt64, False /* virtual */ );
250}
251
252
253/*---------------------------------------------------------*/
254/*--- Amode                                             ---*/
255/*---------------------------------------------------------*/
256
257static __inline__ Bool
258ulong_fits_unsigned_12bit(ULong val)
259{
260   return (val & 0xFFFu) == val;
261}
262
263
264static __inline__ Bool
265ulong_fits_signed_20bit(ULong val)
266{
267   Long v = val & 0xFFFFFu;
268
269   v = (v << 44) >> 44;  /* sign extend */
270
271   return val == (ULong)v;
272}
273
274
275static __inline__ Bool
276ulong_fits_signed_8bit(ULong val)
277{
278   Long v = val & 0xFFu;
279
280   v = (v << 56) >> 56;  /* sign extend */
281
282   return val == (ULong)v;
283}
284
285/* EXPR is an expression that is used as an address. Return an s390_amode
286   for it. */
287static s390_amode *
288s390_isel_amode_wrk(ISelEnv *env, IRExpr *expr)
289{
290   if (expr->tag == Iex_Binop && expr->Iex.Binop.op == Iop_Add64) {
291      IRExpr *arg1 = expr->Iex.Binop.arg1;
292      IRExpr *arg2 = expr->Iex.Binop.arg2;
293
294      /* Move constant into right subtree */
295      if (arg1->tag == Iex_Const) {
296         IRExpr *tmp;
297         tmp  = arg1;
298         arg1 = arg2;
299         arg2 = tmp;
300      }
301
302      /* r + constant: Check for b12 first, then b20 */
303      if (arg2->tag == Iex_Const && arg2->Iex.Const.con->tag == Ico_U64) {
304         ULong value = arg2->Iex.Const.con->Ico.U64;
305
306         if (ulong_fits_unsigned_12bit(value)) {
307            return s390_amode_b12((Int)value, s390_isel_int_expr(env, arg1));
308         }
309         /* If long-displacement is not available, do not construct B20 or
310            BX20 amodes because code generation cannot handle them. */
311         if (s390_host_has_ldisp && ulong_fits_signed_20bit(value)) {
312            return s390_amode_b20((Int)value, s390_isel_int_expr(env, arg1));
313         }
314      }
315   }
316
317   /* Doesn't match anything in particular.  Generate it into
318      a register and use that. */
319   return s390_amode_b12(0, s390_isel_int_expr(env, expr));
320}
321
322
323static s390_amode *
324s390_isel_amode(ISelEnv *env, IRExpr *expr)
325{
326   s390_amode *am;
327
328   /* Address computation should yield a 64-bit value */
329   vassert(typeOfIRExpr(env->type_env, expr) == Ity_I64);
330
331   am = s390_isel_amode_wrk(env, expr);
332
333   /* Check post-condition */
334   vassert(s390_amode_is_sane(am));
335
336   return am;
337}
338
339
340/*---------------------------------------------------------*/
341/*--- Helper functions                                  ---*/
342/*---------------------------------------------------------*/
343
344/* Constants and memory accesses should be right operands */
345#define order_commutative_operands(left, right)                   \
346        do {                                                      \
347          if (left->tag == Iex_Const || left->tag == Iex_Load ||  \
348              left->tag == Iex_Get) {                             \
349            IRExpr *tmp;                                          \
350            tmp   = left;                                         \
351            left  = right;                                        \
352            right = tmp;                                          \
353          }                                                       \
354        } while (0)
355
356
357/* Copy an RMI operand to the DST register */
358static s390_insn *
359s390_opnd_copy(UChar size, HReg dst, s390_opnd_RMI opnd)
360{
361   switch (opnd.tag) {
362   case S390_OPND_AMODE:
363      return s390_insn_load(size, dst, opnd.variant.am);
364
365   case S390_OPND_REG:
366      return s390_insn_move(size, dst, opnd.variant.reg);
367
368   case S390_OPND_IMMEDIATE:
369      return s390_insn_load_immediate(size, dst, opnd.variant.imm);
370
371   default:
372      vpanic("s390_opnd_copy");
373   }
374}
375
376
377/* Construct a RMI operand for a register */
378static __inline__ s390_opnd_RMI
379s390_opnd_reg(HReg reg)
380{
381   s390_opnd_RMI opnd;
382
383   opnd.tag  = S390_OPND_REG;
384   opnd.variant.reg = reg;
385
386   return opnd;
387}
388
389
390/* Construct a RMI operand for an immediate constant */
391static __inline__ s390_opnd_RMI
392s390_opnd_imm(ULong value)
393{
394   s390_opnd_RMI opnd;
395
396   opnd.tag  = S390_OPND_IMMEDIATE;
397   opnd.variant.imm = value;
398
399   return opnd;
400}
401
402
403/* Return 1, if EXPR represents the cosntant 0 */
404static int
405s390_expr_is_const_zero(IRExpr *expr)
406{
407   ULong value;
408
409   if (expr->tag == Iex_Const) {
410      switch (expr->Iex.Const.con->tag) {
411      case Ico_U1:  value = expr->Iex.Const.con->Ico.U1;  break;
412      case Ico_U8:  value = expr->Iex.Const.con->Ico.U8;  break;
413      case Ico_U16: value = expr->Iex.Const.con->Ico.U16; break;
414      case Ico_U32: value = expr->Iex.Const.con->Ico.U32; break;
415      case Ico_U64: value = expr->Iex.Const.con->Ico.U64; break;
416      default:
417         vpanic("s390_expr_is_const_zero");
418      }
419      return value == 0;
420   }
421
422   return 0;
423}
424
425
426/* Call a helper (clean or dirty)
427   Arguments must satisfy the following conditions:
428
429   (a) they are expressions yielding an integer result
430   (b) there can be no more than S390_NUM_GPRPARMS arguments
431
432   guard is a Ity_Bit expression indicating whether or not the
433   call happens.  If guard == NULL, the call is unconditional.
434
435   Calling the helper function proceeds as follows:
436
437   (1) The helper arguments are evaluated and their value stored in
438       virtual registers.
439   (2) The condition code is evaluated
440   (3) The argument values are copied from the virtual registers to the
441       registers mandated by the ABI.
442   (4) Call the helper function.
443
444   This is not the most efficient way as step 3 generates register-to-register
445   moves. But it is the least fragile way as the only hidden dependency here
446   is that register-to-register moves (step 3) must not clobber the condition
447   code. Other schemes (e.g. VEX r2326) that attempt to avoid the register-
448   to-register add more such dependencies. Not good. Besides, it's the job
449   of the register allocator to throw out those reg-to-reg moves.
450*/
451static void
452doHelperCall(ISelEnv *env, Bool passBBP, IRExpr *guard,
453             IRCallee *callee, IRExpr **args, HReg dst)
454{
455   UInt n_args, i, argreg, size;
456   ULong target;
457   HReg tmpregs[S390_NUM_GPRPARMS];
458   s390_cc_t cc;
459
460   n_args = 0;
461   for (i = 0; args[i]; i++)
462      ++n_args;
463
464   if (n_args > (S390_NUM_GPRPARMS - (passBBP ? 1 : 0))) {
465      vpanic("doHelperCall: too many arguments");
466   }
467
468   /* All arguments must have Ity_I64. For two reasons:
469      (1) We do not handle floating point arguments.
470      (2) The ABI requires that integer values are sign- or zero-extended
471           to 64 bit.
472   */
473   Int arg_errors = 0;
474   for (i = 0; i < n_args; ++i) {
475      IRType type = typeOfIRExpr(env->type_env, args[i]);
476      if (type != Ity_I64) {
477         ++arg_errors;
478         vex_printf("calling %s: argument #%d has type ", callee->name, i);
479         ppIRType(type);
480         vex_printf("; Ity_I64 is required\n");
481      }
482   }
483
484   if (arg_errors)
485      vpanic("cannot continue due to errors in argument passing");
486
487   argreg = 0;
488
489   /* If we need the guest state pointer put it in a temporary arg reg */
490   if (passBBP) {
491      tmpregs[argreg] = newVRegI(env);
492      addInstr(env, s390_insn_move(sizeof(ULong), tmpregs[argreg],
493                                   s390_hreg_guest_state_pointer()));
494      argreg++;
495   }
496
497   /* Compute the function arguments into a temporary register each */
498   for (i = 0; i < n_args; i++) {
499      tmpregs[argreg] = s390_isel_int_expr(env, args[i]);
500      argreg++;
501   }
502
503   /* Compute the condition */
504   cc = S390_CC_ALWAYS;
505   if (guard) {
506      if (guard->tag == Iex_Const
507          && guard->Iex.Const.con->tag == Ico_U1
508          && guard->Iex.Const.con->Ico.U1 == True) {
509         /* unconditional -- do nothing */
510      } else {
511         cc = s390_isel_cc(env, guard);
512      }
513   }
514
515   /* Move the args to the final register. It is paramount, that the
516      code to move the registers does not clobber the condition code ! */
517   for (i = 0; i < argreg; i++) {
518      HReg finalreg;
519
520      finalreg = make_gpr(s390_gprno_from_arg_index(i));
521      size = sizeofIRType(Ity_I64);
522      addInstr(env, s390_insn_move(size, finalreg, tmpregs[i]));
523   }
524
525   target = Ptr_to_ULong(callee->addr);
526
527   /* Finally, the call itself. */
528   addInstr(env, s390_insn_helper_call(cc, (Addr64)target, n_args,
529                                       callee->name, dst));
530}
531
532
533/* Given an expression representing a rounding mode using IRRoundingMode
534   encoding convert it to an s390_round_t value.  */
535static s390_round_t
536decode_rounding_mode(IRExpr *rounding_expr)
537{
538   if (rounding_expr->tag == Iex_Const &&
539       rounding_expr->Iex.Const.con->tag == Ico_U32) {
540      IRRoundingMode mode = rounding_expr->Iex.Const.con->Ico.U32;
541
542      switch (mode) {
543      case Irrm_NEAREST:       return S390_ROUND_NEAREST_EVEN;
544      case Irrm_ZERO:          return S390_ROUND_ZERO;
545      case Irrm_PosINF:        return S390_ROUND_POSINF;
546      case Irrm_NegINF:        return S390_ROUND_NEGINF;
547      }
548   }
549
550   vpanic("decode_rounding_mode");
551}
552
553
554/* CC_S390 holds the condition code in s390 encoding. Convert it to
555   VEX encoding
556
557   s390     VEX              b6 b2 b0   cc.1  cc.0
558   0      0x40 EQ             1  0  0     0     0
559   1      0x01 LT             0  0  1     0     1
560   2      0x00 GT             0  0  0     1     0
561   3      0x45 Unordered      1  1  1     1     1
562
563   b0 = cc.0
564   b2 = cc.0 & cc.1
565   b6 = ~(cc.0 ^ cc.1)   // ((cc.0 - cc.1) + 0x1 ) & 0x1
566
567   VEX = b0 | (b2 << 2) | (b6 << 6);
568*/
569static HReg
570convert_s390_fpcc_to_vex(ISelEnv *env, HReg cc_s390)
571{
572   HReg cc0, cc1, b2, b6, cc_vex;
573
574   cc0 = newVRegI(env);
575   addInstr(env, s390_insn_move(4, cc0, cc_s390));
576   addInstr(env, s390_insn_alu(4, S390_ALU_AND, cc0, s390_opnd_imm(1)));
577
578   cc1 = newVRegI(env);
579   addInstr(env, s390_insn_move(4, cc1, cc_s390));
580   addInstr(env, s390_insn_alu(4, S390_ALU_RSH, cc1, s390_opnd_imm(1)));
581
582   b2 = newVRegI(env);
583   addInstr(env, s390_insn_move(4, b2, cc0));
584   addInstr(env, s390_insn_alu(4, S390_ALU_AND, b2, s390_opnd_reg(cc1)));
585   addInstr(env, s390_insn_alu(4, S390_ALU_LSH, b2, s390_opnd_imm(2)));
586
587   b6 = newVRegI(env);
588   addInstr(env, s390_insn_move(4, b6, cc0));
589   addInstr(env, s390_insn_alu(4, S390_ALU_SUB, b6, s390_opnd_reg(cc1)));
590   addInstr(env, s390_insn_alu(4, S390_ALU_ADD, b6, s390_opnd_imm(1)));
591   addInstr(env, s390_insn_alu(4, S390_ALU_AND, b6, s390_opnd_imm(1)));
592   addInstr(env, s390_insn_alu(4, S390_ALU_LSH, b6, s390_opnd_imm(6)));
593
594   cc_vex = newVRegI(env);
595   addInstr(env, s390_insn_move(4, cc_vex, cc0));
596   addInstr(env, s390_insn_alu(4, S390_ALU_OR, cc_vex, s390_opnd_reg(b2)));
597   addInstr(env, s390_insn_alu(4, S390_ALU_OR, cc_vex, s390_opnd_reg(b6)));
598
599   return cc_vex;
600}
601
602
603/*---------------------------------------------------------*/
604/*--- ISEL: Integer expressions (128 bit)               ---*/
605/*---------------------------------------------------------*/
606static void
607s390_isel_int128_expr_wrk(HReg *dst_hi, HReg *dst_lo, ISelEnv *env,
608                          IRExpr *expr)
609{
610   IRType ty = typeOfIRExpr(env->type_env, expr);
611
612   vassert(ty == Ity_I128);
613
614   /* No need to consider the following
615      - 128-bit constants (they do not exist in VEX)
616      - 128-bit loads from memory (will not be generated)
617   */
618
619   /* Read 128-bit IRTemp */
620   if (expr->tag == Iex_RdTmp) {
621      lookupIRTemp128(dst_hi, dst_lo, env, expr->Iex.RdTmp.tmp);
622      return;
623   }
624
625   if (expr->tag == Iex_Binop) {
626      IRExpr *arg1 = expr->Iex.Binop.arg1;
627      IRExpr *arg2 = expr->Iex.Binop.arg2;
628      Bool is_signed_multiply, is_signed_divide;
629
630      switch (expr->Iex.Binop.op) {
631      case Iop_MullU64:
632         is_signed_multiply = False;
633         goto do_multiply64;
634
635      case Iop_MullS64:
636         is_signed_multiply = True;
637         goto do_multiply64;
638
639      case Iop_DivModU128to64:
640         is_signed_divide = False;
641         goto do_divide64;
642
643      case Iop_DivModS128to64:
644         is_signed_divide = True;
645         goto do_divide64;
646
647      case Iop_64HLto128:
648         *dst_hi = s390_isel_int_expr(env, arg1);
649         *dst_lo = s390_isel_int_expr(env, arg2);
650         return;
651
652      case Iop_DivModS64to64: {
653         HReg r10, r11, h1;
654         s390_opnd_RMI op2;
655
656         h1  = s390_isel_int_expr(env, arg1);       /* Process 1st operand */
657         op2 = s390_isel_int_expr_RMI(env, arg2);   /* Process 2nd operand */
658
659         /* We use non-virtual registers r10 and r11 as pair */
660         r10  = make_gpr(10);
661         r11  = make_gpr(11);
662
663         /* Move 1st operand into r11 and */
664         addInstr(env, s390_insn_move(8, r11, h1));
665
666         /* Divide */
667         addInstr(env, s390_insn_divs(8, r10, r11, op2));
668
669         /* The result is in registers r10 (remainder) and r11 (quotient).
670            Move the result into the reg pair that is being returned such
671            such that the low 64 bits are the quotient and the upper 64 bits
672            are the remainder. (see libvex_ir.h). */
673         *dst_hi = newVRegI(env);
674         *dst_lo = newVRegI(env);
675         addInstr(env, s390_insn_move(8, *dst_hi, r10));
676         addInstr(env, s390_insn_move(8, *dst_lo, r11));
677         return;
678      }
679
680      default:
681         break;
682
683      do_multiply64: {
684            HReg r10, r11, h1;
685            s390_opnd_RMI op2;
686
687            order_commutative_operands(arg1, arg2);
688
689            h1   = s390_isel_int_expr(env, arg1);       /* Process 1st operand */
690            op2  = s390_isel_int_expr_RMI(env, arg2);   /* Process 2nd operand */
691
692            /* We use non-virtual registers r10 and r11 as pair */
693            r10  = make_gpr(10);
694            r11  = make_gpr(11);
695
696            /* Move the first operand to r11 */
697            addInstr(env, s390_insn_move(8, r11, h1));
698
699            /* Multiply */
700            addInstr(env, s390_insn_mul(8, r10, r11, op2, is_signed_multiply));
701
702            /* The result is in registers r10 and r11. Assign to two virtual regs
703               and return. */
704            *dst_hi = newVRegI(env);
705            *dst_lo = newVRegI(env);
706            addInstr(env, s390_insn_move(8, *dst_hi, r10));
707            addInstr(env, s390_insn_move(8, *dst_lo, r11));
708            return;
709         }
710
711      do_divide64: {
712         HReg r10, r11, hi, lo;
713         s390_opnd_RMI op2;
714
715         s390_isel_int128_expr(&hi, &lo, env, arg1);
716         op2  = s390_isel_int_expr_RMI(env, arg2);   /* Process 2nd operand */
717
718         /* We use non-virtual registers r10 and r11 as pair */
719         r10  = make_gpr(10);
720         r11  = make_gpr(11);
721
722         /* Move high 64 bits of the 1st operand into r10 and
723            the low 64 bits into r11. */
724         addInstr(env, s390_insn_move(8, r10, hi));
725         addInstr(env, s390_insn_move(8, r11, lo));
726
727         /* Divide */
728         addInstr(env, s390_insn_div(8, r10, r11, op2, is_signed_divide));
729
730         /* The result is in registers r10 (remainder) and r11 (quotient).
731            Move the result into the reg pair that is being returned such
732            such that the low 64 bits are the quotient and the upper 64 bits
733            are the remainder. (see libvex_ir.h). */
734         *dst_hi = newVRegI(env);
735         *dst_lo = newVRegI(env);
736         addInstr(env, s390_insn_move(8, *dst_hi, r10));
737         addInstr(env, s390_insn_move(8, *dst_lo, r11));
738         return;
739      }
740      }
741   }
742
743   vpanic("s390_isel_int128_expr");
744}
745
746
747/* Compute a 128-bit value into two 64-bit registers. These may be either
748   real or virtual regs; in any case they must not be changed by subsequent
749   code emitted by the caller. */
750static void
751s390_isel_int128_expr(HReg *dst_hi, HReg *dst_lo, ISelEnv *env, IRExpr *expr)
752{
753   s390_isel_int128_expr_wrk(dst_hi, dst_lo, env, expr);
754
755   /* Sanity checks ... */
756   vassert(hregIsVirtual(*dst_hi));
757   vassert(hregIsVirtual(*dst_lo));
758   vassert(hregClass(*dst_hi) == HRcInt64);
759   vassert(hregClass(*dst_lo) == HRcInt64);
760}
761
762
763/*---------------------------------------------------------*/
764/*--- ISEL: Integer expressions (64/32/16/8 bit)        ---*/
765/*---------------------------------------------------------*/
766
767/* Select insns for an integer-typed expression, and add them to the
768   code list.  Return a reg holding the result.  This reg will be a
769   virtual register.  THE RETURNED REG MUST NOT BE MODIFIED.  If you
770   want to modify it, ask for a new vreg, copy it in there, and modify
771   the copy.  The register allocator will do its best to map both
772   vregs to the same real register, so the copies will often disappear
773   later in the game.
774
775   This should handle expressions of 64, 32, 16 and 8-bit type.
776   All results are returned in a 64bit register.
777   For 16- and 8-bit expressions, the upper (32/48/56 : 16/24) bits
778   are arbitrary, so you should mask or sign extend partial values
779   if necessary.
780*/
781
782/* DO NOT CALL THIS DIRECTLY ! */
783static HReg
784s390_isel_int_expr_wrk(ISelEnv *env, IRExpr *expr)
785{
786   IRType ty = typeOfIRExpr(env->type_env, expr);
787   UChar size;
788   s390_bfp_unop_t bfpop;
789
790   vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I64);
791
792   size = sizeofIRType(ty);   /* size of the result after evaluating EXPR */
793
794   switch (expr->tag) {
795
796      /* --------- TEMP --------- */
797   case Iex_RdTmp:
798      /* Return the virtual register that holds the temporary. */
799      return lookupIRTemp(env, expr->Iex.RdTmp.tmp);
800
801      /* --------- LOAD --------- */
802   case Iex_Load: {
803      HReg        dst = newVRegI(env);
804      s390_amode *am  = s390_isel_amode(env, expr->Iex.Load.addr);
805
806      if (expr->Iex.Load.end != Iend_BE)
807         goto irreducible;
808
809      addInstr(env, s390_insn_load(size, dst, am));
810
811      return dst;
812   }
813
814      /* --------- BINARY OP --------- */
815   case Iex_Binop: {
816      IRExpr *arg1 = expr->Iex.Binop.arg1;
817      IRExpr *arg2 = expr->Iex.Binop.arg2;
818      HReg h1, res;
819      s390_alu_t opkind;
820      s390_opnd_RMI op2, value, opnd;
821      s390_insn *insn;
822      Bool is_commutative, is_signed_multiply, is_signed_divide;
823
824      is_commutative = True;
825
826      switch (expr->Iex.Binop.op) {
827      case Iop_MullU8:
828      case Iop_MullU16:
829      case Iop_MullU32:
830         is_signed_multiply = False;
831         goto do_multiply;
832
833      case Iop_MullS8:
834      case Iop_MullS16:
835      case Iop_MullS32:
836         is_signed_multiply = True;
837         goto do_multiply;
838
839      do_multiply: {
840            HReg r10, r11;
841            UInt arg_size = size / 2;
842
843            order_commutative_operands(arg1, arg2);
844
845            h1   = s390_isel_int_expr(env, arg1);       /* Process 1st operand */
846            op2  = s390_isel_int_expr_RMI(env, arg2);   /* Process 2nd operand */
847
848            /* We use non-virtual registers r10 and r11 as pair */
849            r10  = make_gpr(10);
850            r11  = make_gpr(11);
851
852            /* Move the first operand to r11 */
853            addInstr(env, s390_insn_move(arg_size, r11, h1));
854
855            /* Multiply */
856            addInstr(env, s390_insn_mul(arg_size, r10, r11, op2, is_signed_multiply));
857
858            /* The result is in registers r10 and r11. Combine them into a SIZE-bit
859               value into the destination register. */
860            res  = newVRegI(env);
861            addInstr(env, s390_insn_move(arg_size, res, r10));
862            value = s390_opnd_imm(arg_size * 8);
863            addInstr(env, s390_insn_alu(size, S390_ALU_LSH, res, value));
864            value = s390_opnd_imm((((ULong)1) << arg_size * 8) - 1);
865            addInstr(env, s390_insn_alu(size, S390_ALU_AND, r11, value));
866            opnd = s390_opnd_reg(r11);
867            addInstr(env, s390_insn_alu(size, S390_ALU_OR,  res, opnd));
868            return res;
869         }
870
871      case Iop_DivModS64to32:
872         is_signed_divide = True;
873         goto do_divide;
874
875      case Iop_DivModU64to32:
876         is_signed_divide = False;
877         goto do_divide;
878
879      do_divide: {
880            HReg r10, r11;
881
882            h1   = s390_isel_int_expr(env, arg1);       /* Process 1st operand */
883            op2  = s390_isel_int_expr_RMI(env, arg2);   /* Process 2nd operand */
884
885            /* We use non-virtual registers r10 and r11 as pair */
886            r10  = make_gpr(10);
887            r11  = make_gpr(11);
888
889            /* Split the first operand and put the high 32 bits into r10 and
890               the low 32 bits into r11. */
891            addInstr(env, s390_insn_move(8, r10, h1));
892            addInstr(env, s390_insn_move(8, r11, h1));
893            value = s390_opnd_imm(32);
894            addInstr(env, s390_insn_alu(8, S390_ALU_RSH, r10, value));
895
896            /* Divide */
897            addInstr(env, s390_insn_div(4, r10, r11, op2, is_signed_divide));
898
899            /* The result is in registers r10 (remainder) and r11 (quotient).
900               Combine them into a 64-bit value such that the low 32 bits are
901               the quotient and the upper 32 bits are the remainder. (see
902               libvex_ir.h). */
903            res  = newVRegI(env);
904            addInstr(env, s390_insn_move(8, res, r10));
905            value = s390_opnd_imm(32);
906            addInstr(env, s390_insn_alu(8, S390_ALU_LSH, res, value));
907            value = s390_opnd_imm((((ULong)1) << 32) - 1);
908            addInstr(env, s390_insn_alu(8, S390_ALU_AND, r11, value));
909            opnd = s390_opnd_reg(r11);
910            addInstr(env, s390_insn_alu(8, S390_ALU_OR,  res, opnd));
911            return res;
912         }
913
914      case Iop_F32toI32S:  bfpop = S390_BFP_F32_TO_I32;  goto do_convert;
915      case Iop_F32toI64S:  bfpop = S390_BFP_F32_TO_I64;  goto do_convert;
916      case Iop_F64toI32S:  bfpop = S390_BFP_F64_TO_I32;  goto do_convert;
917      case Iop_F64toI64S:  bfpop = S390_BFP_F64_TO_I64;  goto do_convert;
918      case Iop_F128toI32S: bfpop = S390_BFP_F128_TO_I32; goto do_convert_128;
919      case Iop_F128toI64S: bfpop = S390_BFP_F128_TO_I64; goto do_convert_128;
920
921      do_convert: {
922         s390_round_t rounding_mode;
923
924         res  = newVRegI(env);
925         h1   = s390_isel_float_expr(env, arg2);   /* Process operand */
926
927         rounding_mode = decode_rounding_mode(arg1);
928         addInstr(env, s390_insn_bfp_unop(size, bfpop, res, h1, rounding_mode));
929         return res;
930      }
931
932      do_convert_128: {
933         s390_round_t rounding_mode;
934         HReg op_hi, op_lo, f13, f15;
935
936         res = newVRegI(env);
937         s390_isel_float128_expr(&op_hi, &op_lo, env, arg2); /* operand */
938
939         /* We use non-virtual registers r13 and r15 as pair */
940         f13 = make_fpr(13);
941         f15 = make_fpr(15);
942
943         /* operand --> (f13, f15) */
944         addInstr(env, s390_insn_move(8, f13, op_hi));
945         addInstr(env, s390_insn_move(8, f15, op_lo));
946
947         rounding_mode = decode_rounding_mode(arg1);
948         addInstr(env, s390_insn_bfp128_convert_from(size, bfpop, res, f13, f15,
949                                                     rounding_mode));
950         return res;
951      }
952
953      case Iop_8HLto16:
954      case Iop_16HLto32:
955      case Iop_32HLto64: {
956         HReg h2;
957         UInt arg_size = size / 2;
958
959         res  = newVRegI(env);
960         h1   = s390_isel_int_expr(env, arg1);   /* Process 1st operand */
961         h2   = s390_isel_int_expr(env, arg2);   /* Process 2nd operand */
962
963         addInstr(env, s390_insn_move(arg_size, res, h1));
964         value = s390_opnd_imm(arg_size * 8);
965         addInstr(env, s390_insn_alu(size, S390_ALU_LSH, res, value));
966         value = s390_opnd_imm((((ULong)1) << arg_size * 8) - 1);
967         addInstr(env, s390_insn_alu(size, S390_ALU_AND, h2, value));
968         opnd = s390_opnd_reg(h2);
969         addInstr(env, s390_insn_alu(size, S390_ALU_OR,  res, opnd));
970         return res;
971      }
972
973      case Iop_Max32U: {
974         /* arg1 > arg2 ? arg1 : arg2   using uint32_t arguments */
975         res = newVRegI(env);
976         h1  = s390_isel_int_expr(env, arg1);
977         op2 = s390_isel_int_expr_RMI(env, arg2);
978
979         addInstr(env, s390_insn_move(size, res, h1));
980         addInstr(env, s390_insn_compare(size, res, op2, False /* signed */));
981         addInstr(env, s390_insn_cond_move(size, S390_CC_L, res, op2));
982         return res;
983      }
984
985      case Iop_CmpF32:
986      case Iop_CmpF64: {
987         HReg cc_s390, h2;
988
989         h1 = s390_isel_float_expr(env, arg1);
990         h2 = s390_isel_float_expr(env, arg2);
991         cc_s390 = newVRegI(env);
992
993         size = (expr->Iex.Binop.op == Iop_CmpF32) ? 4 : 8;
994
995         addInstr(env, s390_insn_bfp_compare(size, cc_s390, h1, h2));
996
997         return convert_s390_fpcc_to_vex(env, cc_s390);
998      }
999
1000      case Iop_CmpF128: {
1001         HReg op1_hi, op1_lo, op2_hi, op2_lo, f12, f13, f14, f15, cc_s390;
1002
1003         s390_isel_float128_expr(&op1_hi, &op1_lo, env, arg1); /* 1st operand */
1004         s390_isel_float128_expr(&op2_hi, &op2_lo, env, arg2); /* 2nd operand */
1005         cc_s390 = newVRegI(env);
1006
1007         /* We use non-virtual registers as pairs (f13, f15) and (f12, f14)) */
1008         f12 = make_fpr(12);
1009         f13 = make_fpr(13);
1010         f14 = make_fpr(14);
1011         f15 = make_fpr(15);
1012
1013         /* 1st operand --> (f12, f14) */
1014         addInstr(env, s390_insn_move(8, f12, op1_hi));
1015         addInstr(env, s390_insn_move(8, f14, op1_lo));
1016
1017         /* 2nd operand --> (f13, f15) */
1018         addInstr(env, s390_insn_move(8, f13, op2_hi));
1019         addInstr(env, s390_insn_move(8, f15, op2_lo));
1020
1021         res = newVRegI(env);
1022         addInstr(env, s390_insn_bfp128_compare(16, cc_s390, f12, f14, f13, f15));
1023
1024         return convert_s390_fpcc_to_vex(env, cc_s390);
1025      }
1026
1027      case Iop_Add8:
1028      case Iop_Add16:
1029      case Iop_Add32:
1030      case Iop_Add64:
1031         opkind = S390_ALU_ADD;
1032         break;
1033
1034      case Iop_Sub8:
1035      case Iop_Sub16:
1036      case Iop_Sub32:
1037      case Iop_Sub64:
1038         opkind = S390_ALU_SUB;
1039         is_commutative = False;
1040         break;
1041
1042      case Iop_And8:
1043      case Iop_And16:
1044      case Iop_And32:
1045      case Iop_And64:
1046         opkind = S390_ALU_AND;
1047         break;
1048
1049      case Iop_Or8:
1050      case Iop_Or16:
1051      case Iop_Or32:
1052      case Iop_Or64:
1053         opkind = S390_ALU_OR;
1054         break;
1055
1056      case Iop_Xor8:
1057      case Iop_Xor16:
1058      case Iop_Xor32:
1059      case Iop_Xor64:
1060         opkind = S390_ALU_XOR;
1061         break;
1062
1063      case Iop_Shl8:
1064      case Iop_Shl16:
1065      case Iop_Shl32:
1066      case Iop_Shl64:
1067         opkind = S390_ALU_LSH;
1068         is_commutative = False;
1069         break;
1070
1071      case Iop_Shr8:
1072      case Iop_Shr16:
1073      case Iop_Shr32:
1074      case Iop_Shr64:
1075         opkind = S390_ALU_RSH;
1076         is_commutative = False;
1077         break;
1078
1079      case Iop_Sar8:
1080      case Iop_Sar16:
1081      case Iop_Sar32:
1082      case Iop_Sar64:
1083         opkind = S390_ALU_RSHA;
1084         is_commutative = False;
1085         break;
1086
1087      default:
1088         goto irreducible;
1089      }
1090
1091      /* Pattern match: 0 - arg1  -->  -arg1   */
1092      if (opkind == S390_ALU_SUB && s390_expr_is_const_zero(arg1)) {
1093         res  = newVRegI(env);
1094         op2  = s390_isel_int_expr_RMI(env, arg2);   /* Process 2nd operand */
1095         insn = s390_insn_unop(size, S390_NEGATE, res, op2);
1096         addInstr(env, insn);
1097
1098         return res;
1099      }
1100
1101      if (is_commutative) {
1102         order_commutative_operands(arg1, arg2);
1103      }
1104
1105      h1   = s390_isel_int_expr(env, arg1);       /* Process 1st operand */
1106      op2  = s390_isel_int_expr_RMI(env, arg2);   /* Process 2nd operand */
1107      res  = newVRegI(env);
1108      addInstr(env, s390_insn_move(size, res, h1));
1109      insn = s390_insn_alu(size, opkind, res, op2);
1110
1111      addInstr(env, insn);
1112
1113      return res;
1114   }
1115
1116      /* --------- UNARY OP --------- */
1117   case Iex_Unop: {
1118      static s390_opnd_RMI mask  = { S390_OPND_IMMEDIATE };
1119      static s390_opnd_RMI shift = { S390_OPND_IMMEDIATE };
1120      s390_opnd_RMI opnd;
1121      s390_insn    *insn;
1122      IRExpr *arg;
1123      HReg    dst, h1;
1124      IROp    unop, binop;
1125
1126      arg = expr->Iex.Unop.arg;
1127
1128      /* Special cases are handled here */
1129
1130      /* 32-bit multiply with 32-bit result or
1131         64-bit multiply with 64-bit result */
1132      unop  = expr->Iex.Unop.op;
1133      binop = arg->Iex.Binop.op;
1134
1135      if ((arg->tag == Iex_Binop &&
1136           ((unop == Iop_64to32 &&
1137             (binop == Iop_MullS32 || binop == Iop_MullU32)) ||
1138            (unop == Iop_128to64 &&
1139             (binop == Iop_MullS64 || binop == Iop_MullU64))))) {
1140         h1   = s390_isel_int_expr(env, arg->Iex.Binop.arg1);     /* 1st opnd */
1141         opnd = s390_isel_int_expr_RMI(env, arg->Iex.Binop.arg2); /* 2nd opnd */
1142         dst  = newVRegI(env);     /* Result goes into a new register */
1143         addInstr(env, s390_insn_move(size, dst, h1));
1144         addInstr(env, s390_insn_alu(size, S390_ALU_MUL, dst, opnd));
1145
1146         return dst;
1147      }
1148
1149      if (unop == Iop_ReinterpF64asI64 || unop == Iop_ReinterpF32asI32) {
1150         dst = newVRegI(env);
1151         h1  = s390_isel_float_expr(env, arg);     /* Process the operand */
1152         addInstr(env, s390_insn_move(size, dst, h1));
1153
1154         return dst;
1155      }
1156
1157      /* Expressions whose argument is 1-bit wide */
1158      if (typeOfIRExpr(env->type_env, arg) == Ity_I1) {
1159         s390_cc_t cond = s390_isel_cc(env, arg);
1160         dst = newVRegI(env);     /* Result goes into a new register */
1161         addInstr(env, s390_insn_cc2bool(dst, cond));
1162
1163         switch (unop) {
1164         case Iop_1Uto8:
1165         case Iop_1Uto32:
1166            /* Zero extend */
1167            mask.variant.imm = 1;
1168            addInstr(env, s390_insn_alu(4, S390_ALU_AND,  dst, mask));
1169            break;
1170
1171         case Iop_1Uto64:
1172            /* Zero extend */
1173            mask.variant.imm = 1;
1174            addInstr(env, s390_insn_alu(8, S390_ALU_AND,  dst, mask));
1175            break;
1176
1177         case Iop_1Sto8:
1178         case Iop_1Sto16:
1179         case Iop_1Sto32:
1180            shift.variant.imm = 31;
1181            addInstr(env, s390_insn_alu(4, S390_ALU_LSH,  dst, shift));
1182            addInstr(env, s390_insn_alu(4, S390_ALU_RSHA, dst, shift));
1183            break;
1184
1185         case Iop_1Sto64:
1186            shift.variant.imm = 63;
1187            addInstr(env, s390_insn_alu(8, S390_ALU_LSH,  dst, shift));
1188            addInstr(env, s390_insn_alu(8, S390_ALU_RSHA, dst, shift));
1189            break;
1190
1191         default:
1192            goto irreducible;
1193         }
1194
1195         return dst;
1196      }
1197
1198      /* Regular processing */
1199
1200      if (unop == Iop_128to64) {
1201         HReg dst_hi, dst_lo;
1202
1203         s390_isel_int128_expr(&dst_hi, &dst_lo, env, arg);
1204         return dst_lo;
1205      }
1206
1207      if (unop == Iop_128HIto64) {
1208         HReg dst_hi, dst_lo;
1209
1210         s390_isel_int128_expr(&dst_hi, &dst_lo, env, arg);
1211         return dst_hi;
1212      }
1213
1214      dst  = newVRegI(env);     /* Result goes into a new register */
1215      opnd = s390_isel_int_expr_RMI(env, arg);     /* Process the operand */
1216
1217      switch (unop) {
1218      case Iop_8Uto16:
1219      case Iop_8Uto32:
1220      case Iop_8Uto64:
1221         insn = s390_insn_unop(size, S390_ZERO_EXTEND_8, dst, opnd);
1222         break;
1223
1224      case Iop_16Uto32:
1225      case Iop_16Uto64:
1226         insn = s390_insn_unop(size, S390_ZERO_EXTEND_16, dst, opnd);
1227         break;
1228
1229      case Iop_32Uto64:
1230         insn = s390_insn_unop(size, S390_ZERO_EXTEND_32, dst, opnd);
1231         break;
1232
1233      case Iop_8Sto16:
1234      case Iop_8Sto32:
1235      case Iop_8Sto64:
1236         insn = s390_insn_unop(size, S390_SIGN_EXTEND_8, dst, opnd);
1237         break;
1238
1239      case Iop_16Sto32:
1240      case Iop_16Sto64:
1241         insn = s390_insn_unop(size, S390_SIGN_EXTEND_16, dst, opnd);
1242         break;
1243
1244      case Iop_32Sto64:
1245         insn = s390_insn_unop(size, S390_SIGN_EXTEND_32, dst, opnd);
1246         break;
1247
1248      case Iop_64to8:
1249      case Iop_64to16:
1250      case Iop_64to32:
1251      case Iop_32to8:
1252      case Iop_32to16:
1253      case Iop_16to8:
1254         /* Down-casts are no-ops. Upstream operations will only look at
1255            the bytes that make up the result of the down-cast. So there
1256            is no point setting the other bytes to 0. */
1257         insn = s390_opnd_copy(8, dst, opnd);
1258         break;
1259
1260      case Iop_64HIto32:
1261         addInstr(env, s390_opnd_copy(8, dst, opnd));
1262         shift.variant.imm = 32;
1263         insn = s390_insn_alu(8, S390_ALU_RSH, dst, shift);
1264         break;
1265
1266      case Iop_32HIto16:
1267         addInstr(env, s390_opnd_copy(4, dst, opnd));
1268         shift.variant.imm = 16;
1269         insn = s390_insn_alu(4, S390_ALU_RSH, dst, shift);
1270         break;
1271
1272      case Iop_16HIto8:
1273         addInstr(env, s390_opnd_copy(2, dst, opnd));
1274         shift.variant.imm = 8;
1275         insn = s390_insn_alu(2, S390_ALU_RSH, dst, shift);
1276         break;
1277
1278      case Iop_Not8:
1279      case Iop_Not16:
1280      case Iop_Not32:
1281      case Iop_Not64:
1282         /* XOR with ffff... */
1283         mask.variant.imm = ~(ULong)0;
1284         addInstr(env, s390_opnd_copy(size, dst, opnd));
1285         insn = s390_insn_alu(size, S390_ALU_XOR, dst, mask);
1286         break;
1287
1288      case Iop_Left8:
1289      case Iop_Left16:
1290      case Iop_Left32:
1291      case Iop_Left64:
1292         addInstr(env, s390_insn_unop(size, S390_NEGATE, dst, opnd));
1293         insn = s390_insn_alu(size, S390_ALU_OR, dst, opnd);
1294         break;
1295
1296      case Iop_CmpwNEZ32:
1297      case Iop_CmpwNEZ64: {
1298         /* Use the fact that x | -x == 0 iff x == 0. Otherwise, either X
1299            or -X will have a 1 in the MSB. */
1300         addInstr(env, s390_insn_unop(size, S390_NEGATE, dst, opnd));
1301         addInstr(env, s390_insn_alu(size, S390_ALU_OR,  dst, opnd));
1302         shift.variant.imm = (unop == Iop_CmpwNEZ32) ? 31 : 63;
1303         addInstr(env, s390_insn_alu(size, S390_ALU_RSHA,  dst, shift));
1304         return dst;
1305      }
1306
1307      case Iop_Clz64: {
1308         HReg r10, r11;
1309
1310         /* This will be implemented using FLOGR, if possible. So we need to
1311            set aside a pair of non-virtual registers. The result (number of
1312            left-most zero bits) will be in r10. The value in r11 is unspecified
1313            and must not be used. */
1314         r10  = make_gpr(10);
1315         r11  = make_gpr(11);
1316
1317         addInstr(env, s390_insn_clz(8, r10, r11, opnd));
1318         addInstr(env, s390_insn_move(8, dst, r10));
1319         return dst;
1320      }
1321
1322      default:
1323         goto irreducible;
1324      }
1325
1326      addInstr(env, insn);
1327
1328      return dst;
1329   }
1330
1331      /* --------- GET --------- */
1332   case Iex_Get: {
1333      HReg dst = newVRegI(env);
1334      s390_amode *am = s390_amode_for_guest_state(expr->Iex.Get.offset);
1335
1336      /* We never load more than 8 bytes from the guest state, because the
1337         floating point register pair is not contiguous. */
1338      vassert(size <= 8);
1339
1340      addInstr(env, s390_insn_load(size, dst, am));
1341
1342      return dst;
1343   }
1344
1345   case Iex_GetI:
1346      /* not needed */
1347      break;
1348
1349      /* --------- CCALL --------- */
1350   case Iex_CCall: {
1351      HReg dst = newVRegI(env);
1352
1353      doHelperCall(env, False, NULL, expr->Iex.CCall.cee,
1354                   expr->Iex.CCall.args, dst);
1355      return dst;
1356   }
1357
1358      /* --------- LITERAL --------- */
1359
1360      /* Load a literal into a register. Create a "load immediate"
1361         v-insn and return the register. */
1362   case Iex_Const: {
1363      ULong value;
1364      HReg  dst = newVRegI(env);
1365      const IRConst *con = expr->Iex.Const.con;
1366
1367      /* Bitwise copy of the value. No sign/zero-extension */
1368      switch (con->tag) {
1369      case Ico_U64: value = con->Ico.U64; break;
1370      case Ico_U32: value = con->Ico.U32; break;
1371      case Ico_U16: value = con->Ico.U16; break;
1372      case Ico_U8:  value = con->Ico.U8;  break;
1373      default:      vpanic("s390_isel_int_expr: invalid constant");
1374      }
1375
1376      addInstr(env, s390_insn_load_immediate(size, dst, value));
1377
1378      return dst;
1379   }
1380
1381      /* --------- MULTIPLEX --------- */
1382   case Iex_Mux0X: {
1383      IRExpr *cond_expr;
1384      HReg dst, tmp, rX;
1385      s390_opnd_RMI cond, r0, zero;
1386
1387      cond_expr = expr->Iex.Mux0X.cond;
1388
1389      dst  = newVRegI(env);
1390      r0   = s390_isel_int_expr_RMI(env, expr->Iex.Mux0X.expr0);
1391      rX   = s390_isel_int_expr(env, expr->Iex.Mux0X.exprX);
1392      size = sizeofIRType(typeOfIRExpr(env->type_env, expr->Iex.Mux0X.exprX));
1393
1394      if (cond_expr->tag == Iex_Unop && cond_expr->Iex.Unop.op == Iop_1Uto8) {
1395         s390_cc_t cc = s390_isel_cc(env, cond_expr->Iex.Unop.arg);
1396
1397         addInstr(env, s390_insn_move(size, dst, rX));
1398         addInstr(env, s390_insn_cond_move(size, s390_cc_invert(cc), dst, r0));
1399         return dst;
1400      }
1401
1402      /* Assume the condition is true and move rX to the destination reg. */
1403      addInstr(env, s390_insn_move(size, dst, rX));
1404
1405      /* Compute the condition ... */
1406      cond = s390_isel_int_expr_RMI(env, cond_expr);
1407
1408      /* tmp = cond & 0xFF */
1409      tmp  = newVRegI(env);
1410      addInstr(env, s390_insn_load_immediate(4, tmp, 0xFF));
1411      addInstr(env, s390_insn_alu(4, S390_ALU_AND, tmp, cond));
1412
1413      /* ... and compare it with zero */
1414      zero = s390_opnd_imm(0);
1415      addInstr(env, s390_insn_compare(4, tmp, zero, 0 /* signed */));
1416
1417      /* ... and if it compared equal move r0 to the destination reg. */
1418      size = sizeofIRType(typeOfIRExpr(env->type_env, expr->Iex.Mux0X.expr0));
1419      addInstr(env, s390_insn_cond_move(size, S390_CC_E, dst, r0));
1420
1421      return dst;
1422   }
1423
1424   default:
1425      break;
1426   }
1427
1428   /* We get here if no pattern matched. */
1429 irreducible:
1430   ppIRExpr(expr);
1431   vpanic("s390_isel_int_expr: cannot reduce tree");
1432}
1433
1434
1435static HReg
1436s390_isel_int_expr(ISelEnv *env, IRExpr *expr)
1437{
1438   HReg dst = s390_isel_int_expr_wrk(env, expr);
1439
1440   /* Sanity checks ... */
1441   vassert(hregClass(dst) == HRcInt64);
1442   vassert(hregIsVirtual(dst));
1443
1444   return dst;
1445}
1446
1447
1448static s390_opnd_RMI
1449s390_isel_int_expr_RMI(ISelEnv *env, IRExpr *expr)
1450{
1451   IRType ty = typeOfIRExpr(env->type_env, expr);
1452   s390_opnd_RMI dst;
1453
1454   vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 ||
1455           ty == Ity_I64);
1456
1457   if (expr->tag == Iex_Load) {
1458      dst.tag = S390_OPND_AMODE;
1459      dst.variant.am = s390_isel_amode(env, expr->Iex.Load.addr);
1460   } else if (expr->tag == Iex_Get) {
1461      dst.tag = S390_OPND_AMODE;
1462      dst.variant.am = s390_amode_for_guest_state(expr->Iex.Get.offset);
1463   } else if (expr->tag == Iex_Const) {
1464      ULong value;
1465
1466      /* The bit pattern for the value will be stored as is in the least
1467         significant bits of VALUE. */
1468      switch (expr->Iex.Const.con->tag) {
1469      case Ico_U1:  value = expr->Iex.Const.con->Ico.U1;  break;
1470      case Ico_U8:  value = expr->Iex.Const.con->Ico.U8;  break;
1471      case Ico_U16: value = expr->Iex.Const.con->Ico.U16; break;
1472      case Ico_U32: value = expr->Iex.Const.con->Ico.U32; break;
1473      case Ico_U64: value = expr->Iex.Const.con->Ico.U64; break;
1474      default:
1475         vpanic("s390_isel_int_expr_RMI");
1476      }
1477
1478      dst.tag = S390_OPND_IMMEDIATE;
1479      dst.variant.imm = value;
1480   } else {
1481      dst.tag = S390_OPND_REG;
1482      dst.variant.reg = s390_isel_int_expr(env, expr);
1483   }
1484
1485   return dst;
1486}
1487
1488
1489/*---------------------------------------------------------*/
1490/*--- ISEL: Floating point expressions (128 bit)        ---*/
1491/*---------------------------------------------------------*/
1492static void
1493s390_isel_float128_expr_wrk(HReg *dst_hi, HReg *dst_lo, ISelEnv *env,
1494                            IRExpr *expr)
1495{
1496   IRType ty = typeOfIRExpr(env->type_env, expr);
1497
1498   vassert(ty == Ity_F128);
1499
1500   /* Read 128-bit IRTemp */
1501   if (expr->tag == Iex_RdTmp) {
1502      lookupIRTemp128(dst_hi, dst_lo, env, expr->Iex.RdTmp.tmp);
1503      return;
1504   }
1505
1506   switch (expr->tag) {
1507   case Iex_RdTmp:
1508      /* Return the virtual registers that hold the temporary. */
1509      lookupIRTemp128(dst_hi, dst_lo, env, expr->Iex.RdTmp.tmp);
1510      return;
1511
1512      /* --------- LOAD --------- */
1513   case Iex_Load: {
1514      IRExpr *addr_hi, *addr_lo;
1515      s390_amode *am_hi, *am_lo;
1516
1517      if (expr->Iex.Load.end != Iend_BE)
1518         goto irreducible;
1519
1520      addr_hi = expr->Iex.Load.addr;
1521      addr_lo = IRExpr_Binop(Iop_Add64, addr_hi, mkU64(8));
1522
1523      am_hi  = s390_isel_amode(env, addr_hi);
1524      am_lo  = s390_isel_amode(env, addr_lo);
1525
1526      *dst_hi = newVRegF(env);
1527      *dst_lo = newVRegF(env);
1528      addInstr(env, s390_insn_load(8, *dst_hi, am_hi));
1529      addInstr(env, s390_insn_load(8, *dst_hi, am_lo));
1530      return;
1531   }
1532
1533
1534      /* --------- GET --------- */
1535   case Iex_Get:
1536      /* This is not supported because loading 128-bit from the guest
1537         state is almost certainly wrong. Use get_fpr_pair instead. */
1538      vpanic("Iex_Get with F128 data");
1539
1540      /* --------- 4-ary OP --------- */
1541   case Iex_Qop:
1542      vpanic("Iex_Qop with F128 data");
1543
1544      /* --------- TERNARY OP --------- */
1545   case Iex_Triop: {
1546      IRTriop *triop = expr->Iex.Triop.details;
1547      IROp    op     = triop->op;
1548      IRExpr *left   = triop->arg2;
1549      IRExpr *right  = triop->arg3;
1550      s390_bfp_binop_t bfpop;
1551      s390_round_t rounding_mode;
1552      HReg op1_hi, op1_lo, op2_hi, op2_lo, f12, f13, f14, f15;
1553
1554      s390_isel_float128_expr(&op1_hi, &op1_lo, env, left);  /* 1st operand */
1555      s390_isel_float128_expr(&op2_hi, &op2_lo, env, right); /* 2nd operand */
1556
1557      /* We use non-virtual registers as pairs (f13, f15) and (f12, f14)) */
1558      f12 = make_fpr(12);
1559      f13 = make_fpr(13);
1560      f14 = make_fpr(14);
1561      f15 = make_fpr(15);
1562
1563      /* 1st operand --> (f12, f14) */
1564      addInstr(env, s390_insn_move(8, f12, op1_hi));
1565      addInstr(env, s390_insn_move(8, f14, op1_lo));
1566
1567      /* 2nd operand --> (f13, f15) */
1568      addInstr(env, s390_insn_move(8, f13, op2_hi));
1569      addInstr(env, s390_insn_move(8, f15, op2_lo));
1570
1571      switch (op) {
1572      case Iop_AddF128: bfpop = S390_BFP_ADD; break;
1573      case Iop_SubF128: bfpop = S390_BFP_SUB; break;
1574      case Iop_MulF128: bfpop = S390_BFP_MUL; break;
1575      case Iop_DivF128: bfpop = S390_BFP_DIV; break;
1576      default:
1577         goto irreducible;
1578      }
1579
1580      rounding_mode = decode_rounding_mode(triop->arg1);
1581      addInstr(env, s390_insn_bfp128_binop(16, bfpop, f12, f14, f13,
1582                                           f15, rounding_mode));
1583
1584      /* Move result to virtual destination register */
1585      *dst_hi = newVRegF(env);
1586      *dst_lo = newVRegF(env);
1587      addInstr(env, s390_insn_move(8, *dst_hi, f12));
1588      addInstr(env, s390_insn_move(8, *dst_lo, f14));
1589
1590      return;
1591   }
1592
1593      /* --------- BINARY OP --------- */
1594   case Iex_Binop: {
1595      HReg op_hi, op_lo, f12, f13, f14, f15;
1596      s390_bfp_unop_t bfpop;
1597      s390_round_t rounding_mode;
1598
1599      /* We use non-virtual registers as pairs (f13, f15) and (f12, f14)) */
1600      f12 = make_fpr(12);
1601      f13 = make_fpr(13);
1602      f14 = make_fpr(14);
1603      f15 = make_fpr(15);
1604
1605      switch (expr->Iex.Binop.op) {
1606      case Iop_SqrtF128:
1607         s390_isel_float128_expr(&op_hi, &op_lo, env, expr->Iex.Binop.arg2);
1608
1609         /* operand --> (f13, f15) */
1610         addInstr(env, s390_insn_move(8, f13, op_hi));
1611         addInstr(env, s390_insn_move(8, f15, op_lo));
1612
1613         bfpop = S390_BFP_SQRT;
1614         rounding_mode = decode_rounding_mode(expr->Iex.Binop.arg1);
1615
1616         addInstr(env, s390_insn_bfp128_unop(16, bfpop, f12, f14, f13, f15,
1617                                             rounding_mode));
1618
1619         /* Move result to virtual destination registers */
1620         *dst_hi = newVRegF(env);
1621         *dst_lo = newVRegF(env);
1622         addInstr(env, s390_insn_move(8, *dst_hi, f12));
1623         addInstr(env, s390_insn_move(8, *dst_lo, f14));
1624         return;
1625
1626      case Iop_F64HLtoF128:
1627         *dst_hi = s390_isel_float_expr(env, expr->Iex.Binop.arg1);
1628         *dst_lo = s390_isel_float_expr(env, expr->Iex.Binop.arg2);
1629         return;
1630
1631      default:
1632         goto irreducible;
1633      }
1634   }
1635
1636      /* --------- UNARY OP --------- */
1637   case Iex_Unop: {
1638      IRExpr *left = expr->Iex.Unop.arg;
1639      s390_bfp_unop_t bfpop;
1640      s390_round_t rounding_mode;
1641      HReg op_hi, op_lo, op, f12, f13, f14, f15;
1642
1643      /* We use non-virtual registers as pairs (f13, f15) and (f12, f14)) */
1644      f12 = make_fpr(12);
1645      f13 = make_fpr(13);
1646      f14 = make_fpr(14);
1647      f15 = make_fpr(15);
1648
1649      switch (expr->Iex.Unop.op) {
1650      case Iop_NegF128:       bfpop = S390_BFP_NEG;          goto float128_opnd;
1651      case Iop_AbsF128:       bfpop = S390_BFP_ABS;          goto float128_opnd;
1652      case Iop_I32StoF128:    bfpop = S390_BFP_I32_TO_F128;  goto convert_int;
1653      case Iop_I64StoF128:    bfpop = S390_BFP_I64_TO_F128;  goto convert_int;
1654      case Iop_F32toF128:     bfpop = S390_BFP_F32_TO_F128;  goto convert_float;
1655      case Iop_F64toF128:     bfpop = S390_BFP_F64_TO_F128;  goto convert_float;
1656      default:
1657         goto irreducible;
1658      }
1659
1660   float128_opnd:
1661      s390_isel_float128_expr(&op_hi, &op_lo, env, left);
1662
1663      /* operand --> (f13, f15) */
1664      addInstr(env, s390_insn_move(8, f13, op_hi));
1665      addInstr(env, s390_insn_move(8, f15, op_lo));
1666
1667      rounding_mode = S390_ROUND_NEAREST_EVEN;  /* will not be used later on */
1668      addInstr(env, s390_insn_bfp128_unop(16, bfpop, f12, f14, f13, f15,
1669                                          rounding_mode));
1670      goto move_dst;
1671
1672   convert_float:
1673      op  = s390_isel_float_expr(env, left);
1674      addInstr(env, s390_insn_bfp128_convert_to(16, bfpop, f12, f14,
1675                                                op));
1676      goto move_dst;
1677
1678   convert_int:
1679      op  = s390_isel_int_expr(env, left);
1680      addInstr(env, s390_insn_bfp128_convert_to(16, bfpop, f12, f14,
1681                                                op));
1682      goto move_dst;
1683
1684   move_dst:
1685      /* Move result to virtual destination registers */
1686      *dst_hi = newVRegF(env);
1687      *dst_lo = newVRegF(env);
1688      addInstr(env, s390_insn_move(8, *dst_hi, f12));
1689      addInstr(env, s390_insn_move(8, *dst_lo, f14));
1690      return;
1691   }
1692
1693   default:
1694      goto irreducible;
1695   }
1696
1697   /* We get here if no pattern matched. */
1698 irreducible:
1699   ppIRExpr(expr);
1700   vpanic("s390_isel_int_expr: cannot reduce tree");
1701}
1702
1703/* Compute a 128-bit value into two 64-bit registers. These may be either
1704   real or virtual regs; in any case they must not be changed by subsequent
1705   code emitted by the caller. */
1706static void
1707s390_isel_float128_expr(HReg *dst_hi, HReg *dst_lo, ISelEnv *env, IRExpr *expr)
1708{
1709   s390_isel_float128_expr_wrk(dst_hi, dst_lo, env, expr);
1710
1711   /* Sanity checks ... */
1712   vassert(hregIsVirtual(*dst_hi));
1713   vassert(hregIsVirtual(*dst_lo));
1714   vassert(hregClass(*dst_hi) == HRcFlt64);
1715   vassert(hregClass(*dst_lo) == HRcFlt64);
1716}
1717
1718
1719/*---------------------------------------------------------*/
1720/*--- ISEL: Floating point expressions (64 bit)         ---*/
1721/*---------------------------------------------------------*/
1722
1723static HReg
1724s390_isel_float_expr_wrk(ISelEnv *env, IRExpr *expr)
1725{
1726   IRType ty = typeOfIRExpr(env->type_env, expr);
1727   UChar size;
1728
1729   vassert(ty == Ity_F32 || ty == Ity_F64);
1730
1731   size = sizeofIRType(ty);
1732
1733   switch (expr->tag) {
1734   case Iex_RdTmp:
1735      /* Return the virtual register that holds the temporary. */
1736      return lookupIRTemp(env, expr->Iex.RdTmp.tmp);
1737
1738      /* --------- LOAD --------- */
1739   case Iex_Load: {
1740      HReg        dst = newVRegF(env);
1741      s390_amode *am  = s390_isel_amode(env, expr->Iex.Load.addr);
1742
1743      if (expr->Iex.Load.end != Iend_BE)
1744         goto irreducible;
1745
1746      addInstr(env, s390_insn_load(size, dst, am));
1747
1748      return dst;
1749   }
1750
1751      /* --------- GET --------- */
1752   case Iex_Get: {
1753      HReg dst = newVRegF(env);
1754      s390_amode *am = s390_amode_for_guest_state(expr->Iex.Get.offset);
1755
1756      addInstr(env, s390_insn_load(size, dst, am));
1757
1758      return dst;
1759   }
1760
1761      /* --------- LITERAL --------- */
1762
1763      /* Load a literal into a register. Create a "load immediate"
1764         v-insn and return the register. */
1765   case Iex_Const: {
1766      ULong value;
1767      HReg  dst = newVRegF(env);
1768      const IRConst *con = expr->Iex.Const.con;
1769
1770      /* Bitwise copy of the value. No sign/zero-extension */
1771      switch (con->tag) {
1772      case Ico_F32i: value = con->Ico.F32i; break;
1773      case Ico_F64i: value = con->Ico.F64i; break;
1774      default:       vpanic("s390_isel_float_expr: invalid constant");
1775      }
1776
1777      if (value != 0) vpanic("cannot load immediate floating point constant");
1778
1779      addInstr(env, s390_insn_load_immediate(size, dst, value));
1780
1781      return dst;
1782   }
1783
1784      /* --------- 4-ary OP --------- */
1785   case Iex_Qop: {
1786      HReg op1, op2, op3, dst;
1787      s390_bfp_triop_t bfpop;
1788      s390_round_t rounding_mode;
1789
1790      op1 = s390_isel_float_expr(env, expr->Iex.Qop.details->arg2);
1791      op2 = s390_isel_float_expr(env, expr->Iex.Qop.details->arg3);
1792      op3 = s390_isel_float_expr(env, expr->Iex.Qop.details->arg4);
1793      dst = newVRegF(env);
1794      addInstr(env, s390_insn_move(size, dst, op1));
1795
1796      switch (expr->Iex.Qop.details->op) {
1797      case Iop_MAddF32:
1798      case Iop_MAddF64:  bfpop = S390_BFP_MADD; break;
1799      case Iop_MSubF32:
1800      case Iop_MSubF64:  bfpop = S390_BFP_MSUB; break;
1801
1802      default:
1803         goto irreducible;
1804      }
1805
1806      rounding_mode = decode_rounding_mode(expr->Iex.Qop.details->arg1);
1807      addInstr(env, s390_insn_bfp_triop(size, bfpop, dst, op2, op3,
1808                                        rounding_mode));
1809      return dst;
1810   }
1811
1812      /* --------- TERNARY OP --------- */
1813   case Iex_Triop: {
1814      IRTriop *triop = expr->Iex.Triop.details;
1815      IROp    op     = triop->op;
1816      IRExpr *left   = triop->arg2;
1817      IRExpr *right  = triop->arg3;
1818      s390_bfp_binop_t bfpop;
1819      s390_round_t rounding_mode;
1820      HReg h1, op2, dst;
1821
1822      h1   = s390_isel_float_expr(env, left);  /* Process 1st operand */
1823      op2  = s390_isel_float_expr(env, right); /* Process 2nd operand */
1824      dst  = newVRegF(env);
1825      addInstr(env, s390_insn_move(size, dst, h1));
1826      switch (op) {
1827      case Iop_AddF32:
1828      case Iop_AddF64:  bfpop = S390_BFP_ADD; break;
1829      case Iop_SubF32:
1830      case Iop_SubF64:  bfpop = S390_BFP_SUB; break;
1831      case Iop_MulF32:
1832      case Iop_MulF64:  bfpop = S390_BFP_MUL; break;
1833      case Iop_DivF32:
1834      case Iop_DivF64:  bfpop = S390_BFP_DIV; break;
1835
1836      default:
1837         goto irreducible;
1838      }
1839
1840      rounding_mode = decode_rounding_mode(triop->arg1);
1841      addInstr(env, s390_insn_bfp_binop(size, bfpop, dst, op2, rounding_mode));
1842      return dst;
1843   }
1844
1845      /* --------- BINARY OP --------- */
1846   case Iex_Binop: {
1847      IROp    op   = expr->Iex.Binop.op;
1848      IRExpr *left = expr->Iex.Binop.arg2;
1849      HReg h1, dst;
1850      s390_bfp_unop_t bfpop;
1851      s390_round_t rounding_mode;
1852      Int integer_operand;
1853
1854      integer_operand = 1;
1855
1856      switch (op) {
1857      case Iop_SqrtF32:
1858      case Iop_SqrtF64:
1859         bfpop = S390_BFP_SQRT;
1860         integer_operand = 0;
1861         break;
1862
1863      case Iop_F64toF32:
1864         bfpop = S390_BFP_F64_TO_F32;
1865         integer_operand = 0;
1866         break;
1867
1868      case Iop_I32StoF32: bfpop = S390_BFP_I32_TO_F32; break;
1869      case Iop_I64StoF32: bfpop = S390_BFP_I64_TO_F32; break;
1870      case Iop_I64StoF64: bfpop = S390_BFP_I64_TO_F64; break;
1871      default:
1872         goto irreducible;
1873
1874      case Iop_F128toF64:
1875      case Iop_F128toF32: {
1876         HReg op_hi, op_lo, f12, f13, f14, f15;
1877
1878         bfpop = op == Iop_F128toF32 ? S390_BFP_F128_TO_F32
1879            : S390_BFP_F128_TO_F64;
1880
1881         rounding_mode = decode_rounding_mode(expr->Iex.Binop.arg1);
1882
1883         s390_isel_float128_expr(&op_hi, &op_lo, env, expr->Iex.Binop.arg2);
1884
1885         /* We use non-virtual registers as pairs (f13, f15) and (f12, f14)) */
1886         f12 = make_fpr(12);
1887         f13 = make_fpr(13);
1888         f14 = make_fpr(14);
1889         f15 = make_fpr(15);
1890
1891         /* operand --> (f13, f15) */
1892         addInstr(env, s390_insn_move(8, f13, op_hi));
1893         addInstr(env, s390_insn_move(8, f15, op_lo));
1894
1895         dst = newVRegF(env);
1896         addInstr(env, s390_insn_bfp128_unop(16, bfpop, f12, f14, f13, f15,
1897                                             rounding_mode));
1898
1899         /* Move result to virtual destination registers */
1900         addInstr(env, s390_insn_move(8, dst, f12));
1901         return dst;
1902      }
1903      }
1904
1905      /* Process operand */
1906      if (integer_operand) {
1907         h1  = s390_isel_int_expr(env, left);
1908      } else {
1909         h1  = s390_isel_float_expr(env, left);
1910      }
1911
1912      dst = newVRegF(env);
1913      rounding_mode = decode_rounding_mode(expr->Iex.Binop.arg1);
1914      addInstr(env, s390_insn_bfp_unop(size, bfpop, dst, h1, rounding_mode));
1915      return dst;
1916   }
1917
1918      /* --------- UNARY OP --------- */
1919   case Iex_Unop: {
1920      IROp    op   = expr->Iex.Unop.op;
1921      IRExpr *left = expr->Iex.Unop.arg;
1922      s390_bfp_unop_t bfpop;
1923      s390_round_t rounding_mode;
1924      HReg h1, dst;
1925
1926      if (op == Iop_F128HItoF64 || op == Iop_F128LOtoF64) {
1927         HReg dst_hi, dst_lo;
1928
1929         s390_isel_float128_expr(&dst_hi, &dst_lo, env, left);
1930         return op == Iop_F128LOtoF64 ? dst_lo : dst_hi;
1931      }
1932
1933      if (op == Iop_ReinterpI64asF64 || op == Iop_ReinterpI32asF32) {
1934         dst = newVRegF(env);
1935         h1  = s390_isel_int_expr(env, left);     /* Process the operand */
1936         addInstr(env, s390_insn_move(size, dst, h1));
1937
1938         return dst;
1939      }
1940
1941      switch (op) {
1942      case Iop_NegF32:
1943      case Iop_NegF64:
1944         if (left->tag == Iex_Unop &&
1945             (left->Iex.Unop.op == Iop_AbsF32 || left->Iex.Unop.op == Iop_AbsF64))
1946            bfpop = S390_BFP_NABS;
1947         else
1948            bfpop = S390_BFP_NEG;
1949         break;
1950
1951      case Iop_AbsF32:
1952      case Iop_AbsF64:        bfpop = S390_BFP_ABS;  break;
1953      case Iop_I32StoF64:     bfpop = S390_BFP_I32_TO_F64;  break;
1954      case Iop_F32toF64:      bfpop = S390_BFP_F32_TO_F64;  break;
1955      default:
1956         goto irreducible;
1957      }
1958
1959      /* Process operand */
1960      if (op == Iop_I32StoF64)
1961         h1 = s390_isel_int_expr(env, left);
1962      else if (bfpop == S390_BFP_NABS)
1963         h1 = s390_isel_float_expr(env, left->Iex.Unop.arg);
1964      else
1965         h1 = s390_isel_float_expr(env, left);
1966
1967      dst = newVRegF(env);
1968      rounding_mode = S390_ROUND_NEAREST_EVEN;  /* will not be used later on */
1969      addInstr(env, s390_insn_bfp_unop(size, bfpop, dst, h1, rounding_mode));
1970      return dst;
1971   }
1972
1973   default:
1974      goto irreducible;
1975   }
1976
1977   /* We get here if no pattern matched. */
1978 irreducible:
1979   ppIRExpr(expr);
1980   vpanic("s390_isel_float_expr: cannot reduce tree");
1981}
1982
1983
1984static HReg
1985s390_isel_float_expr(ISelEnv *env, IRExpr *expr)
1986{
1987   HReg dst = s390_isel_float_expr_wrk(env, expr);
1988
1989   /* Sanity checks ... */
1990   vassert(hregClass(dst) == HRcFlt64);
1991   vassert(hregIsVirtual(dst));
1992
1993   return dst;
1994}
1995
1996
1997/*---------------------------------------------------------*/
1998/*--- ISEL: Condition Code                              ---*/
1999/*---------------------------------------------------------*/
2000
2001/* This function handles all operators that produce a 1-bit result */
2002static s390_cc_t
2003s390_isel_cc(ISelEnv *env, IRExpr *cond)
2004{
2005   UChar size;
2006
2007   vassert(typeOfIRExpr(env->type_env, cond) == Ity_I1);
2008
2009   /* Constant: either 1 or 0 */
2010   if (cond->tag == Iex_Const) {
2011      vassert(cond->Iex.Const.con->tag == Ico_U1);
2012      vassert(cond->Iex.Const.con->Ico.U1 == True
2013              || cond->Iex.Const.con->Ico.U1 == False);
2014
2015      return cond->Iex.Const.con->Ico.U1 == True ? S390_CC_ALWAYS : S390_CC_NEVER;
2016   }
2017
2018   /* Variable: values are 1 or 0 */
2019   if (cond->tag == Iex_RdTmp) {
2020      IRTemp tmp = cond->Iex.RdTmp.tmp;
2021      HReg   reg = lookupIRTemp(env, tmp);
2022
2023      /* Load-and-test does not modify REG; so this is OK. */
2024      if (typeOfIRTemp(env->type_env, tmp) == Ity_I1)
2025         size = 4;
2026      else
2027         size = sizeofIRType(typeOfIRTemp(env->type_env, tmp));
2028      addInstr(env, s390_insn_test(size, s390_opnd_reg(reg)));
2029      return S390_CC_NE;
2030   }
2031
2032   /* Unary operators */
2033   if (cond->tag == Iex_Unop) {
2034      IRExpr *arg = cond->Iex.Unop.arg;
2035
2036      switch (cond->Iex.Unop.op) {
2037      case Iop_Not1:  /* Not1(cond) */
2038         /* Generate code for EXPR, and negate the test condition */
2039         return s390_cc_invert(s390_isel_cc(env, arg));
2040
2041         /* Iop_32/64to1  select the LSB from their operand */
2042      case Iop_32to1:
2043      case Iop_64to1: {
2044         HReg dst = newVRegI(env);
2045         HReg h1  = s390_isel_int_expr(env, arg);
2046
2047         size = sizeofIRType(typeOfIRExpr(env->type_env, arg));
2048
2049         addInstr(env, s390_insn_move(size, dst, h1));
2050         addInstr(env, s390_insn_alu(size, S390_ALU_AND, dst, s390_opnd_imm(1)));
2051         addInstr(env, s390_insn_test(size, s390_opnd_reg(dst)));
2052         return S390_CC_NE;
2053      }
2054
2055      case Iop_CmpNEZ8:
2056      case Iop_CmpNEZ16: {
2057         s390_opnd_RMI src;
2058         s390_unop_t   op;
2059         HReg dst;
2060
2061         op  = (cond->Iex.Unop.op == Iop_CmpNEZ8) ? S390_ZERO_EXTEND_8
2062            : S390_ZERO_EXTEND_16;
2063         dst = newVRegI(env);
2064         src = s390_isel_int_expr_RMI(env, arg);
2065         addInstr(env, s390_insn_unop(4, op, dst, src));
2066         addInstr(env, s390_insn_test(4, s390_opnd_reg(dst)));
2067         return S390_CC_NE;
2068      }
2069
2070      case Iop_CmpNEZ32:
2071      case Iop_CmpNEZ64: {
2072         s390_opnd_RMI src;
2073
2074         src = s390_isel_int_expr_RMI(env, arg);
2075         size = sizeofIRType(typeOfIRExpr(env->type_env, arg));
2076         addInstr(env, s390_insn_test(size, src));
2077         return S390_CC_NE;
2078      }
2079
2080      default:
2081         goto fail;
2082      }
2083   }
2084
2085   /* Binary operators */
2086   if (cond->tag == Iex_Binop) {
2087      IRExpr *arg1 = cond->Iex.Binop.arg1;
2088      IRExpr *arg2 = cond->Iex.Binop.arg2;
2089      HReg reg1, reg2;
2090
2091      size = sizeofIRType(typeOfIRExpr(env->type_env, arg1));
2092
2093      switch (cond->Iex.Binop.op) {
2094         s390_unop_t op;
2095         s390_cc_t   result;
2096
2097      case Iop_CmpEQ8:
2098      case Iop_CasCmpEQ8:
2099         op     = S390_ZERO_EXTEND_8;
2100         result = S390_CC_E;
2101         goto do_compare_ze;
2102
2103      case Iop_CmpNE8:
2104      case Iop_CasCmpNE8:
2105         op     = S390_ZERO_EXTEND_8;
2106         result = S390_CC_NE;
2107         goto do_compare_ze;
2108
2109      case Iop_CmpEQ16:
2110      case Iop_CasCmpEQ16:
2111         op     = S390_ZERO_EXTEND_16;
2112         result = S390_CC_E;
2113         goto do_compare_ze;
2114
2115      case Iop_CmpNE16:
2116      case Iop_CasCmpNE16:
2117         op     = S390_ZERO_EXTEND_16;
2118         result = S390_CC_NE;
2119         goto do_compare_ze;
2120
2121      do_compare_ze: {
2122            s390_opnd_RMI op1, op2;
2123
2124            op1  = s390_isel_int_expr_RMI(env, arg1);
2125            reg1 = newVRegI(env);
2126            addInstr(env, s390_insn_unop(4, op, reg1, op1));
2127
2128            op2  = s390_isel_int_expr_RMI(env, arg2);
2129            reg2 = newVRegI(env);
2130            addInstr(env, s390_insn_unop(4, op, reg2, op2));  /* zero extend */
2131
2132            op2 = s390_opnd_reg(reg2);
2133            addInstr(env, s390_insn_compare(4, reg1, op2, False));
2134
2135            return result;
2136         }
2137
2138      case Iop_CmpEQ32:
2139      case Iop_CmpEQ64:
2140      case Iop_CasCmpEQ32:
2141      case Iop_CasCmpEQ64:
2142         result = S390_CC_E;
2143         goto do_compare;
2144
2145      case Iop_CmpNE32:
2146      case Iop_CmpNE64:
2147      case Iop_CasCmpNE32:
2148      case Iop_CasCmpNE64:
2149         result = S390_CC_NE;
2150         goto do_compare;
2151
2152      do_compare: {
2153            HReg op1;
2154            s390_opnd_RMI op2;
2155
2156            order_commutative_operands(arg1, arg2);
2157
2158            op1 = s390_isel_int_expr(env, arg1);
2159            op2 = s390_isel_int_expr_RMI(env, arg2);
2160
2161            addInstr(env, s390_insn_compare(size, op1, op2, False));
2162
2163            return result;
2164         }
2165
2166      case Iop_CmpLT32S:
2167      case Iop_CmpLE32S:
2168      case Iop_CmpLT64S:
2169      case Iop_CmpLE64S: {
2170         HReg op1;
2171         s390_opnd_RMI op2;
2172
2173         op1 = s390_isel_int_expr(env, arg1);
2174         op2 = s390_isel_int_expr_RMI(env, arg2);
2175
2176         addInstr(env, s390_insn_compare(size, op1, op2, True));
2177
2178         return (cond->Iex.Binop.op == Iop_CmpLT32S ||
2179                 cond->Iex.Binop.op == Iop_CmpLT64S) ? S390_CC_L : S390_CC_LE;
2180      }
2181
2182      case Iop_CmpLT32U:
2183      case Iop_CmpLE32U:
2184      case Iop_CmpLT64U:
2185      case Iop_CmpLE64U: {
2186         HReg op1;
2187         s390_opnd_RMI op2;
2188
2189         op1 = s390_isel_int_expr(env, arg1);
2190         op2 = s390_isel_int_expr_RMI(env, arg2);
2191
2192         addInstr(env, s390_insn_compare(size, op1, op2, False));
2193
2194         return (cond->Iex.Binop.op == Iop_CmpLT32U ||
2195                 cond->Iex.Binop.op == Iop_CmpLT64U) ? S390_CC_L : S390_CC_LE;
2196      }
2197
2198      default:
2199         goto fail;
2200      }
2201   }
2202
2203 fail:
2204   ppIRExpr(cond);
2205   vpanic("s390_isel_cc: unexpected operator");
2206}
2207
2208
2209/*---------------------------------------------------------*/
2210/*--- ISEL: Statements                                  ---*/
2211/*---------------------------------------------------------*/
2212
2213static void
2214s390_isel_stmt(ISelEnv *env, IRStmt *stmt)
2215{
2216   if (vex_traceflags & VEX_TRACE_VCODE) {
2217      vex_printf("\n -- ");
2218      ppIRStmt(stmt);
2219      vex_printf("\n");
2220   }
2221
2222   switch (stmt->tag) {
2223
2224      /* --------- STORE --------- */
2225   case Ist_Store: {
2226      IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.Store.data);
2227      s390_amode *am;
2228      HReg src;
2229
2230      if (stmt->Ist.Store.end != Iend_BE) goto stmt_fail;
2231
2232      am = s390_isel_amode(env, stmt->Ist.Store.addr);
2233
2234      switch (tyd) {
2235      case Ity_I8:
2236      case Ity_I16:
2237      case Ity_I32:
2238      case Ity_I64:
2239         src = s390_isel_int_expr(env, stmt->Ist.Store.data);
2240         break;
2241
2242      case Ity_F32:
2243      case Ity_F64:
2244         src = s390_isel_float_expr(env, stmt->Ist.Store.data);
2245         break;
2246
2247      case Ity_F128:
2248         /* Cannot occur. No such instruction */
2249         vpanic("Ist_Store with F128 data");
2250
2251      default:
2252         goto stmt_fail;
2253      }
2254
2255      addInstr(env, s390_insn_store(sizeofIRType(tyd), am, src));
2256      return;
2257   }
2258
2259      /* --------- PUT --------- */
2260   case Ist_Put: {
2261      IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.Put.data);
2262      HReg src;
2263      s390_amode *am;
2264      ULong new_value, old_value, difference;
2265
2266      /* Detect updates to certain guest registers. We track the contents
2267         of those registers as long as they contain constants. If the new
2268         constant is either zero or in the 8-bit neighbourhood of the
2269         current value we can use a memory-to-memory insn to do the update. */
2270
2271      Int offset = stmt->Ist.Put.offset;
2272
2273      /* Check necessary conditions:
2274         (1) must be one of the registers we care about
2275         (2) assigned value must be a constant */
2276      Int guest_reg = get_guest_reg(offset);
2277
2278      if (guest_reg == GUEST_UNKNOWN) goto not_special;
2279
2280      if (guest_reg == GUEST_IA) {
2281         /* If this is the first assignment to the IA reg, don't special case
2282            it. We need to do a full 8-byte assignment here. The reason is
2283            that in case of a redirected translation the guest IA does not
2284            contain the redirected-to address. Instead it contains the
2285            redirected-from address and those can be far apart. So in order to
2286            do incremnetal updates if the IA in the future we need to get the
2287            initial address of the super block correct. */
2288         if (env->first_IA_assignment) {
2289            env->first_IA_assignment = False;
2290            goto not_special;
2291         }
2292      }
2293
2294      if (stmt->Ist.Put.data->tag != Iex_Const) {
2295         /* Invalidate guest register contents */
2296         env->old_value_valid[guest_reg] = False;
2297         goto not_special;
2298      }
2299
2300      /* We can only handle Ity_I64, but the CC_DEPS field can have floats */
2301      if (tyd != Ity_I64)
2302         goto not_special;
2303
2304      /* OK. Necessary conditions are satisfied. */
2305
2306      old_value = env->old_value[guest_reg];
2307      new_value = stmt->Ist.Put.data->Iex.Const.con->Ico.U64;
2308      env->old_value[guest_reg] = new_value;
2309
2310      Bool old_value_is_valid = env->old_value_valid[guest_reg];
2311      env->old_value_valid[guest_reg] = True;
2312
2313      /* If the register already contains the new value, there is nothing
2314         to do here. Unless the guest register requires precise memory
2315         exceptions. */
2316      if (old_value_is_valid && new_value == old_value) {
2317         if (! guest_s390x_state_requires_precise_mem_exns(offset, offset + 8)) {
2318            return;
2319         }
2320      }
2321
2322      /* guest register = 0 */
2323      if (new_value == 0) {
2324         addInstr(env, s390_insn_gzero(sizeofIRType(tyd), offset));
2325         return;
2326      }
2327
2328      if (old_value_is_valid == False) goto not_special;
2329
2330      /* If the new value is in the neighbourhood of the old value
2331         we can use a memory-to-memory insn */
2332      difference = new_value - old_value;
2333
2334      if (s390_host_has_gie && ulong_fits_signed_8bit(difference)) {
2335         addInstr(env, s390_insn_gadd(sizeofIRType(tyd), offset,
2336                                      (difference & 0xFF), new_value));
2337         return;
2338      }
2339
2340      /* If the high word is the same it is sufficient to load the low word.
2341         Use R0 as a scratch reg. */
2342      if ((old_value >> 32) == (new_value >> 32)) {
2343         HReg r0  = make_gpr(0);
2344         HReg gsp = make_gpr(S390_REGNO_GUEST_STATE_POINTER);
2345         s390_amode *gam;
2346
2347         gam = s390_amode_b12(offset + 4, gsp);
2348         addInstr(env, s390_insn_load_immediate(4, r0,
2349                                                new_value & 0xFFFFFFFF));
2350         addInstr(env, s390_insn_store(4, gam, r0));
2351         return;
2352      }
2353
2354      /* No special case applies... fall through */
2355
2356   not_special:
2357      am = s390_amode_for_guest_state(stmt->Ist.Put.offset);
2358
2359      switch (tyd) {
2360      case Ity_I8:
2361      case Ity_I16:
2362      case Ity_I32:
2363      case Ity_I64:
2364         src = s390_isel_int_expr(env, stmt->Ist.Put.data);
2365         break;
2366
2367      case Ity_F32:
2368      case Ity_F64:
2369         src = s390_isel_float_expr(env, stmt->Ist.Put.data);
2370         break;
2371
2372      case Ity_F128:
2373         /* Does not occur. See function put_fpr_pair. */
2374         vpanic("Ist_Put with F128 data");
2375
2376      default:
2377         goto stmt_fail;
2378      }
2379
2380      addInstr(env, s390_insn_store(sizeofIRType(tyd), am, src));
2381      return;
2382   }
2383
2384      /* --------- TMP --------- */
2385   case Ist_WrTmp: {
2386      IRTemp tmp = stmt->Ist.WrTmp.tmp;
2387      IRType tyd = typeOfIRTemp(env->type_env, tmp);
2388      HReg src, dst;
2389
2390      switch (tyd) {
2391      case Ity_I128: {
2392         HReg dst_hi, dst_lo, res_hi, res_lo;
2393
2394         s390_isel_int128_expr(&res_hi, &res_lo, env, stmt->Ist.WrTmp.data);
2395         lookupIRTemp128(&dst_hi, &dst_lo, env, tmp);
2396
2397         addInstr(env, s390_insn_move(8, dst_hi, res_hi));
2398         addInstr(env, s390_insn_move(8, dst_lo, res_lo));
2399         return;
2400      }
2401
2402      case Ity_I8:
2403      case Ity_I16:
2404      case Ity_I32:
2405      case Ity_I64:
2406         src = s390_isel_int_expr(env, stmt->Ist.WrTmp.data);
2407         dst = lookupIRTemp(env, tmp);
2408         break;
2409
2410      case Ity_I1: {
2411         s390_cc_t cond = s390_isel_cc(env, stmt->Ist.WrTmp.data);
2412         dst = lookupIRTemp(env, tmp);
2413         addInstr(env, s390_insn_cc2bool(dst, cond));
2414         return;
2415      }
2416
2417      case Ity_F32:
2418      case Ity_F64:
2419         src = s390_isel_float_expr(env, stmt->Ist.WrTmp.data);
2420         dst = lookupIRTemp(env, tmp);
2421         break;
2422
2423      case Ity_F128: {
2424         HReg dst_hi, dst_lo, res_hi, res_lo;
2425
2426         s390_isel_float128_expr(&res_hi, &res_lo, env, stmt->Ist.WrTmp.data);
2427         lookupIRTemp128(&dst_hi, &dst_lo, env, tmp);
2428
2429         addInstr(env, s390_insn_move(8, dst_hi, res_hi));
2430         addInstr(env, s390_insn_move(8, dst_lo, res_lo));
2431         return;
2432      }
2433
2434      default:
2435         goto stmt_fail;
2436      }
2437
2438      addInstr(env, s390_insn_move(sizeofIRType(tyd), dst, src));
2439      return;
2440   }
2441
2442      /* --------- Call to DIRTY helper --------- */
2443   case Ist_Dirty: {
2444      IRType   retty;
2445      IRDirty* d = stmt->Ist.Dirty.details;
2446      Bool     passBBP;
2447      HReg dst;
2448      Int i;
2449
2450      /* Invalidate tracked values of those guest state registers that are
2451         modified by this helper. */
2452      for (i = 0; i < d->nFxState; ++i) {
2453         /* JRS 1 June 2012: AFAICS, s390 guest doesn't use 'repeat'
2454            descriptors in guest state effect descriptions.  Hence: */
2455         vassert(d->fxState[i].nRepeats == 0 && d->fxState[i].repeatLen == 0);
2456         if ((d->fxState[i].fx == Ifx_Write || d->fxState[i].fx == Ifx_Modify)) {
2457            Int guest_reg = get_guest_reg(d->fxState[i].offset);
2458            if (guest_reg != GUEST_UNKNOWN)
2459               env->old_value_valid[guest_reg] = False;
2460         }
2461      }
2462
2463      if (d->nFxState == 0)
2464         vassert(!d->needsBBP);
2465
2466      passBBP = toBool(d->nFxState > 0 && d->needsBBP);
2467
2468      if (d->tmp == IRTemp_INVALID) {
2469         /* No return value. */
2470         dst = INVALID_HREG;
2471         doHelperCall(env, passBBP, d->guard, d->cee, d->args, dst);
2472         return;
2473      }
2474
2475      retty = typeOfIRTemp(env->type_env, d->tmp);
2476      if (retty == Ity_I64 || retty == Ity_I32
2477          || retty == Ity_I16 || retty == Ity_I8) {
2478         /* Move the returned value to the destination register */
2479         dst = lookupIRTemp(env, d->tmp);
2480         doHelperCall(env, passBBP, d->guard, d->cee, d->args, dst);
2481         return;
2482      }
2483      break;
2484   }
2485
2486   case Ist_CAS:
2487      if (stmt->Ist.CAS.details->oldHi == IRTemp_INVALID) {
2488         IRCAS *cas = stmt->Ist.CAS.details;
2489         s390_amode *op2 = s390_isel_amode(env, cas->addr);
2490         HReg op3 = s390_isel_int_expr(env, cas->dataLo);  /* new value */
2491         HReg op1 = s390_isel_int_expr(env, cas->expdLo);  /* expected value */
2492         HReg old = lookupIRTemp(env, cas->oldLo);
2493
2494         if (typeOfIRTemp(env->type_env, cas->oldLo) == Ity_I32) {
2495            addInstr(env, s390_insn_cas(4, op1, op2, op3, old));
2496         } else {
2497            addInstr(env, s390_insn_cas(8, op1, op2, op3, old));
2498         }
2499         return;
2500      } else {
2501         IRCAS *cas = stmt->Ist.CAS.details;
2502         s390_amode *op2 = s390_isel_amode(env,  cas->addr);
2503         HReg r8, r9, r10, r11, r1;
2504         HReg op3_high = s390_isel_int_expr(env, cas->dataHi);  /* new value */
2505         HReg op3_low  = s390_isel_int_expr(env, cas->dataLo);  /* new value */
2506         HReg op1_high = s390_isel_int_expr(env, cas->expdHi);  /* expected value */
2507         HReg op1_low  = s390_isel_int_expr(env, cas->expdLo);  /* expected value */
2508         HReg old_low  = lookupIRTemp(env, cas->oldLo);
2509         HReg old_high = lookupIRTemp(env, cas->oldHi);
2510
2511         /* Use non-virtual registers r8 and r9 as pair for op1
2512            and move op1 there */
2513         r8 = make_gpr(8);
2514         r9 = make_gpr(9);
2515         addInstr(env, s390_insn_move(8, r8, op1_high));
2516         addInstr(env, s390_insn_move(8, r9, op1_low));
2517
2518         /* Use non-virtual registers r10 and r11 as pair for op3
2519            and move op3 there */
2520         r10 = make_gpr(10);
2521         r11 = make_gpr(11);
2522         addInstr(env, s390_insn_move(8, r10, op3_high));
2523         addInstr(env, s390_insn_move(8, r11, op3_low));
2524
2525         /* Register r1 is used as a scratch register */
2526         r1 = make_gpr(1);
2527
2528         if (typeOfIRTemp(env->type_env, cas->oldLo) == Ity_I32) {
2529            addInstr(env, s390_insn_cdas(4, r8, r9, op2, r10, r11,
2530                                         old_high, old_low, r1));
2531         } else {
2532            addInstr(env, s390_insn_cdas(8, r8, r9, op2, r10, r11,
2533                                         old_high, old_low, r1));
2534         }
2535         addInstr(env, s390_insn_move(8, op1_high, r8));
2536         addInstr(env, s390_insn_move(8, op1_low,  r9));
2537         addInstr(env, s390_insn_move(8, op3_high, r10));
2538         addInstr(env, s390_insn_move(8, op3_low,  r11));
2539         return;
2540      }
2541      break;
2542
2543      /* --------- EXIT --------- */
2544   case Ist_Exit: {
2545      s390_cc_t cond;
2546      IRConstTag tag = stmt->Ist.Exit.dst->tag;
2547
2548      if (tag != Ico_U64)
2549         vpanic("s390_isel_stmt: Ist_Exit: dst is not a 64-bit value");
2550
2551      s390_amode *guest_IA = s390_amode_for_guest_state(stmt->Ist.Exit.offsIP);
2552      cond = s390_isel_cc(env, stmt->Ist.Exit.guard);
2553
2554      /* Case: boring transfer to known address */
2555      if (stmt->Ist.Exit.jk == Ijk_Boring) {
2556         if (env->chaining_allowed) {
2557            /* .. almost always true .. */
2558            /* Skip the event check at the dst if this is a forwards
2559               edge. */
2560            Bool to_fast_entry
2561               = ((Addr64)stmt->Ist.Exit.dst->Ico.U64) > env->max_ga;
2562            if (0) vex_printf("%s", to_fast_entry ? "Y" : ",");
2563            addInstr(env, s390_insn_xdirect(cond, stmt->Ist.Exit.dst->Ico.U64,
2564                                            guest_IA, to_fast_entry));
2565         } else {
2566            /* .. very occasionally .. */
2567            /* We can't use chaining, so ask for an assisted transfer,
2568               as that's the only alternative that is allowable. */
2569            HReg dst = s390_isel_int_expr(env,
2570                                          IRExpr_Const(stmt->Ist.Exit.dst));
2571            addInstr(env, s390_insn_xassisted(cond, dst, guest_IA, Ijk_Boring));
2572         }
2573         return;
2574      }
2575
2576      /* Case: assisted transfer to arbitrary address */
2577      switch (stmt->Ist.Exit.jk) {
2578      case Ijk_NoDecode:
2579      case Ijk_TInval:
2580      case Ijk_Sys_syscall:
2581      case Ijk_ClientReq:
2582      case Ijk_NoRedir:
2583      case Ijk_Yield:
2584      case Ijk_SigTRAP: {
2585         HReg dst = s390_isel_int_expr(env, IRExpr_Const(stmt->Ist.Exit.dst));
2586         addInstr(env, s390_insn_xassisted(cond, dst, guest_IA,
2587                                           stmt->Ist.Exit.jk));
2588         return;
2589      }
2590      default:
2591         break;
2592      }
2593
2594      /* Do we ever expect to see any other kind? */
2595      goto stmt_fail;
2596   }
2597
2598      /* --------- MEM FENCE --------- */
2599   case Ist_MBE:
2600      switch (stmt->Ist.MBE.event) {
2601         case Imbe_Fence:
2602            addInstr(env, s390_insn_mfence());
2603            return;
2604         default:
2605            break;
2606      }
2607      break;
2608
2609      /* --------- Miscellaneous --------- */
2610
2611   case Ist_PutI:    /* Not needed */
2612   case Ist_IMark:   /* Doesn't generate any executable code */
2613   case Ist_NoOp:    /* Doesn't generate any executable code */
2614   case Ist_AbiHint: /* Meaningless in IR */
2615      return;
2616
2617   default:
2618      break;
2619   }
2620
2621 stmt_fail:
2622   ppIRStmt(stmt);
2623   vpanic("s390_isel_stmt");
2624}
2625
2626
2627/*---------------------------------------------------------*/
2628/*--- ISEL: Basic block terminators (Nexts)             ---*/
2629/*---------------------------------------------------------*/
2630
2631static void
2632iselNext(ISelEnv *env, IRExpr *next, IRJumpKind jk, int offsIP)
2633{
2634   if (vex_traceflags & VEX_TRACE_VCODE) {
2635      vex_printf("\n-- PUT(%d) = ", offsIP);
2636      ppIRExpr(next);
2637      vex_printf("; exit-");
2638      ppIRJumpKind(jk);
2639      vex_printf("\n");
2640   }
2641
2642   s390_amode *guest_IA = s390_amode_for_guest_state(offsIP);
2643
2644   /* Case: boring transfer to known address */
2645   if (next->tag == Iex_Const) {
2646      IRConst *cdst = next->Iex.Const.con;
2647      vassert(cdst->tag == Ico_U64);
2648      if (jk == Ijk_Boring || jk == Ijk_Call) {
2649         /* Boring transfer to known address */
2650         if (env->chaining_allowed) {
2651            /* .. almost always true .. */
2652            /* Skip the event check at the dst if this is a forwards
2653               edge. */
2654            Bool to_fast_entry
2655               = ((Addr64)cdst->Ico.U64) > env->max_ga;
2656            if (0) vex_printf("%s", to_fast_entry ? "X" : ".");
2657            addInstr(env, s390_insn_xdirect(S390_CC_ALWAYS, cdst->Ico.U64,
2658                                            guest_IA, to_fast_entry));
2659         } else {
2660            /* .. very occasionally .. */
2661            /* We can't use chaining, so ask for an indirect transfer,
2662               as that's the cheapest alternative that is allowable. */
2663            HReg dst = s390_isel_int_expr(env, next);
2664            addInstr(env, s390_insn_xassisted(S390_CC_ALWAYS, dst, guest_IA,
2665                                              Ijk_Boring));
2666         }
2667         return;
2668      }
2669   }
2670
2671   /* Case: call/return (==boring) transfer to any address */
2672   switch (jk) {
2673   case Ijk_Boring:
2674   case Ijk_Ret:
2675   case Ijk_Call: {
2676      HReg dst = s390_isel_int_expr(env, next);
2677      if (env->chaining_allowed) {
2678         addInstr(env, s390_insn_xindir(S390_CC_ALWAYS, dst, guest_IA));
2679      } else {
2680         addInstr(env, s390_insn_xassisted(S390_CC_ALWAYS, dst, guest_IA,
2681                                           Ijk_Boring));
2682      }
2683      return;
2684   }
2685   default:
2686      break;
2687   }
2688
2689   /* Case: some other kind of transfer to any address */
2690   switch (jk) {
2691   case Ijk_NoDecode:
2692   case Ijk_TInval:
2693   case Ijk_Sys_syscall:
2694   case Ijk_ClientReq:
2695   case Ijk_NoRedir:
2696   case Ijk_Yield:
2697   case Ijk_SigTRAP: {
2698      HReg dst = s390_isel_int_expr(env, next);
2699      addInstr(env, s390_insn_xassisted(S390_CC_ALWAYS, dst, guest_IA, jk));
2700      return;
2701   }
2702   default:
2703      break;
2704   }
2705
2706   vpanic("iselNext");
2707}
2708
2709
2710/*---------------------------------------------------------*/
2711/*--- Insn selector top-level                           ---*/
2712/*---------------------------------------------------------*/
2713
2714/* Translate an entire SB to s390 code.
2715   Note: archinfo_host is a pointer to a stack-allocated variable.
2716   Do not assign it to a global variable! */
2717
2718HInstrArray *
2719iselSB_S390(IRSB *bb, VexArch arch_host, VexArchInfo *archinfo_host,
2720            VexAbiInfo *vbi, Int offset_host_evcheck_counter,
2721            Int offset_host_evcheck_fail_addr, Bool chaining_allowed,
2722            Bool add_profinc, Addr64 max_ga)
2723{
2724   UInt     i, j;
2725   HReg     hreg, hregHI;
2726   ISelEnv *env;
2727   UInt     hwcaps_host = archinfo_host->hwcaps;
2728
2729   /* KLUDGE: export hwcaps. */
2730   s390_host_hwcaps = hwcaps_host;
2731
2732   /* Do some sanity checks */
2733   vassert((VEX_HWCAPS_S390X(hwcaps_host) & ~(VEX_HWCAPS_S390X_ALL)) == 0);
2734
2735   /* Make up an initial environment to use. */
2736   env = LibVEX_Alloc(sizeof(ISelEnv));
2737   env->vreg_ctr = 0;
2738
2739   /* Set up output code array. */
2740   env->code = newHInstrArray();
2741
2742   /* Copy BB's type env. */
2743   env->type_env = bb->tyenv;
2744
2745   /* Set up data structures for tracking guest register values. */
2746   env->first_IA_assignment = True;
2747   for (i = 0; i < NUM_TRACKED_REGS; ++i) {
2748      env->old_value[i] = 0;  /* just something to have a defined value */
2749      env->old_value_valid[i] = False;
2750   }
2751
2752   /* Make up an IRTemp -> virtual HReg mapping.  This doesn't
2753      change as we go along. For some reason types_used has Int type -- but
2754      it should be unsigned. Internally we use an unsigned type; so we
2755      assert it here. */
2756   vassert(bb->tyenv->types_used >= 0);
2757
2758   env->n_vregmap = bb->tyenv->types_used;
2759   env->vregmap   = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
2760   env->vregmapHI = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
2761
2762   /* and finally ... */
2763   env->hwcaps    = hwcaps_host;
2764
2765   env->max_ga = max_ga;
2766   env->chaining_allowed = chaining_allowed;
2767
2768   /* For each IR temporary, allocate a suitably-kinded virtual
2769      register. */
2770   j = 0;
2771   for (i = 0; i < env->n_vregmap; i++) {
2772      hregHI = hreg = INVALID_HREG;
2773      switch (bb->tyenv->types[i]) {
2774      case Ity_I1:
2775      case Ity_I8:
2776      case Ity_I16:
2777      case Ity_I32:
2778         hreg = mkHReg(j++, HRcInt64, True);
2779         break;
2780
2781      case Ity_I64:
2782         hreg   = mkHReg(j++, HRcInt64, True);
2783         break;
2784
2785      case Ity_I128:
2786         hreg   = mkHReg(j++, HRcInt64, True);
2787         hregHI = mkHReg(j++, HRcInt64, True);
2788         break;
2789
2790      case Ity_F32:
2791      case Ity_F64:
2792         hreg = mkHReg(j++, HRcFlt64, True);
2793         break;
2794
2795      case Ity_F128:
2796         hreg   = mkHReg(j++, HRcFlt64, True);
2797         hregHI = mkHReg(j++, HRcFlt64, True);
2798         break;
2799
2800      case Ity_V128: /* fall through */
2801      default:
2802         ppIRType(bb->tyenv->types[i]);
2803         vpanic("s390_isel_sb: IRTemp type");
2804      }
2805
2806      env->vregmap[i]   = hreg;
2807      env->vregmapHI[i] = hregHI;
2808   }
2809   env->vreg_ctr = j;
2810
2811   /* The very first instruction must be an event check. */
2812   s390_amode *counter, *fail_addr;
2813   counter   = s390_amode_for_guest_state(offset_host_evcheck_counter);
2814   fail_addr = s390_amode_for_guest_state(offset_host_evcheck_fail_addr);
2815   addInstr(env, s390_insn_evcheck(counter, fail_addr));
2816
2817   /* Possibly a block counter increment (for profiling).  At this
2818      point we don't know the address of the counter, so just pretend
2819      it is zero.  It will have to be patched later, but before this
2820      translation is used, by a call to LibVEX_patchProfInc. */
2821   if (add_profinc) {
2822      addInstr(env, s390_insn_profinc());
2823   }
2824
2825   /* Ok, finally we can iterate over the statements. */
2826   for (i = 0; i < bb->stmts_used; i++)
2827      if (bb->stmts[i])
2828         s390_isel_stmt(env, bb->stmts[i]);
2829
2830   iselNext(env, bb->next, bb->jumpkind, bb->offsIP);
2831
2832   /* Record the number of vregs we used. */
2833   env->code->n_vregs = env->vreg_ctr;
2834
2835   return env->code;
2836}
2837
2838/*---------------------------------------------------------------*/
2839/*--- end                                    host_s390_isel.c ---*/
2840/*---------------------------------------------------------------*/
2841