2022. 12. 11. 13:14ㆍ임베디드 시스템 설계/ARM
- ARM 명령어
메모리 접근 명령어
Load / Store
연산의 대상으로 외부 메모리를 직접 사용하지 못합니다.
외부 메모리는 반드시 레지스터를 거쳐서 연산이 이루어집니다.
메모리 > 레지스터 : LDR(Load to register)를 이용합니다.
레지스터 > 메모리: STR(Store to memory)를 이용합니다.
레지스터 간접 참조
Ldr Rd, [Rs]
Rd = [Rs]입니다. Rs의 레지스터 값을 메모리 주소로 하여 내용을 Rd로 load 시켜주는 참조 방식입니다.
Rs, Rd : r0 – r15입니다.
또 다른 레지스터 간접 참조의 예
LDR r0, [r1] > r1이 0x100번지를 로드하여 r0 레지스터에 로드합니다.
STR r0, [r1] > r1이 0x100번지에 R0 레지스터값을 저장합니다.
LDR r0, = 0x1000
LDR r1, = 80
STR r1, [r0]
LDR r1, [r0]
LDR, STR로 메모리 접근시 주소는 반드시 4B align 필요합니다.
데이터처리 명령어
레지스터 안에서 데이터를 조작하는데 사용됨
데이터 이동연산이 가능합니다. (MOV / MVN)
산술 연산이 가능합니다. (ADD / ADC / SUB / SBC / RSB / RSC)
논리 연산이 가능합니다. (AND / ORR / EOR / BIC)
레지스터 안에서 데이터를 조작하는데 사용됨
비교연산
CMP / CMN / TST / TEQ
곱셈 연산 MUL / UMULL / UMLAL / SMULL / SMLAL
명령어 길이 : 32- 비트
형식 : 3-address format로 사용됩니다.
한 사이클 안에 실행됩니다.
조건부 실행이 가능합니다.
그 결과가 상태 플래그에 영향을 주지 않습니다. (‘S’ 접미사 사용)
MOV 명령어
MOV : Move
32비트 값을 레지스터로 이동시킵니다.
표기법
1. MOV<cond>{S} <Rd>, #<rotated_immed>
2. MOV<cond>{S} <Rd>, <Rm>{, <shift>}
배럴 시프터
배럴 시프터(Barrel shifter)
A digital circuit that can shift a data word by a specified number of bits in one clock cycle
ARM에서 데이터처리 명령에 의해 사용되기 전에 배럴 시프터로 미리 시프트 처리 한 후, 그 결과값을 Rm으로 사용 가능합니다.
(MOV<cond>{S} <Rd>, <Rm> {, <shift>})
배럴 시프터를 사용할 수 없는 데이터 처리 명령도 있습니다.
(MUL(multiply), CLZ(count leading zero), QADD(signed saturated 32-bit add))
선처리나 시프트 작업은 한 명령어 실행 사이클 내에서 처리됩니다.
상수값을 레지스터로 로드하여 2의 거듭자리만큼 곱하거나 나눌 때 특히 유용합니다.
MVN 명령어
MVN : Move NOT
32비트 값을 논리 반전 시킵니다.
뒤의 값을 1’s compliment 취해서 연산합니다.
표기법은
1. MVN<cond>{S} <Rd>, #<rotated_immed>
2. MVN<cond>{S} <Rd>, <Rm>{, <shift>}
ARM 명령어 예제 사례
Keil MDK IDE 동작 assemble 사례를 알아봅시다.
- ARM 상수 표현 방법
상수 표현
#상수의 구성
32비트 명령어내에 상수 값을 함께 저장합니다. 이떄 범위 제한이 발생합니다.
8비트 값과 짝수비트 ROR(Rotate Right)로 표현되는 값입니다.
0-255 범위의 상수는 무조건 가능합니다.
#상수의 구성
다음에 사용된 상수의 validaty를 판단합니다.
Mov r0, #0x7f00
Mov r0, #0x30c0
Mov r0, #0x3f000000
Mov r0, #12345678
Mov r0, #0x14e
범위 제한 없는 32비트 값으로 표현 가능합니다.
실제 상수 값은 메모리에 존재하며 레지스터 참조로 변환됩니다.
(32비트 명령어 구조에서 상수가 32비트 표현이 가능한지? : ldr r0, = 12345678)
어셈블 후 역 어셈블하여 결과 확인합니다.
0x00000038 : LDR r0, 0x54
(명령어에 포함 못하므로 상수를 만들고 그 주소를 이용하여 access합니다.)
0x0000003c : MOV r1, #0x1000
(0x1000은 mov 명령어에 포함가능한 상수이므로 LDR을 MOV로 변환합니다.)
0x00000040 : STR r0, [r1, #0]
0x00000054 : DCD 12345678
산술 명령어 : ADD
32비트 signed / unsigned 값의 덧셈과 뺼셈 등을 구현합니다.
ADD : Add
두 32 비트 값의 덧셈을 의미합니다.
표기법
1. ADD<cond>{S} <Rd>, <Rn>, #<rotated_immed>
2. ADD<cond>{S} <Rd>, <Rn>, <Rm>{, <shift>}
(인라인 배럴 시프터가 사용되어 표현할 수 있습니다.)
인라인 배럴 시프터를 활용한 산술연산으로 ARM 명령어 세트에서 매우 강력한 특징입니다.
ADC : Add with carry
캐리를 고려한 두 32비트 값의 덧셈
표기법
1. ADC<cond>{S} <Rd>, <Rn>, #<rotated_immed>
2. ADC<cond>{S} <Rd>, <Rn>, <Rm>{, <shift>}
산술 명령어 : SUB
SUB : subtract
두 32 비트 값의 뺼셈
표기법
1. SUB<cond>{S} <Rd>, <Rn>, #<rotated_immed>
2. SUB<cond>{S} <Rd>, <Rn>, <Rm>{, <shift>}
산술명령어 : SBC
SBC : Subtract with carry
캐리를 고려한 두 32비트 값의 뺄셈입니다.
표기법
1. SBC<cond>{S} <Rd>, <Rn>, #<rotated_immed>
2. SBC<cond>{S} <Rd>, <Rn>, <Rm>{, <shift>}
산술 명령어 (64비트 연산)
64비트 덧셈, 뺄셈을 위한 코드 [R3:R2] +/- [R1:R0]
Carry : flag의 C비트, rotate때는 C비트가 rotate에 포함
덧셈연산시 자리올림 발생시 set, 뺄셈연산시 빌림(borrow) 발생시 clear
R3 : 0x11111111 R2 : 0x88888888
ADD R4, R2, R0
ADC R5, R3, R1
SUBS R4, R2, R0
SBC R5, R3, R1
S-suffix를 붙여야 합니다!!
S-suffix 적용 연산(상태 플래그 반영)
S-suffix
연산 후 상태 register에 결과를 반영합니다.
상태 flag를 갱신하지 않도록 하면 분기 최소화에 도움이 됩니다.
대상
데이터 이동 명령 : MOV, MVN
산술 연산 : ADD, SUB, ADC, SBC, RSB, RSC
논리 연산 : AND, EOR, ORR, BIC
곱셈명령군 : MUL, MLA, UMULL, UMLAL, SMULL, SMLAL
'임베디드 시스템 설계 > ARM' 카테고리의 다른 글
ARM 프로세서 I2C, SPI 제어하기 (1) | 2022.12.18 |
---|---|
ARM 프로세서 NXP GPIO 소개 (0) | 2022.12.13 |
ARM SoC 구조 이해하기 (0) | 2022.12.07 |
Cortex-M3 ARM을 활용한 임베디드 시스템 설계의 이해 (0) | 2022.11.03 |