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
13 # It is encoded as "d9 /5" which means
15 # Where xx is the "mod" which will be 00, 01, or 10 indicating offset
16 # and yyy is the register field
18 # these are instructions with similar encodings to fldcw
19 # that can cause false positives if the test isn't explicit enough
29 # check some varied ways of calling fldcw
33 sub $8,%rsp # allocate space on stack
36 add $8,%rsp # restore stack
52 # Note! The assembler that comes with SuSE 9.1
53 # cannot assemble 32-bit fldcw on 64-bit systems
54 # Hence the need to hand-code them
79 # register + 8-bit offset
84 # fldcw 32(%eax) # eax + 8 bit offset
85 .byte 0x67,0xd9,0x68,0x20
88 # fldcw 32(%ebx) # ebx + 8 bit offset
89 .byte 0x67,0xd9,0x6b,0x20
93 # fldcw 32(%ecx) # ecx + 8 bit offset
94 .byte 0x67,0xd9,0x69,0x20
98 # fldcw 32(%edx) # edx + 8 bit offset
99 .byte 0x67,0xd9,0x6a,0x20
102 # register + 32-bit offset
107 # fldcw 30000(%eax) # eax + 16 bit offset
108 .byte 0x67,0xd9,0xa8,0x30,0x75,0x00,0x00
112 # fldcw 30000(%ebx) # ebx + 16 bit offset
113 .byte 0x67,0xd9,0xab,0x30,0x75,0x00,0x00
117 # fldcw 30000(%ecx) # ecx + 16 bit offset
118 .byte 0x67,0xd9,0xa9,0x30,0x75,0x00,0x00
122 # fldcw 30000(%edx) # edx + 16 bit offset
123 .byte 0x67,0xd9,0xaa,0x30,0x75,0x00,0x00
125 # check an fp/integer conversion
126 # in a loop to give a bigger count
131 fldl three # load value onto fp stack
132 fnstcw saved_cw # store control word to mem
133 movzwl saved_cw, %eax # load cw from mem, zero extending
134 movb $12, %ah # set cw for "round to zero"
135 movw %ax, cw # store back to memory
136 fldcw cw # save new rounding mode
137 fistpl result # save stack value as integer to mem
138 fldcw saved_cw # restore old cw
140 loop big_loop # loop to make the count more obvious
142 movl result, %ebx # sanity check to see if the
143 cmp $3,%rbx # result is the expected one
147 mov $1,%rax # write syscall
149 mov $error,%rsi # string
150 mov $22,%rdx # length of string
154 xor %rdi, %rdi # return 0
155 mov $60, %rax # SYSCALL_EXIT
164 three: .long 0 # a floating point 3.0
166 error: .asciz "Error! Wrong result!\n"