全部博文(146)
分类:
2008-02-04 11:16:18
在整个文档中,‘字’指的是 32 位(4 字节)的内存。
--------------------------------------------------------------------------------
目录
处理器模式
寄存器
流水线
时序
指令
条件代码
数据处理指令
分支指令
乘法
长乘法(ARM7DM)
单一数据传送
块数据传送
软件中断
协处理器数据操作
协处理器数据传送和寄存器传送
单一数据交换(ARM 3 和以后,包括 ARM 2aS)
状态寄存器传送(ARM 6 和以后)
未定义指令
贡献
--------------------------------------------------------------------------------
处理器模式
ARM 有一个用户模式和多个有特权的超级用户模式。它们是:
IRQ
在触发中断请求(IRQ)时进入。
FIQ
在触发快速中断请求(FIQ)时进入。
SVC
在指令一个软件中断(SWI)时进入。
Undef
在执行了一个未定义的指令时进入(不存在于 ARM 2 和 3,在这里进入 SVC 模式)。
Abt
在一个内存访问尝试被内存管理器(例如,MEMC 或 MMU)所终止时进入,通常因为所做的尝试要访问不存在的内存或者在没有充足特权的模式下访问内存(不存在于 ARM 2 和 3,在这里进入 SVC 模式)。
在每种情况下还调用适当的硬件向量。
--------------------------------------------------------------------------------
寄存器
ARM 2 和 3 有 27 个 32 位处理器寄存器,在任何给定时间只有其中的 16 个是可见的(是哪十六个取决于处理器模式)。它们被引用为 R0-R15。
ARM 6 和以后有 31 个 32 位处理器寄存器,在任何给定时间只有其中的 16 个是可见的。
R15 特别重要。在 ARM 2 和 3,其中的 24 位用做程序计数器,而余下的 8 位用于保持处理器模式、状态标志和中断模式。所以 R15 经常被称做 PC。
R15 = PC = NZCVIFpp pppppppp pppppppp ppppppMM
位 0-1 和 26-31 被称为 PSR (处理器状态寄存器)。位 2-25 给出被取回到指令流水线中的当前指令的(以字为单位)地址 (见后)。所以永远只能从字对齐的地址执行指令。
M 当前处理器模式
0 用户模式
1 快速中断处理模式(FIQ 模式)
2 中断处理模式(IRQ 模式)
3 超级用户模式(SVC 模式)
名字 意思
N 负数(Negative)标志
Z 零(Zero)标志
C 进位(Carry)标志
V 溢出(oVerflow)标志
I 中断(Interrupt)请求禁用
F 快速(Fast)中断请求禁用
R14、R14_FIQ、R14_IRQ、和 R14_SVC 由于它们在带连接的分支指令期间的行为而有时被称为‘连接’寄存器。
ARM 6 和以后的处理器核心支持 32 位地址空间。这些处理可以在 26 为和 32 位 PC 模式二者下操作。 在 26 位 PC 模式下,R15 表现如同在以前的处理器上,所以代码只能运行在地址空间的最低的 64M 字节中。在 32 位 PC 模式下,R15 所有 32 位用做程序计数器。使用独立的状态寄存器来存储处理器模式和状态标志。PSR 定义如下:
NZCVxxxx xxxxxxxx xxxxxxxx IFxMMMMM
注意在 32-bit 模式下 R15 的底端两位总是零 - 就是说你仍然只能得到字对齐的指令。忽略对这两位写非零的任何尝试。
当前定义了下列模式:
M 名字 意思
00000 usr_26 26 位 PC Usr 模式
00001 fiq_26 26 位 PC FIQ 模式
00010 irq_26 26 位 PC IRQ 模式
00011 svc_26 26 位 PC SVC 模式
10000 usr_32 32 位 PC Usr 模式
10001 fiq_32 32 位 PC FIQ 模式
10010 irq_32 32 位 PC IRQ 模式
10011 svc_32 32 位 PC SVC 模式
10111 abt_32 32 位 PC Abt 模式
11011 und_32 32 位 PC Und 模式
推测自上面的表,可能期望还定义了下列两个模式:
M 名字 意思
00111 abt_26 26 bit PC Abt Mode
01011 und_26 26 bit PC Und Mode
实际上未定义它们(如果你确实向模式位写了 00111 或 01011,结果的芯片状态不会是你所希望的 - 就是说不会是有适当的 R13 和 R14 被交换进来的一个 26-bit 特权模式。
下表展示在每个处理器模式下可获得那些的寄存器:
+------+---------------------------------------+
| 模式 | 可获得的寄存器 |
+------+---------------------------------------+
| USR | R0 - R14 R15 |
+------+---------+-----------------------------+
| FIQ | R0 - R7 | R8_FIQ - R14_FIQ R15 |
+------+---------+----+------------------------+
| IRQ | R0 - R12 | R13_IRQ - R14_IRQ R15 |
+------+--------------+------------------------+
| SVC | R0 - R12 | R13_SVC - R14_SVC R15 |
+------+--------------+------------------------+
| ABT | R0 - R12 | R13_ABT - R14_ABT R15 | (ARM 6 和以后)
+------+--------------+------------------------+
| UND | R0 - R12 | R13_UND - R14_UND R15 | (ARM 6 和以后)
+------+---------------------------------------+
在 ARM6 和以后的处理器上有六个状态寄存器。一个是当前处理器状态寄存器(CPSR),持有关于当前处理器状态的信息。其它五个是保存的程序状态寄存器(SPSR): 每个特权模式都有一个,持有完成在这个模式下的例外处理时处理器必须返回的关于状态的信息。
分别使用 MSR 和 MRS 指令来设置和读取这些寄存器。
--------------------------------------------------------------------------------
流水线
不同于微编码的处理器,ARM (保持它的 RISC 性)是完全硬布线的。
为了加速 ARM 2 和 3 的执行使用 3 阶段流水线。第一阶段持有从内存中取回的指令。第二阶段开始解码,而第三阶段实际执行它。故此,程序计数器总是超出当前执行的指令两个指令。(在为分支指令计算偏移量时必须计算在内)。
因为有这个流水线,在分支时丢失 2 个指令周期(因为要重新添满流水线)。所以最好利用条件执行指令来避免浪费周期。例如:
...
CMP R0,#0
BEQ over
MOV R1,#1
MOV R2,#2
over
...
可以写为更有效的:
...
CMP R0,#0
MOVNE R1,#1
MOVNE R2,#2
...
--------------------------------------------------------------------------------
时序
ARM 指令在时序上是 S、N、I 和 C 周期的混合。
S 周期是 ARM 在其中访问一个顺序的内存位置的周期。
N 周期是 ARM 在其中访问一个非顺序的内存位置的周期。
I 周期是 ARM 在其中不尝试访问一个内存位置或传送一个字到/从一个协处理器的周期。
C 周期是 ARM 在其中与一个协处理器之间在数据总线(对于无缓存的 ARM)或协处理器总线(对于有缓存的 ARM)上写传送一个字的周期。
各种类型的周期都必须至少与 ARM 的时钟周期一样长。内存系统可以伸展它们: 对于典型的 DRAM 系统,结果是:
N 周期变成最小长度的两倍(主要因为 DRAM 在内存访问是非顺序时要求更长的访问协议)。
S 周期通常是最小长度,但偶尔也会被伸展成 N 周期的长度(在你从一个内存“行”的最后一个字移动到下一行的第一个字的时候[1])。
I 周期和 C 周期总是最小长度。
对于典型的 SRAM 系统,所有类型的周期典型的都是最小长度。
在 Acorn Archimedes A440/1 使用的 8MHz ARM2 中,一个 S (顺序) 周期是 125ns 而一个 N (非顺序) 周期是 250ns。应当注意到这些时序不是 ARM 的属性,而是内存系统的属性。例如,一个 8MHz ARM2 可以与一个给出 125ns 的 N 周期的 RAM 系统相连接。处理器的速率是 8MHz 只是简单的意味着如果你使任何类型的周期在长度上小于 125ns 则它不保证能够工作。
有缓存的处理器: 所有给出的信息依据 ARM 所见到的时钟周期。它们不按固定的速率发生: 缓存控制逻辑在 cache 不中的时候改变提供给 ARM 的时钟周期来源。
典型的,有缓存的 ARM 有两个时钟输入: “快速时钟” FCLK 和“内存时钟”MCLK。 在 cache 命中的时候,ARM 的时钟使用 FCLK 的速度并且所有类型的周期都是最小的长度: 从这点上看 cache 在效果上是某种 SRAM。在 cache 不中发生的时候,ARM 的时钟同步为 MCLK,接着以 MCLK 速度进行 cache 行添充(依赖于在处理器中涉及的 cache 行的长度使用 N+3S 或 N+7S 个周期),接着 ARM 的时钟被同步回到 FCLK。
在发生内存访问的时候,ARM 将守时操作(be clocked): 但是,可以使用一个叫 NWAIT 的输入来导致涉及到的 ARM 周期不做任何事情,直到正确的字从内存中到来,并在仍有余下的字到来的时候通常不做任何事情(为了避免在 cache 仍忙于重新填充 cache 行的时候得到进一步的内存请求)。有缓存的 ARM 可以被配置成使用 FCLK 和 MCLK 来相互同步(所以 FCLK 是准确的 MCLK 倍数,并且每个 MCLK 时钟周期与一个 FCLK 周期同时开始)或异步的(这种情况下 FCLK 和 MCLK 周期相互之间可以有任何关系)使情况更加复杂。
情况非常复杂。这些行为的近似的描述是,在一个 cache 行不中发生的时候,它所涉及的周期耗用以 MCLK 周期为单位的 cache 行重填充时间(例如,N+3S 或 N+7S),对于 N 周期和 S 周期可能按 DRAM 所描述的那样被伸展,加上一些更多的周期用于重新同步阶段。要得到详情,你需要得到所涉及的处理器的 datasheet。
脚注 1: 内存控制器意图使用这个简单的策略: 如果请求一个 N 周期,则把访问作为不在同一行来对待;如果请求一个 S 周期,除非它效果上是这行的最后一个字(可以被快速检测出来),否则把访问作为同行来对待。结果是一些 S 周期将持续与 N 周期相同的时间;如果我记得正确,在 Archimedes 上 S 周期所访问的内存被按 16 字节来分开。对于 Archimedes 代码的实际后果是: (a) 大约 4 个 S 周期中的 1 个变成一个 N 周期,为此,所有地址都是字地址并按 4 来分开;(b) 有时值得仔细关照对齐代码来避免这种效果并得到一些额外的性能。)
--------------------------------------------------------------------------------
指令
每个 ARM 指令都是 32 位宽,下面给出详细的解释。对于每个指令类,我们给出指令位图(bitmap),和典型汇编器使用的语法的例子。
一定要注意助记符的语法不是固定的;它是汇编器的特性,而不是 ARM 机器编码的。
条件代码
每个指令的顶端部分是一个条件代码,所以可以有条件的运行每个单一的 ARM 指令。
条件
指令位图 编号 条件代码 所须标志:
0000xxxx xxxxxxxx xxxxxxxx xxxxxxxx 0 EQ(等于,Equal) Z
0001xxxx xxxxxxxx xxxxxxxx xxxxxxxx 1 NE(不等于,Not Equal) ~Z
0010xxxx xxxxxxxx xxxxxxxx xxxxxxxx 2 CS(进位设置,Carry Set) C
0011xxxx xxxxxxxx xxxxxxxx xxxxxxxx 3 CC(进位清除,Carry Clear) ~C
0100xxxx xxxxxxxx xxxxxxxx xxxxxxxx 4 MI(负号,MInus) N
0101xxxx xxxxxxxx xxxxxxxx xxxxxxxx 5 PL(正号,PLus) ~N
0110xxxx xxxxxxxx xxxxxxxx xxxxxxxx 6 VS(溢出设置,oVerflow Set) V
0111xxxx xxxxxxxx xxxxxxxx xxxxxxxx 7 VC(溢出清除,oVerflow Clear) ~V
1000xxxx xxxxxxxx xxxxxxxx xxxxxxxx 8 HI(高于,HIgher) C and ~Z
1001xxxx xxxxxxxx xxxxxxxx xxxxxxxx 9 LS(低于或同于,Lower or Same) ~C and Z
1010xxxx xxxxxxxx xxxxxxxx xxxxxxxx A GE(大于等于,Greater or equal)N = V
1011xxxx xxxxxxxx xxxxxxxx xxxxxxxx B LT(小于,Less Than) N = ~V
1100xxxx xxxxxxxx xxxxxxxx xxxxxxxx C GT(大于,Greater Than) (N = V) and ~Z
1101xxxx xxxxxxxx xxxxxxxx xxxxxxxx D LE(小于等于,Less or equal) (N = ~V) or Z
1110xxxx xxxxxxxx xxxxxxxx xxxxxxxx E AL(总是,Always) 永真
1111xxxx xxxxxxxx xxxxxxxx xxxxxxxx F NV(从不,Never) 永假
在多数汇编器中,插入条件代码到紧随在助记符根代码(stub)的后面;省略条件代码缺省为使用 AL。
在一些汇编器中把 HS (高于或同于) 和 LO (低于) 分别用做 CS 和 CC 的同义词。
条件 GT、GE、LT、LE 被成为有符号比较,而 HS、HI、LS、LO 被称为无符号比较。
把一个条件代码与 1 进行异或得到相反的条件的代码。
NB: ARM 废弃使用 NV 条件代码 - 假定你使用 MOV R0,R0 作为一个空指令而不是以前推荐的 MOVNV R0,R0 。将来的处理器可能重新使用 NV 条件来做其他事情。
所须条件为假的指令执行 1S 周期,使一个指令有条件执行不招致时间处罚。
数据处理指令
xxxx000a aaaSnnnn ddddcccc ctttmmmm 寄存器形式
xxxx001a aaaSnnnn ddddrrrr bbbbbbbb 立即数形式
典型的汇编语法:
MOV Rd, #0
ADDEQS Rd, Rn, Rm, ASL Rc
ANDEQ Rd, Rn, Rm
TEQP Pn, #&80000000
CMP Rn, Rm
在操作 a 下,组合 Rn 的内容和 Op2,放置结果到 Rd 中。