64bit data-types

Hello,

I’m a bit confused, maybe I’m missing something here. In my Win2K driver
for IA-32 architecture, I need to read/write 64-bit variables. My
questions:

  1. What data-type can I use for such a variable ?

  2. Are there any HAL functions (like READ_REGISTER_ULONG, etc.) for 64-bit
    quantities ?

  3. Also, how can I accomplish the above at application level ?

Appreciate all help!

Thanks
Puja

>I’m a bit confused, maybe I’m missing something here. In my Win2K driver

for IA-32 architecture, I need to read/write 64-bit variables. My
questions:

  1. What data-type can I use for such a variable ?

  2. Are there any HAL functions (like READ_REGISTER_ULONG, etc.) for 64-bit
    quantities ?

  3. Also, how can I accomplish the above at application level ?

Good question. At the app level, and in a driver you can use the
LARGE_INTEGER structure. An easier thing to do is to use Visual C++
“_int64” variables, which the compiler knows how to generate code for. I
believe the compiler is stupid though, and if you use _int64 variables, it
generates multiple 32-bit instructions to handle them. Intel MMX or even FP
instructions can directly handle 64-bit data values (not 64-bit addresses).
Many of the OS calls like a LARGE_INTEGER passed, so you sometimes have to
do type casts from pointers to your _int64 values to (LARGE_INTEGER *)
pointers.

At the kernel level, I don’t offhand remember (and my DDK docs are off-line
at this instant) if there is any equivalent to a READ_REGISTER_ULONG.
Clearly, a PCI device on a 64-bit PCI bus may need to have atomic 64-bit
read/write operations. Just creating a pointer to an unsigned __int64 and
setting the pointer to your device memory is NOT the same as using the
special access functions. The HAL functions have synchronization code in
them to be sure the out-of-order execution of the instruction stream
logically fit’s a programmers expectation. If you just use a pointer,
instructions AFTER the pointer reference may actually be executed BEFORE
the 64-bit data reference, which for device drivers makes a bit difference.

The current state of IA-32 processors is: logical addresses are 32-bits
(and 45-bits if you include FAR addresses), physical addresses can be more
than 32-bits (the whole 64-bit address space I don’t believe is available,
only 40-bits or so of address lines from SOME processors). There are native
MMX and FP instructions to load/store and do data math on 64-bit scalar,
FP,short vector values. Pentium 4’s, I believe now have instructions to do
128-bit data operations (in both scalar and short vector formats).

If you like the definition of a 32-bit processor being controlled by the
logical address size, then yes the IA-32 is mostly a 32-bit processor. If
you believe the physical address space controls how many “bits” a processor
is, then some IA-32 processors are about 40-bit processors. If you believe
the maximum size of a data chuck controls how many “bits” a processor is,
then clearly a Pentium 4 is a 128-bit processor. To really complicate
things, the IA-32 processors also have segment mapping, and the 32-bit
logical address space only applies to a single segment. This means there
are instructions to load about a 45-bit “logical address” and the OS COULD
arrange for programs to use addresses this big. By clever use of not
present pages and not present segments, a program could be written that
uses up to I believe 32 terabytes of RAM. Of course Win2000 application
programs mostly have to use 32-bit linear addresses. If you look at many of
the 64-bit processors, you don’t really get a true 64-bit flat logical
address either. Often the top bunch of bits is some sort of segment index,
so you can’t just have page tables to arbitrarily map any 64-bit page to
any physical page address.

  • Jan