blob: 3bd574f9b1ce1486c1aa8ac6a9cc915f9b5e3aef [file] [log] [blame]
/*
* Copyright (c) 2013 The Native Client Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/*
* Rounding mode control field is bits [11:10] in the x87
* control word, and bits [14:13] in the SSE control word.
* This function takes in %ecx the two-bit value pre-shifted to
* bits [11:10] and sets both control words at the appropriate bits.
*
* The bit patterns for X86 are:
* 0b00 Round to Nearest (RN) mode
* 0b10 Round towards Plus Infinity (RP) mode
* 0b01 Round towards Minus Infinity (RM) mode
* 0b11 Round towards Zero (RZ) mode
*/
.p2align 5
set_rounding_control_field:
/* First set the 87 control word */
#if defined(__x86_64__)
fnstcw -8(%rsp) # Use red zone.
movl -8(%rsp), %eax
#else
sub $12, %esp
fnstcw 0(%esp)
movl 0(%esp), %eax
#endif
andl $0xfffff3ff, %eax
orl %ecx, %eax
#if defined(__x86_64__)
movl %eax, -8(%rsp)
fldcw -8(%rsp)
#else
movl %eax, 0(%esp)
fldcw 0(%esp)
#endif
/* Then set the SSE control word w/ same pattern, but shifted. */
#if defined(__x86_64__)
stmxcsr -8(%rsp)
movl -8(%rsp), %eax
#else
stmxcsr 0(%esp)
movl 0(%esp), %eax
#endif
andl $0xffff9fff, %eax
shl $3, %ecx
orl %ecx, %eax
#if defined(__x86_64__)
movl %eax, -8(%rsp)
ldmxcsr -8(%rsp)
#else
movl %eax, 0(%esp)
ldmxcsr 0(%esp)
add $12, %esp
#endif
naclret
.p2align 5
.global set_round_toward_nearest
set_round_toward_nearest:
/* Use a fast-cc + tail call to avoid stack manipulation/alignment */
movl $0, %ecx
jmp set_rounding_control_field
.p2align 5
.global set_round_toward_plus_infinity
set_round_toward_plus_infinity:
movl $0x800, %ecx
jmp set_rounding_control_field
.p2align 5
.global set_round_toward_minus_infinity
set_round_toward_minus_infinity:
movl $0x400, %ecx
jmp set_rounding_control_field
.p2align 5
.global set_round_toward_zero
set_round_toward_zero:
movl $0xc00, %ecx
jmp set_rounding_control_field