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