regtest: callgrind bug497723 again, order of output can vary
[valgrind.git] / exp-bbv / tests / x86 / fldcw_check.S
blob0418a606cec4501a39ba6954187ecd72af66edeb
2 .globl _start
4 _start:
5         # This code tests for the fldcw "load floating point command word"
6         #   instruction.  On most x86 processors the retired_instruction
7         #   performance counter counts this as one instruction.  However,
8         #   on Pentium 4 systems it counts as two.  Therefore this can
9         #   affect BBV results on such a system.
10         # fldcw is most often used to set the rouding mode when doing
11         #   floating point to integer conversions
12         
13         # It is encoded as "d9 /5" which means
14         #   1101 1001 xx10 1yyy
15         # Where xx is the "mod" which will be 00, 01, or 10 indicating offset
16         #   and yyy is the register field
20         # these are instructions with similar encodings to fldcw
21         # that can cause false positives if the test isn't explicit enough
22 similar:        
23         fld1                            # d9 e8
24         fldl2t                          # d9 e9
25         fldl2e                          # d9 ea
26         fldpi                           # d9 eb
27         fldlg2                          # d9 ec
28         fldln2                          # d9 ed
29         fldz                            # d9 ee
31         # check some varied ways of calling fldcw
34         # offset on stack
35 stack:  
36         sub     $4,%esp                 # allocate space on stack
37         fnstcw  2(%esp)         
38         fldcw   2(%esp)         
39         add     $4,%esp                 # restore stack
40         
41         # 32-bit register
42         
43         fnstcw  cw
44         mov     $cw,%eax
45         fldcw   0(%eax)                 # eax
46         mov     $cw,%ebx
47         fldcw   0(%ebx)                 # ebx
48         mov     $cw,%ecx        
49         fldcw   0(%ecx)                 # ecx
50         mov     $cw,%edx                 
51         fldcw   0(%edx)                 # edx
52         
53         # register + 8-bit offset
54 eight_bit:      
55         mov     $cw,%eax
56         sub     $32,%eax
57         
58         fldcw   32(%eax)                # eax + 8 bit offset
59         mov     %eax,%ebx
60         fldcw   32(%ebx)                # ebx + 8 bit offset    
61         mov     %eax,%ecx
62         fldcw   32(%ecx)                # ecx + 8 bit offset            
63         mov     %eax,%edx
64         fldcw   32(%edx)                # edx + 8 bit offset
65         
66         # register + 32-bit offset
67 thirtytwo_bit:  
68         mov     $cw,%eax
69         sub     $30000,%eax
70         
71         fldcw   30000(%eax)             # eax + 16 bit offset
72         mov     %eax,%ebx
73         fldcw   30000(%ebx)             # ebx + 16 bit offset   
74         mov     %eax,%ecx
75         fldcw   30000(%ecx)             # ecx + 16 bit offset           
76         mov     %eax,%edx
77         fldcw   30000(%edx)             # edx + 16 bit offset                   
79         # check an fp/integer conversion
80         # in a loop to give a bigger count
82         mov     $1024,%ecx
83 big_loop:
85         fldl    three                   # load value onto fp stack
86         fnstcw  saved_cw                # store control word to mem
87         movzwl  saved_cw, %eax          # load cw from mem, zero extending
88         movb    $12, %ah                # set cw for "round to zero"
89         movw    %ax, cw                 # store back to memory
90         fldcw   cw                      # save new rounding mode
91         fistpl  result                  # save stack value as integer to mem
92         fldcw   saved_cw                # restore old cw
93         
94         loop    big_loop                # loop to make the count more obvious
96         movl    result, %ebx            # sanity check to see if the
97         cmp     $3,%ebx                 # result is the expected one
98         je      exit
99         
100 print_error:
101         mov     $4,%eax                 # write syscall
102 #if defined(VGO_darwin) || defined(VGO_freebsd)
103         pushl   $22
104         pushl   $error
105         pushl   $1
106         int     $0x80
107 #elif defined(VGO_linux)
108         mov     $1,%ebx                 # stdout
109         mov     $error,%ecx             # string        
110         mov     $22,%edx                # length of string
111         int     $0x80
112 #elif defined(VGO_solaris)
113         pushl   $22
114         pushl   $error
115         pushl   $1
116         int     $0x91
117 #else
118 #  error "Unknown OS"
119 #endif
121 exit:
122         movl    $1,     %eax            # SYSCALL_EXIT
123 #if defined(VGO_darwin) || defined(VGO_freebsd)
124         pushl   result
125         int     $0x80
126 #elif defined(VGO_linux)
127         movl    result, %ebx            # load converted value
128         int     $0x80
129 #elif defined(VGO_solaris)
130         pushl   result
131         int     $0x91
132 #else
133 #  error "Unknown OS"
134 #endif
137 .data
138 saved_cw:       .long 0
139 cw:     .long   0
140 result: .long   0
141 three:  .long   0                       # a floating point 3.0
142         .long   1074266112
143 error:  .ascii  "Error!  Wrong result!\n\0"