• CortexM0中断控制和系统控制(六)


    转载:https://aijishu.com/a/1060000000248195

    Arm处理器是基于精简指令集计算机(RISC)原理设计的,指令集和相关译码机制较为简单,具有32位Arm指令集和16位Thumb指令集,Arm指令集效率高,但是代码密度低,而Thumb指令集具有更好的代码密度,却仍然保持Arm的大多数性能上的优势,它是Arm指令集的子集。所有Arm指令都是可以有条件执行的,而Thumb指令仅有一条指令具备条件执行功能。Arm程序和Thumb程序可相互调用,相互之间的状态切换开销几乎为零。

    Cortex-M0处理器基于ARMv6-M架构,是一款功耗和性能较为均衡的处理器。Cortex-M0只支持56条指令的小指令集,其中大部分指令是16位指令。

    Arm Cortex-M 指令集对比:
     title=

    1. 指令集

    1.1 在处理器内移动数据
    MOV  <Rd>, <Rm> ;Rm and Rn can be high or low registers.
    MOVS <Rd>, <Rm>
    MOVS <Rd>, #immed8 ;8位立即数值
    
    
    
    MRS  <Rd>, <SpecialReg>
    MSR  <SpecialReg>, <Rd>
    
    1.2 存储器访问

    确保访问的内存地址是对齐的,这一点很重要。在ARMv6-M架构(包括Cortex-M0和Cortex-M0处理器)上不支持非对齐传输。任何未对齐内存访问的尝试都会导致HardFault异常。

    LDR  <Rt>,[<Rn>, <Rm>]    ; Rt = memory[Rn + Rm]
    STR  <Rt>,[<Rn>, <Rm>]    ; memory[Rn + Rm] = Rt
    LDRH <Rt>,[<Rn>, <Rm>]    ; Rt = memory[Rn + Rm]
    STRH <Rt>,[<Rn>, <Rm>]    ; memory[Rn + Rm] = Rt
    LDRB <Rt>,[<Rn>, <Rm>]    ; Rt = memory[Rn + Rm]
    STRB <Rt>,[<Rn>, <Rm>]    ; memory[Rn + Rm] = Rt
    
    
    
    LDRSH <Rt>,[<Rn>, <Rm>]   ; Rt = SignExtend(memory[Rn + Rm])
    LDRSB <Rt>,[<Rn>, <Rm>]   ; Rt = SignExtend(memory[Rn + Rm])
    
    LDR  <Rt>,[<Rn>, #immed5] ; Rt = memory[Rn + ZeroExtend (#immed5<<2)]
    STR  <Rt>,[<Rn>, #immed5] ; memory[Rn + ZeroExtend(#immed5<<2)] = Rt
    LDRH <Rt>,[<Rn>, #immed5] ; Rt = memory[Rn + ZeroExtend (#immed5<<1)]
    STRH <Rt>,[<Rn>, #immed5] ; memory[Rn + ZeroExtend(#immed5<<1)] = Rt
    LDRB <Rt>,[<Rn>, #immed5] ; Rt = memory[Rn + ZeroExtend (#immed5)]STRB <Rt>,[<Rn>, #immed5] ; memory[Rn + ZeroExtend(#immed5)] = Rt
    
    
    
    LDR  <Rt>,[SP, #immed8]   ; Rt = memory[SP + ZeroExtend(#immed8<<2)]
    STR  <Rt>,[SP, #immed8]   ; memory[SP + ZeroExtend(#immed8<<2)] = Rt
    
    
    
    LDR  <Rt>,[PC, #immed8]   ; Rt =memory[WordAligned(PC+4)+ZeroExtend(#immed8<<2)]
    LDR  <Rd>, =immed32       ; pseudo instruction translated to LDR <Rt>,[PC, #immed8]
    LDR  <Rd>, label          ; pseudo instruction translated to LDR <Rt>,[PC, #immed8]
    
    
    
    LDM <Rn>,{<Ra>, <Rb>,..} ; Load Multiple
    // Ra = memory[Rn]
    // Rb = memory[Rn + 4],
    // ...
    
    
    
    LDMIA <Rn>!, {<Ra>, <Rb>,..} ; Load Multiple Increment After
    LDMFD <Rn>!, {<Ra>, <Rb>,..}
    // Ra = memory[Rn],
    // Rb = memory[Rn + 4],
    // ...
    // and then update Rn to last read address plus 4.
    
    
    
    STMIA <Rn>!, {<Ra>, <Rb>,..} ; Store Multiple Increment After
    STMEA <Rn>!, {<Ra>, <Rb>,..}
    // memory[Rn] = Ra,
    // memory[Rn + 4] = Rb,
    // ...
    // and then update Rn to last store address plus 4.
    
    1.3 栈空间访问
    PUSH {<Ra>, <Rb>, ..}
    PUSH {<Ra>, <Rb>, .., LR}
    POP  {<Ra>, <Rb>, ..}
    POP  {<Ra>, <Rb>, .., PC}
    
    1.4 算数运算
    ADD  <Rd>, <Rm>          ; Rd = Rd + Rm. Rd, Rm can be high or low registers.
    
    
    
    ADDS <Rd>, <Rn>, <Rm>    ; Rd = Rn + Rm
    SUBS <Rd>, <Rn>, <Rm>    ; Rd = Rn – Rm
    ADDS <Rd>, <Rn>, #immed3 ; Rd = Rn + ZeroExtend(#immed3)
    SUBS <Rd>, <Rn>, #immed3 ; Rd = Rn – ZeroExtend(#immed3)
    ADDS <Rd>, #immed8       ; Rd = Rd + ZeroExtend(#immed8)
    SUBS <Rd>, #immed8       ; Rd = Rd – ZeroExtend(#immed8)
    
    
    
    ADCS <Rd>, <Rd>, <Rm>    ; Rd = Rd + Rm + Carry
    SBCS <Rd>, <Rd>, <Rm>    ; Rd = Rd – Rm – Borrow
    
    
    
    ADD  SP, SP, #immed7     ; SP = SP + ZeroExtend(#immed7<<2)
    SUB  SP, SP, #immed7     ; SP = SP – ZeroExtend(#immed7<<2)
    ADD  SP, <Rm>            ; SP = SP + Rm. Rm can be high or low register.
    
    
    
    ADD  <Rd>, SP, <Rd>      ; Rd = Rd + SP. Rd can be high or low register.
    ADD  <Rd>, SP, #immed8   ; Rd = SP + ZeroExtend(#immed8<<2)
    
    
    
    ADD  <Rd>, PC, #immed8   ; Rd = (PC[31:2]<<2) + ZeroExtend(#immed8<<2)
    ADR  <Rd>, <label>       ; pseudo instruction translated to ADD <Rd>, PC, #immed8
    
    
    
    RSBS <Rd>, <Rn>,#0       ; Rd = 0 – Rm, Reverse Subtract (negative)
    
    
    
    MULS <Rd>, <Rm>, <Rd>    ; Rd = Rd * Rm
    
    
    
    CMP <Rn>, #immed8        ; Rd – ZeroExtended(#immed8)
    CMP <Rn>, <Rm>           ; Rn – Rm
    CMN <Rn>, <Rm>           ; Rn – NEG(Rm)
    
    1.5 逻辑运算
    ANDS <Rd>, <Rd>, <Rm> ; Rd = AND(Rd, Rm)
    ORRS <Rd>, <Rd>, <Rm> ; Rd = OR(Rd, Rm)
    EORS <Rd>, <Rd>, <Rm> ; Rd = XOR(Rd, Rm)
    BICS <Rd>, <Rd>, <Rm> ; Rd = AND(Rd, NOT(Rm))
    MVNS <Rd>, <Rm>       ; Rd = NOT(Rm)
    TST  <Rn>, <Rm>       ; AND(Rn, Rm)
    
    1.6 移位和循环操作
    ASRS <Rd>, <Rm>, #immed5 ; Rd = Rm>>immed5
    LSLS <Rd>, <Rm>, #immed5 ; Rd = Rm<<#immed5
    LSRS <Rd>, <Rm>, #immed5 ; Rd = Rm>>#immed5ASRS <Rd>, <Rd>, <Rm>    ; Rd = Rd>>Rm
    LSLS <Rd>, <Rd>, <Rm>    ; Rd = Rd<<Rm
    LSRS <Rd>, <Rd>, <Rm>    ; Rd = Rd>>RmRORS <Rd>, <Rd>, <Rm>    ; Rd = Rd rotate right by Rm bits
    // Rotate_Left(Data, offset) = Rotate_Right(Data, (32-offset))
    
    1.7 展开和顺序反转操作

    这些反向指令通常用于在小端和之间转换数据大整数。

    REV <Rd>, <Rm> ; Byte-Reverse Word
    // Rd = {Rm[7:0], Rm[15:8], Rm[23:16], Rm[31:24]}
    
    
    
    REV16 <Rd>, <Rm> ; Byte-Reverse Packed Half Word
    // Rd = {Rm[23:16], Rm[31:24], Rm[7:0] , Rm[15:8]}
    
    
    
    REVSH <Rd>, <Rm> ; Byte-Reverse Signed Half Word
    // Rd = SignExtend({Rm[7:0] , Rm[15:8]})
    
    1.8 扩展操作

    它们通常用于数据类型转换。

    SXTB <Rd>, <Rm> ; Signed Extended Byte
    // Rd = SignExtend(Rm[7:0])
    
    
    
    SXTH <Rd>, <Rm> ; Signed Extended Half Word
    // Rd = SignExtend(Rm[15:0])
    
    
    
    UXTB <Rd>, <Rm> ; Unsigned Extended Byte
    // Rd = ZeroExtend(Rm[7:0])
    
    
    
    UXTH <Rd>, <Rm> ; Unsigned Extended Half Word
    // Rd = ZeroExtend(Rm[15:0])
    
    1.9 程序流控制
    B <label>       ; Branch, Branch range is ±2046 bytes of current PC
    B<cond> <label> ; Conditional Branch, Branch range is ±254 bytes of current PC
    BL <label>      ; Branch and Link, Branch range is ±16 MB of current PC
    BX <Rm>         ; Branch and Exchange
    BLX <Rm>        ; Branch and Link with Exchange
    

    条件转移指令B

     title=

    1.10 内存屏障指令

    在Cortex-M0和Cortex-M0处理器上支持内存屏障指令,从而在Cortex-M处理器和其他ARM处理器家族中提供更好的兼容性。
    //数据内存屏障,确保所有内存访问都完成
    //在新的内存访问被提交之前。

    DMB
    

    //数据同步屏障,确保所有的内存访问都完成
    //在执行下一条指令之前。

    DSB
    

    //指令同步障碍,刷新管道和
    //确保之前所有的指令都已完成
    //在执行新指令之前。

    ISB
    
    1.11 异常相关指令
    SVC <immed8> ; Supervisor call
    CPSIE I      ; Enable Interrupt (Clearing PRIMASK)
    CPSID I      ; Disable Interrupt (Setting PRIMASK)
    
    1.12 睡眠模式功能相关说明

    //等待中断,停止程序执行,直到一个中断到达,
    //如果处理器进入调试状态。

    WFI
    

    //等待事件,如果设置了内部事件寄存器,则清除
    //内部事件注册和继续执行。
    //停止程序执行,直到事件(如中断)到达
    //如果处理器进入调试状态。

    WFE
    

    //发送事件,设置本地事件寄存器并发送一个事件脉冲
    //多处理器系统中的其他微处理器。

    SEV
    
    1.13 其他说明
    NOP           ; No Operation
    BKPT <immed8> ; Break point
    YIELD         ; Execute as NOP on the Cortex-M0 processor
    

    2. 指令说明

    2.1 可访问high registers的指令

    绝大部分指令只能访问low registers,也就是只能访问R0~R7寄存器。可以访问high registers的指令只有两条,这两条指令都不更新APSR,指令没有S后缀。

    MOV  <Rd>, <Rm> ; Rm and Rn can be high or low registers.
    ADD  <Rd>, <Rm> ; Rd = Rd + Rm. Rd, Rm can be high or low registers.
    

    其它两条和SP加法有关的可以访问high registers的指令其本质是ADD指令。

    ADD  SP, <Rm>        
    ADD  <Rd>, SP, <Rd>
    
    2.2   分配临时变量的指令

    函数内的临时变量分配到堆栈,进入函数给临时变量分配空间时使用SUB指令。

    SUB  SP, SP, #immed7     ; SP = SP – ZeroExtend(#immed7<<2)
    

    退出函数释放临时变量空间时使用ADD指令。

    ADD  SP, SP, #immed7     ; SP = SP + ZeroExtend(#immed7<<2)
    

    上面两条指令的立即数只有7位,最多可以增减SP指针127个字空间,如果超过127个字,使用这条指令:

    ADD  SP, <Rm>            ; SP = SP + Rm. Rm can be high or low register.
    

    只有ADD指令,没有SUB指令,如果需要SUB,那么给Rm赋值负数即可。

    2.3 取临时变量地址的指令

    在堆栈分配了临时变量空间后,总要取得临时变量的地址才能做进一步的操作。

    ADD  <Rd>, SP, #immed8   ; Rd = SP + ZeroExtend(#immed8<<2)
    

    立即数不够,可以用寄存器。

    ADD  <Rd>, SP, <Rd>      ; Rd = Rd + SP. Rd can be high or low register.
    
    2.4 RSBS指令
    RSBS <Rd>, <Rn>, #0       ; Rd = 0 – Rm, Reverse Subtract (negative)
    

    这是倒过来的减法,常量减去寄存器值,而且常量只能是0。所以这条指令实质上就是一条取负数指令。

    Rd = 0 - Rm
    等价于:Rd = -Rm
    Rd 寄存器值等于负的 Rm 寄存器值。

  • 相关阅读:
    (SQL)如何将exec执行结果放入外面的变量中--动态sql语句
    Building and Installing ACE on Win32 with MinGW/ MSYS
    TAO和CIAO 简介
    Papervision3D 基础
    ACE网络开发中,各种Reactor实现的总结
    [转]第四期FLASH专家交流会 7月24日 广州东方国际饭店
    ACE介绍及简单服务器实例
    ACE相关资源
    Windows下用Eclipse搭建C/C++开发环境
    ACE的编译和安装,for windows、Linux
  • 原文地址:https://www.cnblogs.com/zhiminyu/p/15621143.html
Copyright © 2020-2023  润新知