Skip to content

Commit 8c5882e

Browse files
committed
Move round_* functions from shims::x86::sse41 module to shims::x86
1 parent c37f4d6 commit 8c5882e

File tree

2 files changed

+84
-84
lines changed

2 files changed

+84
-84
lines changed

src/tools/miri/src/shims/x86/mod.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,89 @@ fn unary_op_ps<'tcx>(
455455
Ok(())
456456
}
457457

458+
// Rounds the first element of `right` according to `rounding`
459+
// and copies the remaining elements from `left`.
460+
fn round_first<'tcx, F: rustc_apfloat::Float>(
461+
this: &mut crate::MiriInterpCx<'_, 'tcx>,
462+
left: &OpTy<'tcx, Provenance>,
463+
right: &OpTy<'tcx, Provenance>,
464+
rounding: &OpTy<'tcx, Provenance>,
465+
dest: &PlaceTy<'tcx, Provenance>,
466+
) -> InterpResult<'tcx, ()> {
467+
let (left, left_len) = this.operand_to_simd(left)?;
468+
let (right, right_len) = this.operand_to_simd(right)?;
469+
let (dest, dest_len) = this.place_to_simd(dest)?;
470+
471+
assert_eq!(dest_len, left_len);
472+
assert_eq!(dest_len, right_len);
473+
474+
let rounding = rounding_from_imm(this.read_scalar(rounding)?.to_i32()?)?;
475+
476+
let op0: F = this.read_scalar(&this.project_index(&right, 0)?)?.to_float()?;
477+
let res = op0.round_to_integral(rounding).value;
478+
this.write_scalar(
479+
Scalar::from_uint(res.to_bits(), Size::from_bits(F::BITS)),
480+
&this.project_index(&dest, 0)?,
481+
)?;
482+
483+
for i in 1..dest_len {
484+
this.copy_op(
485+
&this.project_index(&left, i)?,
486+
&this.project_index(&dest, i)?,
487+
/*allow_transmute*/ false,
488+
)?;
489+
}
490+
491+
Ok(())
492+
}
493+
494+
// Rounds all elements of `op` according to `rounding`.
495+
fn round_all<'tcx, F: rustc_apfloat::Float>(
496+
this: &mut crate::MiriInterpCx<'_, 'tcx>,
497+
op: &OpTy<'tcx, Provenance>,
498+
rounding: &OpTy<'tcx, Provenance>,
499+
dest: &PlaceTy<'tcx, Provenance>,
500+
) -> InterpResult<'tcx, ()> {
501+
let (op, op_len) = this.operand_to_simd(op)?;
502+
let (dest, dest_len) = this.place_to_simd(dest)?;
503+
504+
assert_eq!(dest_len, op_len);
505+
506+
let rounding = rounding_from_imm(this.read_scalar(rounding)?.to_i32()?)?;
507+
508+
for i in 0..dest_len {
509+
let op: F = this.read_scalar(&this.project_index(&op, i)?)?.to_float()?;
510+
let res = op.round_to_integral(rounding).value;
511+
this.write_scalar(
512+
Scalar::from_uint(res.to_bits(), Size::from_bits(F::BITS)),
513+
&this.project_index(&dest, i)?,
514+
)?;
515+
}
516+
517+
Ok(())
518+
}
519+
520+
/// Gets equivalent `rustc_apfloat::Round` from rounding mode immediate of
521+
/// `round.{ss,sd,ps,pd}` intrinsics.
522+
fn rounding_from_imm<'tcx>(rounding: i32) -> InterpResult<'tcx, rustc_apfloat::Round> {
523+
// The fourth bit of `rounding` only affects the SSE status
524+
// register, which cannot be accessed from Miri (or from Rust,
525+
// for that matter), so we can ignore it.
526+
match rounding & !0b1000 {
527+
// When the third bit is 0, the rounding mode is determined by the
528+
// first two bits.
529+
0b000 => Ok(rustc_apfloat::Round::NearestTiesToEven),
530+
0b001 => Ok(rustc_apfloat::Round::TowardNegative),
531+
0b010 => Ok(rustc_apfloat::Round::TowardPositive),
532+
0b011 => Ok(rustc_apfloat::Round::TowardZero),
533+
// When the third bit is 1, the rounding mode is determined by the
534+
// SSE status register. Since we do not support modifying it from
535+
// Miri (or Rust), we assume it to be at its default mode (round-to-nearest).
536+
0b100..=0b111 => Ok(rustc_apfloat::Round::NearestTiesToEven),
537+
rounding => throw_unsup_format!("unsupported rounding mode 0x{rounding:02x}"),
538+
}
539+
}
540+
458541
/// Converts each element of `op` from floating point to signed integer.
459542
///
460543
/// When the input value is NaN or out of range, fall back to minimum value.

