Are variables of type .double stored on two registers?

Viewed 73

When I declare an integer I use the directive .word, which has 32 bits, and if I'm correct that's also the size of a register in the MIPS architecture.

Now, to my understanding, a .double should be 64 bits. Does that mean that when I load the variable into a register (lwc1), that it actually stores on two registers, like an array; or are the registers on the coprocessor twice as big?

2 Answers

It depends on the MIPS version and the hardware implementation. MIPS I and II do indeed have only 32 single floating-point registers so double values must be stored in 2 registers

However MIPS III extended the FPU register size to 64 bits, so each double variable can now be on just one register

The MIPS architecture supports two FPU register models:

  • 32-bit FPU register model: 32, 32-bit registers

    • 32-bit data types stored in any register

    • pre-Release 6: 64-bit data types stored in even-odd pairs of registers.

      In Release 6 the 32-bit register model does not support 64-bit data types (stored in even-odd pairs of registers), and 64-bit operations are required to signal the Reserved Instruction exception.

  • 64-bit FPU register model: 32, 64-bit registers, with all formats supported in a register.

In Release 1 of the Architecture, MIPS32 supported only the 32-bit FPU register model (with even-odd register pairs for 64-bit data), while MIPS64 supported only the 64-bit FPU register model.

As of Release 2 and thereafter, both MIPS32 and MIPS64 support both FPU register models. If the CP0 StatusFR bit is writable, it allows selection of the register model, whereas if this bit is read-only, it indicates which model is supported. In Release 2 and Release 3, the 32-bit FPU register model is required, while the 64-bit FPU register model is optional. In Release 5, the 64-bit FPU register model is required.

MIPS® Architecture For Programmers Volume I-A: Introduction to the MIPS32® Architecture, Revision 6.01

In fact in 64-bit FPU register model each register can store two 32-bit float values which is an early kind of modern SIMD in modern platforms. Only later real SIMD extensions were added to MIPS

Does that mean that when I load the variable into a register (lwc1), that it actually stores on two registers, like an array; or are the registers on the coprocessor twice as big?

Note that the instruction should be ldc1, lwc1 is for loading a 32-bit float.

But anyway: maybe. At the ISA level (the level that you experience when working in assembly), a double precision number is stored in two consecutive registers. Only even-numbered registers are valid to specify as target or source of a double precision operation, the odd-numbered register following it is implicitly used as well. In that sense, double precision floats are stored on two registers like an array.

On the other hand, that doesn't necessarily mean that that's a good description of how the hardware works. There are different ways to implement the same ISA. One of the ways is to literally have a monolithic array of 32 32-bit FPU registers, and literally read 2 consecutive registers from the same array for every source operand and write the result to 2 consecutive registers. But that requires doubling the number of read ports and write ports of the register file, if double precision operations are supported at the same throughput as single precision operations.

A more likely solution is implementing two banks of registers, an even bank and an odd bank, to halve the number of read ports and write ports per bank compared to the "monolithic array" configuration. It doesn't change the total number of ports, but splitting them up like that is useful: adding more ports to an SRAM array is relatively expensive, more expensive than dealing with two banks (which isn't free either since single-precision operands need to be able to come out of either bank, but that's not as bad). That way a double precision value is still stored across two registers, but not like an array, but like two entries with the same index in two separate arrays.

There are more ways to implement it. Using 64-bit registers (as you also suggested) and selecting one half of them for single-precision operands is also an option, somewhat annoying when performing a write.

Related