LXR | KVM | PM | Time | Interrupt | Systems Performance | Bootup Optimization

ARMv7-A Coprocessor概要以及读写

 关键词:MRC/MCR/MRRC/MCRR、CP14、CP15等等。

1. ARMv7-A Coprocessor介绍

ARMv7-A支持16个Coprocessor,分别是:(A2.9 Coprocessor support)

  • CP15-System Control。
  • CP14-Debug、The Thumb Execution Environment、Direct Java bytecode execution。
  • CP10和CP11-Floating-point和Advanced SIMD。
  • CP8/9/12/13-ARM保留。
  • CP0-7-预留厂商自定义。

Coprocessor相关指令有:(A4.10 Coprocessor instructions)

  • 发起Coprocessor数据处理操作:CDP/CDP2。
  • Core寄存器和Coprocessor寄存器之间传输:MCR/MCR2/MCRR/MCRR2/MRC/MRC2/MRRC/MRRC2。
  • 存取Coprocessor寄存器:LDC/LDC2/STC/STC2。

ARM NEON测试代码:《GitHub - christophe-lyon/arm-neon-tests: Tests for ARM/Neon instructions, useful for compilers and simulators.》。

NEON优化库:《GitHub - projectNe10/Ne10: An open optimized software library project for the ARM® Architecture》。

ARM官方NEON编程指导:《Learn the architecture - Neon programmers' guide (arm.com)》。

ARM A7 FPU技术参考手册:《Cortex-A7 Floating-Point Unit Technical Reference Manual r0p5 (arm.com)》。

1.1 CP14

CP14提供Debug/Trace/Execution environment相关控制功能。

32位指令组成形式为{CRn, opc1, CRm, opc2},其中:

  • opc1==0 Debug registers.
  • opc1==1 Trace registers.
  • opc1==6 ThumbEE registers.
  • opc1==7 Jazelle registers.

1.2 CP15

CP15是System Control寄存器集合,其组成形势根据32位或64位不同。

32位组成形式为{CRn, opc1, CRm, opc2};64位组成形式为{CRm, opc1}。

下图为mcr/mrc指令和CP15指令对应关系:

CP15从c0~c15详细如下:

 更详细参考:《B3.17 Organization of the CP15 registers in a VMSA implementation》。

1.3 CP10和CP11

使能CP10和CP11,需要将CPACR.{cp10, cp11}设置为0b01或者0b11。0b00-不可访问;0b01-仅PL1可访问;0b11-PL0/PL1都可访问。

在使能Security情况下,可以配置NSACR.{cp10, cp11}来控制不同安全个状态的是否可用。0-仅安全状态可访问;1-安全和非安全都可访问。

相关寄存器列表如下:

2. ARMv7-A Coprocessor相关指令寄存器

2.1 MCR/MRC/MCRR/MRRC

MRC: Move to general-purpose register from Coprocessor.

MCR: Move to Coprocessor from general-purpose register.

MRRC: Move to two general-purpose registers from Coprocessor.

MCRR:  Move to Coprocessor from two general-purpose registers.

MCR/MCR2将ARM Core寄存器值传递到Coprocessor,指令格式为:

MCR<c> <coproc>, <opc1>, <Rt>, <CRn>, <CRm>{, <opc2>}

coproc-协处理器名称;opc1-Coprocessor的opcode;Rt-传递数据给Coprocessor的ARM Core寄存器;CRn-Coprocessor目的寄存器;CRm-Coprocessor的补充寄存器;opc2-Coprocessor的opcode。

 

MRC/MRC2将Coprocessor内容传递给ARM Core寄存器,指令格式为:

MRC<c> <coproc>, <opc1>, <Rt>, <CRn>, <CRm>{, <opc2>}

相对于MCR,Rt变成目的寄存器,CRn/CRm变成源寄存器。

 

MCRR/MRRC功能类似于MRC/MCR,但是ARM Core寄存器变成了两个。MCRR/MRRC访问的是64位协处理器寄存器,CRn为空,仅靠CRm找到对应寄存器。

指令格式如下:

MCRR<c> <coproc>, <opc1>, <Rt>, <Rt2>, <CRm>
MRRC<c> <coproc>, <opc1>, <Rt>, <Rt2>, <CRm>

参考:《A8.8.99 MCR, MCR2》《A8.8.100 MCRR, MCRR2》《A8.8.108 MRC, MRC2》《A8.8.109 MRRC, MRRC2

2.2 CPACR

CPACR寄存器如下:

ASEDIS:1关闭Advanced SIMD功能。

D32DIS:1关闭对D16-D31寄存器访问。

TRCDIS:1关闭对CP14 Trace寄存器访问。

2.3 VMRS/VMSR

VMRS将Advanced SIMD和FP寄存器内容搬移到ARM Core寄存器;VMSR将ARM Core寄存器搬移到Advanced SIMD和FP寄存器。

3. GCC下Coprocessor读写

CMSIS中定义了对Coprocessor的操作接口:

#define __get_CP(cp, op1, Rt, CRn, CRm, op2) __ASM volatile("MRC p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : "=r" (Rt) : : "memory" )
#define __set_CP(cp, op1, Rt, CRn, CRm, op2) __ASM volatile("MCR p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : : "r" (Rt) : "memory" )
#define __get_CP64(cp, op1, Rt, CRm) __ASM volatile("MRRC p" # cp ", " # op1 ", %Q0, %R0, c" # CRm  : "=r" (Rt) : : "memory" )
#define __set_CP64(cp, op1, Rt, CRm) __ASM volatile("MCRR p" # cp ", " # op1 ", %Q0, %R0, c" # CRm  : : "r" (Rt) : "memory" )

  __get_CP/__set_CP分别读取和设置32位寄存器;__get_CP64/__set_CP64分别读取和设置64位寄存器。

 使用CMSIS提供的API进行Coprocessor操作:

unsigned int cntp_ctl = __get_CNTP_CTL();
__set_CNTP_CTL(cntp_ctl);

unsigned long long cntp_cval = __get_CNTP_CVAL();
__set_CNTP_CVAL(cntp_cval);

__STATIC_FORCEINLINE void __set_CNTP_CTL(uint32_t value)
{
  __set_CP(15, 0, value, 14, 2, 1);
}

__STATIC_FORCEINLINE uint32_t __get_CNTP_CTL(void)
{
  uint32_t result;
  __get_CP(15, 0, result, 14, 2, 1);
  return result;
}

__STATIC_FORCEINLINE void __set_CNTP_CVAL(uint64_t value)
{
  __set_CP64(15, 2, value, 14);
}

__STATIC_FORCEINLINE uint64_t __get_CNTP_CVAL(void)
{
  uint64_t result;
  __get_CP64(15, 2, result, 14);
  return result;
}

得到的汇编结果如下:

 从如下图中可知,当CRn=c14, op1=0, CRm=2, op2=1时,操作的寄存器为CNTP_CTL。

从如下图中可知,当CRn=c14, opc1=2时,操作的寄存器为CNTP_CVAL。

 

 

参考文档:《ARM® Architecture Reference Manual ARMv7-A and ARMv7-R edition》、《Cortex-A7 MPCore™ Revision: r0p5 Technical Reference Manual》。

posted on 2022-12-11 23:00  ArnoldLu  阅读(638)  评论(0编辑  收藏  举报

导航