Reverse Engineering for Beginners

(avery) #1

CHAPTER 17. FLOATING-POINT UNIT CHAPTER 17. FLOATING-POINT UNIT


17.5.6 MIPS.


MIPS can support several coprocessors (up to 4), the zeroth of which is a special control coprocessor, and first coprocessor is
the FPU.


As in ARM, the MIPS coprocessor is not a stack machine, it has 32 32-bit registers ($F0-$F31):C.1.2 on page 900. When one
needs to work with 64-bitdoublevalues, a pair of 32-bit F-registers is used.


Listing 17.6: Optimizing GCC 4.4.5 (IDA)

f:
; $f12-$f13=A
; $f14-$f15=B
lui $v0, (dword_C4 >> 16) ;?
; load low 32-bit part of 3.14 constant to $f0:
lwc1 $f0, dword_BC
or $at, $zero ; load delay slot, NOP
; load high 32-bit part of 3.14 constant to $f1:
lwc1 $f1, $LC0
lui $v0, ($LC1 >> 16) ;?
; A in $f12-$f13, 3.14 constant in $f0-$f1, do division:
div.d $f0, $f12, $f0
; $f0-$f1=A/3.14
; load low 32-bit part of 4.1 to $f2:
lwc1 $f2, dword_C4
or $at, $zero ; load delay slot, NOP
; load high 32-bit part of 4.1 to $f3:
lwc1 $f3, $LC1
or $at, $zero ; load delay slot, NOP
; B in $f14-$f15, 4.1 constant in $f2-$f3, do multiplication:
mul.d $f2, $f14, $f2
; $f2-$f3=B*4.1
jr $ra
; sum 64-bit parts and leave result in $f0-$f1:
add.d $f0, $f2 ; branch delay slot, NOP


.rodata.cst8:000000B8 $LC0: .word 0x40091EB8 # DATA XREF: f+C
.rodata.cst8:000000BC dword_BC: .word 0x51EB851F # DATA XREF: f+4
.rodata.cst8:000000C0 $LC1: .word 0x40106666 # DATA XREF: f+10
.rodata.cst8:000000C4 dword_C4: .word 0x66666666 # DATA XREF: f


The new instructions here are:



  • LWC1 loads a 32-bit word into a register of the first coprocessor (hence “1” in instruction name). A pair of LWC1
    instructions may be combined into a L.D pseudoinstruction.

  • DIV.D, MUL.D, ADD.D do division, multiplication, and addition respectively (“.D” in the suffix stands for double precision,
    “.S” stands for single precision)


There is also a weird compiler anomaly: theLUIinstructions that we’ve marked with a question mark. It’s hard for me to
understand why load a part of a 64-bit constant ofdoubletype into the $V0 register. These instruction have no effect. If
someone knows more about it, please drop an email to author^11.


17.6 Passing floating point numbers via arguments.


#include <math.h>
#include <stdio.h>


int main ()
{
printf ("32.01 ^ 1.54 = %lf\n", pow (32.01,1.54));


return 0;
}


(^11) dennis(a)yurichev.com

Free download pdf