명령어의 집합으로 소프트웨어와 하드웨어가 서로를 추상화 해서 바라보는 인터페이스입니다.
각 컴퓨터는 다른 instruction set이 있습니다.
학문적으로 만든 ISA라 공개 되어있다.
add a, b, ca = b + csub a, b, ca = b - cC code
f = (g + h) - (i + j);
Compiled RISC-V code
add t0, g, h
add t1, i, j
sub f, t0, t1
32개의 32bit의 레지스터를 가지고 있습니다.
정해진 레지스터
x0: 상수 0
x1: return 주소
x2: stack pointer
x3: global pointer
x4: thread pointer
x5 ~ x7, x28 ~ x31: 임시
x8: frame pointer
x9, x18 ~ x27: saved registers
x10 ~ x11: function arguments/results
x12 ~ x17: function arguments
C code
f = (g + h) - (i + j);
Compiled RISC-V code(정확한 표현)
add x5, x20, x21
add x6, x22, x23
sub x19, x5, x6
메인 메모리는 바이트 단위입니다.
RISC_V는 Little Edian입니다.
C code
A[12] = h + A[8];
Compiled RISC-V code
lw x9, 32(x22)
add x9, x21, x9
sw x9, 48(x22)
레지스터가 메모리보다 접근 속도가 더 빠르다.
컴파일러 입장에서는 레지스터를 적게 쓰도록 해야한다.
상수를 바로 계산하면서 로드하는 명령을 줄일 수 있다.
Compiled RISC-V code
addi x22, x22, 4
RISC-V에서는 32비트짜리 명령어를 사용한다.
명령어들을 각각의 포맷으로 묶어 놨다.





C code
if (i == j) f = g + h;
else f = g - h;
Compiled RISC-V code
bne x22, x23, Else
add x19, x20, x21
beq x0, x0, Exit //unconditional
Else: sub x19, x20, 21
Exit: ...
jal x1, label 로 x1에 PC + 1값을 저장해서 돌아갈 주소를 확보하고 label로 branch한다.jalr x0, 0(x1)으로 x1에 저장된 돌아갈 주소로 branch 한다.C code
int leaf_example (int g, int h,int i, int j) {
int f = (g + h) - (i + j);
return f;
}

Compiled RISC-V code
// g부터 x10에 저장된다. f는 x20에 저장된다. x5, 6은 임시공간.
leaf_example: addi sp, sp, -12 // Stack pointer를 3-Byte 확보.
sd x5, 8(sp) // 임시공간 x5 공간확보
sd x6, 4(sp) // 임시공간 x6 공간확보
sd x20, 0(sp) // local variable f를 위한 공간확보
add x5, x10, x11 // g + h
add x6, x12, x13 // i + j
sub x20, x5, x6 / f = x5 - x6
addi x10, x20, 0 // x10에 return value 저장
ld x20, 0(sp) // 저장해뒀던 x20값 백업
ld x6, 4(sp) // 저장해뒀던 x6값 백업
ld x5, 8(sp) // 저장해뒀던 x5값 백업
addi sp, sp, 12 // Stack pointer 복구
jalr x0, 0(x1) // 돌아갈 주소로 RETURN

lr.w rd, (rs1)
sc.w rd, rs2, (rs1)
again: lr.w x10, (x20)
sc.w x11, x23, (x20)
bne x11, x0, again
addi x23, x10, 0
CISC가 성능이 무조건 좋은 것은 아니다.
구현이 복잡해서 한 cycle이 오래걸리기 때문이다.