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
11785952d4bf502fa756b2ac58595fd31fe0f88559sewardj   Copyright IBM Corp. 2010-2015
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
155ca2c3c75784d35d136fc7c952717cdee5063c193sewardjguest_s390x_state_requires_precise_mem_exns (
156ca2c3c75784d35d136fc7c952717cdee5063c193sewardj   Int minoff, Int maxoff, VexRegisterUpdates pxControl
157ca2c3c75784d35d136fc7c952717cdee5063c193sewardj)
1582019a976f07ff418dde2dfc7cc74667ef66d7764sewardj{
159606878860623daa234c68fff81aade73059aaafbsewardj   Int lr_min = S390X_GUEST_OFFSET(guest_LR);
1602019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   Int lr_max = lr_min + 8 - 1;
161606878860623daa234c68fff81aade73059aaafbsewardj   Int sp_min = S390X_GUEST_OFFSET(guest_SP);
1622019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   Int sp_max = sp_min + 8 - 1;
163606878860623daa234c68fff81aade73059aaafbsewardj   Int fp_min = S390X_GUEST_OFFSET(guest_FP);
1642019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   Int fp_max = fp_min + 8 - 1;
165e88b3c94d4e3bf0f40123ffe162dd60e50580366florian   Int ia_min = S390X_GUEST_OFFSET(guest_IA);
1662019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   Int ia_max = ia_min + 8 - 1;
1672019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
1686c46befd9eb90c1b6e739926c1fa335cba75bf46philippe   if (maxoff < sp_min || minoff > sp_max) {
1696c46befd9eb90c1b6e739926c1fa335cba75bf46philippe      /* No overlap with SP */
170ca2c3c75784d35d136fc7c952717cdee5063c193sewardj      if (pxControl == VexRegUpdSpAtMemAccess)
1716c46befd9eb90c1b6e739926c1fa335cba75bf46philippe         return False; // We only need to check stack pointer.
1722019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   } else {
1732019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return True;
1742019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   }
1752019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
1766c46befd9eb90c1b6e739926c1fa335cba75bf46philippe   if (maxoff < lr_min || minoff > lr_max) {
1776c46befd9eb90c1b6e739926c1fa335cba75bf46philippe      /* No overlap with LR */
1782019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   } else {
1792019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return True;
1802019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   }
1812019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
1822019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   if (maxoff < fp_min || minoff > fp_max) {
1832019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* No overlap with FP */
1842019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   } else {
1852019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return True;
1862019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   }
1872019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
1882019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   if (maxoff < ia_min || minoff > ia_max) {
1892019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* No overlap with IA */
1902019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   } else {
1912019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return True;
1922019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   }
1932019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
1942019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   return False;
1952019a976f07ff418dde2dfc7cc74667ef66d7764sewardj}
1962019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
1972019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
1982019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#define ALWAYSDEFD(field)                             \
199e88b3c94d4e3bf0f40123ffe162dd60e50580366florian    { S390X_GUEST_OFFSET(field),            \
2002019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      (sizeof ((VexGuestS390XState*)0)->field) }
2012019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
2022019a976f07ff418dde2dfc7cc74667ef66d7764sewardjVexGuestLayout s390xGuest_layout = {
2032019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
2042019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   /* Total size of the guest state, in bytes. */
2052019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   .total_sizeB = sizeof(VexGuestS390XState),
2062019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
2072019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   /* Describe the stack pointer. */
208606878860623daa234c68fff81aade73059aaafbsewardj   .offset_SP = S390X_GUEST_OFFSET(guest_SP),
2092019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   .sizeof_SP = 8,
2102019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
2112019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   /* Describe the frame pointer. */
212606878860623daa234c68fff81aade73059aaafbsewardj   .offset_FP = S390X_GUEST_OFFSET(guest_FP),
2132019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   .sizeof_FP = 8,
2142019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
2152019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   /* Describe the instruction pointer. */
216e88b3c94d4e3bf0f40123ffe162dd60e50580366florian   .offset_IP = S390X_GUEST_OFFSET(guest_IA),
2172019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   .sizeof_IP = 8,
2182019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
2192019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   /* Describe any sections to be regarded by Memcheck as
2202019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      'always-defined'. */
2212019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   .n_alwaysDefd = 9,
2222019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
2232019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   /* Flags thunk: OP and NDEP are always defined, whereas DEP1
2242019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      and DEP2 have to be tracked.  See detailed comment in
2252019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      gdefs.h on meaning of thunk fields. */
2262019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   .alwaysDefd = {
2272019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /*  0 */ ALWAYSDEFD(guest_CC_OP),     /* generic */
2282019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /*  1 */ ALWAYSDEFD(guest_CC_NDEP),   /* generic */
2296ef84bed9bb3af22060eb1759788034602bbcc88florian      /*  2 */ ALWAYSDEFD(guest_EMNOTE),    /* generic */
23005f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj      /*  3 */ ALWAYSDEFD(guest_CMSTART),   /* generic */
23105f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj      /*  4 */ ALWAYSDEFD(guest_CMLEN),     /* generic */
2322019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /*  5 */ ALWAYSDEFD(guest_IP_AT_SYSCALL), /* generic */
2332019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /*  6 */ ALWAYSDEFD(guest_IA),        /* control reg */
2342019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /*  7 */ ALWAYSDEFD(guest_fpc),       /* control reg */
2352019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /*  8 */ ALWAYSDEFD(guest_counter),   /* internal usage register */
2362019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   }
2372019a976f07ff418dde2dfc7cc74667ef66d7764sewardj};
2382019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
2392019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*------------------------------------------------------------*/
2402019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*--- Dirty helper for EXecute                             ---*/
2412019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*------------------------------------------------------------*/
2422019a976f07ff418dde2dfc7cc74667ef66d7764sewardjvoid
2432019a976f07ff418dde2dfc7cc74667ef66d7764sewardjs390x_dirtyhelper_EX(ULong torun)
2442019a976f07ff418dde2dfc7cc74667ef66d7764sewardj{
2452019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   last_execute_target = torun;
2462019a976f07ff418dde2dfc7cc74667ef66d7764sewardj}
2472019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
2481e5fea63aab1f94925afd49d74560917b37fa505sewardj
2491e5fea63aab1f94925afd49d74560917b37fa505sewardj/*------------------------------------------------------------*/
2501e5fea63aab1f94925afd49d74560917b37fa505sewardj/*--- Dirty helper for Clock instructions                  ---*/
2511e5fea63aab1f94925afd49d74560917b37fa505sewardj/*------------------------------------------------------------*/
2521e5fea63aab1f94925afd49d74560917b37fa505sewardj#if defined(VGA_s390x)
253ae88411aaa8e0b99032fb0bdb04eec21edc54d88florianULong
254ae88411aaa8e0b99032fb0bdb04eec21edc54d88florians390x_dirtyhelper_STCK(ULong *addr)
2551e5fea63aab1f94925afd49d74560917b37fa505sewardj{
256ffbd84dd2205b38d45f3ce13d594787a7c62fd6cflorian   UInt cc;
2571e5fea63aab1f94925afd49d74560917b37fa505sewardj
2581e5fea63aab1f94925afd49d74560917b37fa505sewardj   asm volatile("stck %0\n"
2591e5fea63aab1f94925afd49d74560917b37fa505sewardj                "ipm %1\n"
2601e5fea63aab1f94925afd49d74560917b37fa505sewardj                "srl %1,28\n"
2611e5fea63aab1f94925afd49d74560917b37fa505sewardj                : "+Q" (*addr), "=d" (cc) : : "cc");
2621e5fea63aab1f94925afd49d74560917b37fa505sewardj   return cc;
2631e5fea63aab1f94925afd49d74560917b37fa505sewardj}
2641e5fea63aab1f94925afd49d74560917b37fa505sewardj
265ae88411aaa8e0b99032fb0bdb04eec21edc54d88florianULong
266ae88411aaa8e0b99032fb0bdb04eec21edc54d88florians390x_dirtyhelper_STCKE(ULong *addr)
2671e5fea63aab1f94925afd49d74560917b37fa505sewardj{
268ffbd84dd2205b38d45f3ce13d594787a7c62fd6cflorian   UInt cc;
2691e5fea63aab1f94925afd49d74560917b37fa505sewardj
2701e5fea63aab1f94925afd49d74560917b37fa505sewardj   asm volatile("stcke %0\n"
2711e5fea63aab1f94925afd49d74560917b37fa505sewardj                "ipm %1\n"
2721e5fea63aab1f94925afd49d74560917b37fa505sewardj                "srl %1,28\n"
2731e5fea63aab1f94925afd49d74560917b37fa505sewardj                : "+Q" (*addr), "=d" (cc) : : "cc");
2741e5fea63aab1f94925afd49d74560917b37fa505sewardj   return cc;
2751e5fea63aab1f94925afd49d74560917b37fa505sewardj}
2761e5fea63aab1f94925afd49d74560917b37fa505sewardj
2771e5fea63aab1f94925afd49d74560917b37fa505sewardjULong s390x_dirtyhelper_STCKF(ULong *addr)
2781e5fea63aab1f94925afd49d74560917b37fa505sewardj{
279ffbd84dd2205b38d45f3ce13d594787a7c62fd6cflorian   UInt cc;
2801e5fea63aab1f94925afd49d74560917b37fa505sewardj
2811e5fea63aab1f94925afd49d74560917b37fa505sewardj   asm volatile(".insn s,0xb27c0000,%0\n"
2821e5fea63aab1f94925afd49d74560917b37fa505sewardj                "ipm %1\n"
2831e5fea63aab1f94925afd49d74560917b37fa505sewardj                "srl %1,28\n"
2841e5fea63aab1f94925afd49d74560917b37fa505sewardj                : "+Q" (*addr), "=d" (cc) : : "cc");
2851e5fea63aab1f94925afd49d74560917b37fa505sewardj   return cc;
2861e5fea63aab1f94925afd49d74560917b37fa505sewardj}
2871e5fea63aab1f94925afd49d74560917b37fa505sewardj#else
2881e5fea63aab1f94925afd49d74560917b37fa505sewardjULong s390x_dirtyhelper_STCK(ULong *addr)  {return 3;}
2891e5fea63aab1f94925afd49d74560917b37fa505sewardjULong s390x_dirtyhelper_STCKF(ULong *addr) {return 3;}
2901e5fea63aab1f94925afd49d74560917b37fa505sewardjULong s390x_dirtyhelper_STCKE(ULong *addr) {return 3;}
2911e5fea63aab1f94925afd49d74560917b37fa505sewardj#endif /* VGA_s390x */
2921e5fea63aab1f94925afd49d74560917b37fa505sewardj
2932019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*------------------------------------------------------------*/
294933065d4f3548466da4666c5cfda7e5eaff93759florian/*--- Dirty helper for Store Facility instruction          ---*/
295933065d4f3548466da4666c5cfda7e5eaff93759florian/*------------------------------------------------------------*/
296933065d4f3548466da4666c5cfda7e5eaff93759florian#if defined(VGA_s390x)
297b7def2222c08b119df85bc7231bf0e6806f3a1a6florianstatic void
298b7def2222c08b119df85bc7231bf0e6806f3a1a6florians390_set_facility_bit(ULong *addr, UInt bitno, UInt value)
299b7def2222c08b119df85bc7231bf0e6806f3a1a6florian{
300b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   addr  += bitno / 64;
301b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   bitno  = bitno % 64;
302b7def2222c08b119df85bc7231bf0e6806f3a1a6florian
303b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   ULong mask = 1;
304b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   mask <<= (63 - bitno);
305b7def2222c08b119df85bc7231bf0e6806f3a1a6florian
306b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   if (value == 1) {
307b7def2222c08b119df85bc7231bf0e6806f3a1a6florian      *addr |= mask;   // set
308b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   } else {
309b7def2222c08b119df85bc7231bf0e6806f3a1a6florian      *addr &= ~mask;  // clear
310b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   }
311b7def2222c08b119df85bc7231bf0e6806f3a1a6florian}
312b7def2222c08b119df85bc7231bf0e6806f3a1a6florian
313933065d4f3548466da4666c5cfda7e5eaff93759florianULong
314ae88411aaa8e0b99032fb0bdb04eec21edc54d88florians390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, ULong *addr)
315933065d4f3548466da4666c5cfda7e5eaff93759florian{
316933065d4f3548466da4666c5cfda7e5eaff93759florian   ULong hoststfle[S390_NUM_FACILITY_DW], cc, num_dw, i;
317933065d4f3548466da4666c5cfda7e5eaff93759florian   register ULong reg0 asm("0") = guest_state->guest_r0 & 0xF;  /* r0[56:63] */
318933065d4f3548466da4666c5cfda7e5eaff93759florian
319933065d4f3548466da4666c5cfda7e5eaff93759florian   /* We cannot store more than S390_NUM_FACILITY_DW
320933065d4f3548466da4666c5cfda7e5eaff93759florian      (and it makes not much sense to do so anyhow) */
321933065d4f3548466da4666c5cfda7e5eaff93759florian   if (reg0 > S390_NUM_FACILITY_DW - 1)
322933065d4f3548466da4666c5cfda7e5eaff93759florian      reg0 = S390_NUM_FACILITY_DW - 1;
323933065d4f3548466da4666c5cfda7e5eaff93759florian
324933065d4f3548466da4666c5cfda7e5eaff93759florian   num_dw = reg0 + 1;  /* number of double words written */
325933065d4f3548466da4666c5cfda7e5eaff93759florian
326933065d4f3548466da4666c5cfda7e5eaff93759florian   asm volatile(" .insn s,0xb2b00000,%0\n"   /* stfle */
327933065d4f3548466da4666c5cfda7e5eaff93759florian                "ipm    %2\n"
328933065d4f3548466da4666c5cfda7e5eaff93759florian                "srl    %2,28\n"
329933065d4f3548466da4666c5cfda7e5eaff93759florian                : "=m" (hoststfle), "+d"(reg0), "=d"(cc) : : "cc", "memory");
330933065d4f3548466da4666c5cfda7e5eaff93759florian
331933065d4f3548466da4666c5cfda7e5eaff93759florian   /* Update guest register 0  with what STFLE set r0 to */
332933065d4f3548466da4666c5cfda7e5eaff93759florian   guest_state->guest_r0 = reg0;
333933065d4f3548466da4666c5cfda7e5eaff93759florian
334b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   /* Set default: VM facilities = host facilities */
335933065d4f3548466da4666c5cfda7e5eaff93759florian   for (i = 0; i < num_dw; ++i)
336ae88411aaa8e0b99032fb0bdb04eec21edc54d88florian      addr[i] = hoststfle[i];
337933065d4f3548466da4666c5cfda7e5eaff93759florian
338b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   /* Now adjust the VM facilities according to what the VM supports */
339b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_LDISP,  1);
340b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_EIMM,   1);
341b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_ETF2,   1);
342b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_ETF3,   1);
343b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_GIE,    1);
344b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_EXEXT,  1);
345b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_HIGHW,  1);
346b7def2222c08b119df85bc7231bf0e6806f3a1a6florian
347b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_HFPMAS, 0);
348b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_HFPUNX, 0);
349b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_XCPUT,  0);
350b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_MSA,    0);
351b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_PENH,   0);
352b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_DFP,    0);
353b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_PFPO,   0);
354b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_DFPZC,  0);
355b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_MISC,   0);
356b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_CTREXE, 0);
357b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_TREXE,  0);
358b7def2222c08b119df85bc7231bf0e6806f3a1a6florian   s390_set_facility_bit(addr, S390_FAC_MSA4,   0);
359b7def2222c08b119df85bc7231bf0e6806f3a1a6florian
360933065d4f3548466da4666c5cfda7e5eaff93759florian   return cc;
361933065d4f3548466da4666c5cfda7e5eaff93759florian}
362933065d4f3548466da4666c5cfda7e5eaff93759florian
363933065d4f3548466da4666c5cfda7e5eaff93759florian#else
364933065d4f3548466da4666c5cfda7e5eaff93759florian
365933065d4f3548466da4666c5cfda7e5eaff93759florianULong
366ae88411aaa8e0b99032fb0bdb04eec21edc54d88florians390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, ULong *addr)
367933065d4f3548466da4666c5cfda7e5eaff93759florian{
368933065d4f3548466da4666c5cfda7e5eaff93759florian   return 3;
369933065d4f3548466da4666c5cfda7e5eaff93759florian}
370933065d4f3548466da4666c5cfda7e5eaff93759florian#endif /* VGA_s390x */
371933065d4f3548466da4666c5cfda7e5eaff93759florian
372a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian/*------------------------------------------------------------*/
373a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian/*--- Dirty helper for the "convert unicode" insn family.  ---*/
374a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian/*------------------------------------------------------------*/
375a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorianvoid
376a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorians390x_dirtyhelper_CUxy(UChar *address, ULong data, ULong num_bytes)
377a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian{
378a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   UInt i;
379a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
380a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   vassert(num_bytes >= 1 && num_bytes <= 4);
381a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
382a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   /* Store the least significant NUM_BYTES bytes in DATA left to right
383a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      at ADDRESS. */
384a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   for (i = 1; i <= num_bytes; ++i) {
385a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      address[num_bytes - i] = data & 0xff;
386a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      data >>= 8;
387a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   }
388a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian}
389a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
390a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
391a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian/*------------------------------------------------------------*/
392a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian/*--- Clean helper for CU21.                               ---*/
393a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian/*------------------------------------------------------------*/
394a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
395a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian/* The function performs a CU21 operation. It returns three things
396a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   encoded in an ULong value:
397a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   - the converted bytes (at most 4)
398a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   - the number of converted bytes
399a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   - an indication whether LOW_SURROGATE, if any, is invalid
400a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
401a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   64      48                16           8                       0
402a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian    +-------+-----------------+-----------+-----------------------+
403a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian    |  0x0  | converted bytes | num_bytes | invalid_low_surrogate |
404a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian    +-------+-----------------+-----------+-----------------------+
405a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian*/
406a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorianULong
407a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorians390_do_cu21(UInt srcval, UInt low_surrogate)
408a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian{
409a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   ULong retval = 0;   // shut up gcc
410ae88411aaa8e0b99032fb0bdb04eec21edc54d88florian   UInt b1, b2, b3, b4, num_bytes, invalid_low_surrogate = 0;
411a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
412a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   srcval &= 0xffff;
413a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
414a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   /* Determine the number of bytes in the converted value */
415a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   if (srcval <= 0x007f)
416a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      num_bytes = 1;
417a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   else if (srcval >= 0x0080 && srcval <= 0x07ff)
418a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      num_bytes = 2;
419a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   else if ((srcval >= 0x0800 && srcval <= 0xd7ff) ||
420a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian            (srcval >= 0xdc00 && srcval <= 0xffff))
421a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      num_bytes = 3;
422a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   else
423a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      num_bytes = 4;
424a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
425a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   /* Determine UTF-8 bytes according to calculated num_bytes */
426a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   switch (num_bytes){
427a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   case 1:
428a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      retval = srcval;
429a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      break;
430a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
431a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   case 2:
432a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      /* order of bytes left to right: b1, b2 */
433a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b1  = 0xc0;
434a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b1 |= srcval >> 6;
435a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
436a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b2  = 0x80;
437a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b2 |= srcval & 0x3f;
438a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
439a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      retval = (b1 << 8) | b2;
440a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      break;
441a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
442a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   case 3:
443a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      /* order of bytes left to right: b1, b2, b3 */
444a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b1  = 0xe0;
445a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b1 |= srcval >> 12;
446a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
447a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b2  = 0x80;
448a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b2 |= (srcval >> 6) & 0x3f;
449a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
450a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b3  = 0x80;
451a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b3 |= srcval & 0x3f;
452a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
453a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      retval = (b1 << 16) | (b2 << 8) | b3;
454a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      break;
455a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
456a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   case 4: {
457a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      /* order of bytes left to right: b1, b2, b3, b4 */
458a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      UInt high_surrogate = srcval;
459a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      UInt uvwxy = ((high_surrogate >> 6) & 0xf) + 1;   // abcd + 1
460a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
461a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b1  = 0xf0;
462a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b1 |= uvwxy >> 2;     // uvw
463a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
464a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b2  = 0x80;
465a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b2 |= (uvwxy & 0x3) << 4;           // xy
466a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b2 |= (high_surrogate >> 2) & 0xf;  // efgh
467a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
468a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b3  = 0x80;
469a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b3 |= (high_surrogate & 0x3) << 4;   // ij
470a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b3 |= (low_surrogate >> 6) & 0xf;    // klmn
471a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
472a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b4  = 0x80;
473a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      b4 |= low_surrogate & 0x3f;
474a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
475a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      retval = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
476a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
477a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      invalid_low_surrogate = (low_surrogate & 0xfc00) != 0xdc00;
478a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      break;
479a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   }
480a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   }
481a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
482a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   /* At this point RETVAL contains the converted bytes.
483a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian      Build up the final return value. */
484a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian   return (retval << 16) | (num_bytes << 8) | invalid_low_surrogate;
485a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian}
486a0100c9e17c7cd5a2373d2b3e306d4cb79cbbd1eflorian
487e711c805f1de40b8fafce36d04e589c6a5074e9aflorian
488e711c805f1de40b8fafce36d04e589c6a5074e9aflorian/*------------------------------------------------------------*/
4892a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian/*--- Clean helper for CU24.                               ---*/
4902a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian/*------------------------------------------------------------*/
4912a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian
4922a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian/* The function performs a CU24 operation. It returns two things
4932a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian   encoded in an ULong value:
4942a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian   - the 4 converted bytes
4952a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian   - an indication whether LOW_SURROGATE, if any, is invalid
4962a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian
4972a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian   64     40                 8                       0
4982a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian    +------------------------+-----------------------+
4992a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian    |  0x0 | converted bytes | invalid_low_surrogate |
5002a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian    +------------------------+-----------------------+
5012a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian*/
5022a415a1a1f656e56f88c65f12a37b2658cb45e0bflorianULong
5032a415a1a1f656e56f88c65f12a37b2658cb45e0bflorians390_do_cu24(UInt srcval, UInt low_surrogate)
5042a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian{
5052a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian   ULong retval;
5062a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian   UInt invalid_low_surrogate = 0;
5072a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian
5082a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian   srcval &= 0xffff;
5092a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian
5102a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian   if ((srcval >= 0x0000 && srcval <= 0xd7ff) ||
5112a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian       (srcval >= 0xdc00 && srcval <= 0xffff)) {
5122a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian      retval = srcval;
5132a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian   } else {
5142a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian      /* D800 - DBFF */
5152a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian      UInt high_surrogate = srcval;
5162a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian      UInt uvwxy  = ((high_surrogate >> 6) & 0xf) + 1;   // abcd + 1
5172a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian      UInt efghij = high_surrogate & 0x3f;
5182a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian      UInt klmnoprst = low_surrogate & 0x3ff;
5192a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian
5202a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian      retval = (uvwxy << 16) | (efghij << 10) | klmnoprst;
5212a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian
5222a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian      invalid_low_surrogate = (low_surrogate & 0xfc00) != 0xdc00;
5232a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian   }
5242a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian
5252a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian   /* At this point RETVAL contains the converted bytes.
5262a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian      Build up the final return value. */
5272a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian   return (retval << 8) | invalid_low_surrogate;
5282a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian}
5292a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian
5302a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian
5312a415a1a1f656e56f88c65f12a37b2658cb45e0bflorian/*------------------------------------------------------------*/
532956194bc1039e9dc43dac4b18ab1fdd5054a5671florian/*--- Clean helper for CU42.                               ---*/
533956194bc1039e9dc43dac4b18ab1fdd5054a5671florian/*------------------------------------------------------------*/
534956194bc1039e9dc43dac4b18ab1fdd5054a5671florian
535956194bc1039e9dc43dac4b18ab1fdd5054a5671florian/* The function performs a CU42 operation. It returns three things
536956194bc1039e9dc43dac4b18ab1fdd5054a5671florian   encoded in an ULong value:
537956194bc1039e9dc43dac4b18ab1fdd5054a5671florian   - the converted bytes (at most 4)
538956194bc1039e9dc43dac4b18ab1fdd5054a5671florian   - the number of converted bytes (2 or 4; 0 if invalid character)
539956194bc1039e9dc43dac4b18ab1fdd5054a5671florian   - an indication whether the UTF-32 character is invalid
540956194bc1039e9dc43dac4b18ab1fdd5054a5671florian
541956194bc1039e9dc43dac4b18ab1fdd5054a5671florian   64      48                16           8                   0
542956194bc1039e9dc43dac4b18ab1fdd5054a5671florian    +-------+-----------------+-----------+-------------------+
543956194bc1039e9dc43dac4b18ab1fdd5054a5671florian    |  0x0  | converted bytes | num_bytes | invalid_character |
544956194bc1039e9dc43dac4b18ab1fdd5054a5671florian    +-------+-----------------+-----------+-------------------+
545956194bc1039e9dc43dac4b18ab1fdd5054a5671florian*/
546956194bc1039e9dc43dac4b18ab1fdd5054a5671florianULong
547956194bc1039e9dc43dac4b18ab1fdd5054a5671florians390_do_cu42(UInt srcval)
548956194bc1039e9dc43dac4b18ab1fdd5054a5671florian{
549956194bc1039e9dc43dac4b18ab1fdd5054a5671florian   ULong retval;
550956194bc1039e9dc43dac4b18ab1fdd5054a5671florian   UInt num_bytes, invalid_character = 0;
551956194bc1039e9dc43dac4b18ab1fdd5054a5671florian
552956194bc1039e9dc43dac4b18ab1fdd5054a5671florian   if ((srcval >= 0x0000 && srcval <= 0xd7ff) ||
553956194bc1039e9dc43dac4b18ab1fdd5054a5671florian       (srcval >= 0xdc00 && srcval <= 0xffff)) {
554956194bc1039e9dc43dac4b18ab1fdd5054a5671florian      retval = srcval;
555956194bc1039e9dc43dac4b18ab1fdd5054a5671florian      num_bytes = 2;
556956194bc1039e9dc43dac4b18ab1fdd5054a5671florian   } else if (srcval >= 0x00010000 && srcval <= 0x0010FFFF) {
557956194bc1039e9dc43dac4b18ab1fdd5054a5671florian      UInt uvwxy  = srcval >> 16;
558956194bc1039e9dc43dac4b18ab1fdd5054a5671florian      UInt abcd   = (uvwxy - 1) & 0xf;
559956194bc1039e9dc43dac4b18ab1fdd5054a5671florian      UInt efghij = (srcval >> 10) & 0x3f;
560956194bc1039e9dc43dac4b18ab1fdd5054a5671florian
561956194bc1039e9dc43dac4b18ab1fdd5054a5671florian      UInt high_surrogate = (0xd8 << 8) | (abcd << 6) | efghij;
562956194bc1039e9dc43dac4b18ab1fdd5054a5671florian      UInt low_surrogate  = (0xdc << 8) | (srcval & 0x3ff);
563956194bc1039e9dc43dac4b18ab1fdd5054a5671florian
564956194bc1039e9dc43dac4b18ab1fdd5054a5671florian      retval = (high_surrogate << 16) | low_surrogate;
565956194bc1039e9dc43dac4b18ab1fdd5054a5671florian      num_bytes = 4;
566956194bc1039e9dc43dac4b18ab1fdd5054a5671florian   } else {
567956194bc1039e9dc43dac4b18ab1fdd5054a5671florian      /* D800 - DBFF or 00110000 - FFFFFFFF */
568956194bc1039e9dc43dac4b18ab1fdd5054a5671florian      invalid_character = 1;
569956194bc1039e9dc43dac4b18ab1fdd5054a5671florian      retval = num_bytes = 0;   /* does not matter; not used */
570956194bc1039e9dc43dac4b18ab1fdd5054a5671florian   }
571956194bc1039e9dc43dac4b18ab1fdd5054a5671florian
572956194bc1039e9dc43dac4b18ab1fdd5054a5671florian   /* At this point RETVAL contains the converted bytes.
573956194bc1039e9dc43dac4b18ab1fdd5054a5671florian      Build up the final return value. */
574956194bc1039e9dc43dac4b18ab1fdd5054a5671florian   return (retval << 16) | (num_bytes << 8) | invalid_character;
575956194bc1039e9dc43dac4b18ab1fdd5054a5671florian}
576956194bc1039e9dc43dac4b18ab1fdd5054a5671florian
577956194bc1039e9dc43dac4b18ab1fdd5054a5671florian
578956194bc1039e9dc43dac4b18ab1fdd5054a5671florian/*------------------------------------------------------------*/
579af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian/*--- Clean helper for CU41.                               ---*/
580af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian/*------------------------------------------------------------*/
581af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian
582af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian/* The function performs a CU41 operation. It returns three things
583af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   encoded in an ULong value:
584af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   - the converted bytes (at most 4)
585af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   - the number of converted bytes (1, 2, 3, or 4; 0 if invalid character)
586af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   - an indication whether the UTF-32 character is invalid
587af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian
588af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   64      48                16           8                   0
589af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian    +-------+-----------------+-----------+-------------------+
590af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian    |  0x0  | converted bytes | num_bytes | invalid_character |
591af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian    +-------+-----------------+-----------+-------------------+
592af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian*/
593af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florianULong
594af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florians390_do_cu41(UInt srcval)
595af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian{
596af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   ULong retval;
597af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   UInt num_bytes, invalid_character = 0;
598af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian
599af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   if (srcval <= 0x7f) {
600af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      retval = srcval;
601af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      num_bytes = 1;
602af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   } else if (srcval >= 0x80 && srcval <= 0x7ff) {
603af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt fghij  = srcval >> 6;
604af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt klmnop = srcval & 0x3f;
605af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt byte1  = (0xc0 | fghij);
606af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt byte2  = (0x80 | klmnop);
607af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian
608af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      retval = (byte1 << 8) | byte2;
609af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      num_bytes = 2;
610af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   } else if ((srcval >= 0x800  && srcval <= 0xd7ff) ||
611af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian              (srcval >= 0xdc00 && srcval <= 0xffff)) {
612af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt abcd   = srcval >> 12;
613af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt efghij = (srcval >> 6) & 0x3f;
614af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt klmnop = srcval & 0x3f;
615af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt byte1  = 0xe0 | abcd;
616af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt byte2  = 0x80 | efghij;
617af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt byte3  = 0x80 | klmnop;
618af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian
619af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      retval = (byte1 << 16) | (byte2 << 8) | byte3;
620af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      num_bytes = 3;
621af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   } else if (srcval >= 0x10000 && srcval <= 0x10ffff) {
622af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt uvw    = (srcval >> 18) & 0x7;
623af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt xy     = (srcval >> 16) & 0x3;
624af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt efgh   = (srcval >> 12) & 0xf;
625af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt ijklmn = (srcval >>  6) & 0x3f;
626af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt opqrst = srcval & 0x3f;
627af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt byte1  = 0xf0 | uvw;
628af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt byte2  = 0x80 | (xy << 4) | efgh;
629af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt byte3  = 0x80 | ijklmn;
630af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      UInt byte4  = 0x80 | opqrst;
631af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian
632af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      retval = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
633af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      num_bytes = 4;
634af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   } else {
635af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      /* d800 ... dbff or 00110000 ... ffffffff */
636af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      invalid_character = 1;
637af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian
638af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      retval = 0;
639af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      num_bytes = 0;
640af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   }
641af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian
642af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   /* At this point RETVAL contains the converted bytes.
643af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian      Build up the final return value. */
644af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian   return (retval << 16) | (num_bytes << 8) | invalid_character;
645af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian}
646af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian
647af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian
648af2194f3e45a0bd6db4c4857d1f2be21f857d3f3florian/*------------------------------------------------------------*/
6496d9b9b23ea3541501ea98a39e2d757892a79c78aflorian/*--- Clean helpers for CU12.                              ---*/
6506d9b9b23ea3541501ea98a39e2d757892a79c78aflorian/*------------------------------------------------------------*/
6516d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
6526d9b9b23ea3541501ea98a39e2d757892a79c78aflorian/* The function looks at the first byte of an UTF-8 character and returns
6536d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   two things encoded in an ULong value:
6546d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
6556d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   - the number of bytes that need to be read
6566d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   - an indication whether the UTF-8 character is invalid
6576d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
6586d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   64      16           8                   0
6596d9b9b23ea3541501ea98a39e2d757892a79c78aflorian    +-------------------+-------------------+
6606d9b9b23ea3541501ea98a39e2d757892a79c78aflorian    |  0x0  | num_bytes | invalid_character |
6616d9b9b23ea3541501ea98a39e2d757892a79c78aflorian    +-------+-----------+-------------------+
6626d9b9b23ea3541501ea98a39e2d757892a79c78aflorian*/
6636d9b9b23ea3541501ea98a39e2d757892a79c78aflorianULong
6643f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florians390_do_cu12_cu14_helper1(UInt byte, UInt etf3_and_m3_is_1)
6656d9b9b23ea3541501ea98a39e2d757892a79c78aflorian{
6666d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   vassert(byte <= 0xff);
6676d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
6686d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   /* Check whether the character is invalid */
6696d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   if (byte >= 0x80 && byte <= 0xbf) return 1;
6706d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   if (byte >= 0xf8) return 1;
6716d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
6726d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   if (etf3_and_m3_is_1) {
6736d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      if (byte == 0xc0 || byte == 0xc1) return 1;
6746d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      if (byte >= 0xf5 && byte <= 0xf7) return 1;
6756d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   }
6766d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
6776d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   /* Character is valid */
6786d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   if (byte <= 0x7f) return 1 << 8;   // 1 byte
6796d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   if (byte <= 0xdf) return 2 << 8;   // 2 bytes
6806d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   if (byte <= 0xef) return 3 << 8;   // 3 bytes
6816d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
6826d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   return 4 << 8;  // 4 bytes
6836d9b9b23ea3541501ea98a39e2d757892a79c78aflorian}
6846d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
6853f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian/* The function performs a CU12 or CU14 operation. BYTE1, BYTE2, etc are the
6866d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   bytes as read from the input stream, left to right. BYTE1 is a valid
6876d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   byte. The function returns three things encoded in an ULong value:
6886d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
6896d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   - the converted bytes
6906d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   - the number of converted bytes (2 or 4; 0 if invalid character)
6916d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   - an indication whether the UTF-16 character is invalid
6926d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
6936d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   64      48                16           8                   0
6946d9b9b23ea3541501ea98a39e2d757892a79c78aflorian    +-------+-----------------+-----------+-------------------+
6956d9b9b23ea3541501ea98a39e2d757892a79c78aflorian    |  0x0  | converted bytes | num_bytes | invalid_character |
6966d9b9b23ea3541501ea98a39e2d757892a79c78aflorian    +-------+-----------------+-----------+-------------------+
6976d9b9b23ea3541501ea98a39e2d757892a79c78aflorian*/
6983f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florianstatic ULong
6993f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florians390_do_cu12_cu14_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4,
7003f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian                          ULong stuff, Bool is_cu12)
7016d9b9b23ea3541501ea98a39e2d757892a79c78aflorian{
7023f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian   UInt num_src_bytes = stuff >> 1, etf3_and_m3_is_1 = stuff & 0x1;
7036d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   UInt num_bytes = 0, invalid_character = 0;
7046d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   ULong retval = 0;
7056d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
7066d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   vassert(num_src_bytes <= 4);
7076d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
7086d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   switch (num_src_bytes) {
7096d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   case 1:
7106d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      num_bytes = 2;
7116d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      retval = byte1;
7126d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      break;
7136d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
7146d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   case 2: {
7156d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      /* Test validity */
7166d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      if (etf3_and_m3_is_1) {
7176d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         if (byte2 < 0x80 || byte2 > 0xbf) {
7186d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            invalid_character = 1;
7196d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            break;
7206d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         }
7216d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      }
7226d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
7236d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      /* OK */
7246d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      UInt fghij  = byte1 & 0x1f;
7256d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      UInt klmnop = byte2 & 0x3f;
7266d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
7276d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      num_bytes = 2;
7286d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      retval = (fghij << 6) | klmnop;
7296d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      break;
7306d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   }
7316d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
7326d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   case 3: {
7336d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      /* Test validity */
7346d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      if (etf3_and_m3_is_1) {
7356d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         if (byte1 == 0xe0) {
7366d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            if ((byte2 < 0xa0 || byte2 > 0xbf) ||
7376d9b9b23ea3541501ea98a39e2d757892a79c78aflorian                (byte3 < 0x80 || byte3 > 0xbf)) {
7386d9b9b23ea3541501ea98a39e2d757892a79c78aflorian               invalid_character = 1;
7396d9b9b23ea3541501ea98a39e2d757892a79c78aflorian               break;
7406d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            }
7416d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         }
7426d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         if ((byte1 >= 0xe1 && byte1 <= 0xec) ||
7436d9b9b23ea3541501ea98a39e2d757892a79c78aflorian             byte1 == 0xee || byte1 == 0xef) {
7446d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            if ((byte2 < 0x80 || byte2 > 0xbf) ||
7456d9b9b23ea3541501ea98a39e2d757892a79c78aflorian                (byte3 < 0x80 || byte3 > 0xbf)) {
7466d9b9b23ea3541501ea98a39e2d757892a79c78aflorian               invalid_character = 1;
7476d9b9b23ea3541501ea98a39e2d757892a79c78aflorian               break;
7486d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            }
7496d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         }
7506d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         if (byte1 == 0xed) {
7516d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            if ((byte2 < 0x80 || byte2 > 0x9f) ||
7526d9b9b23ea3541501ea98a39e2d757892a79c78aflorian                (byte3 < 0x80 || byte3 > 0xbf)) {
7536d9b9b23ea3541501ea98a39e2d757892a79c78aflorian               invalid_character = 1;
7546d9b9b23ea3541501ea98a39e2d757892a79c78aflorian               break;
7556d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            }
7566d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         }
7576d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      }
7586d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
7596d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      /* OK */
7606d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      UInt abcd   = byte1 & 0xf;
7616d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      UInt efghij = byte2 & 0x3f;
7626d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      UInt klmnop = byte3 & 0x3f;
7636d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
7646d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      num_bytes = 2;
7656d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      retval = (abcd << 12) | (efghij << 6) | klmnop;
7666d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      break;
7676d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   }
7686d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
7696d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   case 4: {
7706d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      /* Test validity */
7716d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      if (etf3_and_m3_is_1) {
7726d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         if (byte1 == 0xf0) {
7736d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            if ((byte2 < 0x90 || byte2 > 0xbf) ||
7746d9b9b23ea3541501ea98a39e2d757892a79c78aflorian                (byte3 < 0x80 || byte3 > 0xbf) ||
7756d9b9b23ea3541501ea98a39e2d757892a79c78aflorian                (byte4 < 0x80 || byte4 > 0xbf)) {
7766d9b9b23ea3541501ea98a39e2d757892a79c78aflorian               invalid_character = 1;
7776d9b9b23ea3541501ea98a39e2d757892a79c78aflorian               break;
7786d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            }
7796d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         }
7806d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         if (byte1 == 0xf1 || byte1 == 0xf2 || byte1 == 0xf3) {
7816d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            if ((byte2 < 0x80 || byte2 > 0xbf) ||
7826d9b9b23ea3541501ea98a39e2d757892a79c78aflorian                (byte3 < 0x80 || byte3 > 0xbf) ||
7836d9b9b23ea3541501ea98a39e2d757892a79c78aflorian                (byte4 < 0x80 || byte4 > 0xbf)) {
7846d9b9b23ea3541501ea98a39e2d757892a79c78aflorian               invalid_character = 1;
7856d9b9b23ea3541501ea98a39e2d757892a79c78aflorian               break;
7866d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            }
7876d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         }
7886d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         if (byte1 == 0xf4) {
7896d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            if ((byte2 < 0x80 || byte2 > 0x8f) ||
7906d9b9b23ea3541501ea98a39e2d757892a79c78aflorian                (byte3 < 0x80 || byte3 > 0xbf) ||
7916d9b9b23ea3541501ea98a39e2d757892a79c78aflorian                (byte4 < 0x80 || byte4 > 0xbf)) {
7926d9b9b23ea3541501ea98a39e2d757892a79c78aflorian               invalid_character = 1;
7936d9b9b23ea3541501ea98a39e2d757892a79c78aflorian               break;
7946d9b9b23ea3541501ea98a39e2d757892a79c78aflorian            }
7956d9b9b23ea3541501ea98a39e2d757892a79c78aflorian         }
7966d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      }
7976d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
7986d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      /* OK */
7996d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      UInt uvw    = byte1 & 0x7;
8006d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      UInt xy     = (byte2 >> 4) & 0x3;
8016d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      UInt uvwxy  = (uvw << 2) | xy;
8026d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      UInt efgh   = byte2 & 0xf;
8036d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      UInt ij     = (byte3 >> 4) & 0x3;
8046d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      UInt klmn   = byte3 & 0xf;
8056d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      UInt opqrst = byte4 & 0x3f;
8066d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
8073f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian      if (is_cu12) {
8083f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian         UInt abcd = (uvwxy - 1) & 0xf;
8093f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian         UInt high_surrogate = (0xd8 << 8) | (abcd << 6) | (efgh << 2) | ij;
8103f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian         UInt low_surrogate  = (0xdc << 8) | (klmn << 6) | opqrst;
8113f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian
8123f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian         num_bytes = 4;
8133f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian         retval = (high_surrogate << 16) | low_surrogate;
8143f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian      } else {
8153f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian         num_bytes = 4;
8163f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian         retval =
8173f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian            (uvwxy << 16) | (efgh << 12) | (ij << 10) | (klmn << 6) | opqrst;
8183f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian      }
8196d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      break;
8206d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   }
8216d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   }
8226d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
8233f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian   if (! is_cu12) num_bytes = 4;   // for CU14, by definition
8243f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian
8256d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   /* At this point RETVAL contains the converted bytes.
8266d9b9b23ea3541501ea98a39e2d757892a79c78aflorian      Build up the final return value. */
8276d9b9b23ea3541501ea98a39e2d757892a79c78aflorian   return (retval << 16) | (num_bytes << 8) | invalid_character;
8286d9b9b23ea3541501ea98a39e2d757892a79c78aflorian}
8296d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
8303f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florianULong
8313f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florians390_do_cu12_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4,
8323f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian                     ULong stuff)
8333f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian{
8343f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian   return s390_do_cu12_cu14_helper2(byte1, byte2, byte3, byte4, stuff,
8353f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian                                    /* is_cu12 = */ 1);
8363f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian}
8373f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian
8383f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florianULong
8393f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florians390_do_cu14_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4,
8403f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian                     ULong stuff)
8413f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian{
8423f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian   return s390_do_cu12_cu14_helper2(byte1, byte2, byte3, byte4, stuff,
8433f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian                                    /* is_cu12 = */ 0);
8443f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian}
8453f8a96a5e5e9baac2ce8eeeb8d10db92e9bd6ae4florian
8466d9b9b23ea3541501ea98a39e2d757892a79c78aflorian
8476d9b9b23ea3541501ea98a39e2d757892a79c78aflorian/*------------------------------------------------------------*/
848e711c805f1de40b8fafce36d04e589c6a5074e9aflorian/*--- Clean helper for "convert to binary".                ---*/
849e711c805f1de40b8fafce36d04e589c6a5074e9aflorian/*------------------------------------------------------------*/
850e711c805f1de40b8fafce36d04e589c6a5074e9aflorian#if defined(VGA_s390x)
851e711c805f1de40b8fafce36d04e589c6a5074e9aflorianUInt
852e711c805f1de40b8fafce36d04e589c6a5074e9aflorians390_do_cvb(ULong decimal)
853e711c805f1de40b8fafce36d04e589c6a5074e9aflorian{
854e711c805f1de40b8fafce36d04e589c6a5074e9aflorian   UInt binary;
855e711c805f1de40b8fafce36d04e589c6a5074e9aflorian
856e711c805f1de40b8fafce36d04e589c6a5074e9aflorian   __asm__ volatile (
857e711c805f1de40b8fafce36d04e589c6a5074e9aflorian        "cvb %[result],%[input]\n\t"
858e711c805f1de40b8fafce36d04e589c6a5074e9aflorian          : [result] "=d"(binary)
859e711c805f1de40b8fafce36d04e589c6a5074e9aflorian          : [input] "m"(decimal)
860e711c805f1de40b8fafce36d04e589c6a5074e9aflorian   );
861e711c805f1de40b8fafce36d04e589c6a5074e9aflorian
862e711c805f1de40b8fafce36d04e589c6a5074e9aflorian   return binary;
863e711c805f1de40b8fafce36d04e589c6a5074e9aflorian}
864e711c805f1de40b8fafce36d04e589c6a5074e9aflorian
865e711c805f1de40b8fafce36d04e589c6a5074e9aflorian#else
866e711c805f1de40b8fafce36d04e589c6a5074e9aflorianUInt s390_do_cvb(ULong decimal) { return 0; }
867e711c805f1de40b8fafce36d04e589c6a5074e9aflorian#endif
868e711c805f1de40b8fafce36d04e589c6a5074e9aflorian
869e711c805f1de40b8fafce36d04e589c6a5074e9aflorian
870e711c805f1de40b8fafce36d04e589c6a5074e9aflorian/*------------------------------------------------------------*/
871e711c805f1de40b8fafce36d04e589c6a5074e9aflorian/*--- Clean helper for "convert to decimal".                ---*/
872e711c805f1de40b8fafce36d04e589c6a5074e9aflorian/*------------------------------------------------------------*/
873e711c805f1de40b8fafce36d04e589c6a5074e9aflorian#if defined(VGA_s390x)
874e711c805f1de40b8fafce36d04e589c6a5074e9aflorianULong
875e711c805f1de40b8fafce36d04e589c6a5074e9aflorians390_do_cvd(ULong binary_in)
876e711c805f1de40b8fafce36d04e589c6a5074e9aflorian{
877e711c805f1de40b8fafce36d04e589c6a5074e9aflorian   UInt binary = binary_in & 0xffffffffULL;
878e711c805f1de40b8fafce36d04e589c6a5074e9aflorian   ULong decimal;
879e711c805f1de40b8fafce36d04e589c6a5074e9aflorian
880e711c805f1de40b8fafce36d04e589c6a5074e9aflorian   __asm__ volatile (
881e711c805f1de40b8fafce36d04e589c6a5074e9aflorian        "cvd %[input],%[result]\n\t"
882e711c805f1de40b8fafce36d04e589c6a5074e9aflorian          : [result] "=m"(decimal)
883e711c805f1de40b8fafce36d04e589c6a5074e9aflorian          : [input] "d"(binary)
884e711c805f1de40b8fafce36d04e589c6a5074e9aflorian   );
885e711c805f1de40b8fafce36d04e589c6a5074e9aflorian
886e711c805f1de40b8fafce36d04e589c6a5074e9aflorian   return decimal;
887e711c805f1de40b8fafce36d04e589c6a5074e9aflorian}
888e711c805f1de40b8fafce36d04e589c6a5074e9aflorian
889e711c805f1de40b8fafce36d04e589c6a5074e9aflorian#else
890e711c805f1de40b8fafce36d04e589c6a5074e9aflorianULong s390_do_cvd(ULong binary) { return 0; }
891e711c805f1de40b8fafce36d04e589c6a5074e9aflorian#endif
892e711c805f1de40b8fafce36d04e589c6a5074e9aflorian
8938c88cb6ae821021e1e00be18f5a8bea3c557080aflorian/*------------------------------------------------------------*/
8948c88cb6ae821021e1e00be18f5a8bea3c557080aflorian/*--- Clean helper for "Extract cache attribute".          ---*/
8958c88cb6ae821021e1e00be18f5a8bea3c557080aflorian/*------------------------------------------------------------*/
8968c88cb6ae821021e1e00be18f5a8bea3c557080aflorian#if defined(VGA_s390x)
8978c88cb6ae821021e1e00be18f5a8bea3c557080aflorianULong
8988c88cb6ae821021e1e00be18f5a8bea3c557080aflorians390_do_ecag(ULong op2addr)
8998c88cb6ae821021e1e00be18f5a8bea3c557080aflorian{
9008c88cb6ae821021e1e00be18f5a8bea3c557080aflorian   ULong result;
9018c88cb6ae821021e1e00be18f5a8bea3c557080aflorian
9028c88cb6ae821021e1e00be18f5a8bea3c557080aflorian   __asm__ volatile(".insn rsy,0xEB000000004C,%[out],0,0(%[in])\n\t"
9038c88cb6ae821021e1e00be18f5a8bea3c557080aflorian                    : [out] "=d"(result)
9048c88cb6ae821021e1e00be18f5a8bea3c557080aflorian                    : [in] "d"(op2addr));
9058c88cb6ae821021e1e00be18f5a8bea3c557080aflorian   return result;
9068c88cb6ae821021e1e00be18f5a8bea3c557080aflorian}
9078c88cb6ae821021e1e00be18f5a8bea3c557080aflorian
9088c88cb6ae821021e1e00be18f5a8bea3c557080aflorian#else
9098c88cb6ae821021e1e00be18f5a8bea3c557080aflorianULong s390_do_ecag(ULong op2addr) { return 0; }
9108c88cb6ae821021e1e00be18f5a8bea3c557080aflorian#endif
911e711c805f1de40b8fafce36d04e589c6a5074e9aflorian
912933065d4f3548466da4666c5cfda7e5eaff93759florian/*------------------------------------------------------------*/
91378d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian/*--- Clean helper for "Perform Floating Point Operation". ---*/
91478d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian/*------------------------------------------------------------*/
91578d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian#if defined(VGA_s390x)
91678d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florianUInt
91778d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florians390_do_pfpo(UInt gpr0)
91878d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian{
91978d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian   UChar rm;
92078d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian   UChar op1_ty, op2_ty;
92178d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian
92278d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian   rm  = gpr0 & 0xf;
92378d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian   if (rm > 1 && rm < 8)
92478d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian      return EmFail_S390X_invalid_PFPO_rounding_mode;
92578d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian
92678d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian   op1_ty = (gpr0 >> 16) & 0xff; // gpr0[40:47]
92778d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian   op2_ty = (gpr0 >> 8)  & 0xff; // gpr0[48:55]
92878d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian   /* Operand type must be BFP 32, 64, 128 or DFP 32, 64, 128
92978d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian      which correspond to 0x5, 0x6, 0x7, 0x8, 0x9, 0xa respectively.
93078d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian      Any other operand type value is unsupported */
93178d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian   if ((op1_ty == op2_ty) ||
93278d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian       (op1_ty < 0x5 || op1_ty > 0xa) ||
93378d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian       (op2_ty < 0x5 || op2_ty > 0xa))
93478d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian      return EmFail_S390X_invalid_PFPO_function;
93578d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian
93678d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian   return EmNote_NONE;
93778d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian}
93878d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian#else
93978d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florianUInt s390_do_pfpo(UInt gpr0) { return 0; }
94078d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian#endif
94178d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian
94278d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian/*------------------------------------------------------------*/
9432019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*--- Helper for condition code.                           ---*/
9442019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*------------------------------------------------------------*/
9452019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
94683f60b5fac7ad065935f3c2fcf7b1454d552d6e0florian/* Convert an IRRoundingMode value to s390_bfp_round_t */
9473d80fade93ec633f3ad30f871d1a1306f75823c6florian#if defined(VGA_s390x)
948125e20dc4036944b19bed3e98a15d05cce8c29f6florianstatic s390_bfp_round_t
94919e0077d31fe17496eeb76cd008507d1a8f75908floriandecode_bfp_rounding_mode(UInt irrm)
95019e0077d31fe17496eeb76cd008507d1a8f75908florian{
95119e0077d31fe17496eeb76cd008507d1a8f75908florian   switch (irrm) {
952125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case Irrm_NEAREST: return S390_BFP_ROUND_NEAREST_EVEN;
953125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case Irrm_NegINF:  return S390_BFP_ROUND_NEGINF;
954125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case Irrm_PosINF:  return S390_BFP_ROUND_POSINF;
955125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case Irrm_ZERO:    return S390_BFP_ROUND_ZERO;
95619e0077d31fe17496eeb76cd008507d1a8f75908florian   }
95719e0077d31fe17496eeb76cd008507d1a8f75908florian   vpanic("decode_bfp_rounding_mode");
95819e0077d31fe17496eeb76cd008507d1a8f75908florian}
9593d80fade93ec633f3ad30f871d1a1306f75823c6florian#endif
96019e0077d31fe17496eeb76cd008507d1a8f75908florian
96119e0077d31fe17496eeb76cd008507d1a8f75908florian
9622019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#define S390_CC_FOR_BINARY(opcode,cc_dep1,cc_dep2) \
9632019a976f07ff418dde2dfc7cc74667ef66d7764sewardj({ \
9642019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   __asm__ volatile ( \
9652019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        opcode " %[op1],%[op2]\n\t" \
9662019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+d"(cc_dep1) \
9672019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : [op2] "d"(cc_dep2) \
9682019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : "cc");\
9692019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   psw >> 28;   /* cc */ \
9702019a976f07ff418dde2dfc7cc74667ef66d7764sewardj})
9712019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
9722019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#define S390_CC_FOR_TERNARY_SUBB(opcode,cc_dep1,cc_dep2,cc_ndep) \
9732019a976f07ff418dde2dfc7cc74667ef66d7764sewardj({ \
9742019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   /* Recover the original DEP2 value. See comment near s390_cc_thunk_put3 \
9752019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      for rationale. */ \
9762019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   cc_dep2 = cc_dep2 ^ cc_ndep; \
9772019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   __asm__ volatile ( \
9782019a976f07ff418dde2dfc7cc74667ef66d7764sewardj	"lghi 0,1\n\t" \
9792019a976f07ff418dde2dfc7cc74667ef66d7764sewardj	"sr 0,%[op3]\n\t" /* borrow to cc */ \
9802019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        opcode " %[op1],%[op2]\n\t" /* then redo the op */\
9812019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+&d"(cc_dep1) \
9822019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : [op2] "d"(cc_dep2), [op3] "d"(cc_ndep) \
9832019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : "0", "cc");\
9842019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   psw >> 28;   /* cc */ \
9852019a976f07ff418dde2dfc7cc74667ef66d7764sewardj})
9862019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
9872019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#define S390_CC_FOR_TERNARY_ADDC(opcode,cc_dep1,cc_dep2,cc_ndep) \
9882019a976f07ff418dde2dfc7cc74667ef66d7764sewardj({ \
9892019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   /* Recover the original DEP2 value. See comment near s390_cc_thunk_put3 \
9902019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      for rationale. */ \
9912019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   cc_dep2 = cc_dep2 ^ cc_ndep; \
9922019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   __asm__ volatile ( \
9932019a976f07ff418dde2dfc7cc74667ef66d7764sewardj	"lgfr 0,%[op3]\n\t" /* first load cc_ndep */ \
9942019a976f07ff418dde2dfc7cc74667ef66d7764sewardj	"aghi 0,0\n\t" /* and convert it into a cc */ \
9952019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        opcode " %[op1],%[op2]\n\t" /* then redo the op */\
9962019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ipm %[psw]\n\t"           : [psw] "=d"(psw), [op1] "+&d"(cc_dep1) \
9972019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : [op2] "d"(cc_dep2), [op3] "d"(cc_ndep) \
9982019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : "0", "cc");\
9992019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   psw >> 28;   /* cc */ \
10002019a976f07ff418dde2dfc7cc74667ef66d7764sewardj})
10012019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
10022019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
10032019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#define S390_CC_FOR_BFP_RESULT(opcode,cc_dep1) \
10042019a976f07ff418dde2dfc7cc74667ef66d7764sewardj({ \
10052019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   __asm__ volatile ( \
10062019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        opcode " 0,%[op]\n\t" \
10072019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
10082019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : [op]  "f"(cc_dep1) \
10092019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : "cc", "f0");\
10102019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   psw >> 28;   /* cc */ \
10112019a976f07ff418dde2dfc7cc74667ef66d7764sewardj})
10122019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
10132019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#define S390_CC_FOR_BFP128_RESULT(hi,lo) \
10142019a976f07ff418dde2dfc7cc74667ef66d7764sewardj({ \
10152019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   __asm__ volatile ( \
10162019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ldr   4,%[high]\n\t" \
10172019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ldr   6,%[low]\n\t" \
10182019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ltxbr 0,4\n\t" \
10192019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
10202019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : [high] "f"(hi), [low] "f"(lo) \
10212019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : "cc", "f0", "f2", "f4", "f6");\
10222019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   psw >> 28;   /* cc */ \
10232019a976f07ff418dde2dfc7cc74667ef66d7764sewardj})
10242019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
102519e0077d31fe17496eeb76cd008507d1a8f75908florian#define S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,rounding_mode) \
10262019a976f07ff418dde2dfc7cc74667ef66d7764sewardj({ \
10272019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   __asm__ volatile ( \
102819e0077d31fe17496eeb76cd008507d1a8f75908florian        opcode " 0," #rounding_mode ",%[op]\n\t" \
10292019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
10302019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : [op]  "f"(cc_dep1) \
10312019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : "cc", "r0");\
10322019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   psw >> 28;   /* cc */ \
10332019a976f07ff418dde2dfc7cc74667ef66d7764sewardj})
10342019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
103519e0077d31fe17496eeb76cd008507d1a8f75908florian#define S390_CC_FOR_BFP_CONVERT(opcode,cc_dep1,cc_dep2)   \
103619e0077d31fe17496eeb76cd008507d1a8f75908florian({                                                        \
103719e0077d31fe17496eeb76cd008507d1a8f75908florian   UInt cc;                                               \
103819e0077d31fe17496eeb76cd008507d1a8f75908florian   switch (decode_bfp_rounding_mode(cc_dep2)) {           \
1039125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_NEAREST_EVEN:                      \
104019e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,4); \
104119e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                              \
1042125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_ZERO:                              \
104319e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,5); \
104419e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                              \
1045125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_POSINF:                            \
104619e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,6); \
104719e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                              \
1048125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_NEGINF:                            \
104919e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,7); \
105019e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                              \
105119e0077d31fe17496eeb76cd008507d1a8f75908florian   default:                                               \
1052125e20dc4036944b19bed3e98a15d05cce8c29f6florian      vpanic("unexpected bfp rounding mode");             \
105319e0077d31fe17496eeb76cd008507d1a8f75908florian   }                                                      \
105419e0077d31fe17496eeb76cd008507d1a8f75908florian   cc;                                                    \
105519e0077d31fe17496eeb76cd008507d1a8f75908florian})
105619e0077d31fe17496eeb76cd008507d1a8f75908florian
105719e0077d31fe17496eeb76cd008507d1a8f75908florian#define S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,rounding_mode) \
10581c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian({ \
10591c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian   __asm__ volatile ( \
106019e0077d31fe17496eeb76cd008507d1a8f75908florian        opcode ",0,%[op]," #rounding_mode ",0\n\t" \
10611c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian        "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
10621c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian                                   : [op]  "f"(cc_dep1) \
10631c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian                                   : "cc", "r0");\
10641c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian   psw >> 28;   /* cc */ \
10651c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian})
10661c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian
106719e0077d31fe17496eeb76cd008507d1a8f75908florian#define S390_CC_FOR_BFP_UCONVERT(opcode,cc_dep1,cc_dep2)   \
106819e0077d31fe17496eeb76cd008507d1a8f75908florian({                                                         \
106919e0077d31fe17496eeb76cd008507d1a8f75908florian   UInt cc;                                                \
107019e0077d31fe17496eeb76cd008507d1a8f75908florian   switch (decode_bfp_rounding_mode(cc_dep2)) {            \
1071125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_NEAREST_EVEN:                       \
107219e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,4); \
107319e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                               \
1074125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_ZERO:                               \
107519e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,5); \
107619e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                               \
1077125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_POSINF:                             \
107819e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,6); \
107919e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                               \
1080125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_NEGINF:                             \
108119e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,7); \
108219e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                               \
108319e0077d31fe17496eeb76cd008507d1a8f75908florian   default:                                                \
1084125e20dc4036944b19bed3e98a15d05cce8c29f6florian      vpanic("unexpected bfp rounding mode");              \
108519e0077d31fe17496eeb76cd008507d1a8f75908florian   }                                                       \
108619e0077d31fe17496eeb76cd008507d1a8f75908florian   cc;                                                     \
108719e0077d31fe17496eeb76cd008507d1a8f75908florian})
108819e0077d31fe17496eeb76cd008507d1a8f75908florian
108919e0077d31fe17496eeb76cd008507d1a8f75908florian#define S390_CC_FOR_BFP128_CONVERT_AUX(opcode,hi,lo,rounding_mode) \
10902019a976f07ff418dde2dfc7cc74667ef66d7764sewardj({ \
10912019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   __asm__ volatile ( \
10922019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ldr   4,%[high]\n\t" \
10932019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ldr   6,%[low]\n\t" \
109419e0077d31fe17496eeb76cd008507d1a8f75908florian        opcode " 0," #rounding_mode ",4\n\t" \
10952019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
10962019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : [high] "f"(hi), [low] "f"(lo) \
10972019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : "cc", "r0", "f4", "f6");\
10982019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   psw >> 28;   /* cc */ \
10992019a976f07ff418dde2dfc7cc74667ef66d7764sewardj})
11002019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
110119e0077d31fe17496eeb76cd008507d1a8f75908florian#define S390_CC_FOR_BFP128_CONVERT(opcode,cc_dep1,cc_dep2,cc_ndep)   \
110219e0077d31fe17496eeb76cd008507d1a8f75908florian({                                                                   \
110319e0077d31fe17496eeb76cd008507d1a8f75908florian   UInt cc;                                                          \
110419e0077d31fe17496eeb76cd008507d1a8f75908florian   /* Recover the original DEP2 value. See comment near              \
110519e0077d31fe17496eeb76cd008507d1a8f75908florian      s390_cc_thunk_put3 for rationale. */                           \
110619e0077d31fe17496eeb76cd008507d1a8f75908florian   cc_dep2 = cc_dep2 ^ cc_ndep;                                      \
110719e0077d31fe17496eeb76cd008507d1a8f75908florian   switch (decode_bfp_rounding_mode(cc_ndep)) {                      \
1108125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_NEAREST_EVEN:                                 \
110919e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,4); \
111019e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                                         \
1111125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_ZERO:                                         \
111219e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,5); \
111319e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                                         \
1114125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_POSINF:                                       \
111519e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,6); \
111619e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                                         \
1117125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_NEGINF:                                       \
111819e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,7); \
111919e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                                         \
112019e0077d31fe17496eeb76cd008507d1a8f75908florian   default:                                                          \
1121125e20dc4036944b19bed3e98a15d05cce8c29f6florian      vpanic("unexpected bfp rounding mode");                        \
112219e0077d31fe17496eeb76cd008507d1a8f75908florian   }                                                                 \
112319e0077d31fe17496eeb76cd008507d1a8f75908florian   cc;                                                               \
112419e0077d31fe17496eeb76cd008507d1a8f75908florian})
112519e0077d31fe17496eeb76cd008507d1a8f75908florian
112619e0077d31fe17496eeb76cd008507d1a8f75908florian#define S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,hi,lo,rounding_mode) \
11271c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian({ \
11281c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian   __asm__ volatile ( \
11291c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian        "ldr   4,%[high]\n\t" \
11301c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian        "ldr   6,%[low]\n\t" \
113119e0077d31fe17496eeb76cd008507d1a8f75908florian        opcode ",0,4," #rounding_mode ",0\n\t" \
11321c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian        "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
11331c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian                                   : [high] "f"(hi), [low] "f"(lo) \
11341c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian                                   : "cc", "r0", "f4", "f6");\
11351c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian   psw >> 28;   /* cc */ \
11361c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian})
11371c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian
113819e0077d31fe17496eeb76cd008507d1a8f75908florian#define S390_CC_FOR_BFP128_UCONVERT(opcode,cc_dep1,cc_dep2,cc_ndep)   \
113919e0077d31fe17496eeb76cd008507d1a8f75908florian({                                                                    \
114019e0077d31fe17496eeb76cd008507d1a8f75908florian   UInt cc;                                                           \
114119e0077d31fe17496eeb76cd008507d1a8f75908florian   /* Recover the original DEP2 value. See comment near               \
114219e0077d31fe17496eeb76cd008507d1a8f75908florian      s390_cc_thunk_put3 for rationale. */                            \
114319e0077d31fe17496eeb76cd008507d1a8f75908florian   cc_dep2 = cc_dep2 ^ cc_ndep;                                       \
114419e0077d31fe17496eeb76cd008507d1a8f75908florian   switch (decode_bfp_rounding_mode(cc_ndep)) {                       \
1145125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_NEAREST_EVEN:                                  \
114619e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,4); \
114719e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                                          \
1148125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_ZERO:                                          \
114919e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,5); \
115019e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                                          \
1151125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_POSINF:                                        \
115219e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,6); \
115319e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                                          \
1154125e20dc4036944b19bed3e98a15d05cce8c29f6florian   case S390_BFP_ROUND_NEGINF:                                        \
115519e0077d31fe17496eeb76cd008507d1a8f75908florian      cc = S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,7); \
115619e0077d31fe17496eeb76cd008507d1a8f75908florian      break;                                                          \
115719e0077d31fe17496eeb76cd008507d1a8f75908florian   default:                                                           \
1158125e20dc4036944b19bed3e98a15d05cce8c29f6florian      vpanic("unexpected bfp rounding mode");                         \
115919e0077d31fe17496eeb76cd008507d1a8f75908florian   }                                                                  \
116019e0077d31fe17496eeb76cd008507d1a8f75908florian   cc;                                                                \
116119e0077d31fe17496eeb76cd008507d1a8f75908florian})
116219e0077d31fe17496eeb76cd008507d1a8f75908florian
11632019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#define S390_CC_FOR_BFP_TDC(opcode,cc_dep1,cc_dep2) \
11642019a976f07ff418dde2dfc7cc74667ef66d7764sewardj({ \
11652019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   __asm__ volatile ( \
11662019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        opcode " %[value],0(%[class])\n\t" \
11672019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
11682019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : [value] "f"(cc_dep1), \
11692019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                     [class] "a"(cc_dep2)  \
11702019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : "cc");\
11712019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   psw >> 28;   /* cc */ \
11722019a976f07ff418dde2dfc7cc74667ef66d7764sewardj})
11732019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
11742019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#define S390_CC_FOR_BFP128_TDC(cc_dep1,cc_dep2,cc_ndep) \
11752019a976f07ff418dde2dfc7cc74667ef66d7764sewardj({ \
1176cf1527c8f8a8a647cae5ef21b6b126db9b81f622florian   /* Recover the original DEP2 value. See comment near \
1177cf1527c8f8a8a647cae5ef21b6b126db9b81f622florian      s390_cc_thunk_put1f128Z for rationale. */ \
11782019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   cc_dep2 = cc_dep2 ^ cc_ndep; \
11792019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   __asm__ volatile ( \
11802019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ldr  4,%[high]\n\t" \
11812019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ldr  6,%[low]\n\t" \
11822019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "tcxb 4,0(%[class])\n\t" \
11832019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        "ipm  %[psw]\n\t"          : [psw] "=d"(psw) \
11842019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : [high] "f"(cc_dep1), [low] "f"(cc_dep2), \
11852019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                     [class] "a"(cc_ndep)  \
11862019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : "cc", "f4", "f6");\
11872019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   psw >> 28;   /* cc */ \
11882019a976f07ff418dde2dfc7cc74667ef66d7764sewardj})
11892019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
119079e5a4845df6d09250b142c4e160a95cf7688fc8florian/* Convert an IRRoundingMode value to s390_dfp_round_t */
11915f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian#if defined(VGA_s390x)
11925f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florianstatic s390_dfp_round_t
11935f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3floriandecode_dfp_rounding_mode(UInt irrm)
11945f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian{
11955f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   switch (irrm) {
119679e5a4845df6d09250b142c4e160a95cf7688fc8florian   case Irrm_NEAREST:
11975f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_DFP_ROUND_NEAREST_EVEN_4;
119879e5a4845df6d09250b142c4e160a95cf7688fc8florian   case Irrm_NegINF:
11995f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_DFP_ROUND_NEGINF_7;
120079e5a4845df6d09250b142c4e160a95cf7688fc8florian   case Irrm_PosINF:
12015f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_DFP_ROUND_POSINF_6;
120279e5a4845df6d09250b142c4e160a95cf7688fc8florian   case Irrm_ZERO:
12035f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_DFP_ROUND_ZERO_5;
120479e5a4845df6d09250b142c4e160a95cf7688fc8florian   case Irrm_NEAREST_TIE_AWAY_0:
12055f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1;
120679e5a4845df6d09250b142c4e160a95cf7688fc8florian   case Irrm_PREPARE_SHORTER:
12075f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_DFP_ROUND_PREPARE_SHORT_3;
120879e5a4845df6d09250b142c4e160a95cf7688fc8florian   case Irrm_AWAY_FROM_ZERO:
12095f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_DFP_ROUND_AWAY_0;
121079e5a4845df6d09250b142c4e160a95cf7688fc8florian   case Irrm_NEAREST_TIE_TOWARD_0:
12115f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_DFP_ROUND_NEAREST_TIE_TOWARD_0;
12125f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   }
12135f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   vpanic("decode_dfp_rounding_mode");
12145f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian}
12155f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian#endif
12165f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
12171239020c948a6e20faaa8d0fa5dea44302e18f8aflorian#define S390_CC_FOR_DFP_RESULT(cc_dep1) \
12181239020c948a6e20faaa8d0fa5dea44302e18f8aflorian({ \
12191239020c948a6e20faaa8d0fa5dea44302e18f8aflorian   __asm__ volatile ( \
12201239020c948a6e20faaa8d0fa5dea44302e18f8aflorian        ".insn rre, 0xb3d60000,0,%[op]\n\t"              /* LTDTR */ \
12211239020c948a6e20faaa8d0fa5dea44302e18f8aflorian        "ipm %[psw]\n\t"           : [psw] "=d"(psw) \
12221239020c948a6e20faaa8d0fa5dea44302e18f8aflorian                                   : [op]  "f"(cc_dep1) \
12231239020c948a6e20faaa8d0fa5dea44302e18f8aflorian                                   : "cc", "f0"); \
12241239020c948a6e20faaa8d0fa5dea44302e18f8aflorian   psw >> 28;   /* cc */ \
12251239020c948a6e20faaa8d0fa5dea44302e18f8aflorian})
12261239020c948a6e20faaa8d0fa5dea44302e18f8aflorian
1227e38f641461120ea338069a3f45820168959968abflorian#define S390_CC_FOR_DFP128_RESULT(hi,lo) \
1228e38f641461120ea338069a3f45820168959968abflorian({ \
1229e38f641461120ea338069a3f45820168959968abflorian   __asm__ volatile ( \
1230cf1527c8f8a8a647cae5ef21b6b126db9b81f622florian        "ldr   4,%[high]\n\t"                                           \
1231cf1527c8f8a8a647cae5ef21b6b126db9b81f622florian        "ldr   6,%[low]\n\t"                                            \
1232cf1527c8f8a8a647cae5ef21b6b126db9b81f622florian        ".insn rre, 0xb3de0000,0,4\n\t"    /* LTXTR */                  \
1233cf1527c8f8a8a647cae5ef21b6b126db9b81f622florian        "ipm %[psw]\n\t"           : [psw] "=d"(psw)                    \
1234cf1527c8f8a8a647cae5ef21b6b126db9b81f622florian                                   : [high] "f"(hi), [low] "f"(lo)      \
1235cf1527c8f8a8a647cae5ef21b6b126db9b81f622florian                                   : "cc", "f0", "f2", "f4", "f6");     \
1236e38f641461120ea338069a3f45820168959968abflorian   psw >> 28;   /* cc */                                                \
1237e38f641461120ea338069a3f45820168959968abflorian})
1238e38f641461120ea338069a3f45820168959968abflorian
1239ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian#define S390_CC_FOR_DFP_TD(opcode,cc_dep1,cc_dep2)                      \
1240ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian({                                                                      \
1241ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian   __asm__ volatile (                                                   \
1242ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian        opcode ",%[value],0(%[class])\n\t"                              \
1243ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian        "ipm %[psw]\n\t"           : [psw] "=d"(psw)                    \
1244ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian                                   : [value] "f"(cc_dep1),              \
1245ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian                                     [class] "a"(cc_dep2)               \
1246ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian                                   : "cc");                             \
1247ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian   psw >> 28;   /* cc */                                                \
1248ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian})
1249ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian
1250ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian#define S390_CC_FOR_DFP128_TD(opcode,cc_dep1,cc_dep2,cc_ndep)           \
1251ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian({                                                                      \
1252ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian   /* Recover the original DEP2 value. See comment near                 \
1253ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian      s390_cc_thunk_put1d128Z for rationale. */                         \
1254ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian   cc_dep2 = cc_dep2 ^ cc_ndep;                                         \
1255ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian   __asm__ volatile (                                                   \
1256ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian        "ldr  4,%[high]\n\t"                                            \
1257ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian        "ldr  6,%[low]\n\t"                                             \
1258ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian        opcode ",4,0(%[class])\n\t"                                     \
1259ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian        "ipm  %[psw]\n\t"          : [psw] "=d"(psw)                    \
1260ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian                                   : [high] "f"(cc_dep1), [low] "f"(cc_dep2), \
1261ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian                                     [class] "a"(cc_ndep)               \
1262ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian                                   : "cc", "f4", "f6");                 \
1263ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian   psw >> 28;   /* cc */                                                \
1264ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian})
1265ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian
12665f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian#define S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,rounding_mode)       \
12675f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   ({                                                                   \
12685f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      __asm__ volatile (                                                \
12695f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        opcode ",0,%[op]," #rounding_mode ",0\n\t"      \
12705f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        "ipm %[psw]\n\t"           : [psw] "=d"(psw)    \
12715f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        : [op] "f"(cc_dep1)                             \
12725f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        : "cc", "r0");                                  \
12735f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      psw >> 28;   /* cc */                                             \
12745f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   })
12755f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
12765f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian#define S390_CC_FOR_DFP_CONVERT(opcode,cc_dep1,cc_dep2)                 \
12775f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   ({                                                                   \
12785f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      UInt cc;                                                          \
12795f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      switch (decode_dfp_rounding_mode(cc_dep2)) {                      \
12805f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1:                         \
12815f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_12:                        \
12825f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,1);            \
12835f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
12845f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_PREPARE_SHORT_3:                              \
12855f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_PREPARE_SHORT_15:                             \
12865f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,3);            \
12875f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
12885f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_EVEN_4:                               \
12895f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_EVEN_8:                               \
12905f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,4);            \
12915f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
12925f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_ZERO_5:                                       \
12935f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_ZERO_9:                                       \
12945f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,5);            \
12955f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
12965f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_POSINF_6:                                     \
12975f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_POSINF_10:                                    \
12985f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,6);            \
12995f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
13005f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEGINF_7:                                     \
13015f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEGINF_11:                                    \
13025f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,7);            \
13035f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
13045f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_TIE_TOWARD_0:                         \
13055f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,13);           \
13065f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
13075f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_AWAY_0:                                       \
13085f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,14);           \
13095f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
13105f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      default:                                                          \
13115f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         vpanic("unexpected dfp rounding mode");                        \
13125f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      }                                                                 \
13135f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      cc;                                                               \
13145f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   })
13155f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
13165f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian#define S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,rounding_mode)      \
13175f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   ({                                                                   \
13185f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      __asm__ volatile (                                                \
13195f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        opcode ",0,%[op]," #rounding_mode ",0\n\t"      \
13205f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        "ipm %[psw]\n\t"           : [psw] "=d"(psw)    \
13215f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        : [op] "f"(cc_dep1)                             \
13225f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        : "cc", "r0");                                  \
13235f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      psw >> 28;   /* cc */                                             \
13245f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   })
13255f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
13265f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian#define S390_CC_FOR_DFP_UCONVERT(opcode,cc_dep1,cc_dep2)                \
13275f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   ({                                                                   \
13285f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      UInt cc;                                                          \
13295f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      switch (decode_dfp_rounding_mode(cc_dep2)) {                      \
13305f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1:                         \
13315f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_12:                        \
13325f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,1);           \
13335f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
13345f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_PREPARE_SHORT_3:                              \
13355f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_PREPARE_SHORT_15:                             \
13365f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,3);           \
13375f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
13385f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_EVEN_4:                               \
13395f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_EVEN_8:                               \
13405f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,4);           \
13415f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
13425f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_ZERO_5:                                       \
13435f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_ZERO_9:                                       \
13445f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,5);           \
13455f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
13465f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_POSINF_6:                                     \
13475f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_POSINF_10:                                    \
13485f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,6);           \
13495f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
13505f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEGINF_7:                                     \
13515f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEGINF_11:                                    \
13525f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,7);           \
13535f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
13545f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_TIE_TOWARD_0:                         \
13555f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,13);          \
13565f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
13575f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_AWAY_0:                                       \
13585f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,14);          \
13595f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                         \
13605f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      default:                                                          \
13615f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         vpanic("unexpected dfp rounding mode");                        \
13625f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      }                                                                 \
13635f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      cc;                                                               \
13645f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   })
13655f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
13665f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian#define S390_CC_FOR_DFP128_CONVERT_AUX(opcode,hi,lo,rounding_mode)      \
13675f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   ({                                                                   \
13685f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      __asm__ volatile (                                                \
13695f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        "ldr   4,%[high]\n\t"                           \
13705f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        "ldr   6,%[low]\n\t"                            \
13715f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        opcode ",0,4," #rounding_mode ",0\n\t"          \
13725f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        "ipm %[psw]\n\t"           : [psw] "=d"(psw)    \
13735f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        : [high] "f"(hi), [low] "f"(lo)                 \
13745f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        : "cc", "r0", "f4", "f6");                      \
13755f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      psw >> 28;   /* cc */                                             \
13765f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   })
13775f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
13785f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian#define S390_CC_FOR_DFP128_CONVERT(opcode,cc_dep1,cc_dep2,cc_ndep)       \
13795f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   ({                                                                    \
13805f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      UInt cc;                                                           \
13815f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      /* Recover the original DEP2 value. See comment near               \
13825f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         s390_cc_thunk_put3 for rationale. */                            \
13835f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      cc_dep2 = cc_dep2 ^ cc_ndep;                                       \
13845f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      switch (decode_dfp_rounding_mode(cc_ndep)) {                       \
13855f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1:                          \
13865f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_12:                         \
13875f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,1);  \
13885f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                          \
13895f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_PREPARE_SHORT_3:                               \
13905f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_PREPARE_SHORT_15:                              \
13915f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,3);  \
13925f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                          \
13935f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_EVEN_4:                                \
13945f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_EVEN_8:                                \
13955f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,4);  \
13965f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                          \
13975f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_ZERO_5:                                        \
13985f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_ZERO_9:                                        \
13995f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,5);  \
14005f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                          \
14015f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_POSINF_6:                                      \
14025f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_POSINF_10:                                     \
14035f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,6);  \
14045f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                          \
14055f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEGINF_7:                                      \
14065f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEGINF_11:                                     \
14075f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,7);  \
14085f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                          \
14095f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_TIE_TOWARD_0:                          \
14105f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,13); \
14115f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                          \
14125f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_AWAY_0:                                        \
14135f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,14); \
14145f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                          \
14155f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      default:                                                           \
14165f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         vpanic("unexpected dfp rounding mode");                         \
14175f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      }                                                                  \
14185f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      cc;                                                                \
14195f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   })
14205f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
14215f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian#define S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,hi,lo,rounding_mode)      \
14225f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   ({                                                                    \
14235f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      __asm__ volatile (                                                 \
14245f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        "ldr   4,%[high]\n\t"                            \
14255f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        "ldr   6,%[low]\n\t"                             \
14265f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        opcode ",0,4," #rounding_mode ",0\n\t"           \
14275f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        "ipm %[psw]\n\t"           : [psw] "=d"(psw)     \
14285f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        : [high] "f"(hi), [low] "f"(lo)                  \
14295f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                        : "cc", "r0", "f4", "f6");                       \
14305f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      psw >> 28;   /* cc */                                              \
14315f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   })
14325f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
14335f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian#define S390_CC_FOR_DFP128_UCONVERT(opcode,cc_dep1,cc_dep2,cc_ndep)       \
14345f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   ({                                                                     \
14355f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      UInt cc;                                                            \
14365f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      /* Recover the original DEP2 value. See comment near                \
14375f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         s390_cc_thunk_put3 for rationale. */                             \
14385f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      cc_dep2 = cc_dep2 ^ cc_ndep;                                        \
14395f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      switch (decode_dfp_rounding_mode(cc_ndep)) {                        \
14405f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1:                           \
14415f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_12:                          \
14425f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,1);  \
14435f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                           \
14445f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_PREPARE_SHORT_3:                                \
14455f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_PREPARE_SHORT_15:                               \
14465f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,3);  \
14475f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                           \
14485f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_EVEN_4:                                 \
14495f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_EVEN_8:                                 \
14505f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,4);  \
14515f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                           \
14525f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_ZERO_5:                                         \
14535f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_ZERO_9:                                         \
14545f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,5);  \
14555f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                           \
14565f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_POSINF_6:                                       \
14575f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_POSINF_10:                                      \
14585f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,6);  \
14595f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                           \
14605f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEGINF_7:                                       \
14615f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEGINF_11:                                      \
14625f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,7);  \
14635f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                           \
14645f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_NEAREST_TIE_TOWARD_0:                           \
14655f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,13); \
14665f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                           \
14675f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      case S390_DFP_ROUND_AWAY_0:                                         \
14685f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,14); \
14695f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         break;                                                           \
14705f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      default:                                                            \
14715f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian         vpanic("unexpected dfp rounding mode");                          \
14725f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      }                                                                   \
14735f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      cc;                                                                 \
14745f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   })
14755f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
14762019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
14772019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/* Return the value of the condition code from the supplied thunk parameters.
14782019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   This is not the value of the PSW. It is the value of the 2 CC bits within
14792019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   the PSW. The returned value is thusly in the interval [0:3]. */
14802019a976f07ff418dde2dfc7cc74667ef66d7764sewardjUInt
14812019a976f07ff418dde2dfc7cc74667ef66d7764sewardjs390_calculate_cc(ULong cc_op, ULong cc_dep1, ULong cc_dep2, ULong cc_ndep)
14822019a976f07ff418dde2dfc7cc74667ef66d7764sewardj{
14832019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#if defined(VGA_s390x)
14842019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   UInt psw;
14852019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
14862019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   switch (cc_op) {
14872019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
14882019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_BITWISE:
14892019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BINARY("ogr", cc_dep1, (ULong)0);
14902019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
14912019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_SIGNED_COMPARE:
14922019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BINARY("cgr", cc_dep1, cc_dep2);
14932019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
14942019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_UNSIGNED_COMPARE:
14952019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BINARY("clgr", cc_dep1, cc_dep2);
14962019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
14972019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_SIGNED_ADD_64:
14982019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BINARY("agr", cc_dep1, cc_dep2);
14992019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15002019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_SIGNED_ADD_32:
15012019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BINARY("ar", cc_dep1, cc_dep2);
15022019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15032019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_SIGNED_SUB_64:
15042019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BINARY("sgr", cc_dep1, cc_dep2);
15052019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15062019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_SIGNED_SUB_32:
15072019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BINARY("sr", cc_dep1, cc_dep2);
15082019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15092019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_UNSIGNED_ADD_64:
15102019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BINARY("algr", cc_dep1, cc_dep2);
15112019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15122019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_UNSIGNED_ADD_32:
15132019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BINARY("alr", cc_dep1, cc_dep2);
15142019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15152019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_UNSIGNED_ADDC_64:
15162019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_TERNARY_ADDC("alcgr", cc_dep1, cc_dep2, cc_ndep);
15172019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15182019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_UNSIGNED_ADDC_32:
15192019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_TERNARY_ADDC("alcr", cc_dep1, cc_dep2, cc_ndep);
15202019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15212019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_UNSIGNED_SUB_64:
15222019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BINARY("slgr", cc_dep1, cc_dep2);
15232019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15242019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_UNSIGNED_SUB_32:
15252019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BINARY("slr", cc_dep1, cc_dep2);
15262019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15272019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_UNSIGNED_SUBB_64:
15282019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_TERNARY_SUBB("slbgr", cc_dep1, cc_dep2, cc_ndep);
15292019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15302019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_UNSIGNED_SUBB_32:
15312019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_TERNARY_SUBB("slbr", cc_dep1, cc_dep2, cc_ndep);
15322019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15332019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_LOAD_AND_TEST:
15342019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* Like signed comparison with 0 */
15352019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BINARY("cgr", cc_dep1, (Long)0);
15362019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15372019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_LOAD_POSITIVE_32:
15382019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      __asm__ volatile (
15392019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "lpr  %[result],%[op]\n\t"
1540ae88411aaa8e0b99032fb0bdb04eec21edc54d88florian           "ipm  %[psw]\n\t"         : [psw] "=d"(psw), [result] "=d"(cc_dep1)
1541ae88411aaa8e0b99032fb0bdb04eec21edc54d88florian                                     : [op] "d"(cc_dep1)
1542ae88411aaa8e0b99032fb0bdb04eec21edc54d88florian                                     : "cc");
15432019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return psw >> 28;   /* cc */
15442019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15452019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_LOAD_POSITIVE_64:
15462019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      __asm__ volatile (
15472019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "lpgr %[result],%[op]\n\t"
1548ae88411aaa8e0b99032fb0bdb04eec21edc54d88florian           "ipm  %[psw]\n\t"         : [psw] "=d"(psw), [result] "=d"(cc_dep1)
1549ae88411aaa8e0b99032fb0bdb04eec21edc54d88florian                                     : [op] "d"(cc_dep1)
1550ae88411aaa8e0b99032fb0bdb04eec21edc54d88florian                                     : "cc");
15512019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return psw >> 28;   /* cc */
15522019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15532019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_TEST_UNDER_MASK_8: {
15542019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      UChar value  = cc_dep1;
15552019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      UChar mask   = cc_dep2;
15562019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15572019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      __asm__ volatile (
15582019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "bras %%r2,1f\n\t"             /* %r2 = address of next insn */
15592019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "tm %[value],0\n\t"            /* this is skipped, then EXecuted */
15602019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "1: ex %[mask],0(%%r2)\n\t"    /* EXecute TM after modifying mask */
15612019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "ipm %[psw]\n\t"             : [psw] "=d"(psw)
15622019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                        : [value] "m"(value), [mask] "a"(mask)
15632019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                        : "r2", "cc");
15642019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return psw >> 28;   /* cc */
15652019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   }
15662019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15672019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_TEST_UNDER_MASK_16: {
15682019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* Create a TMLL insn with the mask as given by cc_dep2 */
15698cf6637c6d45e8b1c514a658e7290cd5738b1d7dflorian      UInt insn  = (0xA701u << 16) | cc_dep2;
15702019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      UInt value = cc_dep1;
15712019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15722019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      __asm__ volatile (
15732019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "lr   1,%[value]\n\t"
15742019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "lhi  2,0x10\n\t"
15752019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "ex   2,%[insn]\n\t"
15762019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "ipm  %[psw]\n\t"       : [psw] "=d"(psw)
15772019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : [value] "d"(value), [insn] "m"(insn)
15782019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                   : "r1", "r2", "cc");
15792019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return psw >> 28;   /* cc */
15802019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   }
15812019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15822019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_SHIFT_LEFT_32:
15832019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      __asm__ volatile (
15842019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "sla  %[op],0(%[amount])\n\t"
15852019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "ipm  %[psw]\n\t"            : [psw] "=d"(psw), [op] "+d"(cc_dep1)
15862019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                        : [amount] "a"(cc_dep2)
15872019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                        : "cc");
15882019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return psw >> 28;   /* cc */
15892019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15902019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_SHIFT_LEFT_64: {
15912019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      Int high = (Int)(cc_dep1 >> 32);
15922019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      Int low  = (Int)(cc_dep1 & 0xFFFFFFFF);
15932019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
15942019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      __asm__ volatile (
15952019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "lr   2,%[high]\n\t"
15962019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "lr   3,%[low]\n\t"
15972019a976f07ff418dde2dfc7cc74667ef66d7764sewardj           "slda 2,0(%[amount])\n\t"
1598ae88411aaa8e0b99032fb0bdb04eec21edc54d88florian           "ipm %[psw]\n\t"             : [psw] "=d"(psw), [high] "+d"(high),
1599ae88411aaa8e0b99032fb0bdb04eec21edc54d88florian                                          [low] "+d"(low)
16002019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                        : [amount] "a"(cc_dep2)
16012019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                        : "cc", "r2", "r3");
16022019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return psw >> 28;   /* cc */
16032019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   }
16042019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16052019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_INSERT_CHAR_MASK_32: {
16062019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      Int inserted = 0;
16072019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      Int msb = 0;
16082019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16092019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_dep2 & 1) {
16102019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         inserted |= cc_dep1 & 0xff;
16112019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         msb = 0x80;
16122019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
16132019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_dep2 & 2) {
16142019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         inserted |= cc_dep1 & 0xff00;
16152019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         msb = 0x8000;
16162019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
16172019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_dep2 & 4) {
16182019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         inserted |= cc_dep1 & 0xff0000;
16192019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         msb = 0x800000;
16202019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
16212019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_dep2 & 8) {
16222019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         inserted |= cc_dep1 & 0xff000000;
16232019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         msb = 0x80000000;
16242019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
16252019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16262019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (inserted & msb)  // MSB is 1
16272019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         return 1;
16282019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (inserted > 0)
16292019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         return 2;
16302019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return 0;
16312019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   }
16322019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16332019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_BFP_RESULT_32:
16342019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BFP_RESULT("ltebr", cc_dep1);
16352019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16362019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_BFP_RESULT_64:
16372019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BFP_RESULT("ltdbr", cc_dep1);
16382019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16392019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_BFP_RESULT_128:
16402019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BFP128_RESULT(cc_dep1, cc_dep2);
16412019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16422019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_BFP_32_TO_INT_32:
164319e0077d31fe17496eeb76cd008507d1a8f75908florian      return S390_CC_FOR_BFP_CONVERT("cfebr", cc_dep1, cc_dep2);
16442019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16452019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_BFP_64_TO_INT_32:
164619e0077d31fe17496eeb76cd008507d1a8f75908florian      return S390_CC_FOR_BFP_CONVERT("cfdbr", cc_dep1, cc_dep2);
16472019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16482019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_BFP_128_TO_INT_32:
164919e0077d31fe17496eeb76cd008507d1a8f75908florian      return S390_CC_FOR_BFP128_CONVERT("cfxbr", cc_dep1, cc_dep2, cc_ndep);
16502019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16512019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_BFP_32_TO_INT_64:
165219e0077d31fe17496eeb76cd008507d1a8f75908florian      return S390_CC_FOR_BFP_CONVERT("cgebr", cc_dep1, cc_dep2);
16532019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16542019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_BFP_64_TO_INT_64:
165519e0077d31fe17496eeb76cd008507d1a8f75908florian      return S390_CC_FOR_BFP_CONVERT("cgdbr", cc_dep1, cc_dep2);
16562019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16572019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_BFP_128_TO_INT_64:
165819e0077d31fe17496eeb76cd008507d1a8f75908florian      return S390_CC_FOR_BFP128_CONVERT("cgxbr", cc_dep1, cc_dep2, cc_ndep);
16592019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16602019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_BFP_TDC_32:
16612019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BFP_TDC("tceb", cc_dep1, cc_dep2);
16622019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16632019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_BFP_TDC_64:
16642019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BFP_TDC("tcdb", cc_dep1, cc_dep2);
16652019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16662019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_BFP_TDC_128:
16672019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return S390_CC_FOR_BFP128_TDC(cc_dep1, cc_dep2, cc_ndep);
16682019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16692019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case S390_CC_OP_SET:
16702019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      return cc_dep1;
16712019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
16721c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian   case S390_CC_OP_BFP_32_TO_UINT_32:
167319e0077d31fe17496eeb76cd008507d1a8f75908florian      return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb39c0000", cc_dep1, cc_dep2);
16741c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian
16751c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian   case S390_CC_OP_BFP_64_TO_UINT_32:
167619e0077d31fe17496eeb76cd008507d1a8f75908florian      return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb39d0000", cc_dep1, cc_dep2);
16771c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian
16781c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian   case S390_CC_OP_BFP_128_TO_UINT_32:
167919e0077d31fe17496eeb76cd008507d1a8f75908florian      return S390_CC_FOR_BFP128_UCONVERT(".insn rrf,0xb39e0000", cc_dep1,
168019e0077d31fe17496eeb76cd008507d1a8f75908florian                                         cc_dep2, cc_ndep);
16811c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian
16821c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian   case S390_CC_OP_BFP_32_TO_UINT_64:
168319e0077d31fe17496eeb76cd008507d1a8f75908florian      return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb3ac0000", cc_dep1, cc_dep2);
16841c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian
16851c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian   case S390_CC_OP_BFP_64_TO_UINT_64:
168619e0077d31fe17496eeb76cd008507d1a8f75908florian      return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb3ad0000", cc_dep1, cc_dep2);
16871c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian
16881c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian   case S390_CC_OP_BFP_128_TO_UINT_64:
168919e0077d31fe17496eeb76cd008507d1a8f75908florian      return S390_CC_FOR_BFP128_UCONVERT(".insn rrf,0xb3ae0000", cc_dep1,
169019e0077d31fe17496eeb76cd008507d1a8f75908florian                                         cc_dep2, cc_ndep);
16911c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian
16921239020c948a6e20faaa8d0fa5dea44302e18f8aflorian   case S390_CC_OP_DFP_RESULT_64:
16931239020c948a6e20faaa8d0fa5dea44302e18f8aflorian      return S390_CC_FOR_DFP_RESULT(cc_dep1);
16941c8f7ff5e4682f2ea5c33b514881d97e5dbc11ebflorian
1695e38f641461120ea338069a3f45820168959968abflorian   case S390_CC_OP_DFP_RESULT_128:
1696e38f641461120ea338069a3f45820168959968abflorian      return S390_CC_FOR_DFP128_RESULT(cc_dep1, cc_dep2);
1697e38f641461120ea338069a3f45820168959968abflorian
1698ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian   case S390_CC_OP_DFP_TDC_32:  /* TDCET */
1699ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian      return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000050", cc_dep1, cc_dep2);
1700ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian
1701ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian   case S390_CC_OP_DFP_TDC_64:  /* TDCDT */
1702ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian      return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000054", cc_dep1, cc_dep2);
1703ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian
1704ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian   case S390_CC_OP_DFP_TDC_128: /* TDCXT */
1705ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian      return S390_CC_FOR_DFP128_TD(".insn rxe, 0xed0000000058", cc_dep1,
1706ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian                                   cc_dep2, cc_ndep);
1707ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian
1708ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian   case S390_CC_OP_DFP_TDG_32:  /* TDGET */
1709ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian      return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000051", cc_dep1, cc_dep2);
1710ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian
1711ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian   case S390_CC_OP_DFP_TDG_64:  /* TDGDT */
1712ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian      return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000055", cc_dep1, cc_dep2);
1713ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian
1714ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian   case S390_CC_OP_DFP_TDG_128: /* TDGXT */
1715ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian      return S390_CC_FOR_DFP128_TD(".insn rxe, 0xed0000000059", cc_dep1,
1716ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian                                   cc_dep2, cc_ndep);
1717ce9e3dbfe4342b2f9684f2bd3acf06d172982efeflorian
17185f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   case S390_CC_OP_DFP_64_TO_INT_32: /* CFDTR */
17195f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_CC_FOR_DFP_CONVERT(".insn rrf,0xb9410000", cc_dep1, cc_dep2);
17205f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
17215f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   case S390_CC_OP_DFP_128_TO_INT_32: /* CFXTR */
17225f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_CC_FOR_DFP128_CONVERT(".insn rrf,0xb9490000", cc_dep1,
17235f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                                        cc_dep2, cc_ndep);
17245f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
1725a887acd341cb9b90b1dd6d3fdfa4a429f5ddd583florian   case S390_CC_OP_DFP_64_TO_INT_64: /* CGDTR */
1726a887acd341cb9b90b1dd6d3fdfa4a429f5ddd583florian      return S390_CC_FOR_DFP_CONVERT(".insn rrf,0xb3e10000", cc_dep1, cc_dep2);
1727a887acd341cb9b90b1dd6d3fdfa4a429f5ddd583florian
1728a887acd341cb9b90b1dd6d3fdfa4a429f5ddd583florian   case S390_CC_OP_DFP_128_TO_INT_64: /* CGXTR */
1729a887acd341cb9b90b1dd6d3fdfa4a429f5ddd583florian      return S390_CC_FOR_DFP128_CONVERT(".insn rrf,0xb3e90000", cc_dep1,
1730a887acd341cb9b90b1dd6d3fdfa4a429f5ddd583florian                                        cc_dep2, cc_ndep);
1731a887acd341cb9b90b1dd6d3fdfa4a429f5ddd583florian
17325f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   case S390_CC_OP_DFP_64_TO_UINT_32: /* CLFDTR */
17335f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_CC_FOR_DFP_UCONVERT(".insn rrf,0xb9430000", cc_dep1, cc_dep2);
17345f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
17355f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   case S390_CC_OP_DFP_128_TO_UINT_32: /* CLFXTR */
17365f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_CC_FOR_DFP128_UCONVERT(".insn rrf,0xb94b0000", cc_dep1,
17375f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                                         cc_dep2, cc_ndep);
17385f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
17395f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   case S390_CC_OP_DFP_64_TO_UINT_64: /* CLGDTR */
17405f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_CC_FOR_DFP_UCONVERT(".insn rrf,0xb9420000", cc_dep1, cc_dep2);
17415f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
17425f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian   case S390_CC_OP_DFP_128_TO_UINT_64: /* CLGXTR */
17435f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian      return S390_CC_FOR_DFP128_UCONVERT(".insn rrf,0xb94a0000", cc_dep1,
17445f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian                                         cc_dep2, cc_ndep);
17455f03462774bbec01825dfd3c2bcc9ed7b8b7c3a3florian
17467ab421d8483f8462f2bf5ebdd1ef5d72658dd572florian   case S390_CC_OP_PFPO_32: {
17477ab421d8483f8462f2bf5ebdd1ef5d72658dd572florian      __asm__ volatile(
17487ab421d8483f8462f2bf5ebdd1ef5d72658dd572florian           "ler 4, %[cc_dep1]\n\t"      /* 32 bit FR move */
17497ab421d8483f8462f2bf5ebdd1ef5d72658dd572florian           "lr  0, %[cc_dep2]\n\t"      /* 32 bit GR move */
17507ab421d8483f8462f2bf5ebdd1ef5d72658dd572florian           ".short 0x010a\n\t"          /* PFPO */
17517ab421d8483f8462f2bf5ebdd1ef5d72658dd572florian           "ipm %[psw]\n\t"             : [psw] "=d"(psw)
17527ab421d8483f8462f2bf5ebdd1ef5d72658dd572florian                                        : [cc_dep1] "f"(cc_dep1),
17537ab421d8483f8462f2bf5ebdd1ef5d72658dd572florian                                          [cc_dep2] "d"(cc_dep2)
17547ab421d8483f8462f2bf5ebdd1ef5d72658dd572florian                                        : "r0", "r1", "f4");
17557ab421d8483f8462f2bf5ebdd1ef5d72658dd572florian      return psw >> 28;  /* cc */
17567ab421d8483f8462f2bf5ebdd1ef5d72658dd572florian   }
17577ab421d8483f8462f2bf5ebdd1ef5d72658dd572florian
175878d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian   case S390_CC_OP_PFPO_64: {
175978d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian      __asm__ volatile(
176078d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian           "ldr 4, %[cc_dep1]\n\t"
176178d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian           "lr  0, %[cc_dep2]\n\t"      /* 32 bit register move */
176278d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian           ".short 0x010a\n\t"          /* PFPO */
176378d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian           "ipm %[psw]\n\t"             : [psw] "=d"(psw)
1764c589228fe86255c87fdc9ad78d5d9c60e4c9e61eflorian                                        : [cc_dep1] "f"(cc_dep1),
1765c589228fe86255c87fdc9ad78d5d9c60e4c9e61eflorian                                          [cc_dep2] "d"(cc_dep2)
176678d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian                                        : "r0", "r1", "f4");
176778d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian      return psw >> 28;  /* cc */
176878d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian   }
176978d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian
177078d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian   case S390_CC_OP_PFPO_128: {
177178d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian      __asm__ volatile(
177278d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian           "ldr 4,%[cc_dep1]\n\t"
177378d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian           "ldr 6,%[cc_dep2]\n\t"
177478d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian           "lr  0,%[cc_ndep]\n\t"       /* 32 bit register move */
177578d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian           ".short 0x010a\n\t"          /* PFPO */
177678d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian           "ipm %[psw]\n\t"             : [psw] "=d"(psw)
177778d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian                                        : [cc_dep1] "f"(cc_dep1),
177878d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian                                          [cc_dep2] "f"(cc_dep2),
177978d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian                                          [cc_ndep] "d"(cc_ndep)
178078d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian                                        : "r0", "r1", "f0", "f2", "f4", "f6");
178178d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian      return psw >> 28;  /* cc */
178278d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian   }
178378d5ef75d89e5aa6c629a2d47f7e04ddbf1253c3florian
17842019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   default:
17852019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      break;
17862019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   }
17872019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#endif
17882019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   vpanic("s390_calculate_cc");
17892019a976f07ff418dde2dfc7cc74667ef66d7764sewardj}
17902019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
17912019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
17922019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/* Note that this does *not* return a Boolean value. The result needs to be
17932019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   explicitly tested against zero. */
17942019a976f07ff418dde2dfc7cc74667ef66d7764sewardjUInt
17952019a976f07ff418dde2dfc7cc74667ef66d7764sewardjs390_calculate_cond(ULong mask, ULong op, ULong dep1, ULong dep2, ULong ndep)
17962019a976f07ff418dde2dfc7cc74667ef66d7764sewardj{
17972019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   UInt cc = s390_calculate_cc(op, dep1, dep2, ndep);
17982019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
17992019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   return ((mask << cc) & 0x8);
18002019a976f07ff418dde2dfc7cc74667ef66d7764sewardj}
18012019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18022019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*------------------------------------------------------------*/
18032019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*--- spechelper for performance                           ---*/
18042019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*------------------------------------------------------------*/
18052019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18062019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18072019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/* Convenience macros */
18082019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#define unop(op,a1) IRExpr_Unop((op),(a1))
18092019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#define binop(op,a1,a2) IRExpr_Binop((op),(a1),(a2))
18102019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#define mkU64(v) IRExpr_Const(IRConst_U64(v))
18112019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#define mkU32(v) IRExpr_Const(IRConst_U32(v))
18122019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#define mkU8(v)  IRExpr_Const(IRConst_U8(v))
18132019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18142019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18152019a976f07ff418dde2dfc7cc74667ef66d7764sewardjstatic inline Bool
181649adf8664fa8e67c95397022d21ea1b547e2186bflorianisC64(const IRExpr *expr)
18172019a976f07ff418dde2dfc7cc74667ef66d7764sewardj{
18182019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   return expr->tag == Iex_Const && expr->Iex.Const.con->tag == Ico_U64;
18192019a976f07ff418dde2dfc7cc74667ef66d7764sewardj}
18202019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18212019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18222019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/* The returned expression is NULL if no specialization was found. In that
18232019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   case the helper function will be called. Otherwise, the expression has
18242019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   type Ity_I32 and a Boolean value. */
18252019a976f07ff418dde2dfc7cc74667ef66d7764sewardjIRExpr *
18261ff4756e1731485e6bf3cd96717cd8398daec1f2florianguest_s390x_spechelper(const HChar *function_name, IRExpr **args,
18272019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                       IRStmt **precedingStmts, Int n_precedingStmts)
18282019a976f07ff418dde2dfc7cc74667ef66d7764sewardj{
18292019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   UInt i, arity = 0;
18302019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18312019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   for (i = 0; args[i]; i++)
18322019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      arity++;
18332019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18342019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#  if 0
18352019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   vex_printf("spec request:\n");
18362019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   vex_printf("   %s  ", function_name);
18372019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   for (i = 0; i < arity; i++) {
18382019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      vex_printf("  ");
18392019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      ppIRExpr(args[i]);
18402019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   }
18412019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   vex_printf("\n");
18422019a976f07ff418dde2dfc7cc74667ef66d7764sewardj#  endif
18432019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18442019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   /* --------- Specialising "s390_calculate_cond" --------- */
18452019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18462019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   if (vex_streq(function_name, "s390_calculate_cond")) {
18472019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      IRExpr *cond_expr, *cc_op_expr, *cc_dep1, *cc_dep2;
18482019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      ULong cond, cc_op;
18492019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18502019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      vassert(arity == 5);
18512019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18522019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      cond_expr  = args[0];
18532019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      cc_op_expr = args[1];
18542019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18552019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* The necessary requirement for all optimizations here is that the
18562019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         condition and the cc_op are constant. So check that upfront. */
18572019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (! isC64(cond_expr))  return NULL;
18582019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (! isC64(cc_op_expr)) return NULL;
18592019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18602019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      cond    = cond_expr->Iex.Const.con->Ico.U64;
18612019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      cc_op   = cc_op_expr->Iex.Const.con->Ico.U64;
18622019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18632019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      vassert(cond <= 15);
18642019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18652019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /*
18662019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        +------+---+---+---+---+
18672019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        | cc   | 0 | 1 | 2 | 3 |
18682019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        | cond | 8 | 4 | 2 | 1 |
18692019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        +------+---+---+---+---+
18702019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      */
18712019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      cc_dep1 = args[2];
18722019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      cc_dep2 = args[3];
18732019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18742019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* S390_CC_OP_SIGNED_COMPARE */
18752019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_op == S390_CC_OP_SIGNED_COMPARE) {
18762019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /*
18772019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 0  --> cc_dep1 == cc_dep2   (cond == 8)
18782019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 1  --> cc_dep1 <  cc_dep2   (cond == 4)
18792019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 2  --> cc_dep1 >  cc_dep2   (cond == 2)
18802019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
18812019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            Because cc == 3 cannot occur the rightmost bit of cond is
18822019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            a don't care.
18832019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         */
18842019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 || cond == 8 + 1) {
18852019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
18862019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
18872019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 4 + 2 || cond == 4 + 2 + 1) {
18882019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
18892019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
18902019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 4 || cond == 4 + 1) {
18912019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep1, cc_dep2));
18922019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
18932019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 4 || cond == 8 + 4 + 1) {
18942019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep1, cc_dep2));
18952019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
18962019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* cc_dep1 > cc_dep2  ---->  cc_dep2 < cc_dep1 */
18972019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 2 || cond == 2 + 1) {
18982019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep2, cc_dep1));
18992019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19002019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 2 || cond == 8 + 2 + 1) {
19012019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep2, cc_dep1));
19022019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19032019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
19042019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return mkU32(1);
19052019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19062019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* Remaining case */
19072019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         return mkU32(0);
19082019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
19092019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
19102019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* S390_CC_OP_UNSIGNED_COMPARE */
19112019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_op == S390_CC_OP_UNSIGNED_COMPARE) {
19122019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /*
19132019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 0  --> cc_dep1 == cc_dep2   (cond == 8)
19142019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 1  --> cc_dep1 <  cc_dep2   (cond == 4)
19152019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 2  --> cc_dep1 >  cc_dep2   (cond == 2)
19162019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
19172019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            Because cc == 3 cannot occur the rightmost bit of cond is
19182019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            a don't care.
19192019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         */
19202019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 || cond == 8 + 1) {
19212019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
19222019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19232019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 4 + 2 || cond == 4 + 2 + 1) {
19242019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
19252019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19262019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 4 || cond == 4 + 1) {
19272019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
19282019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19292019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 4 || cond == 8 + 4 + 1) {
19302019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
19312019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19322019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* cc_dep1 > cc_dep2  ---->  cc_dep2 < cc_dep1 */
19332019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 2 || cond == 2 + 1) {
19342019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep2, cc_dep1));
19352019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19362019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 2 || cond == 8 + 2 + 1) {
19372019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
19382019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19392019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
19402019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return mkU32(1);
19412019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19422019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* Remaining case */
19432019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         return mkU32(0);
19442019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
19452019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
19462019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* S390_CC_OP_LOAD_AND_TEST */
19472019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_op == S390_CC_OP_LOAD_AND_TEST) {
19482019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /*
19492019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 0  --> cc_dep1 == 0   (cond == 8)
19502019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 1  --> cc_dep1 <  0   (cond == 4)
19512019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 2  --> cc_dep1 >  0   (cond == 2)
19522019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
19532019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            Because cc == 3 cannot occur the rightmost bit of cond is
19542019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            a don't care.
19552019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         */
19562019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 || cond == 8 + 1) {
19572019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, mkU64(0)));
19582019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19592019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 4 + 2 || cond == 4 + 2 + 1) {
19602019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
19612019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19622019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 4 || cond == 4 + 1) {
196318bf154f1c34d8234fb25f63a3b906b46009930ccborntra             /* Special case cc_dep < 0. Only check the MSB to avoid bogus
196418bf154f1c34d8234fb25f63a3b906b46009930ccborntra               memcheck complaints due to gcc magic. Fixes 343802
196518bf154f1c34d8234fb25f63a3b906b46009930ccborntra             */
196618bf154f1c34d8234fb25f63a3b906b46009930ccborntra            return unop(Iop_64to32, binop(Iop_Shr64, cc_dep1, mkU8(63)));
19672019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19682019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 4 || cond == 8 + 4 + 1) {
19692019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep1, mkU64(0)));
19702019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19712019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* cc_dep1 > 0  ---->  0 < cc_dep1 */
19722019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 2 || cond == 2 + 1) {
19732019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLT64S, mkU64(0), cc_dep1));
19742019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19752019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 2 || cond == 8 + 2 + 1) {
197625e1cb271253c82bc8610820004116bad5e8d0a1florian            /* Special case cc_dep >= 0. Only check the MSB to avoid bogus
197725e1cb271253c82bc8610820004116bad5e8d0a1florian               memcheck complaints due to gcc magic. Fixes 308427
1978d7f19c077688845dcea5a037fe42ab5b1f7db717cborntra             */
197925e1cb271253c82bc8610820004116bad5e8d0a1florian            return unop(Iop_64to32, binop(Iop_Xor64,
198025e1cb271253c82bc8610820004116bad5e8d0a1florian                                          binop(Iop_Shr64, cc_dep1, mkU8(63)),
198125e1cb271253c82bc8610820004116bad5e8d0a1florian                                          mkU64(1)));
19822019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19832019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
19842019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return mkU32(1);
19852019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
19862019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* Remaining case */
19872019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         return mkU32(0);
19882019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
19892019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
19902019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* S390_CC_OP_BITWISE */
19912019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_op == S390_CC_OP_BITWISE) {
19922019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /*
19932019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc_dep1 is the result of the boolean operation.
19942019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
19952019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 0  --> cc_dep1 == 0   (cond == 8)
19962019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 1  --> cc_dep1 != 0   (cond == 4)
19972019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
19982019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            Because cc == 2 and cc == 3 cannot occur the two rightmost bits of
19992019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cond are don't cares. Therefore:
20002019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20012019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cond == 00xx  -> always false
20022019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cond == 01xx  -> not equal
20032019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cond == 10xx  -> equal
20042019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cond == 11xx  -> always true
20052019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         */
20062019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if ((cond & (8 + 4)) == 8 + 4) {
20072019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return mkU32(1);
20082019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
20092019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond & 8) {
20102019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, mkU64(0)));
20112019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
20122019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond & 4) {
20132019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
20142019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
20152019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* Remaining case */
20162019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         return mkU32(0);
20172019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
20182019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20192019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* S390_CC_OP_INSERT_CHAR_MASK_32
20202019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         Since the mask comes from an immediate field in the opcode, we
20212019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         expect the mask to be a constant here. That simplifies matters. */
20222019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_op == S390_CC_OP_INSERT_CHAR_MASK_32) {
20232019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         ULong mask;
20242019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         UInt imask = 0, shift = 0;
20252019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         IRExpr *word;
20262019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20272019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (! isC64(cc_dep2)) goto missed;
20282019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20292019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         mask = cc_dep2->Iex.Const.con->Ico.U64;
20302019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20312019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* Extract the 32-bit value from the thunk */
20322019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20332019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         word = unop(Iop_64to32, cc_dep1);
20342019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20352019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         switch (mask) {
20362019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 0:  shift =  0; imask = 0x00000000; break;
20372019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 1:  shift = 24; imask = 0x000000FF; break;
20382019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 2:  shift = 16; imask = 0x0000FF00; break;
20392019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 3:  shift = 16; imask = 0x0000FFFF; break;
20402019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 4:  shift =  8; imask = 0x00FF0000; break;
20412019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 5:  shift =  8; imask = 0x00FF00FF; break;
20422019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 6:  shift =  8; imask = 0x00FFFF00; break;
20432019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 7:  shift =  8; imask = 0x00FFFFFF; break;
20442019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 8:  shift =  0; imask = 0xFF000000; break;
20452019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 9:  shift =  0; imask = 0xFF0000FF; break;
20462019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 10: shift =  0; imask = 0xFF00FF00; break;
20472019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 11: shift =  0; imask = 0xFF00FFFF; break;
20482019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 12: shift =  0; imask = 0xFFFF0000; break;
20492019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 13: shift =  0; imask = 0xFFFF00FF; break;
20502019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 14: shift =  0; imask = 0xFFFFFF00; break;
20512019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         case 15: shift =  0; imask = 0xFFFFFFFF; break;
20522019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
20532019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20542019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* Select the bits that were inserted */
20552019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         word = binop(Iop_And32, word, mkU32(imask));
20562019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20572019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* cc == 0  --> all inserted bits zero or mask == 0   (cond == 8)
20582019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 1  --> leftmost inserted bit is one          (cond == 4)
20592019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 2  --> leftmost inserted bit is zero and not (cond == 2)
20602019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                         all inserted bits are zero
20612019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20622019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            Because cc == 0,1,2 the rightmost bit of the mask is a don't care */
20632019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 || cond == 8 + 1) {
20642019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ32, word, mkU32(0)));
20652019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
20662019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 4 + 2 || cond == 4 + 2 + 1) {
20672019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE32, word, mkU32(0)));
20682019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
20692019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20702019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* Sign extend */
20712019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (shift != 0) {
20722019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            word = binop(Iop_Sar32, binop(Iop_Shl32, word, mkU8(shift)),
20732019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                         mkU8(shift));
20742019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
20752019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20762019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 4 || cond == 4 + 1) {  /* word < 0 */
20772019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLT32S, word, mkU32(0)));
20782019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
20792019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 2 || cond == 2 + 1) {  /* word > 0 */
20802019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLT32S, mkU32(0), word));
20812019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
20822019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 4 || cond == 8 + 4 + 1) {
20832019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLE32S, word, mkU32(0)));
20842019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
20852019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 2 || cond == 8 + 2 + 1) {
20862019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLE32S, mkU32(0), word));
20872019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
20882019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) {
20892019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return mkU32(1);
20902019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
20912019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* Remaining case */
20922019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         return mkU32(0);
20932019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
20942019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
20952019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* S390_CC_OP_TEST_UNDER_MASK_8
20962019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         Since the mask comes from an immediate field in the opcode, we
20972019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         expect the mask to be a constant here. That simplifies matters. */
20982019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_op == S390_CC_OP_TEST_UNDER_MASK_8) {
20992019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         ULong mask16;
21002019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
21012019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (! isC64(cc_dep2)) goto missed;
21022019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
21032019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         mask16 = cc_dep2->Iex.Const.con->Ico.U64;
21042019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
21052019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* Get rid of the mask16 == 0 case first. Some of the simplifications
21062019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            below (e.g. for OVFL) only hold if mask16 == 0.  */
21072019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (mask16 == 0) {   /* cc == 0 */
21082019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            if (cond & 0x8) return mkU32(1);
21092019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return mkU32(0);
21102019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
21112019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
21122019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* cc == 2 is a don't care */
21132019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 || cond == 8 + 2) {
21142019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
21152019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_And64, cc_dep1, cc_dep2),
21162019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU64(0)));
21172019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
21182019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 7 || cond == 7 - 2) {
21192019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE64,
21202019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_And64, cc_dep1, cc_dep2),
21212019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU64(0)));
21222019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
21232019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 1 || cond == 1 + 2) {
21242019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
21252019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_And64, cc_dep1, cc_dep2),
21262019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          cc_dep2));
21272019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
21282019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 14 || cond == 14 - 2) {  /* ! OVFL */
21292019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE64,
21302019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_And64, cc_dep1, cc_dep2),
21312019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          cc_dep2));
21322019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
21332019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         goto missed;
21342019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
21352019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
21362019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* S390_CC_OP_TEST_UNDER_MASK_16
21372019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         Since the mask comes from an immediate field in the opcode, we
21382019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         expect the mask to be a constant here. That simplifies matters. */
21392019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_op == S390_CC_OP_TEST_UNDER_MASK_16) {
21402019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         ULong mask16;
21412019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         UInt msb;
21422019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
21432019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (! isC64(cc_dep2)) goto missed;
21442019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
21452019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         mask16 = cc_dep2->Iex.Const.con->Ico.U64;
21462019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
21472019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* Get rid of the mask16 == 0 case first. Some of the simplifications
21482019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            below (e.g. for OVFL) only hold if mask16 == 0.  */
21492019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (mask16 == 0) {   /* cc == 0 */
21502019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            if (cond & 0x8) return mkU32(1);
21512019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return mkU32(0);
21522019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
21532019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
21549ec12ea8dc0876141a714f7c0411aec9bdae6cffflorian         if (cond == 15) return mkU32(1);
21559ec12ea8dc0876141a714f7c0411aec9bdae6cffflorian
21562019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8) {
21572019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
21582019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_And64, cc_dep1, cc_dep2),
21592019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU64(0)));
21602019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
21612019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 7) {
21622019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE64,
21632019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_And64, cc_dep1, cc_dep2),
21642019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU64(0)));
21652019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
21662019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 1) {
21672019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
21682019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_And64, cc_dep1, cc_dep2),
21692019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU64(mask16)));
21702019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
21712019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 14) {  /* ! OVFL */
21722019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE64,
21732019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_And64, cc_dep1, cc_dep2),
21742019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU64(mask16)));
21752019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
21762019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
21772019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* Find MSB in mask */
21782019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         msb = 0x8000;
21792019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         while (msb > mask16)
21802019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            msb >>= 1;
21812019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
21822019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 2) {  /* cc == 2 */
21832019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            IRExpr *c1, *c2;
21842019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
21852019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            /* (cc_dep & msb) != 0 && (cc_dep & mask16) != mask16 */
21862019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            c1 = binop(Iop_CmpNE64,
21872019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                       binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
21882019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            c2 = binop(Iop_CmpNE64,
21892019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                       binop(Iop_And64, cc_dep1, cc_dep2),
21902019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                       mkU64(mask16));
21912019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return binop(Iop_And32, unop(Iop_1Uto32, c1),
21922019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                         unop(Iop_1Uto32, c2));
21932019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
21942019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
21952019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 4) {  /* cc == 1 */
21962019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            IRExpr *c1, *c2;
21972019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
21982019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            /* (cc_dep & msb) == 0 && (cc_dep & mask16) != 0 */
21992019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            c1 = binop(Iop_CmpEQ64,
22002019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                       binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
22012019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            c2 = binop(Iop_CmpNE64,
22022019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                       binop(Iop_And64, cc_dep1, cc_dep2),
22032019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                       mkU64(0));
22042019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return binop(Iop_And32, unop(Iop_1Uto32, c1),
22052019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                         unop(Iop_1Uto32, c2));
22062019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
22072019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
22082019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 11) {  /* cc == 0,2,3 */
22092019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            IRExpr *c1, *c2;
22102019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
22112019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            c1 = binop(Iop_CmpNE64,
22122019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                       binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0));
22132019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            c2 = binop(Iop_CmpEQ64,
22142019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                       binop(Iop_And64, cc_dep1, cc_dep2),
22152019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                       mkU64(0));
22162019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return binop(Iop_Or32, unop(Iop_1Uto32, c1),
22172019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                         unop(Iop_1Uto32, c2));
22182019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
22192019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
22202019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 3) {  /* cc == 2 || cc == 3 */
22212019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32,
22222019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                        binop(Iop_CmpNE64,
22232019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                              binop(Iop_And64, cc_dep1, mkU64(msb)),
22242019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                              mkU64(0)));
22252019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
22262019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 12) { /* cc == 0 || cc == 1 */
22272019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32,
22282019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                        binop(Iop_CmpEQ64,
22292019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                              binop(Iop_And64, cc_dep1, mkU64(msb)),
22302019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                              mkU64(0)));
22312019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
22329ec12ea8dc0876141a714f7c0411aec9bdae6cffflorian         if (cond == 13) { /* cc == 0 || cc == 1 || cc == 3 */
22339ec12ea8dc0876141a714f7c0411aec9bdae6cffflorian            IRExpr *c01, *c3;
22349ec12ea8dc0876141a714f7c0411aec9bdae6cffflorian
22359ec12ea8dc0876141a714f7c0411aec9bdae6cffflorian            c01 = binop(Iop_CmpEQ64, binop(Iop_And64, cc_dep1, mkU64(msb)),
22369ec12ea8dc0876141a714f7c0411aec9bdae6cffflorian                        mkU64(0));
22379ec12ea8dc0876141a714f7c0411aec9bdae6cffflorian            c3 = binop(Iop_CmpEQ64, binop(Iop_And64, cc_dep1, cc_dep2),
22389ec12ea8dc0876141a714f7c0411aec9bdae6cffflorian                       mkU64(mask16));
22399ec12ea8dc0876141a714f7c0411aec9bdae6cffflorian            return binop(Iop_Or32, unop(Iop_1Uto32, c01),
22409ec12ea8dc0876141a714f7c0411aec9bdae6cffflorian                         unop(Iop_1Uto32, c3));
22419ec12ea8dc0876141a714f7c0411aec9bdae6cffflorian         }
22429ec12ea8dc0876141a714f7c0411aec9bdae6cffflorian         // fixs390: handle cond = 5,6,9,10 (the missing cases)
22432019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         // vex_printf("TUM mask = 0x%llx\n", mask16);
22442019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         goto missed;
22452019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
22462019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
22472019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* S390_CC_OP_UNSIGNED_SUB_64/32 */
22482019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_op == S390_CC_OP_UNSIGNED_SUB_64 ||
22492019a976f07ff418dde2dfc7cc74667ef66d7764sewardj          cc_op == S390_CC_OP_UNSIGNED_SUB_32) {
22502019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /*
22512019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc_dep1, cc_dep2 are the zero extended left and right operands
22522019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
22532019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 1  --> result != 0, borrow    (cond == 4)
22542019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 2  --> result == 0, no borrow (cond == 2)
22552019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 3  --> result != 0, no borrow (cond == 1)
22562019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
22572019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc = (cc_dep1 == cc_dep2) ? 2
22582019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                      : (cc_dep1 > cc_dep2) ? 3 : 1;
22592019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
22602019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            Because cc == 0 cannot occur the leftmost bit of cond is
22612019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            a don't care.
22622019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         */
22632019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 1 || cond == 1 + 8) {  /* cc == 3   op2 < op1 */
22642019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep2, cc_dep1));
22652019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
22662019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 2 || cond == 2 + 8) {  /* cc == 2 */
22672019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
22682019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
22692019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 4 || cond == 4 + 8) {  /* cc == 1 */
22702019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
22712019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
22722019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 3 || cond == 3 + 8) {  /* cc == 2 || cc == 3 */
22732019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
22742019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
22752019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 6 || cond == 6 + 8) {  /* cc == 2 || cc == 1 */
22762019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
22772019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
22782019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
22792019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 5 || cond == 5 + 8) {  /* cc == 3 || cc == 1 */
22802019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2));
22812019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
22822019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 7 || cond == 7 + 8) {
22832019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return mkU32(1);
22842019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
22852019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* Remaining case */
22862019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         return mkU32(0);
22872019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
22882019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
22892019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* S390_CC_OP_UNSIGNED_ADD_64 */
22902019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_op == S390_CC_OP_UNSIGNED_ADD_64) {
22912019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /*
22922019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc_dep1, cc_dep2 are the zero extended left and right operands
22932019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
22942019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 0  --> result == 0, no carry  (cond == 8)
22952019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 1  --> result != 0, no carry  (cond == 4)
22962019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 2  --> result == 0, carry     (cond == 2)
22972019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 3  --> result != 0, carry     (cond == 1)
22982019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         */
22992019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8) { /* cc == 0 */
23002019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            /* Both inputs are 0 */
23012019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
23022019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_Or64, cc_dep1, cc_dep2),
23032019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU64(0)));
23042019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
23052019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 7) { /* cc == 1,2,3 */
23062019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            /* Not both inputs are 0 */
23072019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE64,
23082019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_Or64, cc_dep1, cc_dep2),
23092019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU64(0)));
23102019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
23112019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 2) {  /* cc == 0,2  -> result is zero */
23122019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
23132019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_Add64, cc_dep1, cc_dep2),
23142019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU64(0)));
23152019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
23162019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 4 + 1) {  /* cc == 1,3  -> result is not zero */
23172019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE64,
23182019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_Add64, cc_dep1, cc_dep2),
23192019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU64(0)));
23202019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
23212019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         goto missed;
23222019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
23232019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
23242019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* S390_CC_OP_UNSIGNED_ADD_32 */
23252019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_op == S390_CC_OP_UNSIGNED_ADD_32) {
23262019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /*
23272019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc_dep1, cc_dep2 are the zero extended left and right operands
23282019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
23292019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 0  --> result == 0, no carry  (cond == 8)
23302019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 1  --> result != 0, no carry  (cond == 4)
23312019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 2  --> result == 0, carry     (cond == 2)
23322019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            cc == 3  --> result != 0, carry     (cond == 1)
23332019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         */
23342019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8) { /* cc == 0 */
23352019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            /* Both inputs are 0 */
23362019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ64,
23372019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_Or64, cc_dep1, cc_dep2),
23382019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU64(0)));
23392019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
23402019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 7) { /* cc == 1,2,3 */
23412019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            /* Not both inputs are 0 */
23422019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE64,
23432019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_Or64, cc_dep1, cc_dep2),
23442019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU64(0)));
23452019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
23462019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 8 + 2) {  /* cc == 0,2  -> result is zero */
23472019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpEQ32,
23482019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_Add32,
23492019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                                unop(Iop_64to32, cc_dep1),
23502019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                                unop(Iop_64to32, cc_dep2)),
23512019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU32(0)));
23522019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
23532019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         if (cond == 4 + 1) {  /* cc == 1,3  -> result is not zero */
23542019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            return unop(Iop_1Uto32, binop(Iop_CmpNE32,
23552019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          binop(Iop_Add32,
23562019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                                unop(Iop_64to32, cc_dep1),
23572019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                                unop(Iop_64to32, cc_dep2)),
23582019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                          mkU32(0)));
23592019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         }
23602019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         goto missed;
23612019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
23622019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
23632019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      /* S390_CC_OP_SET */
23642019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      if (cc_op == S390_CC_OP_SET) {
23652019a976f07ff418dde2dfc7cc74667ef66d7764sewardj         /* cc_dep1 is the condition code
23662019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
23672019a976f07ff418dde2dfc7cc74667ef66d7764sewardj            Return 1, if ((cond << cc_dep1) & 0x8) != 0 */
23682019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
23692019a976f07ff418dde2dfc7cc74667ef66d7764sewardj        return unop(Iop_1Uto32,
23702019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                    binop(Iop_CmpNE64,
23712019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                          binop(Iop_And64,
23722019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                binop(Iop_Shl64, cond_expr,
23732019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                      unop(Iop_64to8, cc_dep1)),
23742019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                                mkU64(8)),
23752019a976f07ff418dde2dfc7cc74667ef66d7764sewardj                          mkU64(0)));
23762019a976f07ff418dde2dfc7cc74667ef66d7764sewardj      }
23772019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
2378af514c044bf90048e9bb916024198f9bc5dcb3f5florian      goto missed;
23792019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   }
23802019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
23819ec12ea8dc0876141a714f7c0411aec9bdae6cffflorian   /* --------- Specialising "s390_calculate_cc" --------- */
2382af514c044bf90048e9bb916024198f9bc5dcb3f5florian
2383af514c044bf90048e9bb916024198f9bc5dcb3f5florian   if (vex_streq(function_name, "s390_calculate_cc")) {
2384af514c044bf90048e9bb916024198f9bc5dcb3f5florian      IRExpr *cc_op_expr, *cc_dep1;
2385af514c044bf90048e9bb916024198f9bc5dcb3f5florian      ULong cc_op;
2386af514c044bf90048e9bb916024198f9bc5dcb3f5florian
2387af514c044bf90048e9bb916024198f9bc5dcb3f5florian      vassert(arity == 4);
2388af514c044bf90048e9bb916024198f9bc5dcb3f5florian
2389af514c044bf90048e9bb916024198f9bc5dcb3f5florian      cc_op_expr = args[0];
2390af514c044bf90048e9bb916024198f9bc5dcb3f5florian
2391af514c044bf90048e9bb916024198f9bc5dcb3f5florian      /* The necessary requirement for all optimizations here is that
2392af514c044bf90048e9bb916024198f9bc5dcb3f5florian         cc_op is constant. So check that upfront. */
2393af514c044bf90048e9bb916024198f9bc5dcb3f5florian      if (! isC64(cc_op_expr)) return NULL;
2394af514c044bf90048e9bb916024198f9bc5dcb3f5florian
2395af514c044bf90048e9bb916024198f9bc5dcb3f5florian      cc_op   = cc_op_expr->Iex.Const.con->Ico.U64;
2396af514c044bf90048e9bb916024198f9bc5dcb3f5florian      cc_dep1 = args[1];
2397af514c044bf90048e9bb916024198f9bc5dcb3f5florian
2398af514c044bf90048e9bb916024198f9bc5dcb3f5florian      if (cc_op == S390_CC_OP_BITWISE) {
2399af514c044bf90048e9bb916024198f9bc5dcb3f5florian         return unop(Iop_1Uto32,
2400af514c044bf90048e9bb916024198f9bc5dcb3f5florian                     binop(Iop_CmpNE64, cc_dep1, mkU64(0)));
2401af514c044bf90048e9bb916024198f9bc5dcb3f5florian      }
2402af514c044bf90048e9bb916024198f9bc5dcb3f5florian
2403af514c044bf90048e9bb916024198f9bc5dcb3f5florian      if (cc_op == S390_CC_OP_SET) {
2404af514c044bf90048e9bb916024198f9bc5dcb3f5florian         return unop(Iop_64to32, cc_dep1);
2405af514c044bf90048e9bb916024198f9bc5dcb3f5florian      }
2406af514c044bf90048e9bb916024198f9bc5dcb3f5florian
2407af514c044bf90048e9bb916024198f9bc5dcb3f5florian      goto missed;
2408af514c044bf90048e9bb916024198f9bc5dcb3f5florian   }
2409af514c044bf90048e9bb916024198f9bc5dcb3f5florian
2410af514c044bf90048e9bb916024198f9bc5dcb3f5florianmissed:
24112019a976f07ff418dde2dfc7cc74667ef66d7764sewardj   return NULL;
24122019a976f07ff418dde2dfc7cc74667ef66d7764sewardj}
24132019a976f07ff418dde2dfc7cc74667ef66d7764sewardj
24142019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*---------------------------------------------------------------*/
24152019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*--- end                                guest_s390_helpers.c ---*/
24162019a976f07ff418dde2dfc7cc74667ef66d7764sewardj/*---------------------------------------------------------------*/
2417