There is an interesting story in January's Communications of the ACM called The Long Road to 64 Bits. The magazine is free online here. It charts the long and often twisted road from 32 to 64 bit architectures.
From a software perspective the challenge is around writing C code that compiles and runs cleanly on 32 and 64 bit platforms. The issue being that compilers on different hardware architectures adopt different sized data types for integers, longs and pointers.
So for example, on Windows 32 bit (and many Unix's from the 1990's) all three were 32 bits wide, hence the tag ILP32. On 64 bit Windows, integers and longs remained 32 bits wide while pointers necessarily increased to 64 bits - so that goes by the tag IL32P64, or just P64 for short. Meanwhile many 64 bit Unix systems adopted I32LP64 - meaning integers remained 32 bits while longs and pointers widened to 64 bits.
PHP has to deal with this issue since it is written in C and is ported to many platforms. This issue also comes up when mixing Java and C code because Java has a different approach. Java set out to simplify the programming model by fixing the sizes of all data types. An integer in Java is 32 bits, always 32 bits and never anything apart from 32 bits. Java also has a long data type which is always 64 bits and has no unsigned data types at all.
Problems arise when Java code (with a fixed size data type) interacts with C code (that varies the data type size depending on the platform). Java has no pre-processor like C so it's not easy to write Java code that would, for example, use a Java integer on 32 bit machines, and magically use a Java long on 64 bit machines (and could therefore match the C code). So instead we generally use the wider data type (a Java long) on both 32 and 64 bit machines (and down cast where necessary).
At this point I should also mention z/OS which for it's own honourable reasons supported 24, 31 and 64 bit architectures...!