首页 随笔 乐走天涯 程序资料 评论中心 Tag 论坛 其他资源 搜索 联系我 关于 RSS

MMX技术开发者手册:第五章 MMX™的编码技术(二)


日期: 2000-06-12 14:00 | 联系我 | 关注我: Telegram, Twitter

5.6 含有一个常数的复数乘法

 

  复数的乘法由四个乘法和两个加法构成。PMADDWD正是这样的指令。为了使用该指令,仅需将数据格式化为四个16位值。每个实部和虚部值应为16位值。

  令输入数据为Dr和Di

    这里 Dr=数据的实部

       Di=数据的虚部

  将复数的常系数格式化为内存中的四个16位值[Cr -Ci Ci Cr]。

  记住使用MOVQ指令将值取出送到MMX™寄存器中。

  输入:

MM0: 由Dr,Di构成的复数

MM1: 在格式[Cr -Ci Ci Cr]中的常复数系数

 

  输出:

MM0: 包含[Pr Pi]的两个32位双字复数,

其实部是由Pr=Dr*Cr-Di*Ci生成,

复数的虚部是由Pi=Dr*Ci+Di*Cr生成。

PUNPCKLDQ MM0,MM0 ;生成[Dr Di Dr Di]

PMADDWD MM0,MM1 ;结果为[(Dr*Cr-Di*Ci)(Dr*Ci+Di*Cr)]

 

  注意,输出为一个字组。如果需要,可用一条成组指令将结果转换为16位值(与输入格式匹配)。

5.7 无符号数差值的绝对值

 

  本例计算两个无符号数差值的绝对值。假设是一个无符号字节组数据类型。这里,我们使用无符号饱和模式下的减法指令。指令按无符号饱和方式将无符号操作数相减。仅支持字节组和字组,不支持双字组。

  输入:

MM0: 源操作数

MM1: 源操作数

 

  输出:

MM0: 无符号数差值的绝对值

MOVQ MM2, MM0 ;制做MMO的备份

PSUBSB MM0, MM1 ;计算差值方法1

PSUBSB MM1, MM2 ;计算差值方法2

POR MM0, MM1 ;将两个差值求或

 

  如果操作数有符号,本例不执行。有关有符号差值的绝对值请见下一个例子。

5.8 有符号数差值的绝对值

 

  本例计算两个有符号数差值的绝对值。MMX™指令中没有按无符号饱和方式对有符号操作数进行减法的操作。这里使用的技巧是,先将两个输入的操作数的对应元素按大小排序,生成一个较大的字组数据和一个较小的字组数据。然后,用较大的值减去较小的值,就生成了所要求的差值的绝对值。关键是由B=XOR(A,XOR(A,B))和A=XOR(A,0)构成的快速排序技术。然后在成组数据类型中,使某些元素为XOR(A,B),某些为0,你可以将这一操作数与A进行XOR操作,并在某些地方生成A,某些地方生成B。下例假设一个字组数据类型,每个元素为一个有符号数值。

  输入:

MM0: 有符号源操作数

MM1: 有符号源操作数

 

  输出:

MM0: 有符号数的差值的绝对值

MOVQ MM2, MM0 ;制做源操作数1的备份(A)

PCMPGTW MM0, MM1 ;取得源操作数1>源操作数2的标志

MOVQ MM4, MM2 ;制做源操作数A的另一个备份

PXOR MM2, MM1 ;生成交换操作XOR(A,B)的中间值

PAND MM2, MM0 ;生成0s和XOR(A,B)元素的标志

;当A>B为值XOR(A,B),当A<=B为值0

MOVQ MM3, MM2 ;生成交换掩码的备份

PXOR MM4, MM2 ;XOR(A,swap mask)为较小值

PXOR MM1, MM3 ;XOR(B,swap mask)为较大值

PSUBW MM1, MM4 ;差值的绝对值=较大值-较小值

5.9 绝对值

 

  当X为有符号数时,计算|X|。下例假设操作数为有符号字。

  输入:

MM0: 有符号源操作数

 

  输出:

MM1: ABS(MM0)

MOVQ MM1, MM0 ;备份X

PSRAW MM0, 15 ;复制符号位(是双字则用31位)

PXOR MM0, MM1 ;如负数则取1的补码

PSUBS MM1, MM0 ;如为负数则加1

 

  注意 最大的负数(即16位的8000H)所求的绝对值不正确,但该代码对这种情况也是合理的,它使减一的结果为7fffH。

5.10 有符号数截取到任意有符号区域[HIGH,LOW]

 

  本例说明了如何将一个有符号值截取到有符号区域[HIGH,LOW]。特别是当值小于LOW或大于HIGH时,截取到相应的LOW或HIGH中。本技术按无符号饱和方式进行成组数据加和成组数据减指令,该技术只能用于字节组和字组数据类型。

  下例使用了最大成组数和最小成组数。

  下例显示了对字数据值的操作。为简便起见,使用下列常数(在对字节值操作时,使用相应的常数)。

PACKED_MAX=0x7FFF7FFF7FFF7FFF

PACKED_MIN=0x8000800080008000

PACKED_LOW包含了由LOW值构成的、字组数据类型中的全部4个字。

