관리 메뉴

juniverse

[RISC-V] RV32I 분기 명령어 본문

컴퓨터구조 computer organization and design/RISC-V edition

[RISC-V] RV32I 분기 명령어

iamjunis 2022. 7. 21. 00:20
반응형
SMALL

분기 명령어에는 조건에 따른 분기 conditional branch 명령어와 무조건 분기 unconditional branch 명령어 두 종류가 있다.

branch 명령어의 실행 결과를 말할 때 taken 또는 not-taken과 같은 용어를 자주 사용하는데, 

'beq x3, x4, L1'의 예에서 x3 == x4이면 branch가 taken 됐다고 말하고, 그렇지 않으면 not-taken 됐다고 말한다.

 

# conditional branch / B-type

- beq rs1, rs2, imm[12:1]                

beq x10, x11, L1                // if (x10 == x11) PC → L1;

                                          // else                 PC → PC + 4;

- bne rs1, rs2, imm[12:1]               

bne x10, x11, L1                // if (x10 ≠ x11) PC → L1;

                                          // else                 PC → PC + 4;

- blt rs1, rs2, imm[12:1]               

blt x10, x11, L1                  // x10, x11 : signed 정수

                                          // if (x10 < x11)   PC → L1;

                                          // else                 PC → PC + 4;

- bltu rs1, rs2, imm[12:1]               

bltu x10, x11, L1                // x10, x11 : unsigned 정수

                                          // if (x10 < x11)   PC → L1;

                                          // else                 PC → PC + 4;

- bge rs1, rs2, imm[12:1]               

bge x10, x11, L1                // x10, x11 : signed 정수

                                          // if (x10  x11)   PC → L1;

                                          // else                 PC → PC + 4;

- bgeu rs1, rs2, imm[12:1]               

bgeu x10, x11, L1                // x10, x11 : unsigned 정수

                                          // if (x10  x11)   PC → L1;

                                          // else                 PC → PC + 4;

 

BEQ : equal

BNE : not equal

BLT / BLTU : less than, greater than

BGE / BGEU : less than equal, greater than equal

 

이렇게 보면, signed와 unsigned가 헷갈릴 수 있어 Pseudo 명령어를 이용해 표로 정리해보았다.

Data type 비교 Pseudo 명령어 실제 명령어
Unsigned a == b   beq a, b, label
a != b   bne a, b, label
a > b bgtu a, b, label bltu b, a, label
a ≥ b   bgeu a, b, label 
a < b   bltu a, b, label
a ≤ b bleu a, b, label bgeu b, a, label
Signed a == b   beq a, b, label
a != b   bne a, b, label
a > b bgt a, b, label blt b, a, label
a ≥ b   bge a, b, label 
a < b   blt a, b, label
a ≤ b ble a, b, label bge b, a, label
Signed 정수 a,b에 대해 'a>b' 조건을 판단하려면 pseudo 명령어인 'bgt a, b, L1'을 사용하면 된다.

그러면 컴파일러가 그것을 'blt b, a, L1' 명령어로 바꿔준다.

Unsigned 정수 a,b에 대해 'a≤b' 조건을 판단하려면 pseudo 면령어인 'bleu a, b, L1'을 사용하면 된다.

그러면 컴파일러가 그것을 'bleu b, a, L1' 명령어로 바꿔준다.

 

# unconditional branch

무조건 분기 명령어와 함께 주로 쌍으로 사용되는 명령어 lui, auipc 명령어가 있다.

* U-type / lui, auipc

- lui rd, imm[31:12]            // load upper immediate

lui x10, 0x12345               // x10 = 0x1234_5000

레지스터의 상위 20-bit를 특정 값으로 채울 때 사용하는데,

immediate에 있는 20-bit 값을 destination 레지스터의 위쪽에 채우고 아래쪽 12-bit는 0으로 채운다.

 

- auipc rd, imm[31:12]       // add upper immediate to PC

auipc x10, 0x12345          ]\// x10 = current PC + 0x1234_5000

lui 동작과 비슷한데, 차이는 'auipc 명령어의 PC'를 더한 값으로 레지스터를 채운다는 것이다.

주로 레지스터의 상위 20-bit를 특정 값으로 채울 때 사용하는데,

PC-relative 주소를 만들 때 주로 사용한다. 현재 PC에서 offset만큼 떨어진 곳,

즉 relative하게 떨어져 있는 곳의 주소를 레지스터에 저장하기 위해 사용한다.

 

1) J-type

- jal rd, imm[20:1] 

jal ra, foo                           // foo() 함수 호출

                                          // PC L1;

                                          // ra(=x1) ← PC + 4;

PC-relative 방식으로, 분기하려는 목적지가 현재 명령어 위치에서 immediate만큼 떨어져 있는 direct jump 명령어이다.

 

2) I-type

- jalr rd, imm[20:1] 

jalr ra, 8(x4)                       // PC  x4 +8;

                                          // ra(=x1) ← PC + 4;

목적지가 레지스터 값에서 immediate만큼 떨어져 있는 indirect jump 명령어이다.

* indirect : 분기할 목적지가 명령어에 직접적으로 명시되는 것이 아니라 레지스터를 통해 간접적으로 명시되는 것

 

※ indirect jump를 제공하는 이유?

1) 호출하는 함수의 위치가 너무 멀어 jal 명령어로 도달할 수 없을 수 있기 때문이다.

- jalr 명령어는 레지스터를 통해 32-bit 주소 공간에서 목적지가 어디든 분기할 수 있다.

2) 호출할 함수가 '실행 중' 결정되는 것을 지원하기 위해서이다.

 

JAL : jump and link

JALR : jump and link register

 

RV32I는 unconditional 분기 명령어로 jal와 jalr 명령어 두 개만을 제공하지만 프로그래밍을 통해 직관적으로 사용할 수 있는 다양한 pseudo 명령어를 만들 수 있다.
  Pseudo 명령어 실제 명령어
Jump j offset jal x0, offset
Jump and link jal offset jal x1, offset
Jump register jr  rs jalr x0, 0(rs)
Jump and link register jalr  rs jalr x1, 0(rs)
Return from function ret jair x0,0(x1)
Call function call offset auipc x1, offset[31:12] + offset[11]
jalr x1 offset[11:0](x1)

 

# Reference
원리부터 설계까지 쉽고 명확한 컴퓨터구조 RISC-V 중심으로 - 서태원 지음 - 도서출판 홍릉
반응형
LIST