Chinaunix首页 | 论坛 | 博客
  • 博客访问: 88670
  • 博文数量: 14
  • 博客积分: 1708
  • 博客等级: 上尉
  • 技术积分: 260
  • 用 户 组: 普通用户
  • 注册时间: 2008-01-27 09:29
文章分类

全部博文(14)

文章存档

2011年(1)

2010年(13)

分类:

2010-12-07 18:26:10

PowerPC常见load/store指令中,li/lis/add/addis/lwz/ori等,总是基于符号数来执行。所以需要在一些场合需要小心使用。

先说一些PowerPC Assembly的基本知识。

PowerPC的指令总是只有32位长,而每条指令只有16位可以用来装载数据。

通常指令格式如下所示,

--------------------------------------------------------------------------
| opcode | src register | dest register | immediate value |

| 6 bits   | 5 bits         | 5 bits           | 16 bits              |

--------------------------------------------------------------------------


因为可以看出'immediate value'只有16bits,所以我们不得不分两次操作32位数到寄存器。
由此我们用下面的标识符去指定我们每次是取哪16位。

  1. @highest: Bit[48~63]
  2. @higher:Bit[32~47]
  3. @h:Bit[16~31]
  4. @l:Bit[0~15]

对于32位的PowerPC,寄存器是32位的。因为每次只能取16位,所以Bit16被看作符号,Bit0~Bit15将做sign extended。
举例来说,
        li r25, 0x80008000@l           ==> r25 = 0xffff8000
        oris r25, r25, 0x80008000@h   ==> r25 = 0xffff8000

这显然不是我们期望的结果。所以我们通常这样存储变量:
        lis     r25,0x80008000@h       ==> r25 = 0x80000000  
        ori     r25,r25,0x80008000@l   ==> r25 = 0x80008000

更多时候,我们还要访问变量,就首先要得到它的地址,例如,
        lis     r4,powersave_nap@ha
        lwz    r4,powersave_nap@l(r4)
这里又引入了“@ha”,为什么不用“@h”呢?

如果powersave_nap的地址是0xc0008000。上面的就等价于(这里用lwzu去代替lwz是为执行完后更新r25为地址,方便用simics观察):

        lis     r25, 0xc0008000@h          ==> r25 = 0xc0000000
        lwzu   r24, 0xc0008000@l(r25)     ==> r25 = 0xbfff8000 = 0xc0000000 + 0xffff8000 (本来是0x1BFFF8000,但寄存器是32bit的。)

这样我们就访问了错误的地址导致kernel陷入TLB Error Exception。当然如果有相应的TLB正好map了0xbfff8000,那我们将得到错误的值。

@ha被引入解决这个问题。它将解决sign extended的问题。

        lis     r25, 0xc0008000@ha          ==> r25 = 0xc0010000
        lwzu   r24, 0xc0008000@l(r25)      ==> r25 = 0xc0008000 = 0xc0010000 + 0xffff8000 (本来是0x1C0008000,但寄存器是32bit的。)

用@ha时,bit15将根据bit16来设置。如果bit16是1,那么bit15将被考虑为1,反之为0。这样就解决了符号数的问题。
阅读(7285) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~