아주 작고 단순한 VM의 설계.
글쓴이: 나빌레라 / 작성시간: 일, 2009/04/19 - 1:04오후
llvm이나 jvm을 사용하고 싶었으나, 머리가 나빠서 당최 이해 하질 못해 그냥 VM 아키텍처(라지만 그냥 명령어 셋)를 만들기로 결정했습니다.
그래봐야 ARM 명령어와 학교때 시스템 프로그래밍 교재에 나왔던 sic/xe VM의 명령어 구조를 적절히 조합해서 섞은 수준밖에 되지 않습니다. 그나마도 거기서 스펙을 아주 아주 줄였죠...-_-;
그러다 보니 VM이 제공하는 기능은 매우 협소해졌고 대신 단순하기 때문에 이해하기는 쉬워졌습니다.
문제는 그 단순함으로 인해 꼭 필요하지만 할 수 없는 것들이 생겨버린다는 겁니다.
(꼭 필요하진 않지만 있으면 좋은것들은 왠만하면 하지 않을 생각입니다.^^)
VM 명령어를 설계하고 몇주간 혼자 이리저리 생각해 봤지만 제 능력으로는 더이상 뭘 발견하기 어려워 KLDP에 올려봅니다.
--- 여기 부터 ---
명령어의 길이는 32bit고정
SMP나 pipe line은 고려하지 않음
자료형 역시 1워드로 고정
레지스터
- 4bit로 표현 : 총 16개 제공
- 각 레지스터의 크기는 당연히 32bit
- 범용레지스터 : 12개 (A~L)
- 특수레지스터 : 3개
- PC - Program Counter
- LR - Link Register
- SP - Stack Pointer
- 상태레지스터 : 1개 - ST
- 각 비트별로 사용 4개 정의 28비트 예약
- Overflow - STO
- Carry - STC
- Zero - STZ
- Negative - STN
명령어
- 5bit로 표현 : 최대 32개
- +1bit : 레지스터/값 선택비트 - 이 값이 0이면 마지막 인자는 레지스터, 1이면 값 혹은 주소.
- 그래서 5+1bit : 64개.
- value나 address에 할당된 비트보다 큰 값이 코딩으로 들어오면 어셈블러에서 mov와 add명령으로 레지스터에 넣은다음 처리
- 주소지정 방식은 무조건 직접주소지정(direct indexing)만 사용한다.
- 데이터 처리 명령어
- 이동
- MOV Rd, [Rs | #Value] ; Rs의 값이나 Value를 Rd에 저장
- 산술
- ADD Rd, R1, [R2 | #Value] ; R1의 값과 (R2의값 혹은 Value)를 더해서 Rd에 저장
- SUB Rd, R1, [R2 | #Value] ; R1의 값과 (R2의값 혹은 Value)를 빼서 Rd에 저장
- MUL Rd, R1, [R2 | #Value] ; R1의 값과 (R2의값 혹은 Value)를 곱해서 Rd에 저장
- DIV Rd, R1, [R2 | #Value] ; R1의 값과 (R2의값 혹은 Value)를 나눠서 Rd에 저장
- MOD Rd, R1, [R2 | #Value] ; R1의 값과 (R2의값 혹은 Value)를 나눠서 나머지를 Rd에 저장
- 비교
- CMP R1, [R2 | #Value] ; R1의 값과 (R2의값 혹은 Value)를 비교, 같으면 STZ=1, 작으면 STN=1이 된다. (사실상 빼기와 같다)
- 논리
- AND Rd, R1, [R2 | #Value] ; R1의 값과 (R2의값 혹은 Value)를 논리and 연산해서 Rd에 저장
- OR Rd, R1, [R2 | #Value] ; R1의 값과 (R2의값 혹은 Value)를 논리or 연산해서 Rd에 저장
- XOR Rd, R1, [R2 | #Value] ; R1의 값과 (R2의값 혹은 Value)를 논리xor 연산해서 Rd에 저장
- 비트시프트
- SHL Rd, [Rc | #Value] ; Rd의 값을 (Rc의값 혹은 Value)만큼 왼쪽 비트 시프트
- SHR Rd, [Rc | #Value] ; Rd의 값을 (Rc의값 혹은 Value)만큼 오른쪽 비트 시프트
- 이동
- 분기 명령어
- BR [Reg | #Address] ; Reg의 값 혹은 Address가 가리키는 주소로 무조건 점프
- BSUB [Reg | #Address] ; Reg의 값 혹은 Address가 가리키는 주소로 점프하면서 자동으로 LR = PC + 4를 해 준다. (서브루틴 점프용)
- BEQ [Reg | #Address] ; STZ == 1 이면 Reg의 값 혹은 Address가 가리키는 주소로 점프
- BGT [Reg | #Address] ; (STZ == 0 && STN == 0) 이면 Reg의 값 혹은 Address가 가리키는 주소로 점프
- BLT [Reg | #Address] ; (STZ == 0 && STN == 1) 이면 Reg의 값 혹은 Address가 가리키는 주소로 점프
- BGET [Reg | #Address] ; (STZ == 1 || STN == 0) 이면 Reg의 값 혹은 Address가 가리키는 주소로 점프
- BLET [Reg | #Address] ; (STZ == 1 || STN == 1) 이면 Reg의 값 혹은 Address가 가리키는 주소로 점프
- 메모리 명령어
- 한 레지스터 메모리 처리 명령어
- LDR Rd, [Rs | #Address] ; Rs의 값 혹은 Address가 가리키는 주소에 있는 값을 Rd에 저장
- STR Rd, [Rs | #Address] ; Rd의 값을 Rs의 값 혹은 Address가 가리키는 주소에 저장
- 여러 레지스터 메모리 처리 명령어
- LDM Reg{!}, <Reg1, Reg2, ..., RegN> ; Reg 주소부터 32비트씩 읽어서 Reg1, Reg2, ... RegN에 각각 저장, Reg!로 지정하면 하나씩 저장할때 마다 Reg+=4
- STM Reg{!}, <Reg1, Reg2, ..., RegN> ; Reg1, Reg2, ... RegN의 값을 하나씩 읽으면서 Reg주소부터 32비트씩 저장, Reg!로 지정하면 할때마다 Reg+=4
- 한 레지스터 메모리 처리 명령어
- VM 시스템 콜
- OPT syscall, parameter ; syscall번호의 VM 시스템콜을 수행한다.
- 0x01 - 화면에 parameter를 쓴다. parameter는 레지스터. 레지스터의 값을 화면에 뿌린다.
- 0x02 - 키보드로 부터 32비트를 읽는다. parameter는 레지스터. 키보드로 부터 읽은 32비트 값을 레지스터에 저장한다.
- 0xFF - Exit. Parameter는 레지스터, 값이 리턴값이다.
- OPT syscall, parameter ; syscall번호의 VM 시스템콜을 수행한다.
각 명령별 비트 할당
명령어의 기계어 코드 배정
- MOV 0x01
- ADD 0x02
- SUB 0x03
- MUL 0x04
- DIV 0x05
- MOD 0x06
- CMP 0x07
- AND 0x08
- OR 0x09
- XOR 0x0A
- SHL 0x0B
- SHR 0x0C
- B 0x0D
- BSUB 0x0E
- BEQ 0x0F
- BGT 0x10
- BLT 0x11
- BGET 0x12
- BLET 0x13
- LDR 0x14
- STR 0x15
- LDM 0x16
- STM 0x17
- OPT 0x18
- 0x19~0x1F 까지 예약
레지스터의 기계어 배정
- ST 0x0
- A 0x1
- B 0x2
- C 0x3
- D 0x4
- E 0x5
- F 0x6
- G 0x7
- H 0x8
- I 0x9
- J 0xA
- K 0xB
- L 0xC
- PC 0xD
- LR 0xE
- SP 0xF
File attachments:
첨부 | 파일 크기 |
---|---|
opcode_bit.png | 48.38 KB |
댓글
VM을 이용해서 binary만
VM을 이용해서 binary만 돌리시려는 거라면
instruction set은 기존의 것들 중에 고르시면 어떨까요 ?
( 디코딩하기 좋은 MIPS도 좋겠네요 .. )
VM을 만드시는 데 드는 비용을 많이 줄이실 수 있으실듯 합니다.
Qemu 등 좋은 에뮬레이터들이 많이 있으니까요.
만드시려는 컴파일러에서 바이너리를 바로 생성하실게 아니라면
기존 instruction set에 맞게 어셈블리 코드를 생성해주면
이미 있는 툴들의 도움을 많이 얻으실 수 있을 것 같습니다.
링커나 디버거를 공짜로 얻는 셈이니까요.
사실 재미로 하시려는 부분이 frontend인지 backend인지에 따라
크게 방향이 좌우되실것 같은데요. ^^;
Frontend쪽이시라면 기존것을 많이 쓰시는 편이 좋을듯합니다.
http://en.wikipedia.org/wiki/
http://en.wikipedia.org/wiki/Stack_machine
모든 현대적인 마이크로 VM의 원형이라고 할 수 있는 stack machine을 참조해보세요.
관련 자료들 링크도 많이 있네요~
----
the smile has left your eyes...
----
the smile has left your eyes...
아아...
SIC/XE... orz 추억이 보글보글
몇년 후면
몇년 후면 나빌레라님 이름으로
드래곤북이 나올것 같습니다.
화이팅~~
----
섬기며 사랑하면 더 행복해집니다.
개인 홈페이지가 생겼습니다 http://caoskernel.org
어셈러브를 개편중입니다 http://www.asmlove.co.kr
댓글 달기