异常发生时,The core:
拷贝CPSR到SPSR_<mode>
设置合适的CPSR位
映射合适的banked registers
存储返回地址到LR_<mode>
设置PC为vector address。
从异常返回
从SPSR_<mode>恢复CPSR
从LR_<mode>恢复PC
所有的指令包含一个条件域,CPU以此决定是否执行他们。
未执行的指令消耗一个周期。
这样可以避免许多braches,brach会stall the pipeline (3 cycles to refill)。
为了条件的执行指令,只需要在opcode后加一个后缀即可,如
ADDEQ r0,r1,r2
默认情况下,数据处理指令(不包括测试指令)不影响条件位,使用S来更新条件位。在指令后加后缀S。如
ADDS r0,r1,r2
Branch: B{<cond>} label
Branch with Link: BL{<cond>} sub_routine_label
跳转指令的偏移是汇编器计算的:
目标指令和跳转指令的差再减8(允许pipeline)。
26位偏移右移2位,存储为24位。
跳转范围+-32MB
BL指令,将PC写入当前bank的LR。返回时,只要将LR恢复到PC即可。
MOV pc,lr
pipeline has to refill before execution continus.
表1 条件跳转指令
Branch B BAL BEQ BNE BPL BMI BCC BLO BCS BHS BVC BVS BGT BGE BLT BLE BHI BLS | Interpretation Unconditional Always Equal Not equal Plus Minus Carry clear Lower Carry set Higher or same Overflow clear Overflow set Greater than Greater or equal Less than Less or equal Higher Lower or same | Normal uses Always take this branch Always take this branch Comparison equal or zero result Comparison not equal or non‐zero result Result positive or zero Result minus or negative Arithmetic operation did not give carry‐out Unsigned comparison gave lower Arithmetic operation gave carry‐out Unsigned comparison gave higher or same Signed integer operation; no overflow occurred Signed integer operation; overflow occurred Signed integer comparison gave greater than Signed integer comparison gave greater or equal Signed integer comparison gave less than Signed integer comparison gave less than or equal Unsigned comparison gave higher Unsigned comparison gave lower or same |
ARM指令集中最大的一族。这族指令的格式相同。
包含:
算术运算指令,比较指令,逻辑运算指令,数据移动指令
记住,这是一个 load / store架构,这些指令只操作寄存器,而不是内存。
他们在两个操作数上执行特定的操作,并将结果存放到目标寄存器。
第一个操作数总是一个寄存器Rn。
第二个操作数通过barrel shifter送往ALU。
运算有:
ADD operand1+operand2 ; Add
ADC operand1+operand2+carry ; Add witch carry
SUB operand1-operand2 ; Subtract
SBC operand1-operand2+carry-1 ; Subtract with carry
RSB operand2-operand1 ; Reverse subtract
RSC operand2-operand1+carry-1 ; Reverse subtract with carry
语法:
<Operation>{<cond>}{S} Rd,Rn,Operand2
例子:
ADD r0,r1,r2
SUBGT r3,r3,#1
RSBLES r4,r5,#5
比较的唯一影响是更新条件位,因此无需设置S位。
操作有:
CMP operand1-operand2 ; Compare
CMN operand1+operand2 ; Compare nagative
TST operand1 AND operand2 ; Test
TEQ operand1 EOR operand2 ; Test equivalence
语法:
<Operation>{<cond>} Rn, Operand2
例子:
CMP r0,r1
TSTEQ r2, #5
运算有:
AND op1 AND op2
EOR op1 EOR op2
ORR op1 OR op2
ORN op1 NOR op2
BIC op1 AND not op2 [ie bit clear]
语法:
<Operation>{<cond>}{S} Rd,Rn,Operand2
例子:
AND r0,r1,r2
BICEQ r2,r3,#7
EORS r1,r3,r0
操作有:
MOV op2
MVN NOT op2
这些指令没有操作数1。
语法:
<Operation>{<cond>}{S} Rd, Op2
例子:
MOV r0,r1
MOVS r2,#10
MVNEQ r1,#0
ARM没有实际的移位指令。相反,它有一个barrel shifter,提供指令中的移位机制。
Barrel Shifter提供:
逻辑左移,LSL
逻辑右移,LSR
算术右移,ASR
循环右移,ROR
只有12位来表示立即数。8位存储常量,0-255。4位存储存储移位,移位的位数为4位值乘2,即0,2,4,30。
注意:移位是右移。
如:
MOV r0, #0x40, 26 ; => MOV R0, #0x1000
也可以直接给出数字,让汇编器计算,
MOV r0, #4096
编译器可能使用MVN,如
MOV r0, #0xffffffff ; assembles to MVN r0, #0
如果常量不能满足,则产生一个错误。
1 2 | .text MOV r0, #11111 |
编译:
1 2 3 | herbert@herbert-pc:/work/code/arm_as$ $AS mov.S -o mov.o mov.S: Assembler messages: mov.S:2: Error: invalid constant -- `mov r0,#11111' |
GNU as实现了pseudo opcodes,来支持加载任意32位数。
ldr <register>, = <expression>
as会优先生成MOV和MVN指令。如果这两个指令不能满足,常量将放在最近的literal pool,PC相对LDR指令将产生。
如
1 2 3 | .text MOV r1, #256 LDR r0, =11111 |
汇编后结果:
1 2 3 4 5 6 7 8 9 10 11 | herbert@herbert-pc:/work/code/arm_as$ $AS mov.S -o mov.o herbert@herbert-pc:/work/code/arm_as$ $OBJDUMP -d mov.o mov.o: file format elf32-littlearm Disassembly of section .text: 00000000 <.text>: 0: e3a01c01 mov r1, #256 ; 0x100 4: e51f0004 ldr r0, [pc, #-4] ; 8 <.text+0x8> 8: 00002b67 andeq r2, r0, r7, ror #22 |
0x2b67的值即为11111。
基础ARM提供2条乘法指令
乘法:
MUL{<cond>}{S} Rd,Rm,Rs ; Rd=Rm*Rs
乘加:
MLA{<cond>}{S} Rd,Rm,Rs,Rn ; Rd=Rm*Rs+Rn
注意:
Rd和Rm不能为同一个寄存器。但是Rs可以。
不能使用PC。
ARM是Load/Store架构,不支持直接在内存上进行数据处理。
ARM有3类内存操作指令
Single register data transfer (LDR/STR)
Block data transfer (LDM/STM)
Single Data Swap (SWP)
基本的指令如下:
LDR/STR/LDRB/STRB,支持32位和8位。
ARMv4提供了16位和符号扩展成32位。
LDRH/STRH/LDRSB/LDRSH
所有这些指令可以条件执行,语法:
<LDR|STR>{<cond>}{<size>} Rd, <address>
寄存器:
[r1]
寄存器加立即数偏移:
12位立即数,0-4095。
寄存器加寄存器移位偏移
偏移可以有符号 + 或者-
偏移可以被应用为:
pre-indexed addressing:在内存传输前,先自动更新base register。
post-indexed addressing:在内存传输之后,更新base register。
一些例子:
1 STR r0, [r1,#‐12] 将r1-12处内存的内容移动到r0。
2 STR r0, [r1, #-12]! 将r1减12,然后将新的r1指定内存处的内容移动到r0。
3 STR r0, [r1], #‐12 将r1处的内存移动到r0,再将r1减12。
halfword/signed halfword/signed byte
的偏移只有8位,而且寄存器偏移不能移位。
LDM/STM允许传输1到16个寄存器。
传输的寄存器可以是当前bank寄存器的任何子集。
特权模式下,可以是用户bank寄存器的任何子集,在指令前使用前缀^
base register决定内存访问的地址。
基址寄存器可在传输完成后更新,添加!
低地址内存,总是传输到低编号的寄存器
栈通常向下生长,但是ARM也支持向上生长的栈。
栈指针的值可以指向:
最后一个被占用的地址(Full stack)
下一个被占用的地址(Empty stack)
基于以上,不同的栈,使用不同的指令
STMFD / LDMFD : Full Descending stack
STMFA / LDMFA:Full Ascending stack
STMED / LDMED : Empty descending stack
STMEA / LDMEA : Empty ascending stack
ARM编译器总是使用Full descending stack。
STMFD sp!, {r0,r1,r3-r5}
Stacks and Subroutines
STMFD sp!, {r0-r12,lr}
...
LDMFD sp!,{r0-r12, pc}
如果pop指令有S位(使用^),特权模式下,则使SPSR拷贝到CPSR。
如果不是用于栈,LDM/STM支持额外的语法,类似栈:
STMIA/LDMIA:increment afer
STMIB/LDMIB:increment before
STMDA/LDMDA:decrement after
STMDB/LDMDB:decrement before
在计算机科学中,内存交换用于实现锁机制。
语法:
SWP{<cond>}{B} Rd,Rm,[Rn]
这是一个原子操作:1 将Rn内存拷贝到temp,2将Rm寄存器内容拷贝到Rn内存。3将temp拷贝到Rd
用户调用该指令,切换到supervisor模式。用于实现系统调用。