1 /* -*- mode: C; c-basic-offset: 3; -*- */ 2 3 /*---------------------------------------------------------------*/ 4 /*--- begin guest_s390_helpers.c ---*/ 5 /*---------------------------------------------------------------*/ 6 7 /* 8 This file is part of Valgrind, a dynamic binary instrumentation 9 framework. 10 11 Copyright IBM Corp. 2010-2015 12 13 This program is free software; you can redistribute it and/or 14 modify it under the terms of the GNU General Public License as 15 published by the Free Software Foundation; either version 2 of the 16 License, or (at your option) any later version. 17 18 This program is distributed in the hope that it will be useful, but 19 WITHOUT ANY WARRANTY; without even the implied warranty of 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 General Public License for more details. 22 23 You should have received a copy of the GNU General Public License 24 along with this program; if not, write to the Free Software 25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 26 02110-1301, USA. 27 28 The GNU General Public License is contained in the file COPYING. 29 */ 30 31 /* Contributed by Florian Krohm */ 32 33 #include "libvex_basictypes.h" 34 #include "libvex_emnote.h" 35 #include "libvex_guest_s390x.h" 36 #include "libvex_ir.h" 37 #include "libvex.h" 38 #include "libvex_s390x_common.h" 39 40 #include "main_util.h" 41 #include "main_globals.h" 42 #include "guest_generic_bb_to_IR.h" 43 #include "guest_s390_defs.h" 44 #include "s390_defs.h" /* S390_BFP_ROUND_xyzzy */ 45 46 void 47 LibVEX_GuestS390X_initialise(VexGuestS390XState *state) 48 { 49 /*------------------------------------------------------------*/ 50 /*--- Initialise ar registers ---*/ 51 /*------------------------------------------------------------*/ 52 53 state->guest_a0 = 0; 54 state->guest_a1 = 0; 55 state->guest_a2 = 0; 56 state->guest_a3 = 0; 57 state->guest_a4 = 0; 58 state->guest_a5 = 0; 59 state->guest_a6 = 0; 60 state->guest_a7 = 0; 61 state->guest_a8 = 0; 62 state->guest_a9 = 0; 63 state->guest_a10 = 0; 64 state->guest_a11 = 0; 65 state->guest_a12 = 0; 66 state->guest_a13 = 0; 67 state->guest_a14 = 0; 68 state->guest_a15 = 0; 69 70 /*------------------------------------------------------------*/ 71 /*--- Initialise fpr registers ---*/ 72 /*------------------------------------------------------------*/ 73 74 state->guest_f0 = 0; 75 state->guest_f1 = 0; 76 state->guest_f2 = 0; 77 state->guest_f3 = 0; 78 state->guest_f4 = 0; 79 state->guest_f5 = 0; 80 state->guest_f6 = 0; 81 state->guest_f7 = 0; 82 state->guest_f8 = 0; 83 state->guest_f9 = 0; 84 state->guest_f10 = 0; 85 state->guest_f11 = 0; 86 state->guest_f12 = 0; 87 state->guest_f13 = 0; 88 state->guest_f14 = 0; 89 state->guest_f15 = 0; 90 91 /*------------------------------------------------------------*/ 92 /*--- Initialise gpr registers ---*/ 93 /*------------------------------------------------------------*/ 94 95 state->guest_r0 = 0; 96 state->guest_r1 = 0; 97 state->guest_r2 = 0; 98 state->guest_r3 = 0; 99 state->guest_r4 = 0; 100 state->guest_r5 = 0; 101 state->guest_r6 = 0; 102 state->guest_r7 = 0; 103 state->guest_r8 = 0; 104 state->guest_r9 = 0; 105 state->guest_r10 = 0; 106 state->guest_r11 = 0; 107 state->guest_r12 = 0; 108 state->guest_r13 = 0; 109 state->guest_r14 = 0; 110 state->guest_r15 = 0; 111 112 /*------------------------------------------------------------*/ 113 /*--- Initialise S390 miscellaneous registers ---*/ 114 /*------------------------------------------------------------*/ 115 116 state->guest_counter = 0; 117 state->guest_fpc = 0; 118 state->guest_IA = 0; 119 120 /*------------------------------------------------------------*/ 121 /*--- Initialise S390 pseudo registers ---*/ 122 /*------------------------------------------------------------*/ 123 124 state->guest_SYSNO = 0; 125 126 /*------------------------------------------------------------*/ 127 /*--- Initialise generic pseudo registers ---*/ 128 /*------------------------------------------------------------*/ 129 130 state->guest_NRADDR = 0; 131 state->guest_CMSTART = 0; 132 state->guest_CMLEN = 0; 133 state->guest_IP_AT_SYSCALL = 0; 134 state->guest_EMNOTE = EmNote_NONE; 135 state->host_EvC_COUNTER = 0; 136 state->host_EvC_FAILADDR = 0; 137 138 /*------------------------------------------------------------*/ 139 /*--- Initialise thunk ---*/ 140 /*------------------------------------------------------------*/ 141 142 state->guest_CC_OP = 0; 143 state->guest_CC_DEP1 = 0; 144 state->guest_CC_DEP2 = 0; 145 state->guest_CC_NDEP = 0; 146 147 __builtin_memset(state->padding, 0x0, sizeof(state->padding)); 148 } 149 150 151 /* Figure out if any part of the guest state contained in minoff 152 .. maxoff requires precise memory exceptions. If in doubt return 153 True (but this generates significantly slower code). */ 154 Bool 155 guest_s390x_state_requires_precise_mem_exns ( 156 Int minoff, Int maxoff, VexRegisterUpdates pxControl 157 ) 158 { 159 Int lr_min = S390X_GUEST_OFFSET(guest_LR); 160 Int lr_max = lr_min + 8 - 1; 161 Int sp_min = S390X_GUEST_OFFSET(guest_SP); 162 Int sp_max = sp_min + 8 - 1; 163 Int fp_min = S390X_GUEST_OFFSET(guest_FP); 164 Int fp_max = fp_min + 8 - 1; 165 Int ia_min = S390X_GUEST_OFFSET(guest_IA); 166 Int ia_max = ia_min + 8 - 1; 167 168 if (maxoff < sp_min || minoff > sp_max) { 169 /* No overlap with SP */ 170 if (pxControl == VexRegUpdSpAtMemAccess) 171 return False; // We only need to check stack pointer. 172 } else { 173 return True; 174 } 175 176 if (maxoff < lr_min || minoff > lr_max) { 177 /* No overlap with LR */ 178 } else { 179 return True; 180 } 181 182 if (maxoff < fp_min || minoff > fp_max) { 183 /* No overlap with FP */ 184 } else { 185 return True; 186 } 187 188 if (maxoff < ia_min || minoff > ia_max) { 189 /* No overlap with IA */ 190 } else { 191 return True; 192 } 193 194 return False; 195 } 196 197 198 #define ALWAYSDEFD(field) \ 199 { S390X_GUEST_OFFSET(field), \ 200 (sizeof ((VexGuestS390XState*)0)->field) } 201 202 VexGuestLayout s390xGuest_layout = { 203 204 /* Total size of the guest state, in bytes. */ 205 .total_sizeB = sizeof(VexGuestS390XState), 206 207 /* Describe the stack pointer. */ 208 .offset_SP = S390X_GUEST_OFFSET(guest_SP), 209 .sizeof_SP = 8, 210 211 /* Describe the frame pointer. */ 212 .offset_FP = S390X_GUEST_OFFSET(guest_FP), 213 .sizeof_FP = 8, 214 215 /* Describe the instruction pointer. */ 216 .offset_IP = S390X_GUEST_OFFSET(guest_IA), 217 .sizeof_IP = 8, 218 219 /* Describe any sections to be regarded by Memcheck as 220 'always-defined'. */ 221 .n_alwaysDefd = 9, 222 223 /* Flags thunk: OP and NDEP are always defined, whereas DEP1 224 and DEP2 have to be tracked. See detailed comment in 225 gdefs.h on meaning of thunk fields. */ 226 .alwaysDefd = { 227 /* 0 */ ALWAYSDEFD(guest_CC_OP), /* generic */ 228 /* 1 */ ALWAYSDEFD(guest_CC_NDEP), /* generic */ 229 /* 2 */ ALWAYSDEFD(guest_EMNOTE), /* generic */ 230 /* 3 */ ALWAYSDEFD(guest_CMSTART), /* generic */ 231 /* 4 */ ALWAYSDEFD(guest_CMLEN), /* generic */ 232 /* 5 */ ALWAYSDEFD(guest_IP_AT_SYSCALL), /* generic */ 233 /* 6 */ ALWAYSDEFD(guest_IA), /* control reg */ 234 /* 7 */ ALWAYSDEFD(guest_fpc), /* control reg */ 235 /* 8 */ ALWAYSDEFD(guest_counter), /* internal usage register */ 236 } 237 }; 238 239 /*------------------------------------------------------------*/ 240 /*--- Dirty helper for EXecute ---*/ 241 /*------------------------------------------------------------*/ 242 void 243 s390x_dirtyhelper_EX(ULong torun) 244 { 245 last_execute_target = torun; 246 } 247 248 249 /*------------------------------------------------------------*/ 250 /*--- Dirty helper for Clock instructions ---*/ 251 /*------------------------------------------------------------*/ 252 #if defined(VGA_s390x) 253 ULong 254 s390x_dirtyhelper_STCK(ULong *addr) 255 { 256 UInt cc; 257 258 asm volatile("stck %0\n" 259 "ipm %1\n" 260 "srl %1,28\n" 261 : "+Q" (*addr), "=d" (cc) : : "cc"); 262 return cc; 263 } 264 265 ULong 266 s390x_dirtyhelper_STCKE(ULong *addr) 267 { 268 UInt cc; 269 270 asm volatile("stcke %0\n" 271 "ipm %1\n" 272 "srl %1,28\n" 273 : "+Q" (*addr), "=d" (cc) : : "cc"); 274 return cc; 275 } 276 277 ULong s390x_dirtyhelper_STCKF(ULong *addr) 278 { 279 UInt cc; 280 281 asm volatile(".insn s,0xb27c0000,%0\n" 282 "ipm %1\n" 283 "srl %1,28\n" 284 : "+Q" (*addr), "=d" (cc) : : "cc"); 285 return cc; 286 } 287 #else 288 ULong s390x_dirtyhelper_STCK(ULong *addr) {return 3;} 289 ULong s390x_dirtyhelper_STCKF(ULong *addr) {return 3;} 290 ULong s390x_dirtyhelper_STCKE(ULong *addr) {return 3;} 291 #endif /* VGA_s390x */ 292 293 /*------------------------------------------------------------*/ 294 /*--- Dirty helper for Store Facility instruction ---*/ 295 /*------------------------------------------------------------*/ 296 #if defined(VGA_s390x) 297 static void 298 s390_set_facility_bit(ULong *addr, UInt bitno, UInt value) 299 { 300 addr += bitno / 64; 301 bitno = bitno % 64; 302 303 ULong mask = 1; 304 mask <<= (63 - bitno); 305 306 if (value == 1) { 307 *addr |= mask; // set 308 } else { 309 *addr &= ~mask; // clear 310 } 311 } 312 313 ULong 314 s390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, ULong *addr) 315 { 316 ULong hoststfle[S390_NUM_FACILITY_DW], cc, num_dw, i; 317 register ULong reg0 asm("0") = guest_state->guest_r0 & 0xF; /* r0[56:63] */ 318 319 /* We cannot store more than S390_NUM_FACILITY_DW 320 (and it makes not much sense to do so anyhow) */ 321 if (reg0 > S390_NUM_FACILITY_DW - 1) 322 reg0 = S390_NUM_FACILITY_DW - 1; 323 324 num_dw = reg0 + 1; /* number of double words written */ 325 326 asm volatile(" .insn s,0xb2b00000,%0\n" /* stfle */ 327 "ipm %2\n" 328 "srl %2,28\n" 329 : "=m" (hoststfle), "+d"(reg0), "=d"(cc) : : "cc", "memory"); 330 331 /* Update guest register 0 with what STFLE set r0 to */ 332 guest_state->guest_r0 = reg0; 333 334 /* Set default: VM facilities = host facilities */ 335 for (i = 0; i < num_dw; ++i) 336 addr[i] = hoststfle[i]; 337 338 /* Now adjust the VM facilities according to what the VM supports */ 339 s390_set_facility_bit(addr, S390_FAC_LDISP, 1); 340 s390_set_facility_bit(addr, S390_FAC_EIMM, 1); 341 s390_set_facility_bit(addr, S390_FAC_ETF2, 1); 342 s390_set_facility_bit(addr, S390_FAC_ETF3, 1); 343 s390_set_facility_bit(addr, S390_FAC_GIE, 1); 344 s390_set_facility_bit(addr, S390_FAC_EXEXT, 1); 345 s390_set_facility_bit(addr, S390_FAC_HIGHW, 1); 346 347 s390_set_facility_bit(addr, S390_FAC_HFPMAS, 0); 348 s390_set_facility_bit(addr, S390_FAC_HFPUNX, 0); 349 s390_set_facility_bit(addr, S390_FAC_XCPUT, 0); 350 s390_set_facility_bit(addr, S390_FAC_MSA, 0); 351 s390_set_facility_bit(addr, S390_FAC_PENH, 0); 352 s390_set_facility_bit(addr, S390_FAC_DFP, 0); 353 s390_set_facility_bit(addr, S390_FAC_PFPO, 0); 354 s390_set_facility_bit(addr, S390_FAC_DFPZC, 0); 355 s390_set_facility_bit(addr, S390_FAC_MISC, 0); 356 s390_set_facility_bit(addr, S390_FAC_CTREXE, 0); 357 s390_set_facility_bit(addr, S390_FAC_TREXE, 0); 358 s390_set_facility_bit(addr, S390_FAC_MSA4, 0); 359 360 return cc; 361 } 362 363 #else 364 365 ULong 366 s390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, ULong *addr) 367 { 368 return 3; 369 } 370 #endif /* VGA_s390x */ 371 372 /*------------------------------------------------------------*/ 373 /*--- Dirty helper for the "convert unicode" insn family. ---*/ 374 /*------------------------------------------------------------*/ 375 void 376 s390x_dirtyhelper_CUxy(UChar *address, ULong data, ULong num_bytes) 377 { 378 UInt i; 379 380 vassert(num_bytes >= 1 && num_bytes <= 4); 381 382 /* Store the least significant NUM_BYTES bytes in DATA left to right 383 at ADDRESS. */ 384 for (i = 1; i <= num_bytes; ++i) { 385 address[num_bytes - i] = data & 0xff; 386 data >>= 8; 387 } 388 } 389 390 391 /*------------------------------------------------------------*/ 392 /*--- Clean helper for CU21. ---*/ 393 /*------------------------------------------------------------*/ 394 395 /* The function performs a CU21 operation. It returns three things 396 encoded in an ULong value: 397 - the converted bytes (at most 4) 398 - the number of converted bytes 399 - an indication whether LOW_SURROGATE, if any, is invalid 400 401 64 48 16 8 0 402 +-------+-----------------+-----------+-----------------------+ 403 | 0x0 | converted bytes | num_bytes | invalid_low_surrogate | 404 +-------+-----------------+-----------+-----------------------+ 405 */ 406 ULong 407 s390_do_cu21(UInt srcval, UInt low_surrogate) 408 { 409 ULong retval = 0; // shut up gcc 410 UInt b1, b2, b3, b4, num_bytes, invalid_low_surrogate = 0; 411 412 srcval &= 0xffff; 413 414 /* Determine the number of bytes in the converted value */ 415 if (srcval <= 0x007f) 416 num_bytes = 1; 417 else if (srcval >= 0x0080 && srcval <= 0x07ff) 418 num_bytes = 2; 419 else if ((srcval >= 0x0800 && srcval <= 0xd7ff) || 420 (srcval >= 0xdc00 && srcval <= 0xffff)) 421 num_bytes = 3; 422 else 423 num_bytes = 4; 424 425 /* Determine UTF-8 bytes according to calculated num_bytes */ 426 switch (num_bytes){ 427 case 1: 428 retval = srcval; 429 break; 430 431 case 2: 432 /* order of bytes left to right: b1, b2 */ 433 b1 = 0xc0; 434 b1 |= srcval >> 6; 435 436 b2 = 0x80; 437 b2 |= srcval & 0x3f; 438 439 retval = (b1 << 8) | b2; 440 break; 441 442 case 3: 443 /* order of bytes left to right: b1, b2, b3 */ 444 b1 = 0xe0; 445 b1 |= srcval >> 12; 446 447 b2 = 0x80; 448 b2 |= (srcval >> 6) & 0x3f; 449 450 b3 = 0x80; 451 b3 |= srcval & 0x3f; 452 453 retval = (b1 << 16) | (b2 << 8) | b3; 454 break; 455 456 case 4: { 457 /* order of bytes left to right: b1, b2, b3, b4 */ 458 UInt high_surrogate = srcval; 459 UInt uvwxy = ((high_surrogate >> 6) & 0xf) + 1; // abcd + 1 460 461 b1 = 0xf0; 462 b1 |= uvwxy >> 2; // uvw 463 464 b2 = 0x80; 465 b2 |= (uvwxy & 0x3) << 4; // xy 466 b2 |= (high_surrogate >> 2) & 0xf; // efgh 467 468 b3 = 0x80; 469 b3 |= (high_surrogate & 0x3) << 4; // ij 470 b3 |= (low_surrogate >> 6) & 0xf; // klmn 471 472 b4 = 0x80; 473 b4 |= low_surrogate & 0x3f; 474 475 retval = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4; 476 477 invalid_low_surrogate = (low_surrogate & 0xfc00) != 0xdc00; 478 break; 479 } 480 } 481 482 /* At this point RETVAL contains the converted bytes. 483 Build up the final return value. */ 484 return (retval << 16) | (num_bytes << 8) | invalid_low_surrogate; 485 } 486 487 488 /*------------------------------------------------------------*/ 489 /*--- Clean helper for CU24. ---*/ 490 /*------------------------------------------------------------*/ 491 492 /* The function performs a CU24 operation. It returns two things 493 encoded in an ULong value: 494 - the 4 converted bytes 495 - an indication whether LOW_SURROGATE, if any, is invalid 496 497 64 40 8 0 498 +------------------------+-----------------------+ 499 | 0x0 | converted bytes | invalid_low_surrogate | 500 +------------------------+-----------------------+ 501 */ 502 ULong 503 s390_do_cu24(UInt srcval, UInt low_surrogate) 504 { 505 ULong retval; 506 UInt invalid_low_surrogate = 0; 507 508 srcval &= 0xffff; 509 510 if ((srcval >= 0x0000 && srcval <= 0xd7ff) || 511 (srcval >= 0xdc00 && srcval <= 0xffff)) { 512 retval = srcval; 513 } else { 514 /* D800 - DBFF */ 515 UInt high_surrogate = srcval; 516 UInt uvwxy = ((high_surrogate >> 6) & 0xf) + 1; // abcd + 1 517 UInt efghij = high_surrogate & 0x3f; 518 UInt klmnoprst = low_surrogate & 0x3ff; 519 520 retval = (uvwxy << 16) | (efghij << 10) | klmnoprst; 521 522 invalid_low_surrogate = (low_surrogate & 0xfc00) != 0xdc00; 523 } 524 525 /* At this point RETVAL contains the converted bytes. 526 Build up the final return value. */ 527 return (retval << 8) | invalid_low_surrogate; 528 } 529 530 531 /*------------------------------------------------------------*/ 532 /*--- Clean helper for CU42. ---*/ 533 /*------------------------------------------------------------*/ 534 535 /* The function performs a CU42 operation. It returns three things 536 encoded in an ULong value: 537 - the converted bytes (at most 4) 538 - the number of converted bytes (2 or 4; 0 if invalid character) 539 - an indication whether the UTF-32 character is invalid 540 541 64 48 16 8 0 542 +-------+-----------------+-----------+-------------------+ 543 | 0x0 | converted bytes | num_bytes | invalid_character | 544 +-------+-----------------+-----------+-------------------+ 545 */ 546 ULong 547 s390_do_cu42(UInt srcval) 548 { 549 ULong retval; 550 UInt num_bytes, invalid_character = 0; 551 552 if ((srcval >= 0x0000 && srcval <= 0xd7ff) || 553 (srcval >= 0xdc00 && srcval <= 0xffff)) { 554 retval = srcval; 555 num_bytes = 2; 556 } else if (srcval >= 0x00010000 && srcval <= 0x0010FFFF) { 557 UInt uvwxy = srcval >> 16; 558 UInt abcd = (uvwxy - 1) & 0xf; 559 UInt efghij = (srcval >> 10) & 0x3f; 560 561 UInt high_surrogate = (0xd8 << 8) | (abcd << 6) | efghij; 562 UInt low_surrogate = (0xdc << 8) | (srcval & 0x3ff); 563 564 retval = (high_surrogate << 16) | low_surrogate; 565 num_bytes = 4; 566 } else { 567 /* D800 - DBFF or 00110000 - FFFFFFFF */ 568 invalid_character = 1; 569 retval = num_bytes = 0; /* does not matter; not used */ 570 } 571 572 /* At this point RETVAL contains the converted bytes. 573 Build up the final return value. */ 574 return (retval << 16) | (num_bytes << 8) | invalid_character; 575 } 576 577 578 /*------------------------------------------------------------*/ 579 /*--- Clean helper for CU41. ---*/ 580 /*------------------------------------------------------------*/ 581 582 /* The function performs a CU41 operation. It returns three things 583 encoded in an ULong value: 584 - the converted bytes (at most 4) 585 - the number of converted bytes (1, 2, 3, or 4; 0 if invalid character) 586 - an indication whether the UTF-32 character is invalid 587 588 64 48 16 8 0 589 +-------+-----------------+-----------+-------------------+ 590 | 0x0 | converted bytes | num_bytes | invalid_character | 591 +-------+-----------------+-----------+-------------------+ 592 */ 593 ULong 594 s390_do_cu41(UInt srcval) 595 { 596 ULong retval; 597 UInt num_bytes, invalid_character = 0; 598 599 if (srcval <= 0x7f) { 600 retval = srcval; 601 num_bytes = 1; 602 } else if (srcval >= 0x80 && srcval <= 0x7ff) { 603 UInt fghij = srcval >> 6; 604 UInt klmnop = srcval & 0x3f; 605 UInt byte1 = (0xc0 | fghij); 606 UInt byte2 = (0x80 | klmnop); 607 608 retval = (byte1 << 8) | byte2; 609 num_bytes = 2; 610 } else if ((srcval >= 0x800 && srcval <= 0xd7ff) || 611 (srcval >= 0xdc00 && srcval <= 0xffff)) { 612 UInt abcd = srcval >> 12; 613 UInt efghij = (srcval >> 6) & 0x3f; 614 UInt klmnop = srcval & 0x3f; 615 UInt byte1 = 0xe0 | abcd; 616 UInt byte2 = 0x80 | efghij; 617 UInt byte3 = 0x80 | klmnop; 618 619 retval = (byte1 << 16) | (byte2 << 8) | byte3; 620 num_bytes = 3; 621 } else if (srcval >= 0x10000 && srcval <= 0x10ffff) { 622 UInt uvw = (srcval >> 18) & 0x7; 623 UInt xy = (srcval >> 16) & 0x3; 624 UInt efgh = (srcval >> 12) & 0xf; 625 UInt ijklmn = (srcval >> 6) & 0x3f; 626 UInt opqrst = srcval & 0x3f; 627 UInt byte1 = 0xf0 | uvw; 628 UInt byte2 = 0x80 | (xy << 4) | efgh; 629 UInt byte3 = 0x80 | ijklmn; 630 UInt byte4 = 0x80 | opqrst; 631 632 retval = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4; 633 num_bytes = 4; 634 } else { 635 /* d800 ... dbff or 00110000 ... ffffffff */ 636 invalid_character = 1; 637 638 retval = 0; 639 num_bytes = 0; 640 } 641 642 /* At this point RETVAL contains the converted bytes. 643 Build up the final return value. */ 644 return (retval << 16) | (num_bytes << 8) | invalid_character; 645 } 646 647 648 /*------------------------------------------------------------*/ 649 /*--- Clean helpers for CU12. ---*/ 650 /*------------------------------------------------------------*/ 651 652 /* The function looks at the first byte of an UTF-8 character and returns 653 two things encoded in an ULong value: 654 655 - the number of bytes that need to be read 656 - an indication whether the UTF-8 character is invalid 657 658 64 16 8 0 659 +-------------------+-------------------+ 660 | 0x0 | num_bytes | invalid_character | 661 +-------+-----------+-------------------+ 662 */ 663 ULong 664 s390_do_cu12_cu14_helper1(UInt byte, UInt etf3_and_m3_is_1) 665 { 666 vassert(byte <= 0xff); 667 668 /* Check whether the character is invalid */ 669 if (byte >= 0x80 && byte <= 0xbf) return 1; 670 if (byte >= 0xf8) return 1; 671 672 if (etf3_and_m3_is_1) { 673 if (byte == 0xc0 || byte == 0xc1) return 1; 674 if (byte >= 0xf5 && byte <= 0xf7) return 1; 675 } 676 677 /* Character is valid */ 678 if (byte <= 0x7f) return 1 << 8; // 1 byte 679 if (byte <= 0xdf) return 2 << 8; // 2 bytes 680 if (byte <= 0xef) return 3 << 8; // 3 bytes 681 682 return 4 << 8; // 4 bytes 683 } 684 685 /* The function performs a CU12 or CU14 operation. BYTE1, BYTE2, etc are the 686 bytes as read from the input stream, left to right. BYTE1 is a valid 687 byte. The function returns three things encoded in an ULong value: 688 689 - the converted bytes 690 - the number of converted bytes (2 or 4; 0 if invalid character) 691 - an indication whether the UTF-16 character is invalid 692 693 64 48 16 8 0 694 +-------+-----------------+-----------+-------------------+ 695 | 0x0 | converted bytes | num_bytes | invalid_character | 696 +-------+-----------------+-----------+-------------------+ 697 */ 698 static ULong 699 s390_do_cu12_cu14_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4, 700 ULong stuff, Bool is_cu12) 701 { 702 UInt num_src_bytes = stuff >> 1, etf3_and_m3_is_1 = stuff & 0x1; 703 UInt num_bytes = 0, invalid_character = 0; 704 ULong retval = 0; 705 706 vassert(num_src_bytes <= 4); 707 708 switch (num_src_bytes) { 709 case 1: 710 num_bytes = 2; 711 retval = byte1; 712 break; 713 714 case 2: { 715 /* Test validity */ 716 if (etf3_and_m3_is_1) { 717 if (byte2 < 0x80 || byte2 > 0xbf) { 718 invalid_character = 1; 719 break; 720 } 721 } 722 723 /* OK */ 724 UInt fghij = byte1 & 0x1f; 725 UInt klmnop = byte2 & 0x3f; 726 727 num_bytes = 2; 728 retval = (fghij << 6) | klmnop; 729 break; 730 } 731 732 case 3: { 733 /* Test validity */ 734 if (etf3_and_m3_is_1) { 735 if (byte1 == 0xe0) { 736 if ((byte2 < 0xa0 || byte2 > 0xbf) || 737 (byte3 < 0x80 || byte3 > 0xbf)) { 738 invalid_character = 1; 739 break; 740 } 741 } 742 if ((byte1 >= 0xe1 && byte1 <= 0xec) || 743 byte1 == 0xee || byte1 == 0xef) { 744 if ((byte2 < 0x80 || byte2 > 0xbf) || 745 (byte3 < 0x80 || byte3 > 0xbf)) { 746 invalid_character = 1; 747 break; 748 } 749 } 750 if (byte1 == 0xed) { 751 if ((byte2 < 0x80 || byte2 > 0x9f) || 752 (byte3 < 0x80 || byte3 > 0xbf)) { 753 invalid_character = 1; 754 break; 755 } 756 } 757 } 758 759 /* OK */ 760 UInt abcd = byte1 & 0xf; 761 UInt efghij = byte2 & 0x3f; 762 UInt klmnop = byte3 & 0x3f; 763 764 num_bytes = 2; 765 retval = (abcd << 12) | (efghij << 6) | klmnop; 766 break; 767 } 768 769 case 4: { 770 /* Test validity */ 771 if (etf3_and_m3_is_1) { 772 if (byte1 == 0xf0) { 773 if ((byte2 < 0x90 || byte2 > 0xbf) || 774 (byte3 < 0x80 || byte3 > 0xbf) || 775 (byte4 < 0x80 || byte4 > 0xbf)) { 776 invalid_character = 1; 777 break; 778 } 779 } 780 if (byte1 == 0xf1 || byte1 == 0xf2 || byte1 == 0xf3) { 781 if ((byte2 < 0x80 || byte2 > 0xbf) || 782 (byte3 < 0x80 || byte3 > 0xbf) || 783 (byte4 < 0x80 || byte4 > 0xbf)) { 784 invalid_character = 1; 785 break; 786 } 787 } 788 if (byte1 == 0xf4) { 789 if ((byte2 < 0x80 || byte2 > 0x8f) || 790 (byte3 < 0x80 || byte3 > 0xbf) || 791 (byte4 < 0x80 || byte4 > 0xbf)) { 792 invalid_character = 1; 793 break; 794 } 795 } 796 } 797 798 /* OK */ 799 UInt uvw = byte1 & 0x7; 800 UInt xy = (byte2 >> 4) & 0x3; 801 UInt uvwxy = (uvw << 2) | xy; 802 UInt efgh = byte2 & 0xf; 803 UInt ij = (byte3 >> 4) & 0x3; 804 UInt klmn = byte3 & 0xf; 805 UInt opqrst = byte4 & 0x3f; 806 807 if (is_cu12) { 808 UInt abcd = (uvwxy - 1) & 0xf; 809 UInt high_surrogate = (0xd8 << 8) | (abcd << 6) | (efgh << 2) | ij; 810 UInt low_surrogate = (0xdc << 8) | (klmn << 6) | opqrst; 811 812 num_bytes = 4; 813 retval = (high_surrogate << 16) | low_surrogate; 814 } else { 815 num_bytes = 4; 816 retval = 817 (uvwxy << 16) | (efgh << 12) | (ij << 10) | (klmn << 6) | opqrst; 818 } 819 break; 820 } 821 } 822 823 if (! is_cu12) num_bytes = 4; // for CU14, by definition 824 825 /* At this point RETVAL contains the converted bytes. 826 Build up the final return value. */ 827 return (retval << 16) | (num_bytes << 8) | invalid_character; 828 } 829 830 ULong 831 s390_do_cu12_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4, 832 ULong stuff) 833 { 834 return s390_do_cu12_cu14_helper2(byte1, byte2, byte3, byte4, stuff, 835 /* is_cu12 = */ 1); 836 } 837 838 ULong 839 s390_do_cu14_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4, 840 ULong stuff) 841 { 842 return s390_do_cu12_cu14_helper2(byte1, byte2, byte3, byte4, stuff, 843 /* is_cu12 = */ 0); 844 } 845 846 847 /*------------------------------------------------------------*/ 848 /*--- Clean helper for "convert to binary". ---*/ 849 /*------------------------------------------------------------*/ 850 #if defined(VGA_s390x) 851 UInt 852 s390_do_cvb(ULong decimal) 853 { 854 UInt binary; 855 856 __asm__ volatile ( 857 "cvb %[result],%[input]\n\t" 858 : [result] "=d"(binary) 859 : [input] "m"(decimal) 860 ); 861 862 return binary; 863 } 864 865 #else 866 UInt s390_do_cvb(ULong decimal) { return 0; } 867 #endif 868 869 870 /*------------------------------------------------------------*/ 871 /*--- Clean helper for "convert to decimal". ---*/ 872 /*------------------------------------------------------------*/ 873 #if defined(VGA_s390x) 874 ULong 875 s390_do_cvd(ULong binary_in) 876 { 877 UInt binary = binary_in & 0xffffffffULL; 878 ULong decimal; 879 880 __asm__ volatile ( 881 "cvd %[input],%[result]\n\t" 882 : [result] "=m"(decimal) 883 : [input] "d"(binary) 884 ); 885 886 return decimal; 887 } 888 889 #else 890 ULong s390_do_cvd(ULong binary) { return 0; } 891 #endif 892 893 /*------------------------------------------------------------*/ 894 /*--- Clean helper for "Extract cache attribute". ---*/ 895 /*------------------------------------------------------------*/ 896 #if defined(VGA_s390x) 897 ULong 898 s390_do_ecag(ULong op2addr) 899 { 900 ULong result; 901 902 __asm__ volatile(".insn rsy,0xEB000000004C,%[out],0,0(%[in])\n\t" 903 : [out] "=d"(result) 904 : [in] "d"(op2addr)); 905 return result; 906 } 907 908 #else 909 ULong s390_do_ecag(ULong op2addr) { return 0; } 910 #endif 911 912 /*------------------------------------------------------------*/ 913 /*--- Clean helper for "Perform Floating Point Operation". ---*/ 914 /*------------------------------------------------------------*/ 915 #if defined(VGA_s390x) 916 UInt 917 s390_do_pfpo(UInt gpr0) 918 { 919 UChar rm; 920 UChar op1_ty, op2_ty; 921 922 rm = gpr0 & 0xf; 923 if (rm > 1 && rm < 8) 924 return EmFail_S390X_invalid_PFPO_rounding_mode; 925 926 op1_ty = (gpr0 >> 16) & 0xff; // gpr0[40:47] 927 op2_ty = (gpr0 >> 8) & 0xff; // gpr0[48:55] 928 /* Operand type must be BFP 32, 64, 128 or DFP 32, 64, 128 929 which correspond to 0x5, 0x6, 0x7, 0x8, 0x9, 0xa respectively. 930 Any other operand type value is unsupported */ 931 if ((op1_ty == op2_ty) || 932 (op1_ty < 0x5 || op1_ty > 0xa) || 933 (op2_ty < 0x5 || op2_ty > 0xa)) 934 return EmFail_S390X_invalid_PFPO_function; 935 936 return EmNote_NONE; 937 } 938 #else 939 UInt s390_do_pfpo(UInt gpr0) { return 0; } 940 #endif 941 942 /*------------------------------------------------------------*/ 943 /*--- Helper for condition code. ---*/ 944 /*------------------------------------------------------------*/ 945 946 /* Convert an IRRoundingMode value to s390_bfp_round_t */ 947 #if defined(VGA_s390x) 948 static s390_bfp_round_t 949 decode_bfp_rounding_mode(UInt irrm) 950 { 951 switch (irrm) { 952 case Irrm_NEAREST: return S390_BFP_ROUND_NEAREST_EVEN; 953 case Irrm_NegINF: return S390_BFP_ROUND_NEGINF; 954 case Irrm_PosINF: return S390_BFP_ROUND_POSINF; 955 case Irrm_ZERO: return S390_BFP_ROUND_ZERO; 956 } 957 vpanic("decode_bfp_rounding_mode"); 958 } 959 #endif 960 961 962 #define S390_CC_FOR_BINARY(opcode,cc_dep1,cc_dep2) \ 963 ({ \ 964 __asm__ volatile ( \ 965 opcode " %[op1],%[op2]\n\t" \ 966 "ipm %[psw]\n\t" : [psw] "=d"(psw), [op1] "+d"(cc_dep1) \ 967 : [op2] "d"(cc_dep2) \ 968 : "cc");\ 969 psw >> 28; /* cc */ \ 970 }) 971 972 #define S390_CC_FOR_TERNARY_SUBB(opcode,cc_dep1,cc_dep2,cc_ndep) \ 973 ({ \ 974 /* Recover the original DEP2 value. See comment near s390_cc_thunk_put3 \ 975 for rationale. */ \ 976 cc_dep2 = cc_dep2 ^ cc_ndep; \ 977 __asm__ volatile ( \ 978 "lghi 0,1\n\t" \ 979 "sr 0,%[op3]\n\t" /* borrow to cc */ \ 980 opcode " %[op1],%[op2]\n\t" /* then redo the op */\ 981 "ipm %[psw]\n\t" : [psw] "=d"(psw), [op1] "+&d"(cc_dep1) \ 982 : [op2] "d"(cc_dep2), [op3] "d"(cc_ndep) \ 983 : "0", "cc");\ 984 psw >> 28; /* cc */ \ 985 }) 986 987 #define S390_CC_FOR_TERNARY_ADDC(opcode,cc_dep1,cc_dep2,cc_ndep) \ 988 ({ \ 989 /* Recover the original DEP2 value. See comment near s390_cc_thunk_put3 \ 990 for rationale. */ \ 991 cc_dep2 = cc_dep2 ^ cc_ndep; \ 992 __asm__ volatile ( \ 993 "lgfr 0,%[op3]\n\t" /* first load cc_ndep */ \ 994 "aghi 0,0\n\t" /* and convert it into a cc */ \ 995 opcode " %[op1],%[op2]\n\t" /* then redo the op */\ 996 "ipm %[psw]\n\t" : [psw] "=d"(psw), [op1] "+&d"(cc_dep1) \ 997 : [op2] "d"(cc_dep2), [op3] "d"(cc_ndep) \ 998 : "0", "cc");\ 999 psw >> 28; /* cc */ \ 1000 }) 1001 1002 1003 #define S390_CC_FOR_BFP_RESULT(opcode,cc_dep1) \ 1004 ({ \ 1005 __asm__ volatile ( \ 1006 opcode " 0,%[op]\n\t" \ 1007 "ipm %[psw]\n\t" : [psw] "=d"(psw) \ 1008 : [op] "f"(cc_dep1) \ 1009 : "cc", "f0");\ 1010 psw >> 28; /* cc */ \ 1011 }) 1012 1013 #define S390_CC_FOR_BFP128_RESULT(hi,lo) \ 1014 ({ \ 1015 __asm__ volatile ( \ 1016 "ldr 4,%[high]\n\t" \ 1017 "ldr 6,%[low]\n\t" \ 1018 "ltxbr 0,4\n\t" \ 1019 "ipm %[psw]\n\t" : [psw] "=d"(psw) \ 1020 : [high] "f"(hi), [low] "f"(lo) \ 1021 : "cc", "f0", "f2", "f4", "f6");\ 1022 psw >> 28; /* cc */ \ 1023 }) 1024 1025 #define S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,rounding_mode) \ 1026 ({ \ 1027 __asm__ volatile ( \ 1028 opcode " 0," #rounding_mode ",%[op]\n\t" \ 1029 "ipm %[psw]\n\t" : [psw] "=d"(psw) \ 1030 : [op] "f"(cc_dep1) \ 1031 : "cc", "r0");\ 1032 psw >> 28; /* cc */ \ 1033 }) 1034 1035 #define S390_CC_FOR_BFP_CONVERT(opcode,cc_dep1,cc_dep2) \ 1036 ({ \ 1037 UInt cc; \ 1038 switch (decode_bfp_rounding_mode(cc_dep2)) { \ 1039 case S390_BFP_ROUND_NEAREST_EVEN: \ 1040 cc = S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,4); \ 1041 break; \ 1042 case S390_BFP_ROUND_ZERO: \ 1043 cc = S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,5); \ 1044 break; \ 1045 case S390_BFP_ROUND_POSINF: \ 1046 cc = S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,6); \ 1047 break; \ 1048 case S390_BFP_ROUND_NEGINF: \ 1049 cc = S390_CC_FOR_BFP_CONVERT_AUX(opcode,cc_dep1,7); \ 1050 break; \ 1051 default: \ 1052 vpanic("unexpected bfp rounding mode"); \ 1053 } \ 1054 cc; \ 1055 }) 1056 1057 #define S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,rounding_mode) \ 1058 ({ \ 1059 __asm__ volatile ( \ 1060 opcode ",0,%[op]," #rounding_mode ",0\n\t" \ 1061 "ipm %[psw]\n\t" : [psw] "=d"(psw) \ 1062 : [op] "f"(cc_dep1) \ 1063 : "cc", "r0");\ 1064 psw >> 28; /* cc */ \ 1065 }) 1066 1067 #define S390_CC_FOR_BFP_UCONVERT(opcode,cc_dep1,cc_dep2) \ 1068 ({ \ 1069 UInt cc; \ 1070 switch (decode_bfp_rounding_mode(cc_dep2)) { \ 1071 case S390_BFP_ROUND_NEAREST_EVEN: \ 1072 cc = S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,4); \ 1073 break; \ 1074 case S390_BFP_ROUND_ZERO: \ 1075 cc = S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,5); \ 1076 break; \ 1077 case S390_BFP_ROUND_POSINF: \ 1078 cc = S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,6); \ 1079 break; \ 1080 case S390_BFP_ROUND_NEGINF: \ 1081 cc = S390_CC_FOR_BFP_UCONVERT_AUX(opcode,cc_dep1,7); \ 1082 break; \ 1083 default: \ 1084 vpanic("unexpected bfp rounding mode"); \ 1085 } \ 1086 cc; \ 1087 }) 1088 1089 #define S390_CC_FOR_BFP128_CONVERT_AUX(opcode,hi,lo,rounding_mode) \ 1090 ({ \ 1091 __asm__ volatile ( \ 1092 "ldr 4,%[high]\n\t" \ 1093 "ldr 6,%[low]\n\t" \ 1094 opcode " 0," #rounding_mode ",4\n\t" \ 1095 "ipm %[psw]\n\t" : [psw] "=d"(psw) \ 1096 : [high] "f"(hi), [low] "f"(lo) \ 1097 : "cc", "r0", "f4", "f6");\ 1098 psw >> 28; /* cc */ \ 1099 }) 1100 1101 #define S390_CC_FOR_BFP128_CONVERT(opcode,cc_dep1,cc_dep2,cc_ndep) \ 1102 ({ \ 1103 UInt cc; \ 1104 /* Recover the original DEP2 value. See comment near \ 1105 s390_cc_thunk_put3 for rationale. */ \ 1106 cc_dep2 = cc_dep2 ^ cc_ndep; \ 1107 switch (decode_bfp_rounding_mode(cc_ndep)) { \ 1108 case S390_BFP_ROUND_NEAREST_EVEN: \ 1109 cc = S390_CC_FOR_BFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,4); \ 1110 break; \ 1111 case S390_BFP_ROUND_ZERO: \ 1112 cc = S390_CC_FOR_BFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,5); \ 1113 break; \ 1114 case S390_BFP_ROUND_POSINF: \ 1115 cc = S390_CC_FOR_BFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,6); \ 1116 break; \ 1117 case S390_BFP_ROUND_NEGINF: \ 1118 cc = S390_CC_FOR_BFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,7); \ 1119 break; \ 1120 default: \ 1121 vpanic("unexpected bfp rounding mode"); \ 1122 } \ 1123 cc; \ 1124 }) 1125 1126 #define S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,hi,lo,rounding_mode) \ 1127 ({ \ 1128 __asm__ volatile ( \ 1129 "ldr 4,%[high]\n\t" \ 1130 "ldr 6,%[low]\n\t" \ 1131 opcode ",0,4," #rounding_mode ",0\n\t" \ 1132 "ipm %[psw]\n\t" : [psw] "=d"(psw) \ 1133 : [high] "f"(hi), [low] "f"(lo) \ 1134 : "cc", "r0", "f4", "f6");\ 1135 psw >> 28; /* cc */ \ 1136 }) 1137 1138 #define S390_CC_FOR_BFP128_UCONVERT(opcode,cc_dep1,cc_dep2,cc_ndep) \ 1139 ({ \ 1140 UInt cc; \ 1141 /* Recover the original DEP2 value. See comment near \ 1142 s390_cc_thunk_put3 for rationale. */ \ 1143 cc_dep2 = cc_dep2 ^ cc_ndep; \ 1144 switch (decode_bfp_rounding_mode(cc_ndep)) { \ 1145 case S390_BFP_ROUND_NEAREST_EVEN: \ 1146 cc = S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,4); \ 1147 break; \ 1148 case S390_BFP_ROUND_ZERO: \ 1149 cc = S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,5); \ 1150 break; \ 1151 case S390_BFP_ROUND_POSINF: \ 1152 cc = S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,6); \ 1153 break; \ 1154 case S390_BFP_ROUND_NEGINF: \ 1155 cc = S390_CC_FOR_BFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,7); \ 1156 break; \ 1157 default: \ 1158 vpanic("unexpected bfp rounding mode"); \ 1159 } \ 1160 cc; \ 1161 }) 1162 1163 #define S390_CC_FOR_BFP_TDC(opcode,cc_dep1,cc_dep2) \ 1164 ({ \ 1165 __asm__ volatile ( \ 1166 opcode " %[value],0(%[class])\n\t" \ 1167 "ipm %[psw]\n\t" : [psw] "=d"(psw) \ 1168 : [value] "f"(cc_dep1), \ 1169 [class] "a"(cc_dep2) \ 1170 : "cc");\ 1171 psw >> 28; /* cc */ \ 1172 }) 1173 1174 #define S390_CC_FOR_BFP128_TDC(cc_dep1,cc_dep2,cc_ndep) \ 1175 ({ \ 1176 /* Recover the original DEP2 value. See comment near \ 1177 s390_cc_thunk_put1f128Z for rationale. */ \ 1178 cc_dep2 = cc_dep2 ^ cc_ndep; \ 1179 __asm__ volatile ( \ 1180 "ldr 4,%[high]\n\t" \ 1181 "ldr 6,%[low]\n\t" \ 1182 "tcxb 4,0(%[class])\n\t" \ 1183 "ipm %[psw]\n\t" : [psw] "=d"(psw) \ 1184 : [high] "f"(cc_dep1), [low] "f"(cc_dep2), \ 1185 [class] "a"(cc_ndep) \ 1186 : "cc", "f4", "f6");\ 1187 psw >> 28; /* cc */ \ 1188 }) 1189 1190 /* Convert an IRRoundingMode value to s390_dfp_round_t */ 1191 #if defined(VGA_s390x) 1192 static s390_dfp_round_t 1193 decode_dfp_rounding_mode(UInt irrm) 1194 { 1195 switch (irrm) { 1196 case Irrm_NEAREST: 1197 return S390_DFP_ROUND_NEAREST_EVEN_4; 1198 case Irrm_NegINF: 1199 return S390_DFP_ROUND_NEGINF_7; 1200 case Irrm_PosINF: 1201 return S390_DFP_ROUND_POSINF_6; 1202 case Irrm_ZERO: 1203 return S390_DFP_ROUND_ZERO_5; 1204 case Irrm_NEAREST_TIE_AWAY_0: 1205 return S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1; 1206 case Irrm_PREPARE_SHORTER: 1207 return S390_DFP_ROUND_PREPARE_SHORT_3; 1208 case Irrm_AWAY_FROM_ZERO: 1209 return S390_DFP_ROUND_AWAY_0; 1210 case Irrm_NEAREST_TIE_TOWARD_0: 1211 return S390_DFP_ROUND_NEAREST_TIE_TOWARD_0; 1212 } 1213 vpanic("decode_dfp_rounding_mode"); 1214 } 1215 #endif 1216 1217 #define S390_CC_FOR_DFP_RESULT(cc_dep1) \ 1218 ({ \ 1219 __asm__ volatile ( \ 1220 ".insn rre, 0xb3d60000,0,%[op]\n\t" /* LTDTR */ \ 1221 "ipm %[psw]\n\t" : [psw] "=d"(psw) \ 1222 : [op] "f"(cc_dep1) \ 1223 : "cc", "f0"); \ 1224 psw >> 28; /* cc */ \ 1225 }) 1226 1227 #define S390_CC_FOR_DFP128_RESULT(hi,lo) \ 1228 ({ \ 1229 __asm__ volatile ( \ 1230 "ldr 4,%[high]\n\t" \ 1231 "ldr 6,%[low]\n\t" \ 1232 ".insn rre, 0xb3de0000,0,4\n\t" /* LTXTR */ \ 1233 "ipm %[psw]\n\t" : [psw] "=d"(psw) \ 1234 : [high] "f"(hi), [low] "f"(lo) \ 1235 : "cc", "f0", "f2", "f4", "f6"); \ 1236 psw >> 28; /* cc */ \ 1237 }) 1238 1239 #define S390_CC_FOR_DFP_TD(opcode,cc_dep1,cc_dep2) \ 1240 ({ \ 1241 __asm__ volatile ( \ 1242 opcode ",%[value],0(%[class])\n\t" \ 1243 "ipm %[psw]\n\t" : [psw] "=d"(psw) \ 1244 : [value] "f"(cc_dep1), \ 1245 [class] "a"(cc_dep2) \ 1246 : "cc"); \ 1247 psw >> 28; /* cc */ \ 1248 }) 1249 1250 #define S390_CC_FOR_DFP128_TD(opcode,cc_dep1,cc_dep2,cc_ndep) \ 1251 ({ \ 1252 /* Recover the original DEP2 value. See comment near \ 1253 s390_cc_thunk_put1d128Z for rationale. */ \ 1254 cc_dep2 = cc_dep2 ^ cc_ndep; \ 1255 __asm__ volatile ( \ 1256 "ldr 4,%[high]\n\t" \ 1257 "ldr 6,%[low]\n\t" \ 1258 opcode ",4,0(%[class])\n\t" \ 1259 "ipm %[psw]\n\t" : [psw] "=d"(psw) \ 1260 : [high] "f"(cc_dep1), [low] "f"(cc_dep2), \ 1261 [class] "a"(cc_ndep) \ 1262 : "cc", "f4", "f6"); \ 1263 psw >> 28; /* cc */ \ 1264 }) 1265 1266 #define S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,rounding_mode) \ 1267 ({ \ 1268 __asm__ volatile ( \ 1269 opcode ",0,%[op]," #rounding_mode ",0\n\t" \ 1270 "ipm %[psw]\n\t" : [psw] "=d"(psw) \ 1271 : [op] "f"(cc_dep1) \ 1272 : "cc", "r0"); \ 1273 psw >> 28; /* cc */ \ 1274 }) 1275 1276 #define S390_CC_FOR_DFP_CONVERT(opcode,cc_dep1,cc_dep2) \ 1277 ({ \ 1278 UInt cc; \ 1279 switch (decode_dfp_rounding_mode(cc_dep2)) { \ 1280 case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1: \ 1281 case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_12: \ 1282 cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,1); \ 1283 break; \ 1284 case S390_DFP_ROUND_PREPARE_SHORT_3: \ 1285 case S390_DFP_ROUND_PREPARE_SHORT_15: \ 1286 cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,3); \ 1287 break; \ 1288 case S390_DFP_ROUND_NEAREST_EVEN_4: \ 1289 case S390_DFP_ROUND_NEAREST_EVEN_8: \ 1290 cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,4); \ 1291 break; \ 1292 case S390_DFP_ROUND_ZERO_5: \ 1293 case S390_DFP_ROUND_ZERO_9: \ 1294 cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,5); \ 1295 break; \ 1296 case S390_DFP_ROUND_POSINF_6: \ 1297 case S390_DFP_ROUND_POSINF_10: \ 1298 cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,6); \ 1299 break; \ 1300 case S390_DFP_ROUND_NEGINF_7: \ 1301 case S390_DFP_ROUND_NEGINF_11: \ 1302 cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,7); \ 1303 break; \ 1304 case S390_DFP_ROUND_NEAREST_TIE_TOWARD_0: \ 1305 cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,13); \ 1306 break; \ 1307 case S390_DFP_ROUND_AWAY_0: \ 1308 cc = S390_CC_FOR_DFP_CONVERT_AUX(opcode,cc_dep1,14); \ 1309 break; \ 1310 default: \ 1311 vpanic("unexpected dfp rounding mode"); \ 1312 } \ 1313 cc; \ 1314 }) 1315 1316 #define S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,rounding_mode) \ 1317 ({ \ 1318 __asm__ volatile ( \ 1319 opcode ",0,%[op]," #rounding_mode ",0\n\t" \ 1320 "ipm %[psw]\n\t" : [psw] "=d"(psw) \ 1321 : [op] "f"(cc_dep1) \ 1322 : "cc", "r0"); \ 1323 psw >> 28; /* cc */ \ 1324 }) 1325 1326 #define S390_CC_FOR_DFP_UCONVERT(opcode,cc_dep1,cc_dep2) \ 1327 ({ \ 1328 UInt cc; \ 1329 switch (decode_dfp_rounding_mode(cc_dep2)) { \ 1330 case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1: \ 1331 case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_12: \ 1332 cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,1); \ 1333 break; \ 1334 case S390_DFP_ROUND_PREPARE_SHORT_3: \ 1335 case S390_DFP_ROUND_PREPARE_SHORT_15: \ 1336 cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,3); \ 1337 break; \ 1338 case S390_DFP_ROUND_NEAREST_EVEN_4: \ 1339 case S390_DFP_ROUND_NEAREST_EVEN_8: \ 1340 cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,4); \ 1341 break; \ 1342 case S390_DFP_ROUND_ZERO_5: \ 1343 case S390_DFP_ROUND_ZERO_9: \ 1344 cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,5); \ 1345 break; \ 1346 case S390_DFP_ROUND_POSINF_6: \ 1347 case S390_DFP_ROUND_POSINF_10: \ 1348 cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,6); \ 1349 break; \ 1350 case S390_DFP_ROUND_NEGINF_7: \ 1351 case S390_DFP_ROUND_NEGINF_11: \ 1352 cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,7); \ 1353 break; \ 1354 case S390_DFP_ROUND_NEAREST_TIE_TOWARD_0: \ 1355 cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,13); \ 1356 break; \ 1357 case S390_DFP_ROUND_AWAY_0: \ 1358 cc = S390_CC_FOR_DFP_UCONVERT_AUX(opcode,cc_dep1,14); \ 1359 break; \ 1360 default: \ 1361 vpanic("unexpected dfp rounding mode"); \ 1362 } \ 1363 cc; \ 1364 }) 1365 1366 #define S390_CC_FOR_DFP128_CONVERT_AUX(opcode,hi,lo,rounding_mode) \ 1367 ({ \ 1368 __asm__ volatile ( \ 1369 "ldr 4,%[high]\n\t" \ 1370 "ldr 6,%[low]\n\t" \ 1371 opcode ",0,4," #rounding_mode ",0\n\t" \ 1372 "ipm %[psw]\n\t" : [psw] "=d"(psw) \ 1373 : [high] "f"(hi), [low] "f"(lo) \ 1374 : "cc", "r0", "f4", "f6"); \ 1375 psw >> 28; /* cc */ \ 1376 }) 1377 1378 #define S390_CC_FOR_DFP128_CONVERT(opcode,cc_dep1,cc_dep2,cc_ndep) \ 1379 ({ \ 1380 UInt cc; \ 1381 /* Recover the original DEP2 value. See comment near \ 1382 s390_cc_thunk_put3 for rationale. */ \ 1383 cc_dep2 = cc_dep2 ^ cc_ndep; \ 1384 switch (decode_dfp_rounding_mode(cc_ndep)) { \ 1385 case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1: \ 1386 case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_12: \ 1387 cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,1); \ 1388 break; \ 1389 case S390_DFP_ROUND_PREPARE_SHORT_3: \ 1390 case S390_DFP_ROUND_PREPARE_SHORT_15: \ 1391 cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,3); \ 1392 break; \ 1393 case S390_DFP_ROUND_NEAREST_EVEN_4: \ 1394 case S390_DFP_ROUND_NEAREST_EVEN_8: \ 1395 cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,4); \ 1396 break; \ 1397 case S390_DFP_ROUND_ZERO_5: \ 1398 case S390_DFP_ROUND_ZERO_9: \ 1399 cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,5); \ 1400 break; \ 1401 case S390_DFP_ROUND_POSINF_6: \ 1402 case S390_DFP_ROUND_POSINF_10: \ 1403 cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,6); \ 1404 break; \ 1405 case S390_DFP_ROUND_NEGINF_7: \ 1406 case S390_DFP_ROUND_NEGINF_11: \ 1407 cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,7); \ 1408 break; \ 1409 case S390_DFP_ROUND_NEAREST_TIE_TOWARD_0: \ 1410 cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,13); \ 1411 break; \ 1412 case S390_DFP_ROUND_AWAY_0: \ 1413 cc = S390_CC_FOR_DFP128_CONVERT_AUX(opcode,cc_dep1,cc_dep2,14); \ 1414 break; \ 1415 default: \ 1416 vpanic("unexpected dfp rounding mode"); \ 1417 } \ 1418 cc; \ 1419 }) 1420 1421 #define S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,hi,lo,rounding_mode) \ 1422 ({ \ 1423 __asm__ volatile ( \ 1424 "ldr 4,%[high]\n\t" \ 1425 "ldr 6,%[low]\n\t" \ 1426 opcode ",0,4," #rounding_mode ",0\n\t" \ 1427 "ipm %[psw]\n\t" : [psw] "=d"(psw) \ 1428 : [high] "f"(hi), [low] "f"(lo) \ 1429 : "cc", "r0", "f4", "f6"); \ 1430 psw >> 28; /* cc */ \ 1431 }) 1432 1433 #define S390_CC_FOR_DFP128_UCONVERT(opcode,cc_dep1,cc_dep2,cc_ndep) \ 1434 ({ \ 1435 UInt cc; \ 1436 /* Recover the original DEP2 value. See comment near \ 1437 s390_cc_thunk_put3 for rationale. */ \ 1438 cc_dep2 = cc_dep2 ^ cc_ndep; \ 1439 switch (decode_dfp_rounding_mode(cc_ndep)) { \ 1440 case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_1: \ 1441 case S390_DFP_ROUND_NEAREST_TIE_AWAY_0_12: \ 1442 cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,1); \ 1443 break; \ 1444 case S390_DFP_ROUND_PREPARE_SHORT_3: \ 1445 case S390_DFP_ROUND_PREPARE_SHORT_15: \ 1446 cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,3); \ 1447 break; \ 1448 case S390_DFP_ROUND_NEAREST_EVEN_4: \ 1449 case S390_DFP_ROUND_NEAREST_EVEN_8: \ 1450 cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,4); \ 1451 break; \ 1452 case S390_DFP_ROUND_ZERO_5: \ 1453 case S390_DFP_ROUND_ZERO_9: \ 1454 cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,5); \ 1455 break; \ 1456 case S390_DFP_ROUND_POSINF_6: \ 1457 case S390_DFP_ROUND_POSINF_10: \ 1458 cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,6); \ 1459 break; \ 1460 case S390_DFP_ROUND_NEGINF_7: \ 1461 case S390_DFP_ROUND_NEGINF_11: \ 1462 cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,7); \ 1463 break; \ 1464 case S390_DFP_ROUND_NEAREST_TIE_TOWARD_0: \ 1465 cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,13); \ 1466 break; \ 1467 case S390_DFP_ROUND_AWAY_0: \ 1468 cc = S390_CC_FOR_DFP128_UCONVERT_AUX(opcode,cc_dep1,cc_dep2,14); \ 1469 break; \ 1470 default: \ 1471 vpanic("unexpected dfp rounding mode"); \ 1472 } \ 1473 cc; \ 1474 }) 1475 1476 1477 /* Return the value of the condition code from the supplied thunk parameters. 1478 This is not the value of the PSW. It is the value of the 2 CC bits within 1479 the PSW. The returned value is thusly in the interval [0:3]. */ 1480 UInt 1481 s390_calculate_cc(ULong cc_op, ULong cc_dep1, ULong cc_dep2, ULong cc_ndep) 1482 { 1483 #if defined(VGA_s390x) 1484 UInt psw; 1485 1486 switch (cc_op) { 1487 1488 case S390_CC_OP_BITWISE: 1489 return S390_CC_FOR_BINARY("ogr", cc_dep1, (ULong)0); 1490 1491 case S390_CC_OP_SIGNED_COMPARE: 1492 return S390_CC_FOR_BINARY("cgr", cc_dep1, cc_dep2); 1493 1494 case S390_CC_OP_UNSIGNED_COMPARE: 1495 return S390_CC_FOR_BINARY("clgr", cc_dep1, cc_dep2); 1496 1497 case S390_CC_OP_SIGNED_ADD_64: 1498 return S390_CC_FOR_BINARY("agr", cc_dep1, cc_dep2); 1499 1500 case S390_CC_OP_SIGNED_ADD_32: 1501 return S390_CC_FOR_BINARY("ar", cc_dep1, cc_dep2); 1502 1503 case S390_CC_OP_SIGNED_SUB_64: 1504 return S390_CC_FOR_BINARY("sgr", cc_dep1, cc_dep2); 1505 1506 case S390_CC_OP_SIGNED_SUB_32: 1507 return S390_CC_FOR_BINARY("sr", cc_dep1, cc_dep2); 1508 1509 case S390_CC_OP_UNSIGNED_ADD_64: 1510 return S390_CC_FOR_BINARY("algr", cc_dep1, cc_dep2); 1511 1512 case S390_CC_OP_UNSIGNED_ADD_32: 1513 return S390_CC_FOR_BINARY("alr", cc_dep1, cc_dep2); 1514 1515 case S390_CC_OP_UNSIGNED_ADDC_64: 1516 return S390_CC_FOR_TERNARY_ADDC("alcgr", cc_dep1, cc_dep2, cc_ndep); 1517 1518 case S390_CC_OP_UNSIGNED_ADDC_32: 1519 return S390_CC_FOR_TERNARY_ADDC("alcr", cc_dep1, cc_dep2, cc_ndep); 1520 1521 case S390_CC_OP_UNSIGNED_SUB_64: 1522 return S390_CC_FOR_BINARY("slgr", cc_dep1, cc_dep2); 1523 1524 case S390_CC_OP_UNSIGNED_SUB_32: 1525 return S390_CC_FOR_BINARY("slr", cc_dep1, cc_dep2); 1526 1527 case S390_CC_OP_UNSIGNED_SUBB_64: 1528 return S390_CC_FOR_TERNARY_SUBB("slbgr", cc_dep1, cc_dep2, cc_ndep); 1529 1530 case S390_CC_OP_UNSIGNED_SUBB_32: 1531 return S390_CC_FOR_TERNARY_SUBB("slbr", cc_dep1, cc_dep2, cc_ndep); 1532 1533 case S390_CC_OP_LOAD_AND_TEST: 1534 /* Like signed comparison with 0 */ 1535 return S390_CC_FOR_BINARY("cgr", cc_dep1, (Long)0); 1536 1537 case S390_CC_OP_LOAD_POSITIVE_32: 1538 __asm__ volatile ( 1539 "lpr %[result],%[op]\n\t" 1540 "ipm %[psw]\n\t" : [psw] "=d"(psw), [result] "=d"(cc_dep1) 1541 : [op] "d"(cc_dep1) 1542 : "cc"); 1543 return psw >> 28; /* cc */ 1544 1545 case S390_CC_OP_LOAD_POSITIVE_64: 1546 __asm__ volatile ( 1547 "lpgr %[result],%[op]\n\t" 1548 "ipm %[psw]\n\t" : [psw] "=d"(psw), [result] "=d"(cc_dep1) 1549 : [op] "d"(cc_dep1) 1550 : "cc"); 1551 return psw >> 28; /* cc */ 1552 1553 case S390_CC_OP_TEST_UNDER_MASK_8: { 1554 UChar value = cc_dep1; 1555 UChar mask = cc_dep2; 1556 1557 __asm__ volatile ( 1558 "bras %%r2,1f\n\t" /* %r2 = address of next insn */ 1559 "tm %[value],0\n\t" /* this is skipped, then EXecuted */ 1560 "1: ex %[mask],0(%%r2)\n\t" /* EXecute TM after modifying mask */ 1561 "ipm %[psw]\n\t" : [psw] "=d"(psw) 1562 : [value] "m"(value), [mask] "a"(mask) 1563 : "r2", "cc"); 1564 return psw >> 28; /* cc */ 1565 } 1566 1567 case S390_CC_OP_TEST_UNDER_MASK_16: { 1568 /* Create a TMLL insn with the mask as given by cc_dep2 */ 1569 UInt insn = (0xA701u << 16) | cc_dep2; 1570 UInt value = cc_dep1; 1571 1572 __asm__ volatile ( 1573 "lr 1,%[value]\n\t" 1574 "lhi 2,0x10\n\t" 1575 "ex 2,%[insn]\n\t" 1576 "ipm %[psw]\n\t" : [psw] "=d"(psw) 1577 : [value] "d"(value), [insn] "m"(insn) 1578 : "r1", "r2", "cc"); 1579 return psw >> 28; /* cc */ 1580 } 1581 1582 case S390_CC_OP_SHIFT_LEFT_32: 1583 __asm__ volatile ( 1584 "sla %[op],0(%[amount])\n\t" 1585 "ipm %[psw]\n\t" : [psw] "=d"(psw), [op] "+d"(cc_dep1) 1586 : [amount] "a"(cc_dep2) 1587 : "cc"); 1588 return psw >> 28; /* cc */ 1589 1590 case S390_CC_OP_SHIFT_LEFT_64: { 1591 Int high = (Int)(cc_dep1 >> 32); 1592 Int low = (Int)(cc_dep1 & 0xFFFFFFFF); 1593 1594 __asm__ volatile ( 1595 "lr 2,%[high]\n\t" 1596 "lr 3,%[low]\n\t" 1597 "slda 2,0(%[amount])\n\t" 1598 "ipm %[psw]\n\t" : [psw] "=d"(psw), [high] "+d"(high), 1599 [low] "+d"(low) 1600 : [amount] "a"(cc_dep2) 1601 : "cc", "r2", "r3"); 1602 return psw >> 28; /* cc */ 1603 } 1604 1605 case S390_CC_OP_INSERT_CHAR_MASK_32: { 1606 Int inserted = 0; 1607 Int msb = 0; 1608 1609 if (cc_dep2 & 1) { 1610 inserted |= cc_dep1 & 0xff; 1611 msb = 0x80; 1612 } 1613 if (cc_dep2 & 2) { 1614 inserted |= cc_dep1 & 0xff00; 1615 msb = 0x8000; 1616 } 1617 if (cc_dep2 & 4) { 1618 inserted |= cc_dep1 & 0xff0000; 1619 msb = 0x800000; 1620 } 1621 if (cc_dep2 & 8) { 1622 inserted |= cc_dep1 & 0xff000000; 1623 msb = 0x80000000; 1624 } 1625 1626 if (inserted & msb) // MSB is 1 1627 return 1; 1628 if (inserted > 0) 1629 return 2; 1630 return 0; 1631 } 1632 1633 case S390_CC_OP_BFP_RESULT_32: 1634 return S390_CC_FOR_BFP_RESULT("ltebr", cc_dep1); 1635 1636 case S390_CC_OP_BFP_RESULT_64: 1637 return S390_CC_FOR_BFP_RESULT("ltdbr", cc_dep1); 1638 1639 case S390_CC_OP_BFP_RESULT_128: 1640 return S390_CC_FOR_BFP128_RESULT(cc_dep1, cc_dep2); 1641 1642 case S390_CC_OP_BFP_32_TO_INT_32: 1643 return S390_CC_FOR_BFP_CONVERT("cfebr", cc_dep1, cc_dep2); 1644 1645 case S390_CC_OP_BFP_64_TO_INT_32: 1646 return S390_CC_FOR_BFP_CONVERT("cfdbr", cc_dep1, cc_dep2); 1647 1648 case S390_CC_OP_BFP_128_TO_INT_32: 1649 return S390_CC_FOR_BFP128_CONVERT("cfxbr", cc_dep1, cc_dep2, cc_ndep); 1650 1651 case S390_CC_OP_BFP_32_TO_INT_64: 1652 return S390_CC_FOR_BFP_CONVERT("cgebr", cc_dep1, cc_dep2); 1653 1654 case S390_CC_OP_BFP_64_TO_INT_64: 1655 return S390_CC_FOR_BFP_CONVERT("cgdbr", cc_dep1, cc_dep2); 1656 1657 case S390_CC_OP_BFP_128_TO_INT_64: 1658 return S390_CC_FOR_BFP128_CONVERT("cgxbr", cc_dep1, cc_dep2, cc_ndep); 1659 1660 case S390_CC_OP_BFP_TDC_32: 1661 return S390_CC_FOR_BFP_TDC("tceb", cc_dep1, cc_dep2); 1662 1663 case S390_CC_OP_BFP_TDC_64: 1664 return S390_CC_FOR_BFP_TDC("tcdb", cc_dep1, cc_dep2); 1665 1666 case S390_CC_OP_BFP_TDC_128: 1667 return S390_CC_FOR_BFP128_TDC(cc_dep1, cc_dep2, cc_ndep); 1668 1669 case S390_CC_OP_SET: 1670 return cc_dep1; 1671 1672 case S390_CC_OP_BFP_32_TO_UINT_32: 1673 return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb39c0000", cc_dep1, cc_dep2); 1674 1675 case S390_CC_OP_BFP_64_TO_UINT_32: 1676 return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb39d0000", cc_dep1, cc_dep2); 1677 1678 case S390_CC_OP_BFP_128_TO_UINT_32: 1679 return S390_CC_FOR_BFP128_UCONVERT(".insn rrf,0xb39e0000", cc_dep1, 1680 cc_dep2, cc_ndep); 1681 1682 case S390_CC_OP_BFP_32_TO_UINT_64: 1683 return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb3ac0000", cc_dep1, cc_dep2); 1684 1685 case S390_CC_OP_BFP_64_TO_UINT_64: 1686 return S390_CC_FOR_BFP_UCONVERT(".insn rrf,0xb3ad0000", cc_dep1, cc_dep2); 1687 1688 case S390_CC_OP_BFP_128_TO_UINT_64: 1689 return S390_CC_FOR_BFP128_UCONVERT(".insn rrf,0xb3ae0000", cc_dep1, 1690 cc_dep2, cc_ndep); 1691 1692 case S390_CC_OP_DFP_RESULT_64: 1693 return S390_CC_FOR_DFP_RESULT(cc_dep1); 1694 1695 case S390_CC_OP_DFP_RESULT_128: 1696 return S390_CC_FOR_DFP128_RESULT(cc_dep1, cc_dep2); 1697 1698 case S390_CC_OP_DFP_TDC_32: /* TDCET */ 1699 return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000050", cc_dep1, cc_dep2); 1700 1701 case S390_CC_OP_DFP_TDC_64: /* TDCDT */ 1702 return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000054", cc_dep1, cc_dep2); 1703 1704 case S390_CC_OP_DFP_TDC_128: /* TDCXT */ 1705 return S390_CC_FOR_DFP128_TD(".insn rxe, 0xed0000000058", cc_dep1, 1706 cc_dep2, cc_ndep); 1707 1708 case S390_CC_OP_DFP_TDG_32: /* TDGET */ 1709 return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000051", cc_dep1, cc_dep2); 1710 1711 case S390_CC_OP_DFP_TDG_64: /* TDGDT */ 1712 return S390_CC_FOR_DFP_TD(".insn rxe, 0xed0000000055", cc_dep1, cc_dep2); 1713 1714 case S390_CC_OP_DFP_TDG_128: /* TDGXT */ 1715 return S390_CC_FOR_DFP128_TD(".insn rxe, 0xed0000000059", cc_dep1, 1716 cc_dep2, cc_ndep); 1717 1718 case S390_CC_OP_DFP_64_TO_INT_32: /* CFDTR */ 1719 return S390_CC_FOR_DFP_CONVERT(".insn rrf,0xb9410000", cc_dep1, cc_dep2); 1720 1721 case S390_CC_OP_DFP_128_TO_INT_32: /* CFXTR */ 1722 return S390_CC_FOR_DFP128_CONVERT(".insn rrf,0xb9490000", cc_dep1, 1723 cc_dep2, cc_ndep); 1724 1725 case S390_CC_OP_DFP_64_TO_INT_64: /* CGDTR */ 1726 return S390_CC_FOR_DFP_CONVERT(".insn rrf,0xb3e10000", cc_dep1, cc_dep2); 1727 1728 case S390_CC_OP_DFP_128_TO_INT_64: /* CGXTR */ 1729 return S390_CC_FOR_DFP128_CONVERT(".insn rrf,0xb3e90000", cc_dep1, 1730 cc_dep2, cc_ndep); 1731 1732 case S390_CC_OP_DFP_64_TO_UINT_32: /* CLFDTR */ 1733 return S390_CC_FOR_DFP_UCONVERT(".insn rrf,0xb9430000", cc_dep1, cc_dep2); 1734 1735 case S390_CC_OP_DFP_128_TO_UINT_32: /* CLFXTR */ 1736 return S390_CC_FOR_DFP128_UCONVERT(".insn rrf,0xb94b0000", cc_dep1, 1737 cc_dep2, cc_ndep); 1738 1739 case S390_CC_OP_DFP_64_TO_UINT_64: /* CLGDTR */ 1740 return S390_CC_FOR_DFP_UCONVERT(".insn rrf,0xb9420000", cc_dep1, cc_dep2); 1741 1742 case S390_CC_OP_DFP_128_TO_UINT_64: /* CLGXTR */ 1743 return S390_CC_FOR_DFP128_UCONVERT(".insn rrf,0xb94a0000", cc_dep1, 1744 cc_dep2, cc_ndep); 1745 1746 case S390_CC_OP_PFPO_32: { 1747 __asm__ volatile( 1748 "ler 4, %[cc_dep1]\n\t" /* 32 bit FR move */ 1749 "lr 0, %[cc_dep2]\n\t" /* 32 bit GR move */ 1750 ".short 0x010a\n\t" /* PFPO */ 1751 "ipm %[psw]\n\t" : [psw] "=d"(psw) 1752 : [cc_dep1] "f"(cc_dep1), 1753 [cc_dep2] "d"(cc_dep2) 1754 : "r0", "r1", "f4"); 1755 return psw >> 28; /* cc */ 1756 } 1757 1758 case S390_CC_OP_PFPO_64: { 1759 __asm__ volatile( 1760 "ldr 4, %[cc_dep1]\n\t" 1761 "lr 0, %[cc_dep2]\n\t" /* 32 bit register move */ 1762 ".short 0x010a\n\t" /* PFPO */ 1763 "ipm %[psw]\n\t" : [psw] "=d"(psw) 1764 : [cc_dep1] "f"(cc_dep1), 1765 [cc_dep2] "d"(cc_dep2) 1766 : "r0", "r1", "f4"); 1767 return psw >> 28; /* cc */ 1768 } 1769 1770 case S390_CC_OP_PFPO_128: { 1771 __asm__ volatile( 1772 "ldr 4,%[cc_dep1]\n\t" 1773 "ldr 6,%[cc_dep2]\n\t" 1774 "lr 0,%[cc_ndep]\n\t" /* 32 bit register move */ 1775 ".short 0x010a\n\t" /* PFPO */ 1776 "ipm %[psw]\n\t" : [psw] "=d"(psw) 1777 : [cc_dep1] "f"(cc_dep1), 1778 [cc_dep2] "f"(cc_dep2), 1779 [cc_ndep] "d"(cc_ndep) 1780 : "r0", "r1", "f0", "f2", "f4", "f6"); 1781 return psw >> 28; /* cc */ 1782 } 1783 1784 default: 1785 break; 1786 } 1787 #endif 1788 vpanic("s390_calculate_cc"); 1789 } 1790 1791 1792 /* Note that this does *not* return a Boolean value. The result needs to be 1793 explicitly tested against zero. */ 1794 UInt 1795 s390_calculate_cond(ULong mask, ULong op, ULong dep1, ULong dep2, ULong ndep) 1796 { 1797 UInt cc = s390_calculate_cc(op, dep1, dep2, ndep); 1798 1799 return ((mask << cc) & 0x8); 1800 } 1801 1802 /*------------------------------------------------------------*/ 1803 /*--- spechelper for performance ---*/ 1804 /*------------------------------------------------------------*/ 1805 1806 1807 /* Convenience macros */ 1808 #define unop(op,a1) IRExpr_Unop((op),(a1)) 1809 #define binop(op,a1,a2) IRExpr_Binop((op),(a1),(a2)) 1810 #define mkU64(v) IRExpr_Const(IRConst_U64(v)) 1811 #define mkU32(v) IRExpr_Const(IRConst_U32(v)) 1812 #define mkU8(v) IRExpr_Const(IRConst_U8(v)) 1813 1814 1815 static inline Bool 1816 isC64(const IRExpr *expr) 1817 { 1818 return expr->tag == Iex_Const && expr->Iex.Const.con->tag == Ico_U64; 1819 } 1820 1821 1822 /* The returned expression is NULL if no specialization was found. In that 1823 case the helper function will be called. Otherwise, the expression has 1824 type Ity_I32 and a Boolean value. */ 1825 IRExpr * 1826 guest_s390x_spechelper(const HChar *function_name, IRExpr **args, 1827 IRStmt **precedingStmts, Int n_precedingStmts) 1828 { 1829 UInt i, arity = 0; 1830 1831 for (i = 0; args[i]; i++) 1832 arity++; 1833 1834 # if 0 1835 vex_printf("spec request:\n"); 1836 vex_printf(" %s ", function_name); 1837 for (i = 0; i < arity; i++) { 1838 vex_printf(" "); 1839 ppIRExpr(args[i]); 1840 } 1841 vex_printf("\n"); 1842 # endif 1843 1844 /* --------- Specialising "s390_calculate_cond" --------- */ 1845 1846 if (vex_streq(function_name, "s390_calculate_cond")) { 1847 IRExpr *cond_expr, *cc_op_expr, *cc_dep1, *cc_dep2; 1848 ULong cond, cc_op; 1849 1850 vassert(arity == 5); 1851 1852 cond_expr = args[0]; 1853 cc_op_expr = args[1]; 1854 1855 /* The necessary requirement for all optimizations here is that the 1856 condition and the cc_op are constant. So check that upfront. */ 1857 if (! isC64(cond_expr)) return NULL; 1858 if (! isC64(cc_op_expr)) return NULL; 1859 1860 cond = cond_expr->Iex.Const.con->Ico.U64; 1861 cc_op = cc_op_expr->Iex.Const.con->Ico.U64; 1862 1863 vassert(cond <= 15); 1864 1865 /* 1866 +------+---+---+---+---+ 1867 | cc | 0 | 1 | 2 | 3 | 1868 | cond | 8 | 4 | 2 | 1 | 1869 +------+---+---+---+---+ 1870 */ 1871 cc_dep1 = args[2]; 1872 cc_dep2 = args[3]; 1873 1874 /* S390_CC_OP_SIGNED_COMPARE */ 1875 if (cc_op == S390_CC_OP_SIGNED_COMPARE) { 1876 /* 1877 cc == 0 --> cc_dep1 == cc_dep2 (cond == 8) 1878 cc == 1 --> cc_dep1 < cc_dep2 (cond == 4) 1879 cc == 2 --> cc_dep1 > cc_dep2 (cond == 2) 1880 1881 Because cc == 3 cannot occur the rightmost bit of cond is 1882 a don't care. 1883 */ 1884 if (cond == 8 || cond == 8 + 1) { 1885 return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2)); 1886 } 1887 if (cond == 4 + 2 || cond == 4 + 2 + 1) { 1888 return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2)); 1889 } 1890 if (cond == 4 || cond == 4 + 1) { 1891 return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep1, cc_dep2)); 1892 } 1893 if (cond == 8 + 4 || cond == 8 + 4 + 1) { 1894 return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep1, cc_dep2)); 1895 } 1896 /* cc_dep1 > cc_dep2 ----> cc_dep2 < cc_dep1 */ 1897 if (cond == 2 || cond == 2 + 1) { 1898 return unop(Iop_1Uto32, binop(Iop_CmpLT64S, cc_dep2, cc_dep1)); 1899 } 1900 if (cond == 8 + 2 || cond == 8 + 2 + 1) { 1901 return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep2, cc_dep1)); 1902 } 1903 if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) { 1904 return mkU32(1); 1905 } 1906 /* Remaining case */ 1907 return mkU32(0); 1908 } 1909 1910 /* S390_CC_OP_UNSIGNED_COMPARE */ 1911 if (cc_op == S390_CC_OP_UNSIGNED_COMPARE) { 1912 /* 1913 cc == 0 --> cc_dep1 == cc_dep2 (cond == 8) 1914 cc == 1 --> cc_dep1 < cc_dep2 (cond == 4) 1915 cc == 2 --> cc_dep1 > cc_dep2 (cond == 2) 1916 1917 Because cc == 3 cannot occur the rightmost bit of cond is 1918 a don't care. 1919 */ 1920 if (cond == 8 || cond == 8 + 1) { 1921 return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2)); 1922 } 1923 if (cond == 4 + 2 || cond == 4 + 2 + 1) { 1924 return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2)); 1925 } 1926 if (cond == 4 || cond == 4 + 1) { 1927 return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep1, cc_dep2)); 1928 } 1929 if (cond == 8 + 4 || cond == 8 + 4 + 1) { 1930 return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep1, cc_dep2)); 1931 } 1932 /* cc_dep1 > cc_dep2 ----> cc_dep2 < cc_dep1 */ 1933 if (cond == 2 || cond == 2 + 1) { 1934 return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep2, cc_dep1)); 1935 } 1936 if (cond == 8 + 2 || cond == 8 + 2 + 1) { 1937 return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep2, cc_dep1)); 1938 } 1939 if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) { 1940 return mkU32(1); 1941 } 1942 /* Remaining case */ 1943 return mkU32(0); 1944 } 1945 1946 /* S390_CC_OP_LOAD_AND_TEST */ 1947 if (cc_op == S390_CC_OP_LOAD_AND_TEST) { 1948 /* 1949 cc == 0 --> cc_dep1 == 0 (cond == 8) 1950 cc == 1 --> cc_dep1 < 0 (cond == 4) 1951 cc == 2 --> cc_dep1 > 0 (cond == 2) 1952 1953 Because cc == 3 cannot occur the rightmost bit of cond is 1954 a don't care. 1955 */ 1956 if (cond == 8 || cond == 8 + 1) { 1957 return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, mkU64(0))); 1958 } 1959 if (cond == 4 + 2 || cond == 4 + 2 + 1) { 1960 return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, mkU64(0))); 1961 } 1962 if (cond == 4 || cond == 4 + 1) { 1963 /* Special case cc_dep < 0. Only check the MSB to avoid bogus 1964 memcheck complaints due to gcc magic. Fixes 343802 1965 */ 1966 return unop(Iop_64to32, binop(Iop_Shr64, cc_dep1, mkU8(63))); 1967 } 1968 if (cond == 8 + 4 || cond == 8 + 4 + 1) { 1969 return unop(Iop_1Uto32, binop(Iop_CmpLE64S, cc_dep1, mkU64(0))); 1970 } 1971 /* cc_dep1 > 0 ----> 0 < cc_dep1 */ 1972 if (cond == 2 || cond == 2 + 1) { 1973 return unop(Iop_1Uto32, binop(Iop_CmpLT64S, mkU64(0), cc_dep1)); 1974 } 1975 if (cond == 8 + 2 || cond == 8 + 2 + 1) { 1976 /* Special case cc_dep >= 0. Only check the MSB to avoid bogus 1977 memcheck complaints due to gcc magic. Fixes 308427 1978 */ 1979 return unop(Iop_64to32, binop(Iop_Xor64, 1980 binop(Iop_Shr64, cc_dep1, mkU8(63)), 1981 mkU64(1))); 1982 } 1983 if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) { 1984 return mkU32(1); 1985 } 1986 /* Remaining case */ 1987 return mkU32(0); 1988 } 1989 1990 /* S390_CC_OP_BITWISE */ 1991 if (cc_op == S390_CC_OP_BITWISE) { 1992 /* 1993 cc_dep1 is the result of the boolean operation. 1994 1995 cc == 0 --> cc_dep1 == 0 (cond == 8) 1996 cc == 1 --> cc_dep1 != 0 (cond == 4) 1997 1998 Because cc == 2 and cc == 3 cannot occur the two rightmost bits of 1999 cond are don't cares. Therefore: 2000 2001 cond == 00xx -> always false 2002 cond == 01xx -> not equal 2003 cond == 10xx -> equal 2004 cond == 11xx -> always true 2005 */ 2006 if ((cond & (8 + 4)) == 8 + 4) { 2007 return mkU32(1); 2008 } 2009 if (cond & 8) { 2010 return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, mkU64(0))); 2011 } 2012 if (cond & 4) { 2013 return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, mkU64(0))); 2014 } 2015 /* Remaining case */ 2016 return mkU32(0); 2017 } 2018 2019 /* S390_CC_OP_INSERT_CHAR_MASK_32 2020 Since the mask comes from an immediate field in the opcode, we 2021 expect the mask to be a constant here. That simplifies matters. */ 2022 if (cc_op == S390_CC_OP_INSERT_CHAR_MASK_32) { 2023 ULong mask; 2024 UInt imask = 0, shift = 0; 2025 IRExpr *word; 2026 2027 if (! isC64(cc_dep2)) goto missed; 2028 2029 mask = cc_dep2->Iex.Const.con->Ico.U64; 2030 2031 /* Extract the 32-bit value from the thunk */ 2032 2033 word = unop(Iop_64to32, cc_dep1); 2034 2035 switch (mask) { 2036 case 0: shift = 0; imask = 0x00000000; break; 2037 case 1: shift = 24; imask = 0x000000FF; break; 2038 case 2: shift = 16; imask = 0x0000FF00; break; 2039 case 3: shift = 16; imask = 0x0000FFFF; break; 2040 case 4: shift = 8; imask = 0x00FF0000; break; 2041 case 5: shift = 8; imask = 0x00FF00FF; break; 2042 case 6: shift = 8; imask = 0x00FFFF00; break; 2043 case 7: shift = 8; imask = 0x00FFFFFF; break; 2044 case 8: shift = 0; imask = 0xFF000000; break; 2045 case 9: shift = 0; imask = 0xFF0000FF; break; 2046 case 10: shift = 0; imask = 0xFF00FF00; break; 2047 case 11: shift = 0; imask = 0xFF00FFFF; break; 2048 case 12: shift = 0; imask = 0xFFFF0000; break; 2049 case 13: shift = 0; imask = 0xFFFF00FF; break; 2050 case 14: shift = 0; imask = 0xFFFFFF00; break; 2051 case 15: shift = 0; imask = 0xFFFFFFFF; break; 2052 } 2053 2054 /* Select the bits that were inserted */ 2055 word = binop(Iop_And32, word, mkU32(imask)); 2056 2057 /* cc == 0 --> all inserted bits zero or mask == 0 (cond == 8) 2058 cc == 1 --> leftmost inserted bit is one (cond == 4) 2059 cc == 2 --> leftmost inserted bit is zero and not (cond == 2) 2060 all inserted bits are zero 2061 2062 Because cc == 0,1,2 the rightmost bit of the mask is a don't care */ 2063 if (cond == 8 || cond == 8 + 1) { 2064 return unop(Iop_1Uto32, binop(Iop_CmpEQ32, word, mkU32(0))); 2065 } 2066 if (cond == 4 + 2 || cond == 4 + 2 + 1) { 2067 return unop(Iop_1Uto32, binop(Iop_CmpNE32, word, mkU32(0))); 2068 } 2069 2070 /* Sign extend */ 2071 if (shift != 0) { 2072 word = binop(Iop_Sar32, binop(Iop_Shl32, word, mkU8(shift)), 2073 mkU8(shift)); 2074 } 2075 2076 if (cond == 4 || cond == 4 + 1) { /* word < 0 */ 2077 return unop(Iop_1Uto32, binop(Iop_CmpLT32S, word, mkU32(0))); 2078 } 2079 if (cond == 2 || cond == 2 + 1) { /* word > 0 */ 2080 return unop(Iop_1Uto32, binop(Iop_CmpLT32S, mkU32(0), word)); 2081 } 2082 if (cond == 8 + 4 || cond == 8 + 4 + 1) { 2083 return unop(Iop_1Uto32, binop(Iop_CmpLE32S, word, mkU32(0))); 2084 } 2085 if (cond == 8 + 2 || cond == 8 + 2 + 1) { 2086 return unop(Iop_1Uto32, binop(Iop_CmpLE32S, mkU32(0), word)); 2087 } 2088 if (cond == 8 + 4 + 2 || cond == 8 + 4 + 2 + 1) { 2089 return mkU32(1); 2090 } 2091 /* Remaining case */ 2092 return mkU32(0); 2093 } 2094 2095 /* S390_CC_OP_TEST_UNDER_MASK_8 2096 Since the mask comes from an immediate field in the opcode, we 2097 expect the mask to be a constant here. That simplifies matters. */ 2098 if (cc_op == S390_CC_OP_TEST_UNDER_MASK_8) { 2099 ULong mask16; 2100 2101 if (! isC64(cc_dep2)) goto missed; 2102 2103 mask16 = cc_dep2->Iex.Const.con->Ico.U64; 2104 2105 /* Get rid of the mask16 == 0 case first. Some of the simplifications 2106 below (e.g. for OVFL) only hold if mask16 == 0. */ 2107 if (mask16 == 0) { /* cc == 0 */ 2108 if (cond & 0x8) return mkU32(1); 2109 return mkU32(0); 2110 } 2111 2112 /* cc == 2 is a don't care */ 2113 if (cond == 8 || cond == 8 + 2) { 2114 return unop(Iop_1Uto32, binop(Iop_CmpEQ64, 2115 binop(Iop_And64, cc_dep1, cc_dep2), 2116 mkU64(0))); 2117 } 2118 if (cond == 7 || cond == 7 - 2) { 2119 return unop(Iop_1Uto32, binop(Iop_CmpNE64, 2120 binop(Iop_And64, cc_dep1, cc_dep2), 2121 mkU64(0))); 2122 } 2123 if (cond == 1 || cond == 1 + 2) { 2124 return unop(Iop_1Uto32, binop(Iop_CmpEQ64, 2125 binop(Iop_And64, cc_dep1, cc_dep2), 2126 cc_dep2)); 2127 } 2128 if (cond == 14 || cond == 14 - 2) { /* ! OVFL */ 2129 return unop(Iop_1Uto32, binop(Iop_CmpNE64, 2130 binop(Iop_And64, cc_dep1, cc_dep2), 2131 cc_dep2)); 2132 } 2133 goto missed; 2134 } 2135 2136 /* S390_CC_OP_TEST_UNDER_MASK_16 2137 Since the mask comes from an immediate field in the opcode, we 2138 expect the mask to be a constant here. That simplifies matters. */ 2139 if (cc_op == S390_CC_OP_TEST_UNDER_MASK_16) { 2140 ULong mask16; 2141 UInt msb; 2142 2143 if (! isC64(cc_dep2)) goto missed; 2144 2145 mask16 = cc_dep2->Iex.Const.con->Ico.U64; 2146 2147 /* Get rid of the mask16 == 0 case first. Some of the simplifications 2148 below (e.g. for OVFL) only hold if mask16 == 0. */ 2149 if (mask16 == 0) { /* cc == 0 */ 2150 if (cond & 0x8) return mkU32(1); 2151 return mkU32(0); 2152 } 2153 2154 if (cond == 15) return mkU32(1); 2155 2156 if (cond == 8) { 2157 return unop(Iop_1Uto32, binop(Iop_CmpEQ64, 2158 binop(Iop_And64, cc_dep1, cc_dep2), 2159 mkU64(0))); 2160 } 2161 if (cond == 7) { 2162 return unop(Iop_1Uto32, binop(Iop_CmpNE64, 2163 binop(Iop_And64, cc_dep1, cc_dep2), 2164 mkU64(0))); 2165 } 2166 if (cond == 1) { 2167 return unop(Iop_1Uto32, binop(Iop_CmpEQ64, 2168 binop(Iop_And64, cc_dep1, cc_dep2), 2169 mkU64(mask16))); 2170 } 2171 if (cond == 14) { /* ! OVFL */ 2172 return unop(Iop_1Uto32, binop(Iop_CmpNE64, 2173 binop(Iop_And64, cc_dep1, cc_dep2), 2174 mkU64(mask16))); 2175 } 2176 2177 /* Find MSB in mask */ 2178 msb = 0x8000; 2179 while (msb > mask16) 2180 msb >>= 1; 2181 2182 if (cond == 2) { /* cc == 2 */ 2183 IRExpr *c1, *c2; 2184 2185 /* (cc_dep & msb) != 0 && (cc_dep & mask16) != mask16 */ 2186 c1 = binop(Iop_CmpNE64, 2187 binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0)); 2188 c2 = binop(Iop_CmpNE64, 2189 binop(Iop_And64, cc_dep1, cc_dep2), 2190 mkU64(mask16)); 2191 return binop(Iop_And32, unop(Iop_1Uto32, c1), 2192 unop(Iop_1Uto32, c2)); 2193 } 2194 2195 if (cond == 4) { /* cc == 1 */ 2196 IRExpr *c1, *c2; 2197 2198 /* (cc_dep & msb) == 0 && (cc_dep & mask16) != 0 */ 2199 c1 = binop(Iop_CmpEQ64, 2200 binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0)); 2201 c2 = binop(Iop_CmpNE64, 2202 binop(Iop_And64, cc_dep1, cc_dep2), 2203 mkU64(0)); 2204 return binop(Iop_And32, unop(Iop_1Uto32, c1), 2205 unop(Iop_1Uto32, c2)); 2206 } 2207 2208 if (cond == 11) { /* cc == 0,2,3 */ 2209 IRExpr *c1, *c2; 2210 2211 c1 = binop(Iop_CmpNE64, 2212 binop(Iop_And64, cc_dep1, mkU64(msb)), mkU64(0)); 2213 c2 = binop(Iop_CmpEQ64, 2214 binop(Iop_And64, cc_dep1, cc_dep2), 2215 mkU64(0)); 2216 return binop(Iop_Or32, unop(Iop_1Uto32, c1), 2217 unop(Iop_1Uto32, c2)); 2218 } 2219 2220 if (cond == 3) { /* cc == 2 || cc == 3 */ 2221 return unop(Iop_1Uto32, 2222 binop(Iop_CmpNE64, 2223 binop(Iop_And64, cc_dep1, mkU64(msb)), 2224 mkU64(0))); 2225 } 2226 if (cond == 12) { /* cc == 0 || cc == 1 */ 2227 return unop(Iop_1Uto32, 2228 binop(Iop_CmpEQ64, 2229 binop(Iop_And64, cc_dep1, mkU64(msb)), 2230 mkU64(0))); 2231 } 2232 if (cond == 13) { /* cc == 0 || cc == 1 || cc == 3 */ 2233 IRExpr *c01, *c3; 2234 2235 c01 = binop(Iop_CmpEQ64, binop(Iop_And64, cc_dep1, mkU64(msb)), 2236 mkU64(0)); 2237 c3 = binop(Iop_CmpEQ64, binop(Iop_And64, cc_dep1, cc_dep2), 2238 mkU64(mask16)); 2239 return binop(Iop_Or32, unop(Iop_1Uto32, c01), 2240 unop(Iop_1Uto32, c3)); 2241 } 2242 // fixs390: handle cond = 5,6,9,10 (the missing cases) 2243 // vex_printf("TUM mask = 0x%llx\n", mask16); 2244 goto missed; 2245 } 2246 2247 /* S390_CC_OP_UNSIGNED_SUB_64/32 */ 2248 if (cc_op == S390_CC_OP_UNSIGNED_SUB_64 || 2249 cc_op == S390_CC_OP_UNSIGNED_SUB_32) { 2250 /* 2251 cc_dep1, cc_dep2 are the zero extended left and right operands 2252 2253 cc == 1 --> result != 0, borrow (cond == 4) 2254 cc == 2 --> result == 0, no borrow (cond == 2) 2255 cc == 3 --> result != 0, no borrow (cond == 1) 2256 2257 cc = (cc_dep1 == cc_dep2) ? 2 2258 : (cc_dep1 > cc_dep2) ? 3 : 1; 2259 2260 Because cc == 0 cannot occur the leftmost bit of cond is 2261 a don't care. 2262 */ 2263 if (cond == 1 || cond == 1 + 8) { /* cc == 3 op2 < op1 */ 2264 return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep2, cc_dep1)); 2265 } 2266 if (cond == 2 || cond == 2 + 8) { /* cc == 2 */ 2267 return unop(Iop_1Uto32, binop(Iop_CmpEQ64, cc_dep1, cc_dep2)); 2268 } 2269 if (cond == 4 || cond == 4 + 8) { /* cc == 1 */ 2270 return unop(Iop_1Uto32, binop(Iop_CmpLT64U, cc_dep1, cc_dep2)); 2271 } 2272 if (cond == 3 || cond == 3 + 8) { /* cc == 2 || cc == 3 */ 2273 return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep2, cc_dep1)); 2274 } 2275 if (cond == 6 || cond == 6 + 8) { /* cc == 2 || cc == 1 */ 2276 return unop(Iop_1Uto32, binop(Iop_CmpLE64U, cc_dep1, cc_dep2)); 2277 } 2278 2279 if (cond == 5 || cond == 5 + 8) { /* cc == 3 || cc == 1 */ 2280 return unop(Iop_1Uto32, binop(Iop_CmpNE64, cc_dep1, cc_dep2)); 2281 } 2282 if (cond == 7 || cond == 7 + 8) { 2283 return mkU32(1); 2284 } 2285 /* Remaining case */ 2286 return mkU32(0); 2287 } 2288 2289 /* S390_CC_OP_UNSIGNED_ADD_64 */ 2290 if (cc_op == S390_CC_OP_UNSIGNED_ADD_64) { 2291 /* 2292 cc_dep1, cc_dep2 are the zero extended left and right operands 2293 2294 cc == 0 --> result == 0, no carry (cond == 8) 2295 cc == 1 --> result != 0, no carry (cond == 4) 2296 cc == 2 --> result == 0, carry (cond == 2) 2297 cc == 3 --> result != 0, carry (cond == 1) 2298 */ 2299 if (cond == 8) { /* cc == 0 */ 2300 /* Both inputs are 0 */ 2301 return unop(Iop_1Uto32, binop(Iop_CmpEQ64, 2302 binop(Iop_Or64, cc_dep1, cc_dep2), 2303 mkU64(0))); 2304 } 2305 if (cond == 7) { /* cc == 1,2,3 */ 2306 /* Not both inputs are 0 */ 2307 return unop(Iop_1Uto32, binop(Iop_CmpNE64, 2308 binop(Iop_Or64, cc_dep1, cc_dep2), 2309 mkU64(0))); 2310 } 2311 if (cond == 8 + 2) { /* cc == 0,2 -> result is zero */ 2312 return unop(Iop_1Uto32, binop(Iop_CmpEQ64, 2313 binop(Iop_Add64, cc_dep1, cc_dep2), 2314 mkU64(0))); 2315 } 2316 if (cond == 4 + 1) { /* cc == 1,3 -> result is not zero */ 2317 return unop(Iop_1Uto32, binop(Iop_CmpNE64, 2318 binop(Iop_Add64, cc_dep1, cc_dep2), 2319 mkU64(0))); 2320 } 2321 goto missed; 2322 } 2323 2324 /* S390_CC_OP_UNSIGNED_ADD_32 */ 2325 if (cc_op == S390_CC_OP_UNSIGNED_ADD_32) { 2326 /* 2327 cc_dep1, cc_dep2 are the zero extended left and right operands 2328 2329 cc == 0 --> result == 0, no carry (cond == 8) 2330 cc == 1 --> result != 0, no carry (cond == 4) 2331 cc == 2 --> result == 0, carry (cond == 2) 2332 cc == 3 --> result != 0, carry (cond == 1) 2333 */ 2334 if (cond == 8) { /* cc == 0 */ 2335 /* Both inputs are 0 */ 2336 return unop(Iop_1Uto32, binop(Iop_CmpEQ64, 2337 binop(Iop_Or64, cc_dep1, cc_dep2), 2338 mkU64(0))); 2339 } 2340 if (cond == 7) { /* cc == 1,2,3 */ 2341 /* Not both inputs are 0 */ 2342 return unop(Iop_1Uto32, binop(Iop_CmpNE64, 2343 binop(Iop_Or64, cc_dep1, cc_dep2), 2344 mkU64(0))); 2345 } 2346 if (cond == 8 + 2) { /* cc == 0,2 -> result is zero */ 2347 return unop(Iop_1Uto32, binop(Iop_CmpEQ32, 2348 binop(Iop_Add32, 2349 unop(Iop_64to32, cc_dep1), 2350 unop(Iop_64to32, cc_dep2)), 2351 mkU32(0))); 2352 } 2353 if (cond == 4 + 1) { /* cc == 1,3 -> result is not zero */ 2354 return unop(Iop_1Uto32, binop(Iop_CmpNE32, 2355 binop(Iop_Add32, 2356 unop(Iop_64to32, cc_dep1), 2357 unop(Iop_64to32, cc_dep2)), 2358 mkU32(0))); 2359 } 2360 goto missed; 2361 } 2362 2363 /* S390_CC_OP_SET */ 2364 if (cc_op == S390_CC_OP_SET) { 2365 /* cc_dep1 is the condition code 2366 2367 Return 1, if ((cond << cc_dep1) & 0x8) != 0 */ 2368 2369 return unop(Iop_1Uto32, 2370 binop(Iop_CmpNE64, 2371 binop(Iop_And64, 2372 binop(Iop_Shl64, cond_expr, 2373 unop(Iop_64to8, cc_dep1)), 2374 mkU64(8)), 2375 mkU64(0))); 2376 } 2377 2378 goto missed; 2379 } 2380 2381 /* --------- Specialising "s390_calculate_cc" --------- */ 2382 2383 if (vex_streq(function_name, "s390_calculate_cc")) { 2384 IRExpr *cc_op_expr, *cc_dep1; 2385 ULong cc_op; 2386 2387 vassert(arity == 4); 2388 2389 cc_op_expr = args[0]; 2390 2391 /* The necessary requirement for all optimizations here is that 2392 cc_op is constant. So check that upfront. */ 2393 if (! isC64(cc_op_expr)) return NULL; 2394 2395 cc_op = cc_op_expr->Iex.Const.con->Ico.U64; 2396 cc_dep1 = args[1]; 2397 2398 if (cc_op == S390_CC_OP_BITWISE) { 2399 return unop(Iop_1Uto32, 2400 binop(Iop_CmpNE64, cc_dep1, mkU64(0))); 2401 } 2402 2403 if (cc_op == S390_CC_OP_SET) { 2404 return unop(Iop_64to32, cc_dep1); 2405 } 2406 2407 goto missed; 2408 } 2409 2410 missed: 2411 return NULL; 2412 } 2413 2414 /*---------------------------------------------------------------*/ 2415 /*--- end guest_s390_helpers.c ---*/ 2416 /*---------------------------------------------------------------*/ 2417