}
static const HChar *
-s390_irgen_SRNMB(IRTemp op2addr)
+s390_irgen_SRNMB(UChar b2, UShort d2)
{
- UInt input_mask, fpc_mask;
+ /* Can only check at IR generation time when b2 == 0 */
+ if (b2 == 0) {
+ s390_insn_assert("srnmb", d2 <= 3 || d2 == 7); // valid rounding mode
+ /* d2 == 7 requires fpext */
+ if (d2 == 7 && ! s390_host_has_fpext) {
+ emulation_failure(EmFail_S390X_fpext);
+ return "srnmb";
+ }
+ }
+ IRTemp op2addr = newTemp(Ity_I64);
- input_mask = 7;
- fpc_mask = 7;
+ assign(op2addr, binop(Iop_Add64, mkU64(d2), b2 != 0 ? get_gpr_dw0(b2) :
+ mkU64(0)));
+
+ UInt input_mask = 7;
+ UInt fpc_mask = 7;
put_fpc_w0(binop(Iop_Or32,
binop(Iop_And32, get_fpc_w0(), mkU32(~fpc_mask)),
return "srnmb";
}
-static void
-s390_irgen_srnmb_wrapper(UChar b2, UShort d2)
-{
- if (b2 == 0) { /* This is the typical case */
- if (d2 > 3) {
- if (s390_host_has_fpext && d2 == 7) {
- /* ok */
- } else {
- emulation_warning(EmWarn_S390X_invalid_rounding);
- d2 = S390_FPC_BFP_ROUND_NEAREST_EVEN;
- }
- }
- }
-
- s390_format_S_RD(s390_irgen_SRNMB, b2, d2);
-}
-/* Wrapper to validate the parameter as in SRNMB is not required, as all
- the 8 values in op2addr[61:63] correspond to a valid DFP rounding mode */
+/* All 8 values in op2addr[61:63] correspond to a valid DFP rounding mode */
static const HChar *
s390_irgen_SRNMT(IRTemp op2addr)
{
goto ok;
case 0xb2b1: /* STFL */ goto unimplemented;
case 0xb2b2: /* LPSWE */ goto unimplemented;
- case 0xb2b8: s390_irgen_srnmb_wrapper(S_b2(ovl), S_d2(ovl));
+ case 0xb2b8: s390_format_S_RD_raw(s390_irgen_SRNMB, S_b2(ovl), S_d2(ovl));
goto ok;
case 0xb2b9: s390_format_S_RD(s390_irgen_SRNMT, S_b2(ovl), S_d2(ovl));
goto ok;
" feature requires the floating point extension facility\n"
" which is not available on this host. Continuing using\n"
" the rounding mode from FPC. Results may differ!";
- case EmWarn_S390X_invalid_rounding:
- return "The specified rounding mode is invalid.\n"
- " Continuing using 'round to nearest'. Results may differ!";
case EmFail_S390X_stfle:
return "Instruction stfle is not supported on this host";
case EmFail_S390X_stckf:
facility is not available on this host */
EmWarn_S390X_fpext_rounding,
- /* insn (e.g. srnmb) specifies an invalid rounding mode */
- EmWarn_S390X_invalid_rounding,
-
/* stfle insn is not supported on this host */
EmFail_S390X_stfle,
int main(void)
{
+ setlinebuf(stdout);
printf("initial rounding mode = %u\n", get_rounding_mode());
/* Set basic rounding modes in various ways */
srnmb(0,001);
printf("rounding mode = %u\n", get_rounding_mode());
- srnmb0(004); // -> emul warning invalid rounding mode
+ srnmb0(004); // -> specification exception
printf("rounding mode = %u\n", get_rounding_mode());
return 0;
-Emulation warning: unsupported action:
- The specified rounding mode is invalid.
- Continuing using 'round to nearest'. Results may differ!
- at 0x........: main (srnmb.c:61)
+vex s390->IR: specification exception: B2B8 0004
+valgrind: Unrecognised instruction at address 0x.........
+ at 0x........: main (srnmb.c:59)
+Your program just tried to execute an instruction that Valgrind
+did not recognise. There are two possible reasons for this.
+1. Your program has a bug and erroneously jumped to a non-code
+ location. If you are running Memcheck and you just saw a
+ warning about a bad jump, it's probably your program's fault.
+2. The instruction is legitimate but Valgrind doesn't handle it,
+ i.e. it's Valgrind's fault. If you think this is the case or
+ you are not sure, please let us know and we'll try to fix it.
+Either way, Valgrind will now raise a SIGILL signal which will
+probably kill your program.
+
+Process terminating with default action of signal 4 (SIGILL)
+ Illegal opcode at address 0x........
+ at 0x........: main (srnmb.c:59)
rounding mode = 1
rounding mode = 0
rounding mode = 1
-rounding mode = 0