天衣有缝

冠盖满京华,斯人独憔悴~
posts - 35, comments - 115, trackbacks - 0, articles - 0
   :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

fpu, mmx及sse的一些 介绍(原创)

Posted on 2007-04-18 15:57 天衣有缝 阅读(4556) 评论(2)  编辑 收藏 引用 所属分类: program
为什么要需要FPU和MMX/SSE?
提供了SIMD环境(single instruction multi data),即单指令多数据。
内嵌浮点运算单元,64及128位寄存器等。甚至sin/cos等数学函数也囊括其中,
著名的xvid项目就是使用gcc编译后使用MMX/SSE优化汇编的典型案例。

转载请注明原创:http://www.cppblog.com/jinglexy
msn and mail: jinglexy at yahoo dot com dot cn 上海体育馆2007.4.18

FPU: 8个80位浮点寄存器(数据),16位状态寄存器,16位控制寄存器,16为标识寄存器。
     使用FPU指令对这些寄存器进行操作,这些寄存器构成一个循环栈,st7栈底,st0栈顶,
     当一个值被压入时,被存入st0,原来st0中的值被存入st7
MMX: 将8个FPU寄存器重命名为8个64位MMX寄存器,即mm0到mm7。
     57条MMX指令,加快了整形浮点运算,但是对于复杂浮点运算无帮助

SSE: 8个128位寄存器(从xmm0到xmm7),MXSCR寄存器,EFLAGS寄存器,专有指令(复杂浮点运算)
SSE2: 寄存器和SSE相同,增加了5种数据类型(都是128位),专有指令
SSE3: 仅增加了几个新的指令

由于MMX使用的寄存器影射到FPU寄存器上,所以MMX指令执行前,需要保存FPU堆栈。

示例1,FPU寄存器及指令使用(下面所有程序都使用at&t风格汇编):
data1:
        .byte 0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
data2:
        .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.section .text
.globl _start
_start:
        nop
        fbld  data1     压入st0
        fimul data2     st0中的值和data2相乘,保存在st0中
        fbstp data1     st0弹出到内存44


示例2, SSE寄存器及指令使用
.lcomm data 16
value1:
        .float 12.34, 2345.543, -3493.2, 0.44901
value2:
        .float -54439.234, 23231.4, 1.0098, 0.000003
.section .text
.globl _start
_start:
        movups value1, %xmm0
        movups value2, %xmm1
        movups %xmm0, %xmm2
        movups %xmm0, data


Feedback

# re: fpu, mmx及sse的一些 介绍(原创)  回复  更多评论   

2008-02-19 14:47 by 海枫
你好,我最近也在看FPU的资料(Intel CPU的官方文档)

想向你请教一下:
FPU,SEE和MMX是不是有重叠的部分呢?

在Intel CPU下的GCC对于浮点计算部分代码是不是转换上只用FPU的指令呢?
下面是我在Linux下跑的一个例子,前一部分代码是C源代码,后一部分代码是GCC处理后的相应汇编代码,我发现里面只有涉及FPU的东西,而没有MMX和SEE。

ylin@ylin:~/program/c$ cat double.c

double sum(double s1, double s2)
{
int i = 1;
double c = 3.0;
c += s1;
c += s2;
c += i;

return c;
}


void test()
{
sum(1.0, 2.0);
}
ylin@ylin:~/program/c$ cat double.s
.file "double.c"
.section .rodata
.align 8
.LC0:
.long 0
.long 1074266112
.text
.globl sum
.type sum, @function
sum:
pushl %ebp
movl %esp, %ebp
subl $32, %esp
movl 8(%ebp), %eax
movl %eax, -24(%ebp)
movl 12(%ebp), %eax
movl %eax, -20(%ebp)
movl 16(%ebp), %eax
movl %eax, -32(%ebp)
movl 20(%ebp), %eax
movl %eax, -28(%ebp)
movl $1, -4(%ebp)
fldl .LC0
fstpl -16(%ebp)
fldl -16(%ebp)
faddl -24(%ebp)
fstpl -16(%ebp)
fldl -16(%ebp)
faddl -32(%ebp)
fstpl -16(%ebp)
fildl -4(%ebp)
fldl -16(%ebp)
faddp %st, %st(1)
fstpl -16(%ebp)
fldl -16(%ebp)
leave
ret
.size sum, .-sum
.section .rodata
.align 8
.LC2:
.long 0
.long 1073741824
.text
.globl test
.type test, @function
test:
pushl %ebp
movl %esp, %ebp
subl $16, %esp
fldl .LC2
fstpl 8(%esp)
fld1
fstpl (%esp)
call sum
fstp %st(0)
leave
ret
.size test, .-test
.ident "GCC: (GNU) 4.1.2 (Ubuntu 4.1.2-0ubuntu4)"
.section .note.GNU-stack,"",@progbits

# re: fpu, mmx及sse的一些 介绍(原创)[未登录]  回复  更多评论   

2008-03-19 10:44 by 补考少年
[b]原始短消息:[/b] [url=http://bbs.chinaunix.net/pm.php?action=view&folder=inbox&pmid=757158]你好![/url]
[quote]我在你的博客中有留言!!
想问你个问题!
期待你的回复!![/quote]


很抱歉,才看到你的短信
FPU,SEE和MMX是不是有重叠的部分呢?
你是说寄存器重叠吗?fpu和mmx使用相同的寄存器,名字不同,使用任意一个之前最好保存相关上下文寄存器。
sse和sse2只有比较新的cpu(pII以上)才支持,为了保证兼容性,默认编译器不会使用它。
gcc帮助中有:
i386 and x86-64 Options -mtune=cpu-type -march=cpu-type -mfp-
math=unit -masm=dialect -mno-fancy-math-387 -mno-fp-ret-in-387
-msoft-float -msvr3-shlib -mno-wide-multiply -mrtd -malign-dou-
ble -mpreferred-stack-boundary=num -mmmx -msse -msse2 -msse3
-m3dnow -mthreads -mno-align-stringops -minline-all-stringops
-mpush-args -maccumulate-outgoing-args -m128bit-long-double
-m96bit-long-double -mregparm=num -momit-leaf-frame-pointer
-mno-red-zone -mno-tls-direct-seg-refs -mcmodel=code-model -m32
-m64
就像没有fpu的时候使用libc中软浮点一样,默认gcc对一些复杂算法使用fpu指令和软件算法来解决
可以比较一下:
gcc -c double.c -o double -msse2
objdump -d double
gcc -c double.c -o double -m3dnow
objdump -d double
对优化的一些猜测:针对各个平台编译一套dll或.so(不同的编译优化选项),然后启动时判断平台,加载不同的dll

具体的我也没深入研究过,都是一知半解,希望对你有帮助

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理