Floating Point Instructions

  • May 2020
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Floating Point Instructions as PDF for free.

More details

  • Words: 1,273
  • Pages: 12
CS220 April 18, 2007

Floating Point Instructions • • • • • • • • • • • • •

filds/fildl fists/fistl fbld fbst fadd fdiv fdivr fmul fsub fsubr frndint fsqrt fxch

Loads 32 bits integer into FPU Stores top reg value to 32 bits memory Loads BCD Stores BCD Floating-point addition Floating-point division Reverse floating-point division Floating-point multiplication Floating-point subtraction Reverse floating-point subtraction Rounds the value in st(0) to the nearest int Computes the square root of the value in st(0) Exchange registers

Note: FP instructions can’t use immediate number as operand, and can’t use one FP reg and one memory variable. You need to worry about s/l surffix only when dealing with memory. i.e. fadds -4(%ebp) but fadd %st(1), %st(2)

Examples •

fadds data1 –



fmull data1 –



devide the value st(0) by data1, and store in st(0)

faddp –



st(1)= st(1) - st(0)

Compare: subl %eax, %ebx %ebx=%ebx-%eax

fdivs data1 –



st(1)= st(0) - st(1)

fsubr %st(0), %st(1) –



divide st(0) by the 32-bit integer value at data1, and store in st(0)

fsub %st(0), %st(1) –



multiply the 64-bit value at data1 with the st0 register

fidiv data1 –



add the 32-bit value at data1 to the st(0) register

No operand: st(0) and st(1) One operand: st(0) omitted

Add st(0) to st(1), store the result in st(1), and pop st(0)

flds var1 flds var2 fdivp –

var2 at st(0) is divided by var1 at st(1), store in st(1) then pop, result now in st(0)

pop after operations • • • • • • •

fstp fistp faddp fsubp fmulp fdivp …

After pop: st(1) ->st(0) st(2)->st(1) … st(0)->st(7) (invalid value, can’t be used)

fld1 fldz flds var1 fldpi

faddp

fadds var2

fadd %st(0), %st(2)

(var1=1.1, var2=2.2)

st0 st1 st2 st3 st4 st5 st6 st7

3.1415926535897932385128089594061862 (raw 0x4000c90fdaa22168c235) 1.10000002384185791015625 (raw 0x3fff8ccccd0000000000) 0 (raw 0x00000000000000000000) 1 (raw 0x3fff8000000000000000) 0 (raw 0x00000000000000000000) 0 (raw 0x00000000000000000000) 0 (raw 0x00000000000000000000) 0 (raw 0x00000000000000000000)

st0 st1 st2 st3 st4 st5 st6 invalid st7

4.2415926774316511484522185249090853 0 (raw 0x00000000000000000000) 1 (raw 0x3fff8000000000000000) 0 (raw 0x00000000000000000000) 0 (raw 0x00000000000000000000) 0 (raw 0x00000000000000000000) 0 (raw 0x00000000000000000000) 3.1415926535897932385128089594061862

(raw 0x400187bb209110b4611a)

st0 st1 st2 st3 st4 st5 st6 st7

6.4415927251153669687647185249090853 0 (raw 0x00000000000000000000) 1 (raw 0x3fff8000000000000000) 0 (raw 0x00000000000000000000) 0 (raw 0x00000000000000000000) 0 (raw 0x00000000000000000000) 0 (raw 0x00000000000000000000) 3.1415926535897932385128089594061862

(raw 0x4001ce21871110b4611a)

st0 st1 st2 st3 st4 st5 st6 st7

6.4415927251153669687647185249090853 0 (raw 0x00000000000000000000) 7.4415927251153669687647185249090853 0 (raw 0x00000000000000000000) 0 (raw 0x00000000000000000000) 0 (raw 0x00000000000000000000) 0 (raw 0x00000000000000000000) 3.1415926535897932385128089594061862

(raw 0x4001ce21871110b4611a)

(raw 0x4000c90fdaa22168c235)

(raw 0x4000c90fdaa22168c235)

(raw 0x4001ee21871110b4611a)

(raw 0x4000c90fdaa22168c235)

float add(float a,float b) { return a+b; } .text .globl add .type add, @function add: pushl %ebp movl %esp, %ebp flds 8(%ebp) fadds 12(%ebp) leave ret .size add, .-add

void main() { float f1=1.1f,f2=2.2f; printf("f1 + f2 = %f\n",add(f1,f2)); }

.section .rodata .LC3: .string "f1 + f2 = %f\n" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp subl $8, %esp movl $0x3f8ccccd, %eax movl %eax, -4(%ebp) movl $0x400ccccd, %eax movl %eax, -8(%ebp) pushl -8(%ebp) pushl -4(%ebp) call add addl $8, %esp subl $8, %esp # leal -8(%esp), %esp fstpl (%esp) pushl $.LC3 call printf addl $12, %esp leave ret .size main, .-main