PACKED_HIGH包含了由HIGH值构成的、字组数据类型中的全部4个字。

PACKED_USMAX为全1。

HIGH_US将HIGH值加到PACKED_MIN中的全部元素上。

LOW_US将LOW值加到PACKED_MIN中的全部元素上。

 

  本例显示了对字数据值的操作。

  输入:

MM0: 有符号源操作数

 

  输出:

MM0: 按无符号区域[HIGH,LOW]截取的有符号操作数

PADD MM0, PACKED_MIN ;非饱和方式相加并转换为无符号数

PADDUSW MM0, (PACKED_USMAX-HIGH_US)

;截取HIGH

PSUBUSW MM0, (PACKED_USMAX-HIGH_US+L0W_US)

;截取到LOW

PADDW MM0, PACKED_LOW ;取消前两个偏移量

 

  上述代码先将值转换为无符号数,然后将它们截取到一个无符号区域。最后一条指令将数据转换为有符号数据,并置于有符号区域中。当数据(HIGH-LOW)<0x8000时,将数据转换为无符号数的结果是正确的。

  如果(HIGH-LOW)>=0x8000,算法应按下面所示进行简单修改。

MM0: 有符号源操作数

 

  输出:

MM0: 按无符号区域[HIGH,LOW]截取的有符号操作数

PADDSSW MM0, (PACKED_USMAX-HIGH_US) ;截取HIGH

PSUBSSW MM0, (PACKED_USMAX-PACKED_HIGH+PACKED_LOW)

;截取到LOW

PADDW MM0, LOW ;取消前两个偏移量

 

  如果已知(HIGH-LOW)>=0x8000,本算法则省下一个时钟周期。为了了解为什么在(HIGH-LOW)<0x8000时,这个由三条指令构成的算法不能工作,注意0xFFFF减任何小于0x8000的数都将产生一个在数量级上大于负数0x8000的数。当PSUBSSW MM0, (0xFFFF-HIGH+LOW)(三行算法的第二条指令)被执行时,一个负数将被减,造成MM0中的值不减反加,这样就产生了一个不正确的结果。

5.11 无符号数截取到任意无符号区域[HIGH,LOW]

 

  本例说明了如何将一个无符号数截取到无符号区域[HIGH,LOW]。如果数据小于LOW或者大于HIGH,那么截取到对应的LOW或HIGH中。本技术按无符号饱和方式进行成组数据加和成组数据减指令,该技术只能用于字节组和字组数据类型。

  下例显示了对字数据值的操作。

  输入:

MM0: 无符号源操作数

 

  输出:

MM0: 按无符号区域[HIGH,LOW]截取的无符号操作数

PADDUSW MM0, 0xFFFF-HIGH ;截取到HIGH

PSUBUSW MM0, (0xFFFF-HIGH+LOW) ;截取到LOW

PADDW MM0, LOW ;取消前两个偏移量

5.12 常数生成

 

  在MMX™指令集中不存在能够将立即数常数取到MMX™寄存器的指令。下列代码段用于生成MMX™寄存器中的常用常数。当然,也可以将常数作为内存中的局域变量。但是如果要这样做,就要在内存中进行数据的复制,以便可用MOVQ指令读取。

  在MM0中产生0:

    PXOR   MM0, MM0

  在MM1中产生全1数,每个成组数据类型字段为-1

    PCMPEQ  MM1, MM1

  为每个字节组[或成组字](或双字组)字段产生常数1

    PXOR   MM0, MM0

    PCMPEQ  MM1, MM1

    PSUBB   MM0, MM1 [PSUBW  MM0, MM1] (PSUBD  MM0, MM1)

  在每个字组(或双字组)中生成有符号常数2n-1

    PCMPEO  MM1, MM1

    PSRLW   MM1, 16-n (PSRLD  MM1, 32-n)

  在每个字组(或双字组)字段中生成有符号常数-2n

    PCMPEO  MM1, MM1

    PSLLW   MM1, n  (PSLLD  MM1, n)

  由于MMX™指令集不支持字节的移位指令,2n-1和-2n只与字组和双字组相关。

标签: MMX 优化

 文章评论

第 1 楼  发表于 2009-10-19 16:17 | vêtements femmes 的所有评论
在你这里学到了很多东西都很实用,谢谢了

共有评论 1 条, 显示 1 条。

发表你的评论
如果你想针对此文发表评论, 请填写下列表单:
姓名: * 必填 (Twitter 用户可输入以 @ 开头的用户名, Steemit 用户可输入 @@ 开头的用户名)
E-mail: 可选 (不会被公开。如果我回复了你的评论,你将会收到邮件通知)
反垃圾广告: 为了防止广告机器人自动发贴, 请计算下列表达式的值:
2 x 4 + 4 = * 必填
评论内容:
* 必填
你可以使用下列标签修饰文字:
[b] 文字 [/b]: 加粗文字
[quote] 文字 [/quote]: 引用文字

 
首页 随笔 乐走天涯 猎户星 Google Earth 程序资料 程序生活 评论 Tag 论坛 资源 搜索 联系 关于 隐私声明 版权声明 订阅邮件

程序员小辉 建站于 1997 ◇ 做一名最好的开发者是我不变的理想。
Copyright © XiaoHui.com; 保留所有权利。