Search code examples
assemblyfloating-pointmipscpu-registersfpu

"Odd FP register number" error when using double precision


I am trying to write a program, however I cannot understand why I cannot find out why I keep getting this error "Odd FP register number", I know it is from load double in main but I don't know how to fix it

#Interest Calculator
.data
STR_PRINCIPAL_INPUT: .asciiz "Enter the principal in $ (100 - 1,000,000.00): "
STR_INVALID_PRINCIPAL: .asciiz "The entered Principal is invalid."
HUNDRED: .float 100.00
NEW_LINE:    .asciiz "\n"
.text
.globl main

main:
    l.d $f2, HUNDRED

principal_input:
    li    $v0, 4                          # system call no. 4
    la    $a0, STR_PRINCIPAL_INPUT        # point to the message
    syscall
    li    $v0, 5                          # system call no. 6
    syscall
    c.eq.d $f1, $f0
    bc1t invalid_principal_input

invalid_principal_input:
    li    $v0, 4                          # system call no. 4
    la    $a0, STR_INVALID_PRINCIPAL      # point to the message
    syscall

Solution

  • MIPS has 32 floating point registers, but they are each only 32 bits wide.  Each register alone can hold a single precision float.

    However, the double precision data type takes 64 bits.  So, when you use a double it occupies 2 floating point registers — for example, $f0 & $f1 pair to store one 64-bit double precision value.  For double precision, there are effectively only 16 registers.

    MIPS then also has a rule that you cannot use the odd numbered registers to make a register pair to hold a double, which is a rule the hardware has to make it simpler for the hardware.  Adding 1 to an even register number means simply flipping the low bit, whereas adding 1 to an odd register number would require a 5-bit adder.  Further, this rule imposes virtually no runtime penalty — it would be hard to create a program where this restriction would have an effect on performance.  So, the only downside is for those learning assembly.

    In short: use even numbered registers for doubles, and avoid use of the succeeding odd register number, since that is also used for that double.

    I recommend sticking to the even registers for certain programming tasks — sometimes single float doesn't give sufficient precision, and we want to take that code to double to see if that helps — converting code from using single to using double is simpler if you don't also have to change register numbers.