2008년 8월 2일 토요일

ARM9TDMI 프로세서의 5단계 동작

■ Fetch
pc가 가르키는 메모리 주소로부터 명령어를 읽는다. 이 명령어는 코어로 로드된후, 코어 파이프라인의 다음 단계로 진행된다.
■ Decode
이전 사이클에서 읽어들인 명령어를 해독한다. 만약 이전 단계에서 입력 오퍼랜드들이 사용되지 않았다면 레지스터 뱅크에서 입력 오퍼랜드들도 읽어들인다.
■ ALU
이전 사이클에서 해독한 명령어를 실행한다. 이 명령어는 pc-8(ARM 상태) 또는 pc-4(Thumb 상태)의 주소에서 읽는 것이다. ALU는 보통 데이터 처리 연산을 위한 결과값을 계산하거나 로드, 스토어, 분기 연산을 위한 주소값을 계산한다. 어떤 명령어들은 이 단계에서 여러 사이클을 소모 할 수 있다. 예를 들어, 다중 로드-스토어 명령어와 레지스터 기반의 시프트 연산을 여러 ALU 사이클을 소모한다.
■LS1
로드-스토어 명령어에 의해 규정된 데이터를 읽거나 저장한다. 로드-스토어 명령어가 아니라면 이 단계는 영향을 미치지 않는다.
■LS2
바이트 또는 하프워프 로드 명령어에 의해 로드된 데이터를 제로-또는 부호- 확장한다. 8비트 바이트 또는 16비트 하프워드를 로드하는 명령어가 아니라면 이 단계는 영향을 미치지 않는다.

2008년 7월 30일 수요일

ARM 효과적인 루프문의 코딩

■ 0으로 다운카운트를 하는 루트를 사용하도록 한다. 그러면 컴파일러는 최종값을 저장하기 위해 레지스터를 할당할 필요가 없으며, 0과 비교하는 작업에 비용이 들지 않는다.

■ 디폴트로 unsigned 루트 카운터를 사용하고, 반복 조건으로 i>0보다는 i!=0을 사용하도록 한다. 그러면 루프 오버헤드는 명령어 2개로 줄어든다.

■루프가 적어도 한 번 이상 실행된다면 for문보다는 do-while 문을 사용하도록 한다. 이것은 컴파일러가 루프 카운터가 0인지 아닌지를 체크할 필요성을 없애준다.

■ 루프 오버헤드를 줄어여 하는 중요한 루프문은 언롤링시키도록 한다. 그렇다고 언롤링을 너무 맣이 하지는 않도록 한다. 만약 루프 오버헤드가 전체의 일정 비율만큼 작아진다면, 언롤링은 코드사이즈를 증가시키고 캐시 성능에 좋지 않은 영향을 끼칠 것이다.

■배열에서 요소(element)들의 수는 4나 8의 배수가 되도록 정렬시키도록 한다. 그러면 배열 요소를 추가해야 할 지에 대해 고민하지 않고 루프를 2,4,8배로 쉽게 언롤링 시킬수 있다.

2008년 7월 28일 월요일

ARM 스택 명령어

ARM 아키텍처는 스택 오퍼레이션을 수행하기 위해 다중-레지스터 전송 명령어를 사용하고 있다. 팝(pop) 동작(스택에서 데이터를 제거하는 일)을 위해 LDM 명령어를 사용하며, 푸시(push) 동작(스택에 데이터를 집어넣는 일)을 위해서는 STM 명령어를 사용한다. 스택을 사용할 때에는 스택을 메모리 위쪽으로 증가시킬 지 아래쪽으로 증가시킬 지를 결정해야 한다. 스택은 ascending(A)이나 descending(D) 중 하나이다. ascending 스택은 메모리의 상위 주소 방향으로 스택이 자라는 것을 말하며, descending 스택은 메모리의 하위 주소 방향으로 스택이 자라는 것을 의미한다.

full 스택(F)을 사용하는 경우, 스택 포인터 sp는 마지막으로 사용된 위치의 주소(예를 들어, sp는 스택상에 마지막 아이템을 가르킴)를 가르키고 있다. 반면 empty 스택(E)은 sp가 처음 사용되지 않을 영역의 주소(예를 들어, 스택의 마지막 아이템 다음의 빈공간)를 가르키고 있다.

스택을 처리하기 위해 보번해야 되는, 스택 베이스, 스택 포인터, 스택 리미트의 3개의 인자가 있다. 스택 베이스는 메모리에서 스택의 시작 위치를 나타낸다. 스택 포인터는 초기에는 스택 베이스를 가리키지만, 데이터가 스택으로 들어가면 스택 포인터는 메모리의 하단으로 이동하여 스택의 가장 맨 위를 계속 가르키고 있다. 스택 포인터가 스택 리미트를 넘어가면 스택 오벼플로우 에러가 발생된다.

2008년 7월 21일 월요일

ARM 프로세서 모드

프로세서 모드는 어떤 레지스터가 활성화 되고, cpsr 레지스터를 액세스 할 수 있는 권리를 갖게 될 지를 결정한다. 각 프로세서 모드는 특권 모드일 수도 있고 일반 모드일 수도 있다. 특권모드란 CPSR를 완전히 읽고 쓸 수 있는 모드를 말한다. 반면, 일반 모드에서는 cpsr의 제어 필드는 읽기만 가능하고, 상태 플래그는 읽고 쓰기가 모드 가능하다.
프로세서 모드에는 6개의 특권모드(abort, FIQ, IRQ, supervisor, system, undefined)와 하나의 일반모드(user),즉 전체적으로 7개의 모드가 있다.
프로세서는 메모리 액세스가 실패했을 경우, abort모드로 진입한다. FIQ와 IRQ모도는 ARM 프로세서에서 사용할 수 있는 2가지의 인터럽트 레벨을 위한 모드이다.
supervisor 모드는 프로세서에 리셋이 걸렸을 때에 진입하는 모드로, 일반적으로 운영체제 커널이 동작하는 모드이다. system 모드는 user 모드의 특수한 버전으로 cpsr을 완전히 읽고 쓸 수 있다. undefined 모드는 프로세서가 정의되지 않은 명령어나 지원되지 않은 명령어를 만났을 때에 진입하는 모드이고, user 모드는 프로그램과 어플리케이션을 위해 사용되는 모드이다.