double mul(double a,double b) { return a*b; } .text .globl mul .type mul, @function mul: pushl %ebp movl %esp, %ebp #a: 8(%ebp) and 12(%ebp) fldl 8(%ebp) fmull 16(%ebp) #b: 16(%ebp) and 20(%ebp) leave Little Endian: ret Use lower 32-bit .size mul, .-mul address to access a 64 bits number

void main() { double d1=1.1, d2=2.2; printf("d1 + d2 = %f\n",mul(d1,d2)); }

.section .rodata .LC3: .string "f1 + f2 = %f\n" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp subl $16, %esp #d1’s high part movl $1072798105, %edx #d1’s low part movl $-1717986918, %eax movl %edx, -4(%ebp) Little Endian: movl %eax, -8(%ebp) High part high address movl $1073846681, %edx Low part low address movl $-1717986918, %eax movl %edx, -12(%ebp) movl %eax, -16(%ebp) pushl -12(%ebp) pushl -16(%ebp) #d1’s high part pushl -4(%ebp) #d1’s low part pushl -8(%ebp) call mul addl $16, %esp subl $8, %esp # leal -8(%esp), %esp fstpl (%esp) pushl $.LC3 call printf addl $12, %esp leave ret

Rounding Example •

Control reg 10–11 Rounding control 00 - round to nearest (default) 01 - round down (toward negative infinity) 10 - round up (toward positive infinity) 11 - round toward zero .section .data value1: .float 3.65 .section .bss .lcomm resultnearest, 4 .lcomm resultdown, 4 .lcomm tmp, 2 .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp

pushf push %eax finit flds value1 frndint fists resultnearest

4

fstcw tmp movw tmp, %ax andw $0b1111001111111111, %ax orw $0b0000010000000000, %ax movw %ax, tmp fldcw tmp flds value1 frndint fists resultdown 3 popl %eax popf leave ret .size main, .-main

Reverse Polish Notation (RPN) • Infix notation: x * y • RPN: x y * • Example: x = ((y-z)*a) - ( a + b * c )/3.14159 x = ([y z -] * a) - ( a + b * c )/3.14159 x = [y z - a *] - ( a + b * c )/3.14159 x = [y z - a *] - ( a + [b c *])/3.14159 x = [y z - a *] - [a b c * +]/3.14159 x = [y z - a *] - [a b c * + 3.14159 /] x = [y z - a *] [a b c * + 3.14159 /] x = y z - a * a b c * + 3.14159 / -

((43.65 / 22) + (76.34 * 3.1)) / ((12.43 * 6) – (140.2 / 94.21)) 1. 2. 3. 4.

Load 43.65 into st(0). Divide st(0) by 22, saving the results in st(0). Load 76.34 in st(0) (the answer from step 2 moves to st(1)). Load 3.1 in st(0) (the value in step 3 moves to st(1), and the answer from Step 2 moves to st(2)). 5. Multiply st(0) and st(1), leaving the answer in st(0). 6. Add st(0) and st(2), leaving the answer in st(0) (this is the left side of the equation). 7. Load 12.43 into st(0) (the answer from Step 6 moves to st(1)). 8. Multiply st(0) by 6, leaving the answer in st(0). 9. Load 140.2 into st(0) (the answer from Step 8 moves to st(1), and from Step 6 to st(2)). 10. Load 94.21 into st(0) (the answer from Step 8 moves to st(2), and from Step 6 to ST3). 11. Divide st(1) by st(0), popping the stack and saving the results in st(0) (the answer from Step 8 12. moves to st(1), and from Step 6 to st(2)). 13. Subtract st(0) from st(1), storing the result in st(0) (this is the right side of the equation). 14. Divide st(2) by st(0), storing the result in st(0) (this is the final answer).

This example comes from recommended textbook; it doesn’t really follow RPN notation

((43.65 / 22) + (76.34 * 3.1)) / ((12.43 * 6) – (140.2 / 94.21))

((43.65 / 22) + (76.34 * 3.1)) / ((12.43 * 6) – (140.2 / 94.21)) .section .data value1: .float 43.65 value2: .int 22 value3: .float 76.34 value4: .float 3.1 value5: .float 12.43 value6: .int 6 value7: .float 140.2 value8: .float 94.21 output: .string "The result is %f\n"

.text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp finit flds fidiv flds flds fmul fadd flds fimul flds flds fdivrp fsubr fdivr subl fstpl pushl call add

value1 value2 value3 value4 %st(1), %st(0) %st(2), %st(0) value5 value6 value7 value8 %st(1), %st(0) %st(2), %st(0) $8, %esp (%esp) $output printf $12, %esp

leave ret .size main, .-main

Related Documents