File: test_fpu_control_word.c

package info (click to toggle)
chromium-browser 57.0.2987.98-1~deb8u1
  • links: PTS, VCS
  • area: main
  • in suites: jessie
  • size: 2,637,852 kB
  • ctags: 2,544,394
  • sloc: cpp: 12,815,961; ansic: 3,676,222; python: 1,147,112; asm: 526,608; java: 523,212; xml: 286,794; perl: 92,654; sh: 86,408; objc: 73,271; makefile: 27,698; cs: 18,487; yacc: 13,031; tcl: 12,957; pascal: 4,875; ml: 4,716; lex: 3,904; sql: 3,862; ruby: 1,982; lisp: 1,508; php: 1,368; exp: 404; awk: 325; csh: 117; jsp: 39; sed: 37
file content (135 lines) | stat: -rw-r--r-- 3,122 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
 * Copyright (c) 2012 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.
 */

#include <assert.h>
#include <sched.h>
#include <stdint.h>
#include <stdio.h>

#if defined(__i386__) || defined(__x86_64__)

typedef uint16_t fpcw_t;

#define X86_FPCW_PREC_MASK      0x300
#define X86_FPCW_PREC_DOUBLE    0x200
#define X86_FPCW_PREC_EXTENDED  0x300

static uint16_t get_fpcw(void) {
  uint16_t fpcw;
  __asm__ __volatile__("fnstcw %0": "=m" (fpcw));
  return fpcw;
}

static void set_fpcw(uint16_t fpcw) {
  __asm__  __volatile__("fldcw %0": : "m" (fpcw));
}

static fpcw_t modify_fpcw_bits(fpcw_t orig_fpcw) {
  assert(orig_fpcw & X86_FPCW_PREC_EXTENDED);
  return (orig_fpcw & ~X86_FPCW_PREC_MASK) | X86_FPCW_PREC_DOUBLE;
}

typedef uint32_t mxcsr_t;

#define X86_MXCSR_FLUSH_ZERO    0x8000

static mxcsr_t get_mxcsr(void) {
  uint32_t mxcsr;
  __asm__ __volatile__("stmxcsr %0" : "=m" (mxcsr));
  return mxcsr;
}

static void set_mxcsr(mxcsr_t mxcsr) {
  __asm__ __volatile__("ldmxcsr %0" :: "m" (mxcsr));
}

static mxcsr_t modify_mxcsr_bits(mxcsr_t orig_mxcsr) {
  assert((orig_mxcsr & X86_MXCSR_FLUSH_ZERO) == 0);
  return orig_mxcsr | X86_MXCSR_FLUSH_ZERO;
}

#elif defined(__arm__)

typedef uint32_t fpcw_t;

#define ARM_FPSCR_ROUND_MASK            0xc00000
#define ARM_FPSCR_ROUND_TONEAREST       0x000000
#define ARM_FPSCR_ROUND_UPWARD          0x800000
#define ARM_FPSCR_ROUND_DOWNWARD        0x400000
#define ARM_FPSCR_ROUND_TOWARDZERO      0xc00000

/*
 * These are defined in test_fpu_control_word_arm.S because
 * PNaCl/LLVM cannot handle the inline assembly for these instructions.
 */
fpcw_t get_fpcw(void);
void set_fpcw(fpcw_t);

static fpcw_t modify_fpcw_bits(fpcw_t orig_fpcw) {
  assert((orig_fpcw & ARM_FPSCR_ROUND_MASK) == ARM_FPSCR_ROUND_TONEAREST);
  return (orig_fpcw & ~ARM_FPSCR_ROUND_MASK) | ARM_FPSCR_ROUND_TOWARDZERO;
}

typedef int mxcsr_t;

static mxcsr_t get_mxcsr(void) {
  return 0;
}

static void set_mxcsr(mxcsr_t mxcsr __attribute__((unused))) {
}

static mxcsr_t modify_mxcsr_bits(mxcsr_t orig_mxcsr) {
  return orig_mxcsr;
}

#else
#error unsupported architecture
#endif

int main(void) {
  int result = 0;
  fpcw_t fpcw1;
  fpcw_t fpcw2;
  mxcsr_t mxcsr1;
  mxcsr_t mxcsr2;

  /*
   * Change the FPU control word to a non-default setting.
   */
  fpcw1 = get_fpcw();
  fpcw1 = modify_fpcw_bits(fpcw1);
  set_fpcw(fpcw1);

  mxcsr1 = get_mxcsr();
  mxcsr1 = modify_mxcsr_bits(mxcsr1);
  set_mxcsr(mxcsr1);

  /*
   * Now do a system call.  It's supposed to clear the rest of the FPU
   * state, but leave the control word intact.
   */
  sched_yield();

  /*
   * Now check what we got.
   */
  fpcw2 = get_fpcw();
  if (fpcw2 != fpcw1) {
    fprintf(stderr, "Set FPCW to %#x and got back %#x\n",
            (unsigned int) fpcw1, (unsigned int) fpcw2);
    result = 1;
  }

  mxcsr2 = get_mxcsr();
  if (mxcsr2 != mxcsr1) {
    fprintf(stderr, "Set MXCSR to %#x and got back %#x\n",
            (unsigned int) mxcsr1, (unsigned int) mxcsr2);
    result = 1;
  }

  return result;
}