guest_s390_helpers.c revision 49adf8664fa8e67c95397022d21ea1b547e2186b
12019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/* -*- mode: C; c-basic-offset: 3; -*- */
22019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
32019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*---------------------------------------------------------------*/
42019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*--- begin                              guest_s390_helpers.c ---*/
52019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*---------------------------------------------------------------*/
62019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
72019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*
82019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   This file is part of Valgrind, a dynamic binary instrumentation
92019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   framework.
102019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
1189ae8477745fd2a15453557d729a50e627325ee2sewardj   Copyright IBM Corp. 2010-2013
122019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
132019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   This program is free software; you can redistribute it and/or
142019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   modify it under the terms of the GNU General Public License as
152019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   published by the Free Software Foundation; either version 2 of the
162019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   License, or (at your option) any later version.
172019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
182019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   This program is distributed in the hope that it will be useful, but
192019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
202019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
212019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   General Public License for more details.
222019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
232019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   You should have received a copy of the GNU General Public License
242019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   along with this program; if not, write to the Free Software
252019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
262019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   02110-1301, USA.
272019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
282019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   The GNU General Public License is contained in the file COPYING.
292019a976f07ff418dde2dfc7cc74667ef66d7764sewardj*/
302019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
312019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/* Contributed by Florian Krohm */
322019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
332019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#include "libvex_basictypes.h"
3433b024301d2311965cc68dc4cc900f3d0fdd8085florian#include "libvex_emnote.h"
352019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#include "libvex_guest_s390x.h"
362019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#include "libvex_ir.h"
372019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#include "libvex.h"
38933065d4f3548466da4666c5cfda7e5eaff93759florian#include "libvex_s390x_common.h"
392019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
402019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#include "main_util.h"
416c46befd9eb90c1b6e739926c1fa335cba75bf46philippe#include "main_globals.h"
422019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#include "guest_generic_bb_to_IR.h"
432019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#include "guest_s390_defs.h"
44b0b6710aa770763fd1fd5005075de8a8d5a269fbflorian#include "s390_defs.h"               /* S390_BFP_ROUND_xyzzy */
452019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
462019a976f07ff418dde2dfc7cc74667ef66d7764sewardjvoid
472019a976f07ff418dde2dfc7cc74667ef66d7764sewardjLibVEX_GuestS390X_initialise(VexGuestS390XState *state)
482019a976f07ff418dde2dfc7cc74667ef66d7764sewardj{
492019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*------------------------------------------------------------*/
502019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*--- Initialise ar registers                              ---*/
512019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*------------------------------------------------------------*/
522019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
532019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_a0 = 0;
542019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_a1 = 0;
552019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_a2 = 0;
562019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_a3 = 0;
572019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_a4 = 0;
582019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_a5 = 0;
592019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_a6 = 0;
602019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_a7 = 0;
612019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_a8 = 0;
622019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_a9 = 0;
632019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_a10 = 0;
642019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_a11 = 0;
652019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_a12 = 0;
662019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_a13 = 0;
672019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_a14 = 0;
682019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_a15 = 0;
692019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
702019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*------------------------------------------------------------*/
712019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*--- Initialise fpr registers                             ---*/
722019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*------------------------------------------------------------*/
732019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
742019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_f0 = 0;
752019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_f1 = 0;
762019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_f2 = 0;
772019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_f3 = 0;
782019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_f4 = 0;
792019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_f5 = 0;
802019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_f6 = 0;
812019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_f7 = 0;
822019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_f8 = 0;
832019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_f9 = 0;
842019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_f10 = 0;
852019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_f11 = 0;
862019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_f12 = 0;
872019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_f13 = 0;
882019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_f14 = 0;
892019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_f15 = 0;
902019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
912019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*------------------------------------------------------------*/
922019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*--- Initialise gpr registers                             ---*/
932019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*------------------------------------------------------------*/
942019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
952019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_r0 = 0;
962019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_r1 = 0;
972019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_r2 = 0;
982019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_r3 = 0;
992019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_r4 = 0;
1002019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_r5 = 0;
1012019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_r6 = 0;
1022019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_r7 = 0;
1032019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_r8 = 0;
1042019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_r9 = 0;
1052019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_r10 = 0;
1062019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_r11 = 0;
1072019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_r12 = 0;
1082019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_r13 = 0;
1092019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_r14 = 0;
1102019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_r15 = 0;
1112019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
1122019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*------------------------------------------------------------*/
1132019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*--- Initialise S390 miscellaneous registers              ---*/
1142019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*------------------------------------------------------------*/
1152019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
1162019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_counter = 0;
1172019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_fpc = 0;
1182019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_IA = 0;
1192019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
1202019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*------------------------------------------------------------*/
1212019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*--- Initialise S390 pseudo registers                     ---*/
1222019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*------------------------------------------------------------*/
1232019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
1242019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_SYSNO = 0;
1252019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
1262019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*------------------------------------------------------------*/
1272019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*--- Initialise generic pseudo registers                  ---*/
1282019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*------------------------------------------------------------*/
1292019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
1302019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_NRADDR = 0;
13105f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj   state->guest_CMSTART = 0;
13205f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj   state->guest_CMLEN = 0;
1332019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_IP_AT_SYSCALL = 0;
1346ef84bed9bb3af22060eb1759788034602bbcc88florian   state->guest_EMNOTE = EmNote_NONE;
1358844a6329d275814456e3a2a5a7bffac75da0957florian   state->host_EvC_COUNTER = 0;
1368844a6329d275814456e3a2a5a7bffac75da0957florian   state->host_EvC_FAILADDR = 0;
1372019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
1382019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*------------------------------------------------------------*/
1392019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*--- Initialise thunk                                     ---*/
1402019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*------------------------------------------------------------*/
1412019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
1422019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_CC_OP = 0;
1432019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_CC_DEP1 = 0;
1442019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_CC_DEP2 = 0;
1452019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   state->guest_CC_NDEP = 0;
1465c328c00cfaad8b53006366e4db232543f8df5e1florian
1475c328c00cfaad8b53006366e4db232543f8df5e1florian   __builtin_memset(state->padding, 0x0, sizeof(state->padding));
1482019a976f07ff418dde2dfc7cc74667ef66d7764sewardj}
1492019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
1502019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
1512019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/* Figure out if any part of the guest state contained in minoff
1522019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   .. maxoff requires precise memory exceptions.  If in doubt return
1536c46befd9eb90c1b6e739926c1fa335cba75bf46philippe   True (but this generates significantly slower code).  */
1542019a976f07ff418dde2dfc7cc74667ef66d7764sewardjBool
1552019a976f07ff418dde2dfc7cc74667ef66d7764sewardjguest_s390x_state_requires_precise_mem_exns(Int minoff, Int maxoff)
1562019a976f07ff418dde2dfc7cc74667ef66d7764sewardj{
157606878860623daa234c68fff81aade73059aaafbsewardj   Int lr_min = S390X_GUEST_OFFSET(guest_LR);
1582019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   Int lr_max = lr_min + 8 - 1;
159606878860623daa234c68fff81aade73059aaafbsewardj   Int sp_min = S390X_GUEST_OFFSET(guest_SP);
1602019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   Int sp_max = sp_min + 8 - 1;
161606878860623daa234c68fff81aade73059aaafbsewardj   Int fp_min = S390X_GUEST_OFFSET(guest_FP);
1622019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   Int fp_max = fp_min + 8 - 1;
163e88b3c94d4e3bf0f40123ffe162dd60e50580366florian   Int ia_min = S390X_GUEST_OFFSET(guest_IA);
1642019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   Int ia_max = ia_min + 8 - 1;
1652019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
1666c46befd9eb90c1b6e739926c1fa335cba75bf46philippe   if (maxoff < sp_min || minoff > sp_max) {
1676c46befd9eb90c1b6e739926c1fa335cba75bf46philippe      /* No overlap with SP */
1686c46befd9eb90c1b6e739926c1fa335cba75bf46philippe      if (vex_control.iropt_register_updates == VexRegUpdSpAtMemAccess)
1696c46befd9eb90c1b6e739926c1fa335cba75bf46philippe         return False; // We only need to check stack pointer.
1702019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   } else {
1712019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return True;
1722019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   }
1732019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
1746c46befd9eb90c1b6e739926c1fa335cba75bf46philippe   if (maxoff < lr_min || minoff > lr_max) {
1756c46befd9eb90c1b6e739926c1fa335cba75bf46philippe      /* No overlap with LR */
1762019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   } else {
1772019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return True;
1782019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   }
1792019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
1802019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   if (maxoff < fp_min || minoff > fp_max) {
1812019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* No overlap with FP */
1822019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   } else {
1832019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return True;
1842019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   }
1852019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
1862019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   if (maxoff < ia_min || minoff > ia_max) {
1872019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* No overlap with IA */
1882019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   } else {
1892019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return True;
1902019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   }
1912019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
1922019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   return False;
1932019a976f07ff418dde2dfc7cc74667ef66d7764sewardj}
1942019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
1952019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
1962019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#define ALWAYSDEFD(field)                             \
197e88b3c94d4e3bf0f40123ffe162dd60e50580366florian    { S390X_GUEST_OFFSET(field),            \
1982019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      (sizeof ((VexGuestS390XState*)0)->field) }
1992019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
2002019a976f07ff418dde2dfc7cc74667ef66d7764sewardjVexGuestLayout s390xGuest_layout = {
2012019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
2022019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   /* Total size of the guest state, in bytes. */
2032019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   .total_sizeB = sizeof(VexGuestS390XState),
2042019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
2052019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   /* Describe the stack pointer. */
206606878860623daa234c68fff81aade73059aaafbsewardj   .offset_SP = S390X_GUEST_OFFSET(guest_SP),
2072019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   .sizeof_SP = 8,
2082019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
2092019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   /* Describe the frame pointer. */
210606878860623daa234c68fff81aade73059aaafbsewardj   .offset_FP = S390X_GUEST_OFFSET(guest_FP),
2112019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   .sizeof_FP = 8,
2122019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
2132019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   /* Describe the instruction pointer. */
214e88b3c94d4e3bf0f40123ffe162dd60e50580366florian   .offset_IP = S390X_GUEST_OFFSET(guest_IA),
2152019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   .sizeof_IP = 8,
2162019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
2172019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   /* Describe any sections to be regarded by Memcheck as
2182019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      'always-defined'. */
2192019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   .n_alwaysDefd = 9,
2202019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
2212019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   /* Flags thunk: OP and NDEP are always defined, whereas DEP1
2222019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      and DEP2 have to be tracked.  See detailed comment in
2232019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      gdefs.h on meaning of thunk fields. */
2242019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   .alwaysDefd = {
2252019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /*  0 */ ALWAYSDEFD(guest_CC_OP),     /* generic */
2262019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /*  1 */ ALWAYSDEFD(guest_CC_NDEP),   /* generic */
2276ef84bed9bb3af22060eb1759788034602bbcc88florian      /*  2 */ ALWAYSDEFD(guest_EMNOTE),    /* generic */
22805f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj      /*  3 */ ALWAYSDEFD(guest_CMSTART),   /* generic */
22905f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj      /*  4 */ ALWAYSDEFD(guest_CMLEN),     /* generic */
2302019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /*  5 */ ALWAYSDEFD(guest_IP_AT_SYSCALL), /* generic */
2312019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /*  6 */ ALWAYSDEFD(guest_IA),        /* control reg */
2322019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /*  7 */ ALWAYSDEFD(guest_fpc),       /* control reg */
2332019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /*  8 */ ALWAYSDEFD(guest_counter),   /* internal usage register */
2342019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   }
2352019a976f07ff418dde2dfc7cc74667ef66d7764sewardj};
2362019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
2372019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*------------------------------------------------------------*/
2382019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*--- Dirty helper for EXecute                             ---*/
2392019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*------------------------------------------------------------*/
2402019a976f07ff418dde2dfc7cc74667ef66d7764sewardjvoid
2412019a976f07ff418dde2dfc7cc74667ef66d7764sewardjs390x_dirtyhelper_EX(ULong torun)
2422019a976f07ff418dde2dfc7cc74667ef66d7764sewardj{
2432019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   last_execute_target = torun;
2442019a976f07ff418dde2dfc7cc74667ef66d7764sewardj}
2452019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
2461e5fea63aab1f94925afd49d74560917b37fa505sewardj
2471e5fea63aab1f94925afd49d74560917b37fa505sewardj/*------------------------------------------------------------*/
2481e5fea63aab1f94925afd49d74560917b37fa505sewardj/*--- Dirty helper for Clock instructions                  ---*/
2491e5fea63aab1f94925afd49d74560917b37fa505sewardj/*------------------------------------------------------------*/
2501e5fea63aab1f94925afd49d74560917b37fa505sewardj#if defined(VGA_s390x)
251ae88411aaa8e0b99032fb0bdb04eec21edc54d88florianULong
252ae88411aaa8e0b99032fb0bdb04eec21edc54d88florians390x_dirtyhelper_STCK(ULong *addr)
2531e5fea63aab1f94925afd49d74560917b37fa505sewardj{
254ffbd84dd2205b38d45f3ce13d594787a7c62fd6cflorian   UInt cc;
2551e5fea63aab1f94925afd49d74560917b37fa505sewardj
2561e5fea63aab1f94925afd49d74560917b37fa505sewardj   asm volatile("stck %0\n"
2571e5fea63aab1f94925afd49d74560917b37fa505sewardj                "ipm %1\n"
2581e5fea63aab1f94925afd49d74560917b37fa505sewardj                "srl %1,28\n"
2591e5fea63aab1f94925afd49d74560917b37fa505sewardj                : "+Q" (*addr), "=d" (cc) : : "cc");
2601e5fea63aab1f94925afd49d74560917b37fa505sewardj   return cc;
2611e5fea63aab1f94925afd49d74560917b37fa505sewardj}
2621e5fea63aab1f94925afd49d74560917b37fa505sewardj
263ae88411aaa8e0b99032fb0bdb04eec21edc54d88florianULong
264ae88411aaa8e0b99032fb0bdb04eec21edc54d88florians390x_dirtyhelper_STCKE(ULong *addr)
2651e5fea63aab1f94925afd49d74560917b37fa505sewardj{
266ffbd84dd2205b38d45f3ce13d594787a7c62fd6cflorian   UInt cc;
2671e5fea63aab1f94925afd49d74560917b37fa505sewardj
2681e5fea63aab1f94925afd49d74560917b37fa505sewardj   asm volatile("stcke %0\n"
2691e5fea63aab1f94925afd49d74560917b37fa505sewardj                "ipm %1\n"
2701e5fea63aab1f94925afd49d74560917b37fa505sewardj                "srl %1,28\n"
2711e5fea63aab1f94925afd49d74560917b37fa505sewardj                : "+Q" (*addr), "=d" (cc) : : "cc");
2721e5fea63aab1f94925afd49d74560917b37fa505sewardj   return cc;
2731e5fea63aab1f94925afd49d74560917b37fa505sewardj}
2741e5fea63aab1f94925afd49d74560917b37fa505sewardj
2751e5fea63aab1f94925afd49d74560917b37fa505sewardjULong s390x_dirtyhelper_STCKF(ULong *addr)
2761e5fea63aab1f94925afd49d74560917b37fa505sewardj{
277ffbd84dd2205b38d45f3ce13d594787a7c62fd6cflorian   UInt cc;
2781e5fea63aab1f94925afd49d74560917b37fa505sewardj
2791e5fea63aab1f94925afd49d74560917b37fa505sewardj   asm volatile(".insn s,0xb27c0000,%0\n"
2801e5fea63aab1f94925afd49d74560917b37fa505sewardj                "ipm %1\n"
2811e5fea63aab1f94925afd49d74560917b37fa505sewardj                "srl %1,28\n"
2821e5fea63aab1f94925afd49d74560917b37fa505sewardj                : "+Q" (*addr), "=d" (cc) : : "cc");
2831e5fea63aab1f94925afd49d74560917b37fa505sewardj   return cc;
2841e5fea63aab1f94925afd49d74560917b37fa505sewardj}
2851e5fea63aab1f94925afd49d74560917b37fa505sewardj#else
2861e5fea63aab1f94925afd49d74560917b37fa505sewardjULong s390x_dirtyhelper_STCK(ULong *addr)  {return 3;}
2871e5fea63aab1f94925afd49d74560917b37fa505sewardjULong s390x_dirtyhelper_STCKF(ULong *addr) {return 3;}
2881e5fea63aab1f94925afd49d74560917b37fa505sewardjULong s390x_dirtyhelper_STCKE(ULong *addr) {return 3;}
2891e5fea63aab1f94925afd49d74560917b37fa505sewardj#endif /* VGA_s390x */
2901e5fea63aab1f94925afd49d74560917b37fa505sewardj
2912019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*------------------------------------------------------------*/
292933065d4f3548466da4666c5cfda7e5eaff93759florian/*--- Dirty helper for Store Facility instruction          ---*/
293933065d4f3548466da4666c5cfda7e5eaff93759florian/*------------------------------------------------------------*/
294933065d4f3548466da4666c5cfda7e5eaff93759florian#if defined(VGA_s390x)
295b7def2222c08b119df85bc7231bf0e6806f3a1a6florianstatic void
296b7def2222c08b119df85bc7231bf0e6806f3a1a6florians390_set_facility_bit(ULong *addr, UInt bitno, UInt value)
297b7def2222c08b119df85bc7231bf0e6806f3a1a6florian{
298b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   addr  += bitno / 64;
299b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   bitno  = bitno % 64;
300b7def2222c08b119df85bc7231bf0e6806f3a1a6florian
301b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   ULong mask = 1;
302b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   mask <<= (63 - bitno);
303b7def2222c08b119df85bc7231bf0e6806f3a1a6florian
304b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   if (value == 1) {
305b7def2222c08b119df85bc7231bf0e6806f3a1a6florian      *addr |= mask;   // set
306b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   } else {
307b7def2222c08b119df85bc7231bf0e6806f3a1a6florian      *addr &= ~mask;  // clear
308b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   }
309b7def2222c08b119df85bc7231bf0e6806f3a1a6florian}
310b7def2222c08b119df85bc7231bf0e6806f3a1a6florian
311933065d4f3548466da4666c5cfda7e5eaff93759florianULong
312ae88411aaa8e0b99032fb0bdb04eec21edc54d88florians390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, ULong *addr)
313933065d4f3548466da4666c5cfda7e5eaff93759florian{
314933065d4f3548466da4666c5cfda7e5eaff93759florian   ULong hoststfle[S390_NUM_FACILITY_DW], cc, num_dw, i;
315933065d4f3548466da4666c5cfda7e5eaff93759florian   register ULong reg0 asm("0") = guest_state->guest_r0 & 0xF;  /* r0[56:63] */
316933065d4f3548466da4666c5cfda7e5eaff93759florian
317933065d4f3548466da4666c5cfda7e5eaff93759florian   /* We cannot store more than S390_NUM_FACILITY_DW
318933065d4f3548466da4666c5cfda7e5eaff93759florian      (and it makes not much sense to do so anyhow) */
319933065d4f3548466da4666c5cfda7e5eaff93759florian   if (reg0 > S390_NUM_FACILITY_DW - 1)
320933065d4f3548466da4666c5cfda7e5eaff93759florian      reg0 = S390_NUM_FACILITY_DW - 1;
321933065d4f3548466da4666c5cfda7e5eaff93759florian
322933065d4f3548466da4666c5cfda7e5eaff93759florian   num_dw = reg0 + 1;  /* number of double words written */
323933065d4f3548466da4666c5cfda7e5eaff93759florian
324933065d4f3548466da4666c5cfda7e5eaff93759florian   asm volatile(" .insn s,0xb2b00000,%0\n"   /* stfle */
325933065d4f3548466da4666c5cfda7e5eaff93759florian                "ipm    %2\n"
326933065d4f3548466da4666c5cfda7e5eaff93759florian                "srl    %2,28\n"
327933065d4f3548466da4666c5cfda7e5eaff93759florian                : "=m" (hoststfle), "+d"(reg0), "=d"(cc) : : "cc", "memory");
328933065d4f3548466da4666c5cfda7e5eaff93759florian
329933065d4f3548466da4666c5cfda7e5eaff93759florian   /* Update guest register 0  with what STFLE set r0 to */
330933065d4f3548466da4666c5cfda7e5eaff93759florian   guest_state->guest_r0 = reg0;
331933065d4f3548466da4666c5cfda7e5eaff93759florian
332b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   /* Set default: VM facilities = host facilities */
333933065d4f3548466da4666c5cfda7e5eaff93759florian   for (i = 0; i < num_dw; ++i)
334ae88411aaa8e0b99032fb0bdb04eec21edc54d88florian      addr[i] = hoststfle[i];
335933065d4f3548466da4666c5cfda7e5eaff93759florian
336b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   /* Now adjust the VM facilities according to what the VM supports */
337b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_LDISP,  1);
338b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_EIMM,   1);
339b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_ETF2,   1);
340b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_ETF3,   1);
341b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_GIE,    1);
342b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_EXEXT,  1);
343b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_HIGHW,  1);
344b7def2222c08b119df85bc7231bf0e6806f3a1a6florian
345b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_HFPMAS, 0);
346b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_HFPUNX, 0);
347b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_XCPUT,  0);
348b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_MSA,    0);
349b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_PENH,   0);
350b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_DFP,    0);
351b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_PFPO,   0);
352b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_DFPZC,  0);
353b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_MISC,   0);
354b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_CTREXE, 0);
355b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_TREXE,  0);
356b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_MSA4,   0);
357b7def2222c08b119df85bc7231bf0e6806f3a1a6florian
358933065d4f3548466da4666c5cfda7e5eaff93759florian   return cc;
359933065d4f3548466da4666c5cfda7e5eaff93759florian}
360933065d4f3548466da4666c5cfda7e5eaff93759florian
361933065d4f3548466da4666c5cfda7e5eaff93759florian#else
362933065d4f3548466da4666c5cfda7e5eaff93759florian
363933065d4f3548466da4666c5cfda7e5eaff93759florianULong
364ae88411aaa8e0b99032fb0bdb04eec21edc54d88florians390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, ULong *addr)
365933065d4f3548466da4666c5cfda7e5eaff93759florian{
366933065d4f3548466da4666c5cfda7e5eaff93759florian   return 3;
367933065d4f3548466da4666c5cfda7e5eaff93759florian}
368933065d4f3548466da4666c5cfda7e5eaff93759florian#endif /* VGA_s390x */
369933065d4f3548466da4666c5cfda7e5eaff93759florian
370a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian/*------------------------------------------------------------*/
371a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian/*--- Dirty helper for the "convert unicode" insn family.  ---*/
372a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian/*------------------------------------------------------------*/
373a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorianvoid
374a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorians390x_dirtyhelper_CUxy(UChar *address, ULong data, ULong num_bytes)
375a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian{
376a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   UInt i;
377a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
378a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   vassert(num_bytes >= 1 && num_bytes <= 4);
379a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
380a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   /* Store the least significant NUM_BYTES bytes in DATA left to right
381a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      at ADDRESS. */
382a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   for (i = 1; i <= num_bytes; ++i) {
383a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      address[num_bytes - i] = data & 0xff;
384a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      data >>= 8;
385a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   }
386a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian}
387a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
388a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
389a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian/*------------------------------------------------------------*/
390a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian/*--- Clean helper for CU21.                               ---*/
391a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian/*------------------------------------------------------------*/
392a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
393a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian/* The function performs a CU21 operation. It returns three things
394a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   encoded in an ULong value:
395a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   - the converted bytes (at most 4)
396a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   - the number of converted bytes
397a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   - an indication whether LOW_SURROGATE, if any, is invalid
398a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
399a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   64      48                16           8                       0
400a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian    +-------+-----------------+-----------+-----------------------+
401a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian    |  0x0  | converted bytes | num_bytes | invalid_low_surrogate |
402a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian    +-------+-----------------+-----------+-----------------------+
403a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian*/
404a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorianULong
405a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorians390_do_cu21(UInt srcval, UInt low_surrogate)
406a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian{
407a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   ULong retval = 0;   // shut up gcc
408ae88411aaa8e0b99032fb0bdb04eec21edc54d88florian   UInt b1, b2, b3, b4, num_bytes, invalid_low_surrogate = 0;
409a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
410a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   srcval &= 0xffff;
411a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
412a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   /* Determine the number of bytes in the converted value */
413a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   if (srcval <= 0x007f)
414a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      num_bytes = 1;
415a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   else if (srcval >= 0x0080 && srcval <= 0x07ff)
416a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      num_bytes = 2;
417a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   else if ((srcval >= 0x0800 && srcval <= 0xd7ff) ||
418a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian            (srcval >= 0xdc00 && srcval <= 0xffff))
419a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      num_bytes = 3;
420a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   else
421a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      num_bytes = 4;
422a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
423a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   /* Determine UTF-8 bytes according to calculated num_bytes */
424a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   switch (num_bytes){
425a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   case 1:
426a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      retval = srcval;
427a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      break;
428a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
429a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   case 2:
430a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      /* order of bytes left to right: b1, b2 */
431a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b1  = 0xc0;
432a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b1 |= srcval >> 6;
433a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
434a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b2  = 0x80;
435a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b2 |= srcval & 0x3f;
436a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
437a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      retval = (b1 << 8) | b2;
438a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      break;
439a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
440a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   case 3:
441a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      /* order of bytes left to right: b1, b2, b3 */
442a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b1  = 0xe0;
443a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b1 |= srcval >> 12;
444a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
445a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b2  = 0x80;
446a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b2 |= (srcval >> 6) & 0x3f;
447a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
448a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b3  = 0x80;
449a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b3 |= srcval & 0x3f;
450a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
451a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      retval = (b1 << 16) | (b2 << 8) | b3;
452a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      break;
453a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
454a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   case 4: {
455a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      /* order of bytes left to right: b1, b2, b3, b4 */
456a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      UInt high_surrogate = srcval;
457a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      UInt uvwxy = ((high_surrogate >> 6) & 0xf) + 1;   // abcd + 1
458a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
459a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b1  = 0xf0;
460a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b1 |= uvwxy >> 2;     // uvw
461a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
462a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b2  = 0x80;
463a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b2 |= (uvwxy & 0x3) << 4;           // xy
464a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b2 |= (high_surrogate >> 2) & 0xf;  // efgh
465a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
466a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b3  = 0x80;
467a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b3 |= (high_surrogate & 0x3) << 4;   // ij
468a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b3 |= (low_surrogate >> 6) & 0xf;    // klmn
469a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
470a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b4  = 0x80;
471a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b4 |= low_surrogate & 0x3f;
472a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
473a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      retval = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
474a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
475a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      invalid_low_surrogate = (low_surrogate & 0xfc00) != 0xdc00;
476a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      break;
477a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   }
478a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   }
479a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
480a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   /* At this point RETVAL contains the converted bytes.
481a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      Build up the final return value. */
482a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   return (retval << 16) | (num_bytes << 8) | invalid_low_surrogate;
483a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian}
484a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
485e711c805f1de40b8fafce36d04e589c6a5074e9aflorian
486e711c805f1de40b8fafce36d04e589c6a5074e9aflorian/*------------------------------------------------------------*/
4872a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian/*--- Clean helper for CU24.                               ---*/
4882a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian/*------------------------------------------------------------*/
4892a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian
4902a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian/* The function performs a CU24 operation. It returns two things
4912a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian   encoded in an ULong value:
4922a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian   - the 4 converted bytes
4932a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian   - an indication whether LOW_SURROGATE, if any, is invalid
4942a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian
4952a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian   64     40                 8                       0
4962a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian    +------------------------+-----------------------+
4972a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian    |  0x0 | converted bytes | invalid_low_surrogate |
4982a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian    +------------------------+-----------------------+
4992a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian*/
5002a415a1a1f656e56f88c65f12a37b2658cb45e0bflorianULong
5012a415a1a1f656e56f88c65f12a37b2658cb45e0bflorians390_do_cu24(UInt srcval, UInt low_surrogate)
5022a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian{
5032a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian   ULong retval;
5042a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian   UInt invalid_low_surrogate = 0;
5052a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian
5062a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian   srcval &= 0xffff;
5072a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian
5082a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian   if ((srcval >= 0x0000 && srcval <= 0xd7ff) ||
5092a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian       (srcval >= 0xdc00 && srcval <= 0xffff)) {
5102a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian      retval = srcval;
5112a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian   } else {
5122a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian      /* D800 - DBFF */
5132a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian      UInt high_surrogate = srcval;
5142a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian      UInt uvwxy  = ((high_surrogate >> 6) & 0xf) + 1;   // abcd + 1
5152a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian      UInt efghij = high_surrogate & 0x3f;
5162a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian      UInt klmnoprst = low_surrogate & 0x3ff;
5172a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian
5182a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian      retval = (uvwxy << 16) | (efghij << 10) | klmnoprst;
5192a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian
5202a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian      invalid_low_surrogate = (low_surrogate & 0xfc00) != 0xdc00;
5212a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian   }
5222a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian
5232a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian   /* At this point RETVAL contains the converted bytes.
5242a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian      Build up the final return value. */
5252a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian   return (retval << 8) | invalid_low_surrogate;
5262a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian}
5272a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian
5282a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian
5292a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian/*------------------------------------------------------------*/
530956194bc1039e9dc43dac4b18ab1fdd5054a5671florian/*--- Clean helper for CU42.                               ---*/
531956194bc1039e9dc43dac4b18ab1fdd5054a5671florian/*------------------------------------------------------------*/
532956194bc1039e9dc43dac4b18ab1fdd5054a5671florian
533956194bc1039e9dc43dac4b18ab1fdd5054a5671florian/* The function performs a CU42 operation. It returns three things
534956194bc1039e9dc43dac4b18ab1fdd5054a5671florian   encoded in an ULong value:
535956194bc1039e9dc43dac4b18ab1fdd5054a5671florian   - the converted bytes (at most 4)
536956194bc1039e9dc43dac4b18ab1fdd5054a5671florian   - the number of converted bytes (2 or 4; 0 if invalid character)
537956194bc1039e9dc43dac4b18ab1fdd5054a5671florian   - an indication whether the UTF-32 character is invalid
538956194bc1039e9dc43dac4b18ab1fdd5054a5671florian
539956194bc1039e9dc43dac4b18ab1fdd5054a5671florian   64      48                16           8                   0
540956194bc1039e9dc43dac4b18ab1fdd5054a5671florian    +-------+-----------------+-----------+-------------------+
541956194bc1039e9dc43dac4b18ab1fdd5054a5671florian    |  0x0  | converted bytes | num_bytes | invalid_character |
542956194bc1039e9dc43dac4b18ab1fdd5054a5671florian    +-------+-----------------+-----------+-------------------+
543956194bc1039e9dc43dac4b18ab1fdd5054a5671florian*/
544956194bc1039e9dc43dac4b18ab1fdd5054a5671florianULong
545956194bc1039e9dc43dac4b18ab1fdd5054a5671florians390_do_cu42(UInt srcval)
546956194bc1039e9dc43dac4b18ab1fdd5054a5671florian{
547956194bc1039e9dc43dac4b18ab1fdd5054a5671florian   ULong retval;
548956194bc1039e9dc43dac4b18ab1fdd5054a5671florian   UInt num_bytes, invalid_character = 0;
549956194bc1039e9dc43dac4b18ab1fdd5054a5671florian
550956194bc1039e9dc43dac4b18ab1fdd5054a5671florian   if ((srcval >= 0x0000 && srcval <= 0xd7ff) ||
551956194bc1039e9dc43dac4b18ab1fdd5054a5671florian       (srcval >= 0xdc00 && srcval <= 0xffff)) {
552956194bc1039e9dc43dac4b18ab1fdd5054a5671florian      retval = srcval;
553956194bc1039e9dc43dac4b18ab1fdd5054a5671florian      num_bytes = 2;
554956194bc1039e9dc43dac4b18ab1fdd5054a5671florian   } else if (srcval >= 0x00010000 && srcval <= 0x0010FFFF) {
555956194bc1039e9dc43dac4b18ab1fdd5054a5671florian      UInt uvwxy  = srcval >> 16;
556956194bc1039e9dc43dac4b18ab1fdd5054a5671florian      UInt abcd   = (uvwxy - 1) & 0xf;
557956194bc1039e9dc43dac4b18ab1fdd5054a5671florian      UInt efghij = (srcval >> 10) & 0x3f;
558956194bc1039e9dc43dac4b18ab1fdd5054a5671florian
559956194bc1039e9dc43dac4b18ab1fdd5054a5671florian      UInt high_surrogate = (0xd8 << 8) | (abcd << 6) | efghij;
560956194bc1039e9dc43dac4b18ab1fdd5054a5671florian      UInt low_surrogate  = (0xdc << 8) | (srcval & 0x3ff);
561956194bc1039e9dc43dac4b18ab1fdd5054a5671florian
562956194bc1039e9dc43dac4b18ab1fdd5054a5671florian      retval = (high_surrogate << 16) | low_surrogate;
563956194bc1039e9dc43dac4b18ab1fdd5054a5671florian      num_bytes = 4;
564956194bc1039e9dc43dac4b18ab1fdd5054a5671florian   } else {
565956194bc1039e9dc43dac4b18ab1fdd5054a5671florian      /* D800 - DBFF or 00110000 - FFFFFFFF */
566956194bc1039e9dc43dac4b18ab1fdd5054a5671florian      invalid_character = 1;
567956194bc1039e9dc43dac4b18ab1fdd5054a5671florian      retval = num_bytes = 0;   /* does not matter; not used */
568956194bc1039e9dc43dac4b18ab1fdd5054a5671florian   }
569956194bc1039e9dc43dac4b18ab1fdd5054a5671florian
570956194bc1039e9dc43dac4b18ab1fdd5054a5671florian   /* At this point RETVAL contains the converted bytes.
571956194bc1039e9dc43dac4b18ab1fdd5054a5671florian      Build up the final return value. */
572956194bc1039e9dc43dac4b18ab1fdd5054a5671florian   return (retval << 16) | (num_bytes << 8) | invalid_character;
573956194bc1039e9dc43dac4b18ab1fdd5054a5671florian}
574956194bc1039e9dc43dac4b18ab1fdd5054a5671florian
575956194bc1039e9dc43dac4b18ab1fdd5054a5671florian
576956194bc1039e9dc43dac4b18ab1fdd5054a5671florian/*------------------------------------------------------------*/
577af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian/*--- Clean helper for CU41.                               ---*/
578af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian/*------------------------------------------------------------*/
579af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian
580af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian/* The function performs a CU41 operation. It returns three things
581af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   encoded in an ULong value:
582af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   - the converted bytes (at most 4)
583af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   - the number of converted bytes (1, 2, 3, or 4; 0 if invalid character)
584af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   - an indication whether the UTF-32 character is invalid
585af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian
586af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   64      48                16           8                   0
587af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian    +-------+-----------------+-----------+-------------------+
588af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian    |  0x0  | converted bytes | num_bytes | invalid_character |
589af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian    +-------+-----------------+-----------+-------------------+
590af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian*/
591af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florianULong
592af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florians390_do_cu41(UInt srcval)
593af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian{
594af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   ULong retval;
595af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   UInt num_bytes, invalid_character = 0;
596af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian
597af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   if (srcval <= 0x7f) {
598af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      retval = srcval;
599af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      num_bytes = 1;
600af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   } else if (srcval >= 0x80 && srcval <= 0x7ff) {
601af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt fghij  = srcval >> 6;
602af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt klmnop = srcval & 0x3f;
603af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt byte1  = (0xc0 | fghij);
604af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt byte2  = (0x80 | klmnop);
605af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian
606af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      retval = (byte1 << 8) | byte2;
607af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      num_bytes = 2;
608af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   } else if ((srcval >= 0x800  && srcval <= 0xd7ff) ||
609af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian              (srcval >= 0xdc00 && srcval <= 0xffff)) {
610af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt abcd   = srcval >> 12;
611af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt efghij = (srcval >> 6) & 0x3f;
612af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt klmnop = srcval & 0x3f;
613af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt byte1  = 0xe0 | abcd;
614af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt byte2  = 0x80 | efghij;
615af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt byte3  = 0x80 | klmnop;
616af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian
617af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      retval = (byte1 << 16) | (byte2 << 8) | byte3;
618af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      num_bytes = 3;
619af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   } else if (srcval >= 0x10000 && srcval <= 0x10ffff) {
620af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt uvw    = (srcval >> 18) & 0x7;
621af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt xy     = (srcval >> 16) & 0x3;
622af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt efgh   = (srcval >> 12) & 0xf;
623af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt ijklmn = (srcval >>  6) & 0x3f;
624af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt opqrst = srcval & 0x3f;
625af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt byte1  = 0xf0 | uvw;
626af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt byte2  = 0x80 | (xy << 4) | efgh;
627af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt byte3  = 0x80 | ijklmn;
628af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt byte4  = 0x80 | opqrst;
629af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian
630af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      retval = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
631af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      num_bytes = 4;
632af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   } else {
633af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      /* d800 ... dbff or 00110000 ... ffffffff */
634af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      invalid_character = 1;
635af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian
636af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      retval = 0;
637af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      num_bytes = 0;
638af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   }
639af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian
640af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   /* At this point RETVAL contains the converted bytes.
641af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      Build up the final return value. */
642af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   return (retval << 16) | (num_bytes << 8) | invalid_character;
643af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian}
644af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian
645af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian
646af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian/*------------------------------------------------------------*/
6476d9b9b23ea3541501ea98a39e2d757892a79c78aflorian/*--- Clean helpers for CU12.                              ---*/
6486d9b9b23ea3541501ea98a39e2d757892a79c78aflorian/*------------------------------------------------------------*/
6496d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
6506d9b9b23ea3541501ea98a39e2d757892a79c78aflorian/* The function looks at the first byte of an UTF-8 character and returns
6516d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   two things encoded in an ULong value:
6526d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
6536d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   - the number of bytes that need to be read
6546d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   - an indication whether the UTF-8 character is invalid
6556d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
6566d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   64      16           8                   0
6576d9b9b23ea3541501ea98a39e2d757892a79c78aflorian    +-------------------+-------------------+
6586d9b9b23ea3541501ea98a39e2d757892a79c78aflorian    |  0x0  | num_bytes | invalid_character |
6596d9b9b23ea3541501ea98a39e2d757892a79c78aflorian    +-------+-----------+-------------------+
6606d9b9b23ea3541501ea98a39e2d757892a79c78aflorian*/
6616d9b9b23ea3541501ea98a39e2d757892a79c78aflorianULong
6623f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florians390_do_cu12_cu14_helper1(UInt byte, UInt etf3_and_m3_is_1)
6636d9b9b23ea3541501ea98a39e2d757892a79c78aflorian{
6646d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   vassert(byte <= 0xff);
6656d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
6666d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   /* Check whether the character is invalid */
6676d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   if (byte >= 0x80 && byte <= 0xbf) return 1;
6686d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   if (byte >= 0xf8) return 1;
6696d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
6706d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   if (etf3_and_m3_is_1) {
6716d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      if (byte == 0xc0 || byte == 0xc1) return 1;
6726d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      if (byte >= 0xf5 && byte <= 0xf7) return 1;
6736d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   }
6746d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
6756d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   /* Character is valid */
6766d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   if (byte <= 0x7f) return 1 << 8;   // 1 byte
6776d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   if (byte <= 0xdf) return 2 << 8;   // 2 bytes
6786d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   if (byte <= 0xef) return 3 << 8;   // 3 bytes
6796d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
6806d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   return 4 << 8;  // 4 bytes
6816d9b9b23ea3541501ea98a39e2d757892a79c78aflorian}
6826d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
6833f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian/* The function performs a CU12 or CU14 operation. BYTE1, BYTE2, etc are the
6846d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   bytes as read from the input stream, left to right. BYTE1 is a valid
6856d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   byte. The function returns three things encoded in an ULong value:
6866d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
6876d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   - the converted bytes
6886d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   - the number of converted bytes (2 or 4; 0 if invalid character)
6896d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   - an indication whether the UTF-16 character is invalid
6906d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
6916d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   64      48                16           8                   0
6926d9b9b23ea3541501ea98a39e2d757892a79c78aflorian    +-------+-----------------+-----------+-------------------+
6936d9b9b23ea3541501ea98a39e2d757892a79c78aflorian    |  0x0  | converted bytes | num_bytes | invalid_character |
6946d9b9b23ea3541501ea98a39e2d757892a79c78aflorian    +-------+-----------------+-----------+-------------------+
6956d9b9b23ea3541501ea98a39e2d757892a79c78aflorian*/
6963f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florianstatic ULong
6973f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florians390_do_cu12_cu14_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4,
6983f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian                          ULong stuff, Bool is_cu12)
6996d9b9b23ea3541501ea98a39e2d757892a79c78aflorian{
7003f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian   UInt num_src_bytes = stuff >> 1, etf3_and_m3_is_1 = stuff & 0x1;
7016d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   UInt num_bytes = 0, invalid_character = 0;
7026d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   ULong retval = 0;
7036d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
7046d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   vassert(num_src_bytes <= 4);
7056d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
7066d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   switch (num_src_bytes) {
7076d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   case 1:
7086d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      num_bytes = 2;
7096d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      retval = byte1;
7106d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      break;
7116d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
7126d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   case 2: {
7136d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      /* Test validity */
7146d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      if (etf3_and_m3_is_1) {
7156d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         if (byte2 < 0x80 || byte2 > 0xbf) {
7166d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            invalid_character = 1;
7176d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            break;
7186d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         }
7196d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      }
7206d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
7216d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      /* OK */
7226d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      UInt fghij  = byte1 & 0x1f;
7236d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      UInt klmnop = byte2 & 0x3f;
7246d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
7256d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      num_bytes = 2;
7266d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      retval = (fghij << 6) | klmnop;
7276d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      break;
7286d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   }
7296d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
7306d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   case 3: {
7316d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      /* Test validity */
7326d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      if (etf3_and_m3_is_1) {
7336d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         if (byte1 == 0xe0) {
7346d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            if ((byte2 < 0xa0 || byte2 > 0xbf) ||
7356d9b9b23ea3541501ea98a39e2d757892a79c78aflorian                (byte3 < 0x80 || byte3 > 0xbf)) {
7366d9b9b23ea3541501ea98a39e2d757892a79c78aflorian               invalid_character = 1;
7376d9b9b23ea3541501ea98a39e2d757892a79c78aflorian               break;
7386d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            }
7396d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         }
7406d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         if ((byte1 >= 0xe1 && byte1 <= 0xec) ||
7416d9b9b23ea3541501ea98a39e2d757892a79c78aflorian             byte1 == 0xee || byte1 == 0xef) {
7426d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            if ((byte2 < 0x80 || byte2 > 0xbf) ||
7436d9b9b23ea3541501ea98a39e2d757892a79c78aflorian                (byte3 < 0x80 || byte3 > 0xbf)) {
7446d9b9b23ea3541501ea98a39e2d757892a79c78aflorian               invalid_character = 1;
7456d9b9b23ea3541501ea98a39e2d757892a79c78aflorian               break;
7466d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            }
7476d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         }
7486d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         if (byte1 == 0xed) {
7496d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            if ((byte2 < 0x80 || byte2 > 0x9f) ||
7506d9b9b23ea3541501ea98a39e2d757892a79c78aflorian                (byte3 < 0x80 || byte3 > 0xbf)) {
7516d9b9b23ea3541501ea98a39e2d757892a79c78aflorian               invalid_character = 1;
7526d9b9b23ea3541501ea98a39e2d757892a79c78aflorian               break;
7536d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            }
7546d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         }
7556d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      }
7566d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
7576d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      /* OK */
7586d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      UInt abcd   = byte1 & 0xf;
7596d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      UInt efghij = byte2 & 0x3f;
7606d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      UInt klmnop = byte3 & 0x3f;
7616d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
7626d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      num_bytes = 2;
7636d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      retval = (abcd << 12) | (efghij << 6) | klmnop;
7646d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      break;
7656d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   }
7666d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
7676d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   case 4: {
7686d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      /* Test validity */
7696d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      if (etf3_and_m3_is_1) {
7706d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         if (byte1 == 0xf0) {
7716d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            if ((byte2 < 0x90 || byte2 > 0xbf) ||
7726d9b9b23ea3541501ea98a39e2d757892a79c78aflorian                (byte3 < 0x80 || byte3 > 0xbf) ||
7736d9b9b23ea3541501ea98a39e2d757892a79c78aflorian                (byte4 < 0x80 || byte4 > 0xbf)) {
7746d9b9b23ea3541501ea98a39e2d757892a79c78aflorian               invalid_character = 1;
7756d9b9b23ea3541501ea98a39e2d757892a79c78aflorian               break;
7766d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            }
7776d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         }
7786d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         if (byte1 == 0xf1 || byte1 == 0xf2 || byte1 == 0xf3) {
7796d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            if ((byte2 < 0x80 || byte2 > 0xbf) ||
7806d9b9b23ea3541501ea98a39e2d757892a79c78aflorian                (byte3 < 0x80 || byte3 > 0xbf) ||
7816d9b9b23ea3541501ea98a39e2d757892a79c78aflorian                (byte4 < 0x80 || byte4 > 0xbf)) {
7826d9b9b23ea3541501ea98a39e2d757892a79c78aflorian               invalid_character = 1;
7836d9b9b23ea3541501ea98a39e2d757892a79c78aflorian               break;
7846d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            }
7856d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         }
7866d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         if (byte1 == 0xf4) {
7876d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            if ((byte2 < 0x80 || byte2 > 0x8f) ||
7886d9b9b23ea3541501ea98a39e2d757892a79c78aflorian                (byte3 < 0x80 || byte3 > 0xbf) ||
7896d9b9b23ea3541501ea98a39e2d757892a79c78aflorian                (byte4 < 0x80 || byte4 > 0xbf)) {
7906d9b9b23ea3541501ea98a39e2d757892a79c78aflorian               invalid_character = 1;
7916d9b9b23ea3541501ea98a39e2d757892a79c78aflorian               break;
7926d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            }
7936d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         }
7946d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      }
7956d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
7966d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      /* OK */
7976d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      UInt uvw    = byte1 & 0x7;
7986d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      UInt xy     = (byte2 >> 4) & 0x3;
7996d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      UInt uvwxy  = (uvw << 2) | xy;
8006d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      UInt efgh   = byte2 & 0xf;
8016d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      UInt ij     = (byte3 >> 4) & 0x3;
8026d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      UInt klmn   = byte3 & 0xf;
8036d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      UInt opqrst = byte4 & 0x3f;
8046d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
8053f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian      if (is_cu12) {
8063f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian         UInt abcd = (uvwxy - 1) & 0xf;
8073f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian         UInt high_surrogate = (0xd8 << 8) | (abcd << 6) | (efgh << 2) | ij;
8083f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian         UInt low_surrogate  = (0xdc << 8) | (klmn << 6) | opqrst;
8093f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian
8103f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian         num_bytes = 4;
8113f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian         retval = (high_surrogate << 16) | low_surrogate;
8123f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian      } else {
8133f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian         num_bytes = 4;
8143f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian         retval =
8153f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian            (uvwxy << 16) | (efgh << 12) | (ij << 10) | (klmn << 6) | opqrst;
8163f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian      }
8176d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      break;
8186d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   }
8196d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   }
8206d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
8213f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian   if (! is_cu12) num_bytes = 4;   // for CU14, by definition
8223f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian
8236d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   /* At this point RETVAL contains the converted bytes.
8246d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      Build up the final return value. */
8256d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   return (retval << 16) | (num_bytes << 8) | invalid_character;
8266d9b9b23ea3541501ea98a39e2d757892a79c78aflorian}
8276d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
8283f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florianULong
8293f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florians390_do_cu12_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4,
8303f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian                     ULong stuff)
8313f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian{
8323f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian   return s390_do_cu12_cu14_helper2(byte1, byte2, byte3, byte4, stuff,
8333f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian                                    /* is_cu12 = */ 1);
8343f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian}
8353f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian
8363f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florianULong
8373f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florians390_do_cu14_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4,
8383f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian                     ULong stuff)
8393f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian{
8403f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian   return s390_do_cu12_cu14_helper2(byte1, byte2, byte3, byte4, stuff,
8413f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian                                    /* is_cu12 = */ 0);
8423f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian}
8433f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian
8446d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
8456d9b9b23ea3541501ea98a39e2d757892a79c78aflorian/*------------------------------------------------------------*/
846e711c805f1de40b8fafce36d04e589c6a5074e9aflorian/*--- Clean helper for "convert to binary".                ---*/
847e711c805f1de40b8fafce36d04e589c6a5074e9aflorian/*------------------------------------------------------------*/
848e711c805f1de40b8fafce36d04e589c6a5074e9aflorian#if defined(VGA_s390x)
849e711c805f1de40b8fafce36d04e589c6a5074e9aflorianUInt
850e711c805f1de40b8fafce36d04e589c6a5074e9aflorians390_do_cvb(ULong decimal)
851e711c805f1de40b8fafce36d04e589c6a5074e9aflorian{
852e711c805f1de40b8fafce36d04e589c6a5074e9aflorian   UInt binary;
853e711c805f1de40b8fafce36d04e589c6a5074e9aflorian
854e711c805f1de40b8fafce36d04e589c6a5074e9aflorian   __asm__ volatile (
855e711c805f1de40b8fafce36d04e589c6a5074e9aflorian        "cvb %[result],%[input]\n\t"
856e711c805f1de40b8fafce36d04e589c6a5074e9aflorian          : [result] "=d"(binary)
857e711c805f1de40b8fafce36d04e589c6a5074e9aflorian          : [input] "m"(decimal)
858e711c805f1de40b8fafce36d04e589c6a5074e9aflorian   );
859e711c805f1de40b8fafce36d04e589c6a5074e9aflorian
860e711c805f1de40b8fafce36d04e589c6a5074e9aflorian   return binary;
861e711c805f1de40b8fafce36d04e589c6a5074e9aflorian}
862e711c805f1de40b8fafce36d04e589c6a5074e9aflorian
863e711c805f1de40b8fafce36d04e589c6a5074e9aflorian#else
864e711c805f1de40b8fafce36d04e589c6a5074e9aflorianUInt s390_do_cvb(ULong decimal) { return 0; }
865e711c805f1de40b8fafce36d04e589c6a5074e9aflorian#endif
866e711c805f1de40b8fafce36d04e589c6a5074e9aflorian
867e711c805f1de40b8fafce36d04e589c6a5074e9aflorian
868e711c805f1de40b8fafce36d04e589c6a5074e9aflorian/*------------------------------------------------------------*/
869e711c805f1de40b8fafce36d04e589c6a5074e9aflorian/*--- Clean helper for "convert to decimal".                ---*/
870e711c805f1de40b8fafce36d04e589c6a5074e9aflorian/*------------------------------------------------------------*/
871e711c805f1de40b8fafce36d04e589c6a5074e9aflorian#if defined(VGA_s390x)
872e711c805f1de40b8fafce36d04e589c6a5074e9aflorianULong
873e711c805f1de40b8fafce36d04e589c6a5074e9aflorians390_do_cvd(ULong binary_in)
874e711c805f1de40b8fafce36d04e589c6a5074e9aflorian{
875e711c805f1de40b8fafce36d04e589c6a5074e9aflorian   UInt binary = binary_in & 0xffffffffULL;
876e711c805f1de40b8fafce36d04e589c6a5074e9aflorian   ULong decimal;
877e711c805f1de40b8fafce36d04e589c6a5074e9aflorian
878e711c805f1de40b8fafce36d04e589c6a5074e9aflorian   __asm__ volatile (
879e711c805f1de40b8fafce36d04e589c6a5074e9aflorian        "cvd %[input],%[result]\n\t"
880e711c805f1de40b8fafce36d04e589c6a5074e9aflorian          : [result] "=m"(decimal)
881e711c805f1de40b8fafce36d04e589c6a5074e9aflorian          : [input] "d"(binary)
882e711c805f1de40b8fafce36d04e589c6a5074e9aflorian   );
883e711c805f1de40b8fafce36d04e589c6a5074e9aflorian
884e711c805f1de40b8fafce36d04e589c6a5074e9aflorian   return decimal;
885e711c805f1de40b8fafce36d04e589c6a5074e9aflorian}
886e711c805f1de40b8fafce36d04e589c6a5074e9aflorian
887e711c805f1de40b8fafce36d04e589c6a5074e9aflorian#else
888e711c805f1de40b8fafce36d04e589c6a5074e9aflorianULong s390_do_cvd(ULong binary) { return 0; }
889e711c805f1de40b8fafce36d04e589c6a5074e9aflorian#endif
890e711c805f1de40b8fafce36d04e589c6a5074e9aflorian
8918c88cb6ae821021e1e00be18f5a8bea3c557080aflorian/*------------------------------------------------------------*/
8928c88cb6ae821021e1e00be18f5a8bea3c557080aflorian/*--- Clean helper for "Extract cache attribute".          ---*/
8938c88cb6ae821021e1e00be18f5a8bea3c557080aflorian/*------------------------------------------------------------*/
8948c88cb6ae821021e1e00be18f5a8bea3c557080aflorian#if defined(VGA_s390x)
8958c88cb6ae821021e1e00be18f5a8bea3c557080aflorianULong
8968c88cb6ae821021e1e00be18f5a8bea3c557080aflorians390_do_ecag(ULong op2addr)
8978c88cb6ae821021e1e00be18f5a8bea3c557080aflorian{
8988c88cb6ae821021e1e00be18f5a8bea3c557080aflorian   ULong result;
8998c88cb6ae821021e1e00be18f5a8bea3c557080aflorian
9008c88cb6ae821021e1e00be18f5a8bea3c557080aflorian   __asm__ volatile(".insn rsy,0xEB000000004C,%[out],0,0(%[in])\n\t"
9018c88cb6ae821021e1e00be18f5a8bea3c557080aflorian                    : [out] "=d"(result)
9028c88cb6ae821021e1e00be18f5a8bea3c557080aflorian                    : [in] "d"(op2addr));
9038c88cb6ae821021e1e00be18f5a8bea3c557080aflorian   return result;
9048c88cb6ae821021e1e00be18f5a8bea3c557080aflorian}
9058c88cb6ae821021e1e00be18f5a8bea3c557080aflorian
9068c88cb6ae821021e1e00be18f5a8bea3c557080aflorian#else
9078c88cb6ae821021e1e00be18f5a8bea3c557080aflorianULong s390_do_ecag(ULong op2addr) { return 0; }
9088c88cb6ae821021e1e00be18f5a8bea3c557080aflorian#endif
909e711c805f1de40b8fafce36d04e589c6a5074e9aflorian
910933065d4f3548466da4666c5cfda7e5eaff93759florian/*------------------------------------------------------------*/
91178d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian/*--- Clean helper for "Perform Floating Point Operation". ---*/
91278d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian/*------------------------------------------------------------*/
91378d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian#if defined(VGA_s390x)
91478d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florianUInt
91578d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florians390_do_pfpo(UInt gpr0)
91678d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian{
91778d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian   UChar rm;
91878d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian   UChar op1_ty, op2_ty;
91978d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian
92078d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian   rm  = gpr0 & 0xf;
92178d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian   if (rm > 1 && rm < 8)
92278d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian      return EmFail_S390X_invalid_PFPO_rounding_mode;
92378d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian
92478d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian   op1_ty = (gpr0 >> 16) & 0xff; // gpr0[40:47]
92578d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian   op2_ty = (gpr0 >> 8)  & 0xff; // gpr0[48:55]
92678d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian   /* Operand type must be BFP 32, 64, 128 or DFP 32, 64, 128
92778d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian      which correspond to 0x5, 0x6, 0x7, 0x8, 0x9, 0xa respectively.
92878d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian      Any other operand type value is unsupported */
92978d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian   if ((op1_ty == op2_ty) ||
93078d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian       (op1_ty < 0x5 || op1_ty > 0xa) ||
93178d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian       (op2_ty < 0x5 || op2_ty > 0xa))
93278d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian      return EmFail_S390X_invalid_PFPO_function;
93378d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian
93478d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian   return EmNote_NONE;
93578d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian}
93678d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian#else
93778d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florianUInt s390_do_pfpo(UInt gpr0) { return 0; }
93878d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian#endif
93978d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian
94078d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian/*------------------------------------------------------------*/
9412019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*--- Helper for condition code.                           ---*/
9422019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*------------------------------------------------------------*/
9432019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
94483f60b5fac7ad065935f3c2fcf7b1454d552d6e0florian/* Convert an IRRoundingMode value to s390_bfp_round_t */
9453d80fade93ec633f3ad30f871d1a1306f75823c6florian#if defined(VGA_s390x)
946125e20dc4036944b19bed3e98a15d05cce8c29f6florianstatic s390_bfp_round_t
94719e0077d31fe17496eeb76cd008507d1a8f75908floriandecode_bfp_rounding_mode(UInt irrm)
94819e0077d31fe17496eeb76cd008507d1a8f75908florian{
94919e0077d31fe17496eeb76cd008507d1a8f75908florian   switch (irrm) {
950125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case Irrm_NEAREST: return S390_BFP_ROUND_NEAREST_EVEN;
951125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case Irrm_NegINF:  return S390_BFP_ROUND_NEGINF;
952125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case Irrm_PosINF:  return S390_BFP_ROUND_POSINF;
953125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case Irrm_ZERO:    return S390_BFP_ROUND_ZERO;
95419e0077d31fe17496eeb76cd008507d1a8f75908florian   }
95519e0077d31fe17496eeb76cd008507d1a8f75908florian   vpanic("decode_bfp_rounding_mode");
95619e0077d31fe17496eeb76cd008507d1a8f75908florian}
9573d80fade93ec633f3ad30f871d1a1306f75823c6florian#endif
95819e0077d31fe17496eeb76cd008507d1a8f75908florian
95919e0077d31fe17496eeb76cd008507d1a8f75908florian
9602019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#define S390_CC_FOR_BINARY(opcode,cc_dep1,cc_dep2) \
9612019a976f07ff418dde2dfc7cc74667ef66d7764sewardj({ \
9622019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   __asm__ volatile ( \
9632019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        opcode " %[op1],%[op2]\n\t" \
9642019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+d"(cc_dep1) \
9652019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : [op2] "d"(cc_dep2) \
9662019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : "cc");\
9672019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   psw >> 28;   /* cc */ \
9682019a976f07ff418dde2dfc7cc74667ef66d7764sewardj})
9692019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
9702019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#define S390_CC_FOR_TERNARY_SUBB(opcode,cc_dep1,cc_dep2,cc_ndep) \
9712019a976f07ff418dde2dfc7cc74667ef66d7764sewardj({ \
9722019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   /* Recover the original DEP2 value. See comment near s390_cc_thunk_put3 \
9732019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      for rationale. */ \
9742019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   cc_dep2 = cc_dep2 ^ cc_ndep; \
9752019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   __asm__ volatile ( \
9762019a976f07ff418dde2dfc7cc74667ef66d7764sewardj	"lghi 0,1\n\t" \
9772019a976f07ff418dde2dfc7cc74667ef66d7764sewardj	"sr 0,%[op3]\n\t" /* borrow to cc */ \
9782019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        opcode " %[op1],%[op2]\n\t" /* then redo the op */\
9792019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+&d"(cc_dep1) \
9802019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : [op2] "d"(cc_dep2), [op3] "d"(cc_ndep) \
9812019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : "0", "cc");\
9822019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   psw >> 28;   /* cc */ \
9832019a976f07ff418dde2dfc7cc74667ef66d7764sewardj})
9842019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
9852019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#define S390_CC_FOR_TERNARY_ADDC(opcode,cc_dep1,cc_dep2,cc_ndep) \
9862019a976f07ff418dde2dfc7cc74667ef66d7764sewardj({ \
9872019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   /* Recover the original DEP2 value. See comment near s390_cc_thunk_put3 \
9882019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      for rationale. */ \
9892019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   cc_dep2 = cc_dep2 ^ cc_ndep; \
9902019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   __asm__ volatile ( \
9912019a976f07ff418dde2dfc7cc74667ef66d7764sewardj	"lgfr 0,%[op3]\n\t" /* first load cc_ndep */ \
9922019a976f07ff418dde2dfc7cc74667ef66d7764sewardj	"aghi 0,0\n\t" /* and convert it into a cc */ \
9932019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        opcode " %[op1],%[op2]\n\t" /* then redo the op */\
9942019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+&d"(cc_dep1) \
9952019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : [op2] "d"(cc_dep2), [op3] "d"(cc_ndep) \
9962019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : "0", "cc");\
9972019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   psw >> 28;   /* cc */ \
9982019a976f07ff418dde2dfc7cc74667ef66d7764sewardj})
9992019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
10002019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
10012019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#define S390_CC_FOR_BFP_RESULT(opcode,cc_dep1) \
10022019a976f07ff418dde2dfc7cc74667ef66d7764sewardj({ \
10032019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   __asm__ volatile ( \
10042019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        opcode " 0,%[op]\n\t" \
10052019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
10062019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : [op]  "f"(cc_dep1) \
10072019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : "cc", "f0");\
10082019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   psw >> 28;   /* cc */ \
10092019a976f07ff418dde2dfc7cc74667ef66d7764sewardj})
10102019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
10112019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#define S390_CC_FOR_BFP128_RESULT(hi,lo) \
10122019a976f07ff418dde2dfc7cc74667ef66d7764sewardj({ \
10132019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   __asm__ volatile ( \
10142019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ldr   4,%[high]\n\t" \
10152019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ldr   6,%[low]\n\t" \
10162019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ltxbr 0,4\n\t" \
10172019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
10182019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : [high] "f"(hi), [low] "f"(lo) \
10192019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : "cc", "f0", "f2", "f4", "f6");\
10202019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   psw >> 28;   /* cc */ \
10212019a976f07ff418dde2dfc7cc74667ef66d7764sewardj})
10222019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
102319e0077d31fe17496eeb76cd008507d1a8f75908florian#define S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,rounding_mode) \
10242019a976f07ff418dde2dfc7cc74667ef66d7764sewardj({ \
10252019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   __asm__ volatile ( \
102619e0077d31fe17496eeb76cd008507d1a8f75908florian        opcode " 0," #rounding_mode ",%[op]\n\t" \
10272019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
10282019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : [op]  "f"(cc_dep1) \
10292019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : "cc", "r0");\
10302019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   psw >> 28;   /* cc */ \
10312019a976f07ff418dde2dfc7cc74667ef66d7764sewardj})
10322019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
103319e0077d31fe17496eeb76cd008507d1a8f75908florian#define S390_CC_FOR_BFP_CONVERT(opcode,cc_dep1,cc_dep2)   \
103419e0077d31fe17496eeb76cd008507d1a8f75908florian({                                                        \
103519e0077d31fe17496eeb76cd008507d1a8f75908florian   UInt cc;                                               \
103619e0077d31fe17496eeb76cd008507d1a8f75908florian   switch (decode_bfp_rounding_mode(cc_dep2)) {           \
1037125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_NEAREST_EVEN:                      \
103819e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,4); \
103919e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                              \
1040125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_ZERO:                              \
104119e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,5); \
104219e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                              \
1043125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_POSINF:                            \
104419e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,6); \
104519e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                              \
1046125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_NEGINF:                            \
104719e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,7); \
104819e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                              \
104919e0077d31fe17496eeb76cd008507d1a8f75908florian   default:                                               \
1050125e20dc4036944b19bed3e98a15d05cce8c29f6florian      vpanic("unexpected bfp rounding mode");             \
105119e0077d31fe17496eeb76cd008507d1a8f75908florian   }                                                      \
105219e0077d31fe17496eeb76cd008507d1a8f75908florian   cc;                                                    \
105319e0077d31fe17496eeb76cd008507d1a8f75908florian})
105419e0077d31fe17496eeb76cd008507d1a8f75908florian
105519e0077d31fe17496eeb76cd008507d1a8f75908florian#define S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,rounding_mode) \
10561c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian({ \
10571c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian   __asm__ volatile ( \
105819e0077d31fe17496eeb76cd008507d1a8f75908florian        opcode ",0,%[op]," #rounding_mode ",0\n\t" \
10591c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian        "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
10601c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian                                   : [op]  "f"(cc_dep1) \
10611c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian                                   : "cc", "r0");\
10621c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian   psw >> 28;   /* cc */ \
10631c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian})
10641c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian
106519e0077d31fe17496eeb76cd008507d1a8f75908florian#define S390_CC_FOR_BFP_UCONVERT(opcode,cc_dep1,cc_dep2)   \
106619e0077d31fe17496eeb76cd008507d1a8f75908florian({                                                         \
106719e0077d31fe17496eeb76cd008507d1a8f75908florian   UInt cc;                                                \
106819e0077d31fe17496eeb76cd008507d1a8f75908florian   switch (decode_bfp_rounding_mode(cc_dep2)) {            \
1069125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_NEAREST_EVEN:                       \
107019e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,4); \
107119e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                               \
1072125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_ZERO:                               \
107319e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,5); \
107419e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                               \
1075125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_POSINF:                             \
107619e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,6); \
107719e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                               \
1078125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_NEGINF:                             \
107919e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,7); \
108019e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                               \
108119e0077d31fe17496eeb76cd008507d1a8f75908florian   default:                                                \
1082125e20dc4036944b19bed3e98a15d05cce8c29f6florian      vpanic("unexpected bfp rounding mode");              \
108319e0077d31fe17496eeb76cd008507d1a8f75908florian   }                                                       \
108419e0077d31fe17496eeb76cd008507d1a8f75908florian   cc;                                                     \
108519e0077d31fe17496eeb76cd008507d1a8f75908florian})
108619e0077d31fe17496eeb76cd008507d1a8f75908florian
108719e0077d31fe17496eeb76cd008507d1a8f75908florian#define S390_CC_FOR_BFP128_CONVERT_AUX(opcode,hi,lo,rounding_mode) \
10882019a976f07ff418dde2dfc7cc74667ef66d7764sewardj({ \
10892019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   __asm__ volatile ( \
10902019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ldr   4,%[high]\n\t" \
10912019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ldr   6,%[low]\n\t" \
109219e0077d31fe17496eeb76cd008507d1a8f75908florian        opcode " 0," #rounding_mode ",4\n\t" \
10932019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
10942019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : [high] "f"(hi), [low] "f"(lo) \
10952019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : "cc", "r0", "f4", "f6");\
10962019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   psw >> 28;   /* cc */ \
10972019a976f07ff418dde2dfc7cc74667ef66d7764sewardj})
10982019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
109919e0077d31fe17496eeb76cd008507d1a8f75908florian#define S390_CC_FOR_BFP128_CONVERT(opcode,cc_dep1,cc_dep2,cc_ndep)   \
110019e0077d31fe17496eeb76cd008507d1a8f75908florian({                                                                   \
110119e0077d31fe17496eeb76cd008507d1a8f75908florian   UInt cc;                                                          \
110219e0077d31fe17496eeb76cd008507d1a8f75908florian   /* Recover the original DEP2 value. See comment near              \
110319e0077d31fe17496eeb76cd008507d1a8f75908florian      s390_cc_thunk_put3 for rationale. */                           \
110419e0077d31fe17496eeb76cd008507d1a8f75908florian   cc_dep2 = cc_dep2 ^ cc_ndep;                                      \
110519e0077d31fe17496eeb76cd008507d1a8f75908florian   switch (decode_bfp_rounding_mode(cc_ndep)) {                      \
1106125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_NEAREST_EVEN:                                 \
110719e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,4); \
110819e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                                         \
1109125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_ZERO:                                         \
111019e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,5); \
111119e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                                         \
1112125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_POSINF:                                       \
111319e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,6); \
111419e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                                         \
1115125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_NEGINF:                                       \
111619e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,7); \
111719e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                                         \
111819e0077d31fe17496eeb76cd008507d1a8f75908florian   default:                                                          \
1119125e20dc4036944b19bed3e98a15d05cce8c29f6florian      vpanic("unexpected bfp rounding mode");                        \
112019e0077d31fe17496eeb76cd008507d1a8f75908florian   }                                                                 \
112119e0077d31fe17496eeb76cd008507d1a8f75908florian   cc;                                                               \
112219e0077d31fe17496eeb76cd008507d1a8f75908florian})
112319e0077d31fe17496eeb76cd008507d1a8f75908florian
112419e0077d31fe17496eeb76cd008507d1a8f75908florian#define S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,hi,lo,rounding_mode) \
11251c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian({ \
11261c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian   __asm__ volatile ( \
11271c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian        "ldr   4,%[high]\n\t" \
11281c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian        "ldr   6,%[low]\n\t" \
112919e0077d31fe17496eeb76cd008507d1a8f75908florian        opcode ",0,4," #rounding_mode ",0\n\t" \
11301c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian        "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
11311c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian                                   : [high] "f"(hi), [low] "f"(lo) \
11321c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian                                   : "cc", "r0", "f4", "f6");\
11331c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian   psw >> 28;   /* cc */ \
11341c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian})
11351c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian
113619e0077d31fe17496eeb76cd008507d1a8f75908florian#define S390_CC_FOR_BFP128_UCONVERT(opcode,cc_dep1,cc_dep2,cc_ndep)   \
113719e0077d31fe17496eeb76cd008507d1a8f75908florian({                                                                    \
113819e0077d31fe17496eeb76cd008507d1a8f75908florian   UInt cc;                                                           \
113919e0077d31fe17496eeb76cd008507d1a8f75908florian   /* Recover the original DEP2 value. See comment near               \
114019e0077d31fe17496eeb76cd008507d1a8f75908florian      s390_cc_thunk_put3 for rationale. */                            \
114119e0077d31fe17496eeb76cd008507d1a8f75908florian   cc_dep2 = cc_dep2 ^ cc_ndep;                                       \
114219e0077d31fe17496eeb76cd008507d1a8f75908florian   switch (decode_bfp_rounding_mode(cc_ndep)) {                       \
1143125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_NEAREST_EVEN:                                  \
114419e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,4); \
114519e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                                          \
1146125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_ZERO:                                          \
114719e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,5); \
114819e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                                          \
1149125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_POSINF:                                        \
115019e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,6); \
115119e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                                          \
1152125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_NEGINF:                                        \
115319e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,7); \
115419e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                                          \
115519e0077d31fe17496eeb76cd008507d1a8f75908florian   default:                                                           \
1156125e20dc4036944b19bed3e98a15d05cce8c29f6florian      vpanic("unexpected bfp rounding mode");                         \
115719e0077d31fe17496eeb76cd008507d1a8f75908florian   }                                                                  \
115819e0077d31fe17496eeb76cd008507d1a8f75908florian   cc;                                                                \
115919e0077d31fe17496eeb76cd008507d1a8f75908florian})
116019e0077d31fe17496eeb76cd008507d1a8f75908florian
11612019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#define S390_CC_FOR_BFP_TDC(opcode,cc_dep1,cc_dep2) \
11622019a976f07ff418dde2dfc7cc74667ef66d7764sewardj({ \
11632019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   __asm__ volatile ( \
11642019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        opcode " %[value],0(%[class])\n\t" \
11652019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
11662019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : [value] "f"(cc_dep1), \
11672019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                     [class] "a"(cc_dep2)  \
11682019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : "cc");\
11692019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   psw >> 28;   /* cc */ \
11702019a976f07ff418dde2dfc7cc74667ef66d7764sewardj})
11712019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
11722019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#define S390_CC_FOR_BFP128_TDC(cc_dep1,cc_dep2,cc_ndep) \
11732019a976f07ff418dde2dfc7cc74667ef66d7764sewardj({ \
1174cf1527c8f8a8a647cae5ef21b6b126db9b81f622florian   /* Recover the original DEP2 value. See comment near \
1175cf1527c8f8a8a647cae5ef21b6b126db9b81f622florian      s390_cc_thunk_put1f128Z for rationale. */ \
11762019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   cc_dep2 = cc_dep2 ^ cc_ndep; \
11772019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   __asm__ volatile ( \
11782019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ldr  4,%[high]\n\t" \
11792019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ldr  6,%[low]\n\t" \
11802019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "tcxb 4,0(%[class])\n\t" \
11812019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ipm  %[psw]\n\t"          : [psw] "=d"(psw) \
11822019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : [high] "f"(cc_dep1), [low] "f"(cc_dep2), \
11832019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                     [class] "a"(cc_ndep)  \
11842019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : "cc", "f4", "f6");\
11852019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   psw >> 28;   /* cc */ \
11862019a976f07ff418dde2dfc7cc74667ef66d7764sewardj})
11872019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
118879e5a4845df6d09250b142c4e160a95cf7688fc8florian/* Convert an IRRoundingMode value to s390_dfp_round_t */
11895f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian#if defined(VGA_s390x)
11905f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florianstatic s390_dfp_round_t
11915f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3floriandecode_dfp_rounding_mode(UInt irrm)
11925f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian{
11935f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   switch (irrm) {
119479e5a4845df6d09250b142c4e160a95cf7688fc8florian   case Irrm_NEAREST:
11955f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_DFP_ROUND_NEAREST_EVEN_4;
119679e5a4845df6d09250b142c4e160a95cf7688fc8florian   case Irrm_NegINF:
11975f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_DFP_ROUND_NEGINF_7;
119879e5a4845df6d09250b142c4e160a95cf7688fc8florian   case Irrm_PosINF:
11995f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_DFP_ROUND_POSINF_6;
120079e5a4845df6d09250b142c4e160a95cf7688fc8florian   case Irrm_ZERO:
12015f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_DFP_ROUND_ZERO_5;
120279e5a4845df6d09250b142c4e160a95cf7688fc8florian   case Irrm_NEAREST_TIE_AWAY_0:
12035f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1;
120479e5a4845df6d09250b142c4e160a95cf7688fc8florian   case Irrm_PREPARE_SHORTER:
12055f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_DFP_ROUND_PREPARE_SHORT_3;
120679e5a4845df6d09250b142c4e160a95cf7688fc8florian   case Irrm_AWAY_FROM_ZERO:
12075f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_DFP_ROUND_AWAY_0;
120879e5a4845df6d09250b142c4e160a95cf7688fc8florian   case Irrm_NEAREST_TIE_TOWARD_0:
12095f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_DFP_ROUND_NEAREST_TIE_TOWARD_0;
12105f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   }
12115f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   vpanic("decode_dfp_rounding_mode");
12125f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian}
12135f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian#endif
12145f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
12151239020c948a6e20faaa8d0fa5dea44302e18f8aflorian#define S390_CC_FOR_DFP_RESULT(cc_dep1) \
12161239020c948a6e20faaa8d0fa5dea44302e18f8aflorian({ \
12171239020c948a6e20faaa8d0fa5dea44302e18f8aflorian   __asm__ volatile ( \
12181239020c948a6e20faaa8d0fa5dea44302e18f8aflorian        ".insn rre, 0xb3d60000,0,%[op]\n\t"              /* LTDTR */ \
12191239020c948a6e20faaa8d0fa5dea44302e18f8aflorian        "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
12201239020c948a6e20faaa8d0fa5dea44302e18f8aflorian                                   : [op]  "f"(cc_dep1) \
12211239020c948a6e20faaa8d0fa5dea44302e18f8aflorian                                   : "cc", "f0"); \
12221239020c948a6e20faaa8d0fa5dea44302e18f8aflorian   psw >> 28;   /* cc */ \
12231239020c948a6e20faaa8d0fa5dea44302e18f8aflorian})
12241239020c948a6e20faaa8d0fa5dea44302e18f8aflorian
1225e38f641461120ea338069a3f45820168959968abflorian#define S390_CC_FOR_DFP128_RESULT(hi,lo) \
1226e38f641461120ea338069a3f45820168959968abflorian({ \
1227e38f641461120ea338069a3f45820168959968abflorian   __asm__ volatile ( \
1228cf1527c8f8a8a647cae5ef21b6b126db9b81f622florian        "ldr   4,%[high]\n\t"                                           \
1229cf1527c8f8a8a647cae5ef21b6b126db9b81f622florian        "ldr   6,%[low]\n\t"                                            \
1230cf1527c8f8a8a647cae5ef21b6b126db9b81f622florian        ".insn rre, 0xb3de0000,0,4\n\t"    /* LTXTR */                  \
1231cf1527c8f8a8a647cae5ef21b6b126db9b81f622florian        "ipm %[psw]\n\t"           : [psw] "=d"(psw)                    \
1232cf1527c8f8a8a647cae5ef21b6b126db9b81f622florian                                   : [high] "f"(hi), [low] "f"(lo)      \
1233cf1527c8f8a8a647cae5ef21b6b126db9b81f622florian                                   : "cc", "f0", "f2", "f4", "f6");     \
1234e38f641461120ea338069a3f45820168959968abflorian   psw >> 28;   /* cc */                                                \
1235e38f641461120ea338069a3f45820168959968abflorian})
1236e38f641461120ea338069a3f45820168959968abflorian
1237ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian#define S390_CC_FOR_DFP_TD(opcode,cc_dep1,cc_dep2)                      \
1238ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian({                                                                      \
1239ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian   __asm__ volatile (                                                   \
1240ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian        opcode ",%[value],0(%[class])\n\t"                              \
1241ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian        "ipm %[psw]\n\t"           : [psw] "=d"(psw)                    \
1242ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian                                   : [value] "f"(cc_dep1),              \
1243ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian                                     [class] "a"(cc_dep2)               \
1244ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian                                   : "cc");                             \
1245ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian   psw >> 28;   /* cc */                                                \
1246ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian})
1247ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian
1248ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian#define S390_CC_FOR_DFP128_TD(opcode,cc_dep1,cc_dep2,cc_ndep)           \
1249ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian({                                                                      \
1250ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian   /* Recover the original DEP2 value. See comment near                 \
1251ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian      s390_cc_thunk_put1d128Z for rationale. */                         \
1252ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian   cc_dep2 = cc_dep2 ^ cc_ndep;                                         \
1253ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian   __asm__ volatile (                                                   \
1254ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian        "ldr  4,%[high]\n\t"                                            \
1255ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian        "ldr  6,%[low]\n\t"                                             \
1256ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian        opcode ",4,0(%[class])\n\t"                                     \
1257ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian        "ipm  %[psw]\n\t"          : [psw] "=d"(psw)                    \
1258ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian                                   : [high] "f"(cc_dep1), [low] "f"(cc_dep2), \
1259ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian                                     [class] "a"(cc_ndep)               \
1260ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian                                   : "cc", "f4", "f6");                 \
1261ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian   psw >> 28;   /* cc */                                                \
1262ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian})
1263ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian
12645f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian#define S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,rounding_mode)       \
12655f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   ({                                                                   \
12665f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      __asm__ volatile (                                                \
12675f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        opcode ",0,%[op]," #rounding_mode ",0\n\t"      \
12685f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        "ipm %[psw]\n\t"           : [psw] "=d"(psw)    \
12695f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        : [op] "f"(cc_dep1)                             \
12705f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        : "cc", "r0");                                  \
12715f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      psw >> 28;   /* cc */                                             \
12725f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   })
12735f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
12745f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian#define S390_CC_FOR_DFP_CONVERT(opcode,cc_dep1,cc_dep2)                 \
12755f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   ({                                                                   \
12765f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      UInt cc;                                                          \
12775f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      switch (decode_dfp_rounding_mode(cc_dep2)) {                      \
12785f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1:                         \
12795f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_12:                        \
12805f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,1);            \
12815f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
12825f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_PREPARE_SHORT_3:                              \
12835f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_PREPARE_SHORT_15:                             \
12845f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,3);            \
12855f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
12865f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_EVEN_4:                               \
12875f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_EVEN_8:                               \
12885f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,4);            \
12895f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
12905f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_ZERO_5:                                       \
12915f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_ZERO_9:                                       \
12925f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,5);            \
12935f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
12945f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_POSINF_6:                                     \
12955f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_POSINF_10:                                    \
12965f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,6);            \
12975f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
12985f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEGINF_7:                                     \
12995f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEGINF_11:                                    \
13005f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,7);            \
13015f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
13025f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_TIE_TOWARD_0:                         \
13035f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,13);           \
13045f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
13055f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_AWAY_0:                                       \
13065f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,14);           \
13075f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
13085f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      default:                                                          \
13095f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         vpanic("unexpected dfp rounding mode");                        \
13105f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      }                                                                 \
13115f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      cc;                                                               \
13125f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   })
13135f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
13145f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian#define S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,rounding_mode)      \
13155f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   ({                                                                   \
13165f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      __asm__ volatile (                                                \
13175f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        opcode ",0,%[op]," #rounding_mode ",0\n\t"      \
13185f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        "ipm %[psw]\n\t"           : [psw] "=d"(psw)    \
13195f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        : [op] "f"(cc_dep1)                             \
13205f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        : "cc", "r0");                                  \
13215f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      psw >> 28;   /* cc */                                             \
13225f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   })
13235f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
13245f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian#define S390_CC_FOR_DFP_UCONVERT(opcode,cc_dep1,cc_dep2)                \
13255f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   ({                                                                   \
13265f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      UInt cc;                                                          \
13275f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      switch (decode_dfp_rounding_mode(cc_dep2)) {                      \
13285f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1:                         \
13295f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_12:                        \
13305f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,1);           \
13315f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
13325f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_PREPARE_SHORT_3:                              \
13335f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_PREPARE_SHORT_15:                             \
13345f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,3);           \
13355f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
13365f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_EVEN_4:                               \
13375f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_EVEN_8:                               \
13385f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,4);           \
13395f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
13405f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_ZERO_5:                                       \
13415f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_ZERO_9:                                       \
13425f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,5);           \
13435f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
13445f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_POSINF_6:                                     \
13455f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_POSINF_10:                                    \
13465f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,6);           \
13475f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
13485f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEGINF_7:                                     \
13495f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEGINF_11:                                    \
13505f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,7);           \
13515f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
13525f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_TIE_TOWARD_0:                         \
13535f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,13);          \
13545f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
13555f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_AWAY_0:                                       \
13565f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,14);          \
13575f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
13585f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      default:                                                          \
13595f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         vpanic("unexpected dfp rounding mode");                        \
13605f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      }                                                                 \
13615f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      cc;                                                               \
13625f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   })
13635f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
13645f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian#define S390_CC_FOR_DFP128_CONVERT_AUX(opcode,hi,lo,rounding_mode)      \
13655f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   ({                                                                   \
13665f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      __asm__ volatile (                                                \
13675f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        "ldr   4,%[high]\n\t"                           \
13685f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        "ldr   6,%[low]\n\t"                            \
13695f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        opcode ",0,4," #rounding_mode ",0\n\t"          \
13705f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        "ipm %[psw]\n\t"           : [psw] "=d"(psw)    \
13715f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        : [high] "f"(hi), [low] "f"(lo)                 \
13725f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        : "cc", "r0", "f4", "f6");                      \
13735f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      psw >> 28;   /* cc */                                             \
13745f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   })
13755f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
13765f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian#define S390_CC_FOR_DFP128_CONVERT(opcode,cc_dep1,cc_dep2,cc_ndep)       \
13775f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   ({                                                                    \
13785f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      UInt cc;                                                           \
13795f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      /* Recover the original DEP2 value. See comment near               \
13805f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         s390_cc_thunk_put3 for rationale. */                            \
13815f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      cc_dep2 = cc_dep2 ^ cc_ndep;                                       \
13825f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      switch (decode_dfp_rounding_mode(cc_ndep)) {                       \
13835f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1:                          \
13845f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_12:                         \
13855f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,1);  \
13865f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                          \
13875f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_PREPARE_SHORT_3:                               \
13885f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_PREPARE_SHORT_15:                              \
13895f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,3);  \
13905f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                          \
13915f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_EVEN_4:                                \
13925f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_EVEN_8:                                \
13935f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,4);  \
13945f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                          \
13955f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_ZERO_5:                                        \
13965f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_ZERO_9:                                        \
13975f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,5);  \
13985f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                          \
13995f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_POSINF_6:                                      \
14005f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_POSINF_10:                                     \
14015f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,6);  \
14025f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                          \
14035f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEGINF_7:                                      \
14045f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEGINF_11:                                     \
14055f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,7);  \
14065f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                          \
14075f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_TIE_TOWARD_0:                          \
14085f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,13); \
14095f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                          \
14105f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_AWAY_0:                                        \
14115f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,14); \
14125f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                          \
14135f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      default:                                                           \
14145f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         vpanic("unexpected dfp rounding mode");                         \
14155f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      }                                                                  \
14165f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      cc;                                                                \
14175f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   })
14185f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
14195f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian#define S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,hi,lo,rounding_mode)      \
14205f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   ({                                                                    \
14215f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      __asm__ volatile (                                                 \
14225f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        "ldr   4,%[high]\n\t"                            \
14235f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        "ldr   6,%[low]\n\t"                             \
14245f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        opcode ",0,4," #rounding_mode ",0\n\t"           \
14255f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        "ipm %[psw]\n\t"           : [psw] "=d"(psw)     \
14265f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        : [high] "f"(hi), [low] "f"(lo)                  \
14275f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        : "cc", "r0", "f4", "f6");                       \
14285f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      psw >> 28;   /* cc */                                              \
14295f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   })
14305f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
14315f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian#define S390_CC_FOR_DFP128_UCONVERT(opcode,cc_dep1,cc_dep2,cc_ndep)       \
14325f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   ({                                                                     \
14335f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      UInt cc;                                                            \
14345f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      /* Recover the original DEP2 value. See comment near                \
14355f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         s390_cc_thunk_put3 for rationale. */                             \
14365f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      cc_dep2 = cc_dep2 ^ cc_ndep;                                        \
14375f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      switch (decode_dfp_rounding_mode(cc_ndep)) {                        \
14385f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1:                           \
14395f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_12:                          \
14405f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,1);  \
14415f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                           \
14425f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_PREPARE_SHORT_3:                                \
14435f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_PREPARE_SHORT_15:                               \
14445f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,3);  \
14455f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                           \
14465f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_EVEN_4:                                 \
14475f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_EVEN_8:                                 \
14485f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,4);  \
14495f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                           \
14505f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_ZERO_5:                                         \
14515f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_ZERO_9:                                         \
14525f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,5);  \
14535f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                           \
14545f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_POSINF_6:                                       \
14555f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_POSINF_10:                                      \
14565f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,6);  \
14575f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                           \
14585f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEGINF_7:                                       \
14595f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEGINF_11:                                      \
14605f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,7);  \
14615f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                           \
14625f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_TIE_TOWARD_0:                           \
14635f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,13); \
14645f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                           \
14655f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_AWAY_0:                                         \
14665f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,14); \
14675f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                           \
14685f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      default:                                                            \
14695f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         vpanic("unexpected dfp rounding mode");                          \
14705f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      }                                                                   \
14715f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      cc;                                                                 \
14725f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   })
14735f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
14742019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
14752019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/* Return the value of the condition code from the supplied thunk parameters.
14762019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   This is not the value of the PSW. It is the value of the 2 CC bits within
14772019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   the PSW. The returned value is thusly in the interval [0:3]. */
14782019a976f07ff418dde2dfc7cc74667ef66d7764sewardjUInt
14792019a976f07ff418dde2dfc7cc74667ef66d7764sewardjs390_calculate_cc(ULong cc_op, ULong cc_dep1, ULong cc_dep2, ULong cc_ndep)
14802019a976f07ff418dde2dfc7cc74667ef66d7764sewardj{
14812019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#if defined(VGA_s390x)
14822019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   UInt psw;
14832019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
14842019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   switch (cc_op) {
14852019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
14862019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_BITWISE:
14872019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BINARY("ogr", cc_dep1, (ULong)0);
14882019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
14892019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_SIGNED_COMPARE:
14902019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BINARY("cgr", cc_dep1, cc_dep2);
14912019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
14922019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_UNSIGNED_COMPARE:
14932019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BINARY("clgr", cc_dep1, cc_dep2);
14942019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
14952019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_SIGNED_ADD_64:
14962019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BINARY("agr", cc_dep1, cc_dep2);
14972019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
14982019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_SIGNED_ADD_32:
14992019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BINARY("ar", cc_dep1, cc_dep2);
15002019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15012019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_SIGNED_SUB_64:
15022019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BINARY("sgr", cc_dep1, cc_dep2);
15032019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15042019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_SIGNED_SUB_32:
15052019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BINARY("sr", cc_dep1, cc_dep2);
15062019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15072019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_UNSIGNED_ADD_64:
15082019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BINARY("algr", cc_dep1, cc_dep2);
15092019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15102019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_UNSIGNED_ADD_32:
15112019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BINARY("alr", cc_dep1, cc_dep2);
15122019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15132019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_UNSIGNED_ADDC_64:
15142019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_TERNARY_ADDC("alcgr", cc_dep1, cc_dep2, cc_ndep);
15152019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15162019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_UNSIGNED_ADDC_32:
15172019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_TERNARY_ADDC("alcr", cc_dep1, cc_dep2, cc_ndep);
15182019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15192019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_UNSIGNED_SUB_64:
15202019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BINARY("slgr", cc_dep1, cc_dep2);
15212019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15222019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_UNSIGNED_SUB_32:
15232019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BINARY("slr", cc_dep1, cc_dep2);
15242019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15252019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_UNSIGNED_SUBB_64:
15262019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_TERNARY_SUBB("slbgr", cc_dep1, cc_dep2, cc_ndep);
15272019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15282019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_UNSIGNED_SUBB_32:
15292019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_TERNARY_SUBB("slbr", cc_dep1, cc_dep2, cc_ndep);
15302019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15312019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_LOAD_AND_TEST:
15322019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* Like signed comparison with 0 */
15332019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BINARY("cgr", cc_dep1, (Long)0);
15342019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15352019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_LOAD_POSITIVE_32:
15362019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      __asm__ volatile (
15372019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "lpr  %[result],%[op]\n\t"
1538ae88411aaa8e0b99032fb0bdb04eec21edc54d88florian           "ipm  %[psw]\n\t"         : [psw] "=d"(psw), [result] "=d"(cc_dep1)
1539ae88411aaa8e0b99032fb0bdb04eec21edc54d88florian                                     : [op] "d"(cc_dep1)
1540ae88411aaa8e0b99032fb0bdb04eec21edc54d88florian                                     : "cc");
15412019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return psw >> 28;   /* cc */
15422019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15432019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_LOAD_POSITIVE_64:
15442019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      __asm__ volatile (
15452019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "lpgr %[result],%[op]\n\t"
1546ae88411aaa8e0b99032fb0bdb04eec21edc54d88florian           "ipm  %[psw]\n\t"         : [psw] "=d"(psw), [result] "=d"(cc_dep1)
1547ae88411aaa8e0b99032fb0bdb04eec21edc54d88florian                                     : [op] "d"(cc_dep1)
1548ae88411aaa8e0b99032fb0bdb04eec21edc54d88florian                                     : "cc");
15492019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return psw >> 28;   /* cc */
15502019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15512019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_TEST_UNDER_MASK_8: {
15522019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      UChar value  = cc_dep1;
15532019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      UChar mask   = cc_dep2;
15542019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15552019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      __asm__ volatile (
15562019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "bras %%r2,1f\n\t"             /* %r2 = address of next insn */
15572019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "tm %[value],0\n\t"            /* this is skipped, then EXecuted */
15582019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "1: ex %[mask],0(%%r2)\n\t"    /* EXecute TM after modifying mask */
15592019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "ipm %[psw]\n\t"             : [psw] "=d"(psw)
15602019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                        : [value] "m"(value), [mask] "a"(mask)
15612019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                        : "r2", "cc");
15622019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return psw >> 28;   /* cc */
15632019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   }
15642019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15652019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_TEST_UNDER_MASK_16: {
15662019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* Create a TMLL insn with the mask as given by cc_dep2 */
15672019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      UInt insn  = (0xA701 << 16) | cc_dep2;
15682019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      UInt value = cc_dep1;
15692019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15702019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      __asm__ volatile (
15712019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "lr   1,%[value]\n\t"
15722019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "lhi  2,0x10\n\t"
15732019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "ex   2,%[insn]\n\t"
15742019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "ipm  %[psw]\n\t"       : [psw] "=d"(psw)
15752019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : [value] "d"(value), [insn] "m"(insn)
15762019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : "r1", "r2", "cc");
15772019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return psw >> 28;   /* cc */
15782019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   }
15792019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15802019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_SHIFT_LEFT_32:
15812019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      __asm__ volatile (
15822019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "sla  %[op],0(%[amount])\n\t"
15832019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "ipm  %[psw]\n\t"            : [psw] "=d"(psw), [op] "+d"(cc_dep1)
15842019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                        : [amount] "a"(cc_dep2)
15852019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                        : "cc");
15862019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return psw >> 28;   /* cc */
15872019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15882019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_SHIFT_LEFT_64: {
15892019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      Int high = (Int)(cc_dep1 >> 32);
15902019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      Int low  = (Int)(cc_dep1 & 0xFFFFFFFF);
15912019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15922019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      __asm__ volatile (
15932019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "lr   2,%[high]\n\t"
15942019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "lr   3,%[low]\n\t"
15952019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "slda 2,0(%[amount])\n\t"
1596ae88411aaa8e0b99032fb0bdb04eec21edc54d88florian           "ipm %[psw]\n\t"             : [psw] "=d"(psw), [high] "+d"(high),
1597ae88411aaa8e0b99032fb0bdb04eec21edc54d88florian                                          [low] "+d"(low)
15982019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                        : [amount] "a"(cc_dep2)
15992019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                        : "cc", "r2", "r3");
16002019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return psw >> 28;   /* cc */
16012019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   }
16022019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16032019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_INSERT_CHAR_MASK_32: {
16042019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      Int inserted = 0;
16052019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      Int msb = 0;
16062019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16072019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_dep2 & 1) {
16082019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         inserted |= cc_dep1 & 0xff;
16092019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         msb = 0x80;
16102019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
16112019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_dep2 & 2) {
16122019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         inserted |= cc_dep1 & 0xff00;
16132019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         msb = 0x8000;
16142019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
16152019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_dep2 & 4) {
16162019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         inserted |= cc_dep1 & 0xff0000;
16172019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         msb = 0x800000;
16182019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
16192019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_dep2 & 8) {
16202019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         inserted |= cc_dep1 & 0xff000000;
16212019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         msb = 0x80000000;
16222019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
16232019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16242019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (inserted & msb)  // MSB is 1
16252019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         return 1;
16262019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (inserted > 0)
16272019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         return 2;
16282019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return 0;
16292019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   }
16302019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16312019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_BFP_RESULT_32:
16322019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BFP_RESULT("ltebr", cc_dep1);
16332019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16342019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_BFP_RESULT_64:
16352019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BFP_RESULT("ltdbr", cc_dep1);
16362019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16372019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_BFP_RESULT_128:
16382019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BFP128_RESULT(cc_dep1, cc_dep2);
16392019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16402019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_BFP_32_TO_INT_32:
164119e0077d31fe17496eeb76cd008507d1a8f75908florian      return S390_CC_FOR_BFP_CONVERT("cfebr", cc_dep1, cc_dep2);
16422019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16432019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_BFP_64_TO_INT_32:
164419e0077d31fe17496eeb76cd008507d1a8f75908florian      return S390_CC_FOR_BFP_CONVERT("cfdbr", cc_dep1, cc_dep2);
16452019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16462019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_BFP_128_TO_INT_32:
164719e0077d31fe17496eeb76cd008507d1a8f75908florian      return S390_CC_FOR_BFP128_CONVERT("cfxbr", cc_dep1, cc_dep2, cc_ndep);
16482019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16492019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_BFP_32_TO_INT_64:
165019e0077d31fe17496eeb76cd008507d1a8f75908florian      return S390_CC_FOR_BFP_CONVERT("cgebr", cc_dep1, cc_dep2);
16512019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16522019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_BFP_64_TO_INT_64:
165319e0077d31fe17496eeb76cd008507d1a8f75908florian      return S390_CC_FOR_BFP_CONVERT("cgdbr", cc_dep1, cc_dep2);
16542019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16552019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_BFP_128_TO_INT_64:
165619e0077d31fe17496eeb76cd008507d1a8f75908florian      return S390_CC_FOR_BFP128_CONVERT("cgxbr", cc_dep1, cc_dep2, cc_ndep);
16572019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16582019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_BFP_TDC_32:
16592019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BFP_TDC("tceb", cc_dep1, cc_dep2);
16602019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16612019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_BFP_TDC_64:
16622019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BFP_TDC("tcdb", cc_dep1, cc_dep2);
16632019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16642019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_BFP_TDC_128:
16652019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BFP128_TDC(cc_dep1, cc_dep2, cc_ndep);
16662019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16672019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_SET:
16682019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return cc_dep1;
16692019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16701c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian   case S390_CC_OP_BFP_32_TO_UINT_32:
167119e0077d31fe17496eeb76cd008507d1a8f75908florian      return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb39c0000", cc_dep1, cc_dep2);
16721c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian
16731c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian   case S390_CC_OP_BFP_64_TO_UINT_32:
167419e0077d31fe17496eeb76cd008507d1a8f75908florian      return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb39d0000", cc_dep1, cc_dep2);
16751c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian
16761c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian   case S390_CC_OP_BFP_128_TO_UINT_32:
167719e0077d31fe17496eeb76cd008507d1a8f75908florian      return S390_CC_FOR_BFP128_UCONVERT(".insn rrf,0xb39e0000", cc_dep1,
167819e0077d31fe17496eeb76cd008507d1a8f75908florian                                         cc_dep2, cc_ndep);
16791c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian
16801c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian   case S390_CC_OP_BFP_32_TO_UINT_64:
168119e0077d31fe17496eeb76cd008507d1a8f75908florian      return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb3ac0000", cc_dep1, cc_dep2);
16821c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian
16831c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian   case S390_CC_OP_BFP_64_TO_UINT_64:
168419e0077d31fe17496eeb76cd008507d1a8f75908florian      return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb3ad0000", cc_dep1, cc_dep2);
16851c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian
16861c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian   case S390_CC_OP_BFP_128_TO_UINT_64:
168719e0077d31fe17496eeb76cd008507d1a8f75908florian      return S390_CC_FOR_BFP128_UCONVERT(".insn rrf,0xb3ae0000", cc_dep1,
168819e0077d31fe17496eeb76cd008507d1a8f75908florian                                         cc_dep2, cc_ndep);
16891c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian
16901239020c948a6e20faaa8d0fa5dea44302e18f8aflorian   case S390_CC_OP_DFP_RESULT_64:
16911239020c948a6e20faaa8d0fa5dea44302e18f8aflorian      return S390_CC_FOR_DFP_RESULT(cc_dep1);
16921c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian
1693e38f641461120ea338069a3f45820168959968abflorian   case S390_CC_OP_DFP_RESULT_128:
1694e38f641461120ea338069a3f45820168959968abflorian      return S390_CC_FOR_DFP128_RESULT(cc_dep1, cc_dep2);
1695e38f641461120ea338069a3f45820168959968abflorian
1696ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian   case S390_CC_OP_DFP_TDC_32:  /* TDCET */
1697ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian      return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000050", cc_dep1, cc_dep2);
1698ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian
1699ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian   case S390_CC_OP_DFP_TDC_64:  /* TDCDT */
1700ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian      return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000054", cc_dep1, cc_dep2);
1701ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian
1702ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian   case S390_CC_OP_DFP_TDC_128: /* TDCXT */
1703ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian      return S390_CC_FOR_DFP128_TD(".insn rxe, 0xed0000000058", cc_dep1,
1704ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian                                   cc_dep2, cc_ndep);
1705ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian
1706ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian   case S390_CC_OP_DFP_TDG_32:  /* TDGET */
1707ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian      return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000051", cc_dep1, cc_dep2);
1708ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian
1709ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian   case S390_CC_OP_DFP_TDG_64:  /* TDGDT */
1710ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian      return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000055", cc_dep1, cc_dep2);
1711ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian
1712ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian   case S390_CC_OP_DFP_TDG_128: /* TDGXT */
1713ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian      return S390_CC_FOR_DFP128_TD(".insn rxe, 0xed0000000059", cc_dep1,
1714ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian                                   cc_dep2, cc_ndep);
1715ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian
17165f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   case S390_CC_OP_DFP_64_TO_INT_32: /* CFDTR */
17175f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_CC_FOR_DFP_CONVERT(".insn rrf,0xb9410000", cc_dep1, cc_dep2);
17185f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
17195f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   case S390_CC_OP_DFP_128_TO_INT_32: /* CFXTR */
17205f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_CC_FOR_DFP128_CONVERT(".insn rrf,0xb9490000", cc_dep1,
17215f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                                        cc_dep2, cc_ndep);
17225f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
1723a887acd341cb9b90b1dd6d3fdfa4a429f5ddd583florian   case S390_CC_OP_DFP_64_TO_INT_64: /* CGDTR */
1724a887acd341cb9b90b1dd6d3fdfa4a429f5ddd583florian      return S390_CC_FOR_DFP_CONVERT(".insn rrf,0xb3e10000", cc_dep1, cc_dep2);
1725a887acd341cb9b90b1dd6d3fdfa4a429f5ddd583florian
1726a887acd341cb9b90b1dd6d3fdfa4a429f5ddd583florian   case S390_CC_OP_DFP_128_TO_INT_64: /* CGXTR */
1727a887acd341cb9b90b1dd6d3fdfa4a429f5ddd583florian      return S390_CC_FOR_DFP128_CONVERT(".insn rrf,0xb3e90000", cc_dep1,
1728a887acd341cb9b90b1dd6d3fdfa4a429f5ddd583florian                                        cc_dep2, cc_ndep);
1729a887acd341cb9b90b1dd6d3fdfa4a429f5ddd583florian
17305f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   case S390_CC_OP_DFP_64_TO_UINT_32: /* CLFDTR */
17315f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_CC_FOR_DFP_UCONVERT(".insn rrf,0xb9430000", cc_dep1, cc_dep2);
17325f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
17335f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   case S390_CC_OP_DFP_128_TO_UINT_32: /* CLFXTR */
17345f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_CC_FOR_DFP128_UCONVERT(".insn rrf,0xb94b0000", cc_dep1,
17355f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                                         cc_dep2, cc_ndep);
17365f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
17375f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   case S390_CC_OP_DFP_64_TO_UINT_64: /* CLGDTR */
17385f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_CC_FOR_DFP_UCONVERT(".insn rrf,0xb9420000", cc_dep1, cc_dep2);
17395f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
17405f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   case S390_CC_OP_DFP_128_TO_UINT_64: /* CLGXTR */
17415f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_CC_FOR_DFP128_UCONVERT(".insn rrf,0xb94a0000", cc_dep1,
17425f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                                         cc_dep2, cc_ndep);
17435f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
17447ab421d8483f8462f2bf5ebdd1ef5d72658dd572florian   case S390_CC_OP_PFPO_32: {
17457ab421d8483f8462f2bf5ebdd1ef5d72658dd572florian      __asm__ volatile(
17467ab421d8483f8462f2bf5ebdd1ef5d72658dd572florian           "ler 4, %[cc_dep1]\n\t"      /* 32 bit FR move */
17477ab421d8483f8462f2bf5ebdd1ef5d72658dd572florian           "lr  0, %[cc_dep2]\n\t"      /* 32 bit GR move */
17487ab421d8483f8462f2bf5ebdd1ef5d72658dd572florian           ".short 0x010a\n\t"          /* PFPO */
17497ab421d8483f8462f2bf5ebdd1ef5d72658dd572florian           "ipm %[psw]\n\t"             : [psw] "=d"(psw)
17507ab421d8483f8462f2bf5ebdd1ef5d72658dd572florian                                        : [cc_dep1] "f"(cc_dep1),
17517ab421d8483f8462f2bf5ebdd1ef5d72658dd572florian                                          [cc_dep2] "d"(cc_dep2)
17527ab421d8483f8462f2bf5ebdd1ef5d72658dd572florian                                        : "r0", "r1", "f4");
17537ab421d8483f8462f2bf5ebdd1ef5d72658dd572florian      return psw >> 28;  /* cc */
17547ab421d8483f8462f2bf5ebdd1ef5d72658dd572florian   }
17557ab421d8483f8462f2bf5ebdd1ef5d72658dd572florian
175678d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian   case S390_CC_OP_PFPO_64: {
175778d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian      __asm__ volatile(
175878d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian           "ldr 4, %[cc_dep1]\n\t"
175978d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian           "lr  0, %[cc_dep2]\n\t"      /* 32 bit register move */
176078d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian           ".short 0x010a\n\t"          /* PFPO */
176178d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian           "ipm %[psw]\n\t"             : [psw] "=d"(psw)
1762c589228fe86255c87fdc9ad78d5d9c60e4c9e61eflorian                                        : [cc_dep1] "f"(cc_dep1),
1763c589228fe86255c87fdc9ad78d5d9c60e4c9e61eflorian                                          [cc_dep2] "d"(cc_dep2)
176478d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian                                        : "r0", "r1", "f4");
176578d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian      return psw >> 28;  /* cc */
176678d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian   }
176778d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian
176878d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian   case S390_CC_OP_PFPO_128: {
176978d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian      __asm__ volatile(
177078d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian           "ldr 4,%[cc_dep1]\n\t"
177178d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian           "ldr 6,%[cc_dep2]\n\t"
177278d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian           "lr  0,%[cc_ndep]\n\t"       /* 32 bit register move */
177378d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian           ".short 0x010a\n\t"          /* PFPO */
177478d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian           "ipm %[psw]\n\t"             : [psw] "=d"(psw)
177578d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian                                        : [cc_dep1] "f"(cc_dep1),
177678d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian                                          [cc_dep2] "f"(cc_dep2),
177778d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian                                          [cc_ndep] "d"(cc_ndep)
177878d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian                                        : "r0", "r1", "f0", "f2", "f4", "f6");
177978d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian      return psw >> 28;  /* cc */
178078d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian   }
178178d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian
17822019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   default:
17832019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      break;
17842019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   }
17852019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#endif
17862019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   vpanic("s390_calculate_cc");
17872019a976f07ff418dde2dfc7cc74667ef66d7764sewardj}
17882019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
17892019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
17902019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/* Note that this does *not* return a Boolean value. The result needs to be
17912019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   explicitly tested against zero. */
17922019a976f07ff418dde2dfc7cc74667ef66d7764sewardjUInt
17932019a976f07ff418dde2dfc7cc74667ef66d7764sewardjs390_calculate_cond(ULong mask, ULong op, ULong dep1, ULong dep2, ULong ndep)
17942019a976f07ff418dde2dfc7cc74667ef66d7764sewardj{
17952019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   UInt cc = s390_calculate_cc(op, dep1, dep2, ndep);
17962019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
17972019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   return ((mask << cc) & 0x8);
17982019a976f07ff418dde2dfc7cc74667ef66d7764sewardj}
17992019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18002019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*------------------------------------------------------------*/
18012019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*--- spechelper for performance                           ---*/
18022019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*------------------------------------------------------------*/
18032019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18042019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18052019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/* Convenience macros */
18062019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#define unop(op,a1) IRExpr_Unop((op),(a1))
18072019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#define binop(op,a1,a2) IRExpr_Binop((op),(a1),(a2))
18082019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#define mkU64(v) IRExpr_Const(IRConst_U64(v))
18092019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#define mkU32(v) IRExpr_Const(IRConst_U32(v))
18102019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#define mkU8(v)  IRExpr_Const(IRConst_U8(v))
18112019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18122019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18132019a976f07ff418dde2dfc7cc74667ef66d7764sewardjstatic inline Bool
181449adf8664fa8e67c95397022d21ea1b547e2186bflorianisC64(const IRExpr *expr)
18152019a976f07ff418dde2dfc7cc74667ef66d7764sewardj{
18162019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   return expr->tag == Iex_Const && expr->Iex.Const.con->tag == Ico_U64;
18172019a976f07ff418dde2dfc7cc74667ef66d7764sewardj}
18182019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18192019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18202019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/* The returned expression is NULL if no specialization was found. In that
18212019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case the helper function will be called. Otherwise, the expression has
18222019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   type Ity_I32 and a Boolean value. */
18232019a976f07ff418dde2dfc7cc74667ef66d7764sewardjIRExpr *
18241ff4756e1731485e6bf3cd96717cd8398daec1f2florianguest_s390x_spechelper(const HChar *function_name, IRExpr **args,
18252019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                       IRStmt **precedingStmts, Int n_precedingStmts)
18262019a976f07ff418dde2dfc7cc74667ef66d7764sewardj{
18272019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   UInt i, arity = 0;
18282019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18292019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   for (i = 0; args[i]; i++)
18302019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      arity++;
18312019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18322019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#  if 0
18332019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   vex_printf("spec request:\n");
18342019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   vex_printf("   %s  ", function_name);
18352019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   for (i = 0; i < arity; i++) {
18362019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      vex_printf("  ");
18372019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      ppIRExpr(args[i]);
18382019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   }
18392019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   vex_printf("\n");
18402019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#  endif
18412019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18422019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   /* --------- Specialising "s390_calculate_cond" --------- */
18432019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18442019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   if (vex_streq(function_name, "s390_calculate_cond")) {
18452019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      IRExpr *cond_expr, *cc_op_expr, *cc_dep1, *cc_dep2;
18462019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      ULong cond, cc_op;
18472019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18482019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      vassert(arity == 5);
18492019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18502019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      cond_expr  = args[0];
18512019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      cc_op_expr = args[1];
18522019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18532019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* The necessary requirement for all optimizations here is that the
18542019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         condition and the cc_op are constant. So check that upfront. */
18552019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (! isC64(cond_expr))  return NULL;
18562019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (! isC64(cc_op_expr)) return NULL;
18572019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18582019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      cond    = cond_expr->Iex.Const.con->Ico.U64;
18592019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      cc_op   = cc_op_expr->Iex.Const.con->Ico.U64;
18602019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18612019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      vassert(cond <= 15);
18622019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18632019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /*
18642019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        +------+---+---+---+---+
18652019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        | cc   | 0 | 1 | 2 | 3 |
18662019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        | cond | 8 | 4 | 2 | 1 |
18672019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        +------+---+---+---+---+
18682019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      */
18692019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      cc_dep1 = args[2];
18702019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      cc_dep2 = args[3];
18712019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18722019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* S390_CC_OP_SIGNED_COMPARE */
18732019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_op == S390_CC_OP_SIGNED_COMPARE) {
18742019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /*
18752019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 0  --> cc_dep1 == cc_dep2   (cond == 8)
18762019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 1  --> cc_dep1 <  cc_dep2   (cond == 4)
18772019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 2  --> cc_dep1 >  cc_dep2   (cond == 2)
18782019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18792019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            Because cc == 3 cannot occur the rightmost bit of cond is
18802019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            a don't care.
18812019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         */
18822019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 || cond == 8 + 1) {
18832019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
18842019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
18852019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 4 + 2 || cond == 4 + 2 + 1) {
18862019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
18872019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
18882019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 4 || cond == 4 + 1) {
18892019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep1, cc_dep2));
18902019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
18912019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 4 || cond == 8 + 4 + 1) {
18922019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep1, cc_dep2));
18932019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
18942019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* cc_dep1 > cc_dep2  ---->  cc_dep2 < cc_dep1 */
18952019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 2 || cond == 2 + 1) {
18962019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep2, cc_dep1));
18972019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
18982019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 2 || cond == 8 + 2 + 1) {
18992019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep2, cc_dep1));
19002019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19012019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
19022019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return mkU32(1);
19032019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19042019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* Remaining case */
19052019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         return mkU32(0);
19062019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
19072019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
19082019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* S390_CC_OP_UNSIGNED_COMPARE */
19092019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_op == S390_CC_OP_UNSIGNED_COMPARE) {
19102019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /*
19112019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 0  --> cc_dep1 == cc_dep2   (cond == 8)
19122019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 1  --> cc_dep1 <  cc_dep2   (cond == 4)
19132019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 2  --> cc_dep1 >  cc_dep2   (cond == 2)
19142019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
19152019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            Because cc == 3 cannot occur the rightmost bit of cond is
19162019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            a don't care.
19172019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         */
19182019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 || cond == 8 + 1) {
19192019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
19202019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19212019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 4 + 2 || cond == 4 + 2 + 1) {
19222019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
19232019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19242019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 4 || cond == 4 + 1) {
19252019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
19262019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19272019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 4 || cond == 8 + 4 + 1) {
19282019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
19292019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19302019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* cc_dep1 > cc_dep2  ---->  cc_dep2 < cc_dep1 */
19312019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 2 || cond == 2 + 1) {
19322019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep2, cc_dep1));
19332019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19342019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 2 || cond == 8 + 2 + 1) {
19352019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
19362019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19372019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
19382019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return mkU32(1);
19392019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19402019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* Remaining case */
19412019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         return mkU32(0);
19422019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
19432019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
19442019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* S390_CC_OP_LOAD_AND_TEST */
19452019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_op == S390_CC_OP_LOAD_AND_TEST) {
19462019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /*
19472019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 0  --> cc_dep1 == 0   (cond == 8)
19482019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 1  --> cc_dep1 <  0   (cond == 4)
19492019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 2  --> cc_dep1 >  0   (cond == 2)
19502019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
19512019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            Because cc == 3 cannot occur the rightmost bit of cond is
19522019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            a don't care.
19532019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         */
19542019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 || cond == 8 + 1) {
19552019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, mkU64(0)));
19562019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19572019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 4 + 2 || cond == 4 + 2 + 1) {
19582019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
19592019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19602019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 4 || cond == 4 + 1) {
19612019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep1, mkU64(0)));
19622019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19632019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 4 || cond == 8 + 4 + 1) {
19642019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep1, mkU64(0)));
19652019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19662019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* cc_dep1 > 0  ---->  0 < cc_dep1 */
19672019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 2 || cond == 2 + 1) {
19682019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLT64S, mkU64(0), cc_dep1));
19692019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19702019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 2 || cond == 8 + 2 + 1) {
197125e1cb271253c82bc8610820004116bad5e8d0a1florian            /* Special case cc_dep >= 0. Only check the MSB to avoid bogus
197225e1cb271253c82bc8610820004116bad5e8d0a1florian               memcheck complaints due to gcc magic. Fixes 308427
1973d7f19c077688845dcea5a037fe42ab5b1f7db717cborntra             */
197425e1cb271253c82bc8610820004116bad5e8d0a1florian            return unop(Iop_64to32, binop(Iop_Xor64,
197525e1cb271253c82bc8610820004116bad5e8d0a1florian                                          binop(Iop_Shr64, cc_dep1, mkU8(63)),
197625e1cb271253c82bc8610820004116bad5e8d0a1florian                                          mkU64(1)));
19772019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19782019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
19792019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return mkU32(1);
19802019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19812019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* Remaining case */
19822019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         return mkU32(0);
19832019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
19842019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
19852019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* S390_CC_OP_BITWISE */
19862019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_op == S390_CC_OP_BITWISE) {
19872019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /*
19882019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc_dep1 is the result of the boolean operation.
19892019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
19902019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 0  --> cc_dep1 == 0   (cond == 8)
19912019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 1  --> cc_dep1 != 0   (cond == 4)
19922019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
19932019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            Because cc == 2 and cc == 3 cannot occur the two rightmost bits of
19942019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cond are don't cares. Therefore:
19952019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
19962019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cond == 00xx  -> always false
19972019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cond == 01xx  -> not equal
19982019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cond == 10xx  -> equal
19992019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cond == 11xx  -> always true
20002019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         */
20012019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if ((cond & (8 + 4)) == 8 + 4) {
20022019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return mkU32(1);
20032019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
20042019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond & 8) {
20052019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, mkU64(0)));
20062019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
20072019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond & 4) {
20082019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
20092019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
20102019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* Remaining case */
20112019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         return mkU32(0);
20122019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
20132019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20142019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* S390_CC_OP_INSERT_CHAR_MASK_32
20152019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         Since the mask comes from an immediate field in the opcode, we
20162019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         expect the mask to be a constant here. That simplifies matters. */
20172019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_op == S390_CC_OP_INSERT_CHAR_MASK_32) {
20182019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         ULong mask;
20192019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         UInt imask = 0, shift = 0;
20202019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         IRExpr *word;
20212019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20222019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (! isC64(cc_dep2)) goto missed;
20232019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20242019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         mask = cc_dep2->Iex.Const.con->Ico.U64;
20252019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20262019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* Extract the 32-bit value from the thunk */
20272019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20282019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         word = unop(Iop_64to32, cc_dep1);
20292019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20302019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         switch (mask) {
20312019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 0:  shift =  0; imask = 0x00000000; break;
20322019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 1:  shift = 24; imask = 0x000000FF; break;
20332019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 2:  shift = 16; imask = 0x0000FF00; break;
20342019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 3:  shift = 16; imask = 0x0000FFFF; break;
20352019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 4:  shift =  8; imask = 0x00FF0000; break;
20362019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 5:  shift =  8; imask = 0x00FF00FF; break;
20372019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 6:  shift =  8; imask = 0x00FFFF00; break;
20382019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 7:  shift =  8; imask = 0x00FFFFFF; break;
20392019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 8:  shift =  0; imask = 0xFF000000; break;
20402019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 9:  shift =  0; imask = 0xFF0000FF; break;
20412019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 10: shift =  0; imask = 0xFF00FF00; break;
20422019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 11: shift =  0; imask = 0xFF00FFFF; break;
20432019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 12: shift =  0; imask = 0xFFFF0000; break;
20442019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 13: shift =  0; imask = 0xFFFF00FF; break;
20452019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 14: shift =  0; imask = 0xFFFFFF00; break;
20462019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 15: shift =  0; imask = 0xFFFFFFFF; break;
20472019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
20482019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20492019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* Select the bits that were inserted */
20502019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         word = binop(Iop_And32, word, mkU32(imask));
20512019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20522019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* cc == 0  --> all inserted bits zero or mask == 0   (cond == 8)
20532019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 1  --> leftmost inserted bit is one          (cond == 4)
20542019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 2  --> leftmost inserted bit is zero and not (cond == 2)
20552019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                         all inserted bits are zero
20562019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20572019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            Because cc == 0,1,2 the rightmost bit of the mask is a don't care */
20582019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 || cond == 8 + 1) {
20592019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ32, word, mkU32(0)));
20602019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
20612019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 4 + 2 || cond == 4 + 2 + 1) {
20622019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE32, word, mkU32(0)));
20632019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
20642019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20652019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* Sign extend */
20662019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (shift != 0) {
20672019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            word = binop(Iop_Sar32, binop(Iop_Shl32, word, mkU8(shift)),
20682019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                         mkU8(shift));
20692019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
20702019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20712019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 4 || cond == 4 + 1) {  /* word < 0 */
20722019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLT32S, word, mkU32(0)));
20732019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
20742019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 2 || cond == 2 + 1) {  /* word > 0 */
20752019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLT32S, mkU32(0), word));
20762019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
20772019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 4 || cond == 8 + 4 + 1) {
20782019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLE32S, word, mkU32(0)));
20792019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
20802019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 2 || cond == 8 + 2 + 1) {
20812019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLE32S, mkU32(0), word));
20822019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
20832019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
20842019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return mkU32(1);
20852019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
20862019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* Remaining case */
20872019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         return mkU32(0);
20882019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
20892019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20902019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* S390_CC_OP_TEST_UNDER_MASK_8
20912019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         Since the mask comes from an immediate field in the opcode, we
20922019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         expect the mask to be a constant here. That simplifies matters. */
20932019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_op == S390_CC_OP_TEST_UNDER_MASK_8) {
20942019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         ULong mask16;
20952019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20962019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (! isC64(cc_dep2)) goto missed;
20972019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20982019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         mask16 = cc_dep2->Iex.Const.con->Ico.U64;
20992019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
21002019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* Get rid of the mask16 == 0 case first. Some of the simplifications
21012019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            below (e.g. for OVFL) only hold if mask16 == 0.  */
21022019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (mask16 == 0) {   /* cc == 0 */
21032019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            if (cond & 0x8) return mkU32(1);
21042019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return mkU32(0);
21052019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
21062019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
21072019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* cc == 2 is a don't care */
21082019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 || cond == 8 + 2) {
21092019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
21102019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_And64, cc_dep1, cc_dep2),
21112019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU64(0)));
21122019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
21132019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 7 || cond == 7 - 2) {
21142019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE64,
21152019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_And64, cc_dep1, cc_dep2),
21162019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU64(0)));
21172019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
21182019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 1 || cond == 1 + 2) {
21192019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
21202019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_And64, cc_dep1, cc_dep2),
21212019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          cc_dep2));
21222019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
21232019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 14 || cond == 14 - 2) {  /* ! OVFL */
21242019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE64,
21252019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_And64, cc_dep1, cc_dep2),
21262019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          cc_dep2));
21272019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
21282019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         goto missed;
21292019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
21302019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
21312019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* S390_CC_OP_TEST_UNDER_MASK_16
21322019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         Since the mask comes from an immediate field in the opcode, we
21332019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         expect the mask to be a constant here. That simplifies matters. */
21342019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_op == S390_CC_OP_TEST_UNDER_MASK_16) {
21352019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         ULong mask16;
21362019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         UInt msb;
21372019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
21382019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (! isC64(cc_dep2)) goto missed;
21392019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
21402019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         mask16 = cc_dep2->Iex.Const.con->Ico.U64;
21412019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
21422019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* Get rid of the mask16 == 0 case first. Some of the simplifications
21432019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            below (e.g. for OVFL) only hold if mask16 == 0.  */
21442019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (mask16 == 0) {   /* cc == 0 */
21452019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            if (cond & 0x8) return mkU32(1);
21462019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return mkU32(0);
21472019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
21482019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
21492019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8) {
21502019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
21512019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_And64, cc_dep1, cc_dep2),
21522019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU64(0)));
21532019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
21542019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 7) {
21552019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE64,
21562019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_And64, cc_dep1, cc_dep2),
21572019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU64(0)));
21582019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
21592019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 1) {
21602019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
21612019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_And64, cc_dep1, cc_dep2),
21622019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU64(mask16)));
21632019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
21642019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 14) {  /* ! OVFL */
21652019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE64,
21662019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_And64, cc_dep1, cc_dep2),
21672019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU64(mask16)));
21682019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
21692019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
21702019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* Find MSB in mask */
21712019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         msb = 0x8000;
21722019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         while (msb > mask16)
21732019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            msb >>= 1;
21742019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
21752019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 2) {  /* cc == 2 */
21762019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            IRExpr *c1, *c2;
21772019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
21782019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            /* (cc_dep & msb) != 0 && (cc_dep & mask16) != mask16 */
21792019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            c1 = binop(Iop_CmpNE64,
21802019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                       binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
21812019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            c2 = binop(Iop_CmpNE64,
21822019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                       binop(Iop_And64, cc_dep1, cc_dep2),
21832019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                       mkU64(mask16));
21842019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return binop(Iop_And32, unop(Iop_1Uto32, c1),
21852019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                         unop(Iop_1Uto32, c2));
21862019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
21872019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
21882019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 4) {  /* cc == 1 */
21892019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            IRExpr *c1, *c2;
21902019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
21912019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            /* (cc_dep & msb) == 0 && (cc_dep & mask16) != 0 */
21922019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            c1 = binop(Iop_CmpEQ64,
21932019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                       binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
21942019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            c2 = binop(Iop_CmpNE64,
21952019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                       binop(Iop_And64, cc_dep1, cc_dep2),
21962019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                       mkU64(0));
21972019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return binop(Iop_And32, unop(Iop_1Uto32, c1),
21982019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                         unop(Iop_1Uto32, c2));
21992019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
22002019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
22012019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 11) {  /* cc == 0,2,3 */
22022019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            IRExpr *c1, *c2;
22032019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
22042019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            c1 = binop(Iop_CmpNE64,
22052019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                       binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
22062019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            c2 = binop(Iop_CmpEQ64,
22072019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                       binop(Iop_And64, cc_dep1, cc_dep2),
22082019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                       mkU64(0));
22092019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return binop(Iop_Or32, unop(Iop_1Uto32, c1),
22102019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                         unop(Iop_1Uto32, c2));
22112019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
22122019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
22132019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 3) {  /* cc == 2 || cc == 3 */
22142019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32,
22152019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                        binop(Iop_CmpNE64,
22162019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                              binop(Iop_And64, cc_dep1, mkU64(msb)),
22172019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                              mkU64(0)));
22182019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
22192019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 12) { /* cc == 0 || cc == 1 */
22202019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32,
22212019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                        binop(Iop_CmpEQ64,
22222019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                              binop(Iop_And64, cc_dep1, mkU64(msb)),
22232019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                              mkU64(0)));
22242019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
22252019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         // vex_printf("TUM mask = 0x%llx\n", mask16);
22262019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         goto missed;
22272019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
22282019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
22292019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* S390_CC_OP_UNSIGNED_SUB_64/32 */
22302019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_op == S390_CC_OP_UNSIGNED_SUB_64 ||
22312019a976f07ff418dde2dfc7cc74667ef66d7764sewardj          cc_op == S390_CC_OP_UNSIGNED_SUB_32) {
22322019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /*
22332019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc_dep1, cc_dep2 are the zero extended left and right operands
22342019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
22352019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 1  --> result != 0, borrow    (cond == 4)
22362019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 2  --> result == 0, no borrow (cond == 2)
22372019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 3  --> result != 0, no borrow (cond == 1)
22382019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
22392019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc = (cc_dep1 == cc_dep2) ? 2
22402019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                      : (cc_dep1 > cc_dep2) ? 3 : 1;
22412019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
22422019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            Because cc == 0 cannot occur the leftmost bit of cond is
22432019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            a don't care.
22442019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         */
22452019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 1 || cond == 1 + 8) {  /* cc == 3   op2 < op1 */
22462019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep2, cc_dep1));
22472019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
22482019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 2 || cond == 2 + 8) {  /* cc == 2 */
22492019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
22502019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
22512019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 4 || cond == 4 + 8) {  /* cc == 1 */
22522019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
22532019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
22542019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 3 || cond == 3 + 8) {  /* cc == 2 || cc == 3 */
22552019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
22562019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
22572019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 6 || cond == 6 + 8) {  /* cc == 2 || cc == 1 */
22582019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
22592019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
22602019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
22612019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 5 || cond == 5 + 8) {  /* cc == 3 || cc == 1 */
22622019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
22632019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
22642019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 7 || cond == 7 + 8) {
22652019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return mkU32(1);
22662019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
22672019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* Remaining case */
22682019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         return mkU32(0);
22692019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
22702019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
22712019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* S390_CC_OP_UNSIGNED_ADD_64 */
22722019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_op == S390_CC_OP_UNSIGNED_ADD_64) {
22732019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /*
22742019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc_dep1, cc_dep2 are the zero extended left and right operands
22752019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
22762019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 0  --> result == 0, no carry  (cond == 8)
22772019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 1  --> result != 0, no carry  (cond == 4)
22782019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 2  --> result == 0, carry     (cond == 2)
22792019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 3  --> result != 0, carry     (cond == 1)
22802019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         */
22812019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8) { /* cc == 0 */
22822019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            /* Both inputs are 0 */
22832019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
22842019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_Or64, cc_dep1, cc_dep2),
22852019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU64(0)));
22862019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
22872019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 7) { /* cc == 1,2,3 */
22882019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            /* Not both inputs are 0 */
22892019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE64,
22902019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_Or64, cc_dep1, cc_dep2),
22912019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU64(0)));
22922019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
22932019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 2) {  /* cc == 0,2  -> result is zero */
22942019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
22952019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_Add64, cc_dep1, cc_dep2),
22962019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU64(0)));
22972019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
22982019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 4 + 1) {  /* cc == 1,3  -> result is not zero */
22992019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE64,
23002019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_Add64, cc_dep1, cc_dep2),
23012019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU64(0)));
23022019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
23032019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         goto missed;
23042019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
23052019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
23062019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* S390_CC_OP_UNSIGNED_ADD_32 */
23072019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_op == S390_CC_OP_UNSIGNED_ADD_32) {
23082019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /*
23092019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc_dep1, cc_dep2 are the zero extended left and right operands
23102019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
23112019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 0  --> result == 0, no carry  (cond == 8)
23122019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 1  --> result != 0, no carry  (cond == 4)
23132019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 2  --> result == 0, carry     (cond == 2)
23142019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 3  --> result != 0, carry     (cond == 1)
23152019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         */
23162019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8) { /* cc == 0 */
23172019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            /* Both inputs are 0 */
23182019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
23192019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_Or64, cc_dep1, cc_dep2),
23202019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU64(0)));
23212019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
23222019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 7) { /* cc == 1,2,3 */
23232019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            /* Not both inputs are 0 */
23242019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE64,
23252019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_Or64, cc_dep1, cc_dep2),
23262019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU64(0)));
23272019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
23282019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 2) {  /* cc == 0,2  -> result is zero */
23292019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ32,
23302019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_Add32,
23312019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                                unop(Iop_64to32, cc_dep1),
23322019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                                unop(Iop_64to32, cc_dep2)),
23332019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU32(0)));
23342019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
23352019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 4 + 1) {  /* cc == 1,3  -> result is not zero */
23362019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE32,
23372019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_Add32,
23382019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                                unop(Iop_64to32, cc_dep1),
23392019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                                unop(Iop_64to32, cc_dep2)),
23402019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU32(0)));
23412019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
23422019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         goto missed;
23432019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
23442019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
23452019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* S390_CC_OP_SET */
23462019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_op == S390_CC_OP_SET) {
23472019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* cc_dep1 is the condition code
23482019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
23492019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            Return 1, if ((cond << cc_dep1) & 0x8) != 0 */
23502019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
23512019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        return unop(Iop_1Uto32,
23522019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                    binop(Iop_CmpNE64,
23532019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                          binop(Iop_And64,
23542019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                binop(Iop_Shl64, cond_expr,
23552019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                      unop(Iop_64to8, cc_dep1)),
23562019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                mkU64(8)),
23572019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                          mkU64(0)));
23582019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
23592019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
2360af514c044bf90048e9bb916024198f9bc5dcb3f5florian      goto missed;
23612019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   }
23622019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
2363af514c044bf90048e9bb916024198f9bc5dcb3f5florian   /* --------- Specialising "s390_calculate_cond" --------- */
2364af514c044bf90048e9bb916024198f9bc5dcb3f5florian
2365af514c044bf90048e9bb916024198f9bc5dcb3f5florian   if (vex_streq(function_name, "s390_calculate_cc")) {
2366af514c044bf90048e9bb916024198f9bc5dcb3f5florian      IRExpr *cc_op_expr, *cc_dep1;
2367af514c044bf90048e9bb916024198f9bc5dcb3f5florian      ULong cc_op;
2368af514c044bf90048e9bb916024198f9bc5dcb3f5florian
2369af514c044bf90048e9bb916024198f9bc5dcb3f5florian      vassert(arity == 4);
2370af514c044bf90048e9bb916024198f9bc5dcb3f5florian
2371af514c044bf90048e9bb916024198f9bc5dcb3f5florian      cc_op_expr = args[0];
2372af514c044bf90048e9bb916024198f9bc5dcb3f5florian
2373af514c044bf90048e9bb916024198f9bc5dcb3f5florian      /* The necessary requirement for all optimizations here is that
2374af514c044bf90048e9bb916024198f9bc5dcb3f5florian         cc_op is constant. So check that upfront. */
2375af514c044bf90048e9bb916024198f9bc5dcb3f5florian      if (! isC64(cc_op_expr)) return NULL;
2376af514c044bf90048e9bb916024198f9bc5dcb3f5florian
2377af514c044bf90048e9bb916024198f9bc5dcb3f5florian      cc_op   = cc_op_expr->Iex.Const.con->Ico.U64;
2378af514c044bf90048e9bb916024198f9bc5dcb3f5florian      cc_dep1 = args[1];
2379af514c044bf90048e9bb916024198f9bc5dcb3f5florian
2380af514c044bf90048e9bb916024198f9bc5dcb3f5florian      if (cc_op == S390_CC_OP_BITWISE) {
2381af514c044bf90048e9bb916024198f9bc5dcb3f5florian         return unop(Iop_1Uto32,
2382af514c044bf90048e9bb916024198f9bc5dcb3f5florian                     binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
2383af514c044bf90048e9bb916024198f9bc5dcb3f5florian      }
2384af514c044bf90048e9bb916024198f9bc5dcb3f5florian
2385af514c044bf90048e9bb916024198f9bc5dcb3f5florian      if (cc_op == S390_CC_OP_SET) {
2386af514c044bf90048e9bb916024198f9bc5dcb3f5florian         return unop(Iop_64to32, cc_dep1);
2387af514c044bf90048e9bb916024198f9bc5dcb3f5florian      }
2388af514c044bf90048e9bb916024198f9bc5dcb3f5florian
2389af514c044bf90048e9bb916024198f9bc5dcb3f5florian      goto missed;
2390af514c044bf90048e9bb916024198f9bc5dcb3f5florian   }
2391af514c044bf90048e9bb916024198f9bc5dcb3f5florian
2392af514c044bf90048e9bb916024198f9bc5dcb3f5florianmissed:
23932019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   return NULL;
23942019a976f07ff418dde2dfc7cc74667ef66d7764sewardj}
23952019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
23962019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*---------------------------------------------------------------*/
23972019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*--- end                                guest_s390_helpers.c ---*/
23982019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*---------------------------------------------------------------*/
2399