I am currently reading up on the AArch64 architecture by ARM. They are using a RISC-like instruction set with a fixed instruction length of 32-bit while operating on 64-bit addresses. I am still new to the topic of ISA so my question is: how can you operate with 64-bit long addresses when you only have 32-bit length in your instructions?
2 Answers
32-bit is the length of an instruction in bytes, not the operand-size or the address size.
ARM 32-bit (like all other 32-bit RISCs that use 32-bit fixed-width instruction words) can't fit a 32-bit address as an immediate into a single instruction either: there'd be no room for an opcode to say what instruction it is.
The width of an instruction limits the number of registers you can have. With 3 registers per instruction (dst, src1, src2), AArch64's increase from 16 to 32 registers means that each instruction needs 3 * log2(32) = 3* 5
= 15 bits to encode the registers. Or fewer for instructions with only 2 or 1 registers. (e.g. mov-immediate or add-immediate). The rest of the space goes to number of possible opcodes, and the size of immediates.
To get an address into a register, ARM compilers will typically load it from a nearby pool of constants (with a PC-relative addressing mode).
The other option is what most RISC CPUs do: use a 2-instruction sequence to put a 16-bit immediate in the upper half of a register, then OR a 16-bit immediate into the low half. (Or use the lower half of a static address as the displacement to a load/store instruction that uses an addressing mode like register + 16-bit offset.)
MIPS is a good example of a very simple RISC, see it's ISA with binary encoding. Its lui reg, imm16
puts imm16 <<16
into a register. (Load Upper Immediate). Then lw dst, imm16(base_reg)
is a load like I was talking about in the last paragraph.
Even in 64-bit code, most numbers are still small, so there's not much need for wider immediate operands (except for addresses). e.g. x86 still uses a choice of 32-bit or 8-bit immediate operands for add r64, imm
. x86 being a variable length ISA saves space when immediates are between -128
and +127
in a lot of cases.

- 328,167
- 45
- 605
- 847
-
Okay, so in the second part you talk about the principle of displacement? (http://web.eng.fiu.edu/watsonh/EEL4709/PresentsSu11/Group4Chapt11.pptx) – SuperTasche Nov 06 '17 at 19:20
You could have a 4-bit CPU that operates on 4096 bit values, it just wouldn't be terribly fast at doing it. Any programming language with a "bignum" type will work this way, though usually not to the same extreme.
The way a 32-bit CPU can operate on 64-bit values is because the hardware or software allows it, no other reason.
It's not like we couldn't manipulate 64-bit integer values before we had 64-bit CPUs. Even the old Intel 80386 could support 64-bit operations and it was released in 1985.

- 208,517
- 23
- 234
- 262
-
Are you talking about x87 `fild` of a 64-bit integer? Other than using x87 or MMX/SSE2, 32-bit x86 can only do 64-bit integers with extended precision stuff like add/adc. (Using half as many operations for add/sub as 16-bit code, though). Producing a 64-bit full result from a 32x32 multiply doesn't quite count as a 64-bit operation, IMO, but it does make 64x64 => 64bit multiply *much* more efficient than for a 16-bit CPU. – Peter Cordes Nov 06 '17 at 18:24
-
It might be ugly, it might be inefficient, but it can be done. 64-bit CPUs just handle it a lot better, but some more modern 32-bit CPUs have 64-bit math instructions since `long long` type values are more prevalent these days than in the 1980s. Even modern 64-bit CPUs often manipulate values in excess of 64-bits: SIMD manipulates 256-bit values and floating point can easily be 80-bits. The size of the instructions, the instruction set, or the default register size has little to do with it. – tadman Nov 06 '17 at 18:33