src/tools/miri/src/shims/x86/sse41.rs

Lines changed: 1 addition & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use rustc_middle::mir;
22
use rustc_span::Symbol;
3-
use rustc_target::abi::Size;
43
use rustc_target::spec::abi::Abi;
54

5+
use super::{round_all, round_first};
66
use crate::*;
77
use shims::foreign_items::EmulateForeignItemResult;
88

@@ -283,86 +283,3 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
283283
Ok(EmulateForeignItemResult::NeedsJumping)
284284
}
285285
}
286-
287-
// Rounds the first element of `right` according to `rounding`
288-
// and copies the remaining elements from `left`.
289-
fn round_first<'tcx, F: rustc_apfloat::Float>(
290-
this: &mut crate::MiriInterpCx<'_, 'tcx>,
291-
left: &OpTy<'tcx, Provenance>,
292-
right: &OpTy<'tcx, Provenance>,
293-
rounding: &OpTy<'tcx, Provenance>,
294-
dest: &PlaceTy<'tcx, Provenance>,
295-
) -> InterpResult<'tcx, ()> {
296-
let (left, left_len) = this.operand_to_simd(left)?;
297-
let (right, right_len) = this.operand_to_simd(right)?;
298-
let (dest, dest_len) = this.place_to_simd(dest)?;
299-
300-
assert_eq!(dest_len, left_len);
301-
assert_eq!(dest_len, right_len);
302-
303-
let rounding = rounding_from_imm(this.read_scalar(rounding)?.to_i32()?)?;
304-
305-
let op0: F = this.read_scalar(&this.project_index(&right, 0)?)?.to_float()?;
306-
let res = op0.round_to_integral(rounding).value;
307-
this.write_scalar(
308-
Scalar::from_uint(res.to_bits(), Size::from_bits(F::BITS)),
309-
&this.project_index(&dest, 0)?,
310-
)?;
311-
312-
for i in 1..dest_len {
313-
this.copy_op(
314-
&this.project_index(&left, i)?,
315-
&this.project_index(&dest, i)?,
316-
/*allow_transmute*/ false,
317-
)?;
318-
}
319-
320-
Ok(())
321-
}
322-
323-
// Rounds all elements of `op` according to `rounding`.
324-
fn round_all<'tcx, F: rustc_apfloat::Float>(
325-
this: &mut crate::MiriInterpCx<'_, 'tcx>,
326-
op: &OpTy<'tcx, Provenance>,
327-
rounding: &OpTy<'tcx, Provenance>,
328-
dest: &PlaceTy<'tcx, Provenance>,
329-
) -> InterpResult<'tcx, ()> {
330-
let (op, op_len) = this.operand_to_simd(op)?;
331-
let (dest, dest_len) = this.place_to_simd(dest)?;
332-
333-
assert_eq!(dest_len, op_len);
334-
335-
let rounding = rounding_from_imm(this.read_scalar(rounding)?.to_i32()?)?;
336-
337-
for i in 0..dest_len {
338-
let op: F = this.read_scalar(&this.project_index(&op, i)?)?.to_float()?;
339-
let res = op.round_to_integral(rounding).value;
340-
this.write_scalar(
341-
Scalar::from_uint(res.to_bits(), Size::from_bits(F::BITS)),
342-
&this.project_index(&dest, i)?,
343-
)?;
344-
}
345-
346-
Ok(())
347-
}
348-
349-
/// Gets equivalent `rustc_apfloat::Round` from rounding mode immediate of
350-
/// `round.{ss,sd,ps,pd}` intrinsics.
351-
fn rounding_from_imm<'tcx>(rounding: i32) -> InterpResult<'tcx, rustc_apfloat::Round> {
352-
// The fourth bit of `rounding` only affects the SSE status
353-
// register, which cannot be accessed from Miri (or from Rust,
354-
// for that matter), so we can ignore it.
355-
match rounding & !0b1000 {
356-
// When the third bit is 0, the rounding mode is determined by the
357-
// first two bits.
358-
0b000 => Ok(rustc_apfloat::Round::NearestTiesToEven),
359-
0b001 => Ok(rustc_apfloat::Round::TowardNegative),
360-
0b010 => Ok(rustc_apfloat::Round::TowardPositive),
361-
0b011 => Ok(rustc_apfloat::Round::TowardZero),
362-
// When the third bit is 1, the rounding mode is determined by the
363-
// SSE status register. Since we do not support modifying it from
364-
// Miri (or Rust), we assume it to be at its default mode (round-to-nearest).
365-
0b100..=0b111 => Ok(rustc_apfloat::Round::NearestTiesToEven),
366-
rounding => throw_unsup_format!("unsupported rounding mode 0x{rounding:02x}"),
367-
}
368-
}

0 commit comments

Comments
 (0)