With gfortran running on x86-64, I finally got around
to writing the routine to return the value of the rdtsc
(time stamp counter).
rdtsc was designed for IA32 and returns the 64 bit value
in the EAX and EDX registers. This is conveniently
the right place for the return value of a 64 bit integer
for most IA32 calling conventions.
For x86-64 a function return value is in the 64 bit
RAX register, but rdtsc still returns the value in
EAX and EDX. I now have the following running with
gfortran/x86-64/Linux:
.file "rdtsc.s"
.text
.globl rdtsc_
.type rdtsc_, @function
rdtsc_:
rdtsc
movl %eax,%ecx
movl %edx,%eax
shlq $32,%rax
addq %rcx,%rax
ret
.size rdtsc_, .-rdtsc_
It should be declared as INTEGER*8 rdtsc, or your preferred way
of declaring functions that return 64 bit integers.
This was formed by compiling a simple function with the -S option,
removing unneeded code and data from the generated rdtsc.s file,
adding the appropriate instruction, and then compiling it with
gfortran -c rdtsc.s
For 32 bit code, it should be something like:
.file "rdtsc.s"
.text
.globl rdtsc_
.type rdtsc_, @function
rdtsc_:
rdtsc
ret
.size rdtsc_, .-rdtsc_
but I haven't tried this one, yet.
(I have gfortran on an x86-64 machine and g95 on an IA32 machine.)
You can test it with a program like:
integer*8 rdtsc,t0,t1
t0=rdtsc(1)
do 1 i=1,1000000000
1 continue
t1=rdtsc(2)
print *,t1-t0
write(*,'(z18,z18)') t0,t1
stop
end
gfortran seems to generate seven instructions for the DO
loop, the first two instruction skip the loop if
1 is greater than 1000000000 (it never is). It would
seem that it could use the same two instruction test
inside the loop, but it uses seven instead. I suppose,
though, it optimizes for loops with statements in them.
cmpl $1000000000, -12(%rbp)
jg .L2
.L3:
cmpl $1000000000, -12(%rbp)
sete %al
movzbl %al, %eax
addl $1, -12(%rbp)
testl %eax, %eax
jne .L2
jmp .L3
.L2:
-- glen