2008년 7월 17일 목요일

ARM 인터럽트 컨트롤러

주변 장치나 디바이스가 실행되려고 할 때, 이것은 프로세서에게 인터럽트를 발생시킨다. 인터럽트 컨트롤러란 인터럽트 컨트롤러 레지스터 안에 있는 해당 비트를 1로 설정함으로써 특정 시간에 어떤 주변 장치나 디바이스가 프로세서에게 인터럽트를 발생시킬수 있도록 할 지에 대한 소프트웨어 정책을 제공한다.

ARM 프로세서에서 사용할 수 있는 2가지 인터럽트 컨트롤러로는 표준 인터럽트 컨트롤러와 백터 인터럽트 컨트롤러(VIC, Vector Interrupt Controller)가 있다.

표준 인처럽트 컨트롤러는 외부 다바이스가 서비스를 요청하면, 그 인터럽트 신호를 프로세서 코어에게 보낸다. 이 컨트롤러는 각 디바이스나 디바이스 세트의 요청을 무시할지, 수렴할 지에 대해 프로그램적으로 설정할 수 있다. 인터럽트 핸들러는 인터럽트 컨트롤러 안에 있는 디바이스 비드맵 레지스터를 읽은 후 어떤 디바이스가 서비스를 요청 했는지를 결정한다.

VIC는 표준 인터럽트 컨트롤러보다 강력한 기능을 가지고, 인터럽트에 우선순위를 부여하여 어떤 디바이스가 인터럽트를 발생시켰는지를 쉽게 결정할 수 있다. VIC는 운선순위와 각 인터럽트에 대한 핸들러 주소를 살펴본 후, 새로운 인터럽트가 현재 실행되고 있는 인터럽트 핸들러보다 우선순위가 높은 경우에만 프로세서에게 인터럽트 신호를 보낸다. VIC는 다비이스를 위한 핸들러 주소를 읽어들이기 위해 표준 인터럽트 익셉션 핸들러를 호출하거나 디바이스를 위해 직접 핸들러로 분기한다.

2008년 7월 16일 수요일

ARM 버스

임베디드 시스템은 x86 PC를 위해 설계된 것과는 다른 버스 체계를 사용하고 있다. 임베디드 디바이스는 칩 내부 보스를 사용하는데, 이 버스는 칩 내부에 위치하여, 다른 주변 장치가 ARM 코어와 내부에서 연결될 수 있도록 해준다.

버스에 연결될 수 있는 디바이스에는 두 종류가 있다. ARM 프로세서 코어는 버스 마스터이다. 버스 마스터란 다른 디바이스로 데이터를 전송할 수 있는 논리 장치를 말한다. 주변 장치는 버스 슬레이브처럼 동작하는데, 이는 버스 마스터로부터 전송 요청이 있을 때에만 동작한다.

버스 아키텍처는 두 단계로 구성되어 있다. 하나는 전기적인 특성과 버스폭(16, 32, 64비트)를 담당하는 물리적인 단계이며, 다른 하나는 프로토콜 처리 단계이다. 프로토콜이란 츠로세서와 주변 장치간의 통신을 담당하는 논리적인 규칙이다.

RISC의 특징

RISC란 매우 빠른 속도로 한 클럭 안에 실행될 수 있는 간결하면서도 막강한 명령어들을 가지고 있는 아키텍처를 말한다. RISC는 하드웨어에 의해 수행되는 명령어들의 복잡도를 줄이는 것을 목표로 하고 있는데, 그 이유는 하드웨어보다는 소프트웨어에 유연성과 기능성을 제공하는 것이 보다 유리하기 때문이다. 결과적으로 RISC는 컴퍼일러에 더욱 의존하게 되었다. RISC는 다음 4가지의 설계 방식을 기본으로 한다.

1. 명령어
RISC 프로세서는 상대적으로 적은 수의 명령어군을 가지고 있다. 컴파일러와 프로그래머는 간단한 명령어 몇 개를 조합하여 복잡한 연산들을 구현하다.

2. 파이프라인
명령어는 파이프라인에 의해 병렬로 실행될 수 있는 작은 단계로 쪼게져 실행된다. 이상적인 파이프라인에서는 한 사이클에 각 명령어를 한 단계씩 앞서 처리하고, 명령어들을 한 파이프라인 단계에서 해독될 수 있다.

3.레지스터
RISC 프로세서는 거대한 레지스터군을 가지고 있으며, 이 레지스터에는 데이터와 주소가 저장될 수 있다. 레지스터들은 모든 데이터 처리 동작을 위해 사용되는 빠른 로컬 메모리처럼 동작한다.

4. 로드-스토어(Load-Store) 아키텍처
프로세서는 보통 레지스터 안에 저장되어 있는 데이터를 이용하여 어떤 동작을 수행한다.메모리에서 레지스터로 데이터를 읽어 들일때에는 로드 명령어를, 레지스터에서 메모리로 데이터를 저장할 때에는 스토어 명령어를 사용한다.