Data Transfer Operation은 연산에 필요한 데이터를 메모리로부터 읽어오거나 연산 결과를 다시 메모리에 저장하는 동작을 말한다.
RISC-V에서는 'ld'(Load)/'sd'(Store)를 통해서만 메모리를 접근할 수 있다.
(나머지 Instruction은 Register를 통해서 데이터를 접근할 수 있다.)
아래와 같이 메모리에 있는 Array 'A'의 Element 간의 연산을 수행하는 코드가 있다고 하자.
// h in x21
// base address of A in x22
A[12] = h + A[8]
Array 'A'는 메모리에 저장되어 있으므로, 'ld' 명령어를 통해서 데이터를 읽어오고, 'st' 명령어를 통해서 데이터를 저장해야 한다. 기본적으로 Array 내부의 Element를 접근하는 방법은 base address + offset를 통해서 접근한다. base address는 Array의 시작 주소이며, offset은 element size*element index를 수행하여 얻을 수 있다.
// 8 bytes per doubleword
// &A[8] = A + 64
ld x9, 64(x22) # x9 = M[x22+64]
add x9, x21, x9 # x9 = x21 + x9
sd x9, 96(x22) # M[x22+96] = x9
아래와 같이 메모리에 Access 하는 데이터의 크기도 정할 수 있으며, 'Sign extend'와 'Zero extend'를 선택할 수도 있다.
Load는 I-type, Store는 S-type을 사용한다.
메모리의 접근 주소는 Byte-addressable 이고, RISC-V는 Littel Endian을 사용한다. 또한 RISC-V는 Words단위 Alignment를 요구하지 않는다.
Memory Alignment 는 아래 글에서 설명하였다.
2024.04.27 - [IT_Study/CS_Study] - [Computer Architecture] (2) Memory Alignment
Endian 개념은 아래 글에서 설명하였다.
2024.04.27 - [IT_Study/CS_Study] - [Computer Architecture] (3) Big endian & Little endian
아래와 같이 swap을 수행하는 함수가 어떻게 ld/st로 구현되는지 알아보자.
// 주소 xp와 주소 yp에 있는 데이터를 교환하여 변경.
void swap(long *xp, long *yp)
{
long t0 = *xp; // 주소 xp에 있는 데이터를 t0에 로드
long t1 = *yp; // 주소 yp에 있는 데이터를 t1에 로드
*xp = t1; // t1 데이터를 주소 xp에 저장.
*yp = t0; // t0 데이터를 주소 yp에 저장.
}
이를 Instruction으로 변경하면 아래와 같다.
// a0 = xp
// a1 = yp
swap:
ld a4, 0(a0) # a4 = M[a0] // t0 = *xp
ld a5, 0(a1) # a5 = M[a1] // t1 = *yp
sd a5, 0(a0) # M[a0] = a5 // *xp = t1
sd a4, 0(a1) # M[a1] = a4 // *yp = t0
ret
NULL Character '\0'는 8-bit 모두 0으로 표현할 수 있고, 이는 주로 string 마지막을 표현할 때 사용한다.
이를 활용하면 아래와 같이 String Copy를 구현할 수 있다.
// copy y to x
void strcpy(char x[], char y[])
{
size_t i;
i = 0;
while((x[i] = y[i]) != '\0') // x[y] = y[i]를 수행하고 값이 Null인지 체크.
i += 1;
}
이를 Inst.으로 구현하면 아래와 같다.
strcpy:
; x is in a0
; y is in a1
; i is allocated in t3
add t3, zero, zero ; t3 <- 0 // i = 0
L1: add t0, t3, a1 ; t0 = i + y[] = &y[i]
lbu t1, 0(t0) ; t1 <- y[i] // t1 = y[i], char -> 1B, unsigned byte load
add t2, t3, a0 ; t2 <- x[i] // t2 = x[i], char -> 1B, unsigned byte load
sb t1, 0(t2) ; x[i] <- y[i] // x[i] = y[i]
beq t1, zero, L2 ; if(t1==0), goto L2 // if(x[i]=='\0'), goto return
addi t3, t3, 1 ; else t3+=1 // i+=1
j L1 ; goto L1
L2 ret ; return
'IT_Study > CS_Study' 카테고리의 다른 글
[Computer Architecture] (5) RISC-V Procedure Call (1) | 2024.04.28 |
---|---|
[Computer Architecture] (4-5) RISC-V Control Transfer Operation (1) | 2024.04.28 |
[Computer Architecture] (4-3) RISC-V Arithmetic / Logical Operation (0) | 2024.04.27 |
[Computer Architecture] (4-2) RISC-V Register 설명 (0) | 2024.04.27 |
[Computer Architecture] (4-1) RISC-V란 무엇인가? (1) | 2024.04.27 |
댓글