iT邦幫忙

2021 iThome 鐵人賽

DAY 2
1

親愛的,幫忙去超市買 1 顆蘋果回來,如果他們有雞蛋的話,買 6 顆。
Simple logic problem that engineers should know.

前面的指令都是執行到就會做對應的事,
只有 Branch 系列指令會先做檢查,
然後決定接下來是要執行下一道指令(current_pc + 4),
還是跳到其他位置再繼續執行(current_pc + imm*2)。

行為上可以把 BRANCH 指令當作範圍較小的 JUMP 指令用,
但為了不讓 Branch Prediction 的預測方法受到影響,
規格書建議不要這樣做。

和 JUMP 指令同樣要注意的是,
如果跳到不合法的位置會觸發 instruction-address-misaligned exception。

B-type

指令格式如下:

|31     25|24   20|19   15|14    12|11   7|6       0|
+---------------------------------------------------+
|   imm   |  rs2  |  rs1  | funct3 | imm  | opcode  |
+---------------------------------------------------+

BEQ

pc = current_pc + (rs1 == rs2 ? imm*2 : 4)

|31     25|24   20|19   15|14    12|11   7|6       0|
+---------------------------------------------------+
|   imm   |  rs2  |  rs1  |  000  | imm  | opcode  |
+---------------------------------------------------+

BNE

pc = current_pc + (rs1 != rs2 ? imm*2 : 4)

|31     25|24   20|19   15|14    12|11   7|6       0|
+---------------------------------------------------+
|   imm   |  rs2  |  rs1  |  001  | imm  | opcode  |
+---------------------------------------------------+

BLT

pc = current_pc + (rs1 < rs2 ? imm*2 : 4)

|31     25|24   20|19   15|14    12|11   7|6       0|
+---------------------------------------------------+
|   imm   |  rs2  |  rs1  |  100  | imm  | opcode  |
+---------------------------------------------------+

BGE

pc = current_pc + (rs1 >= rs2 ? imm*2 : 4)

|31     25|24   20|19   15|14    12|11   7|6       0|
+---------------------------------------------------+
|   imm   |  rs2  |  rs1  |  101  | imm  | opcode  |
+---------------------------------------------------+

BLTU

pc = current_pc + ((uint32_t)rs1 < (uint32_t)rs2 ? imm*2 : 4)

|31     25|24   20|19   15|14    12|11   7|6       0|
+---------------------------------------------------+
|   imm   |  rs2  |  rs1  |  110  | imm  | opcode  |
+---------------------------------------------------+

BGEU

pc = current_pc + ((uint32_t)rs1 >= (uint32_t)rs2 ? imm*2 : 4)

|31     25|24   20|19   15|14    12|11   7|6       0|
+---------------------------------------------------+
|   imm   |  rs2  |  rs1  |  111  | imm  | opcode  |
+---------------------------------------------------+

實際程式

github 頁面 Tag: ITDay19

吸取昨天的經驗,
這次先實作 get_imm_b 減少指令實作的複雜度。

//instructionDecoder.cpp
int32_t INSTRUCTION_DECODER::get_imm_b()
{
	auto value = sc_dt::sc_int<32>();
	value(12, 12) = instruction_value(31, 31);
	value(11, 11) = instruction_value(7, 7);
	value(10, 5) = instruction_value(30, 25);
	value(4, 1) = instruction_value(11, 8);
	value <<= 19;
	value >>= 19;
	return value;
}

指令實作的部分很單純,就跟上面寫的一樣,
只要把依照比較結果設定 new_pc 的值就好,
這邊只列出 BEQ 指令當作範例。

//executor.cpp
...
		case INSTRUCTION_DECODER_INTERFACE::BRANCH_OP:
			switch (instruction_decoder->get_func3()) {
				case INSTRUCTION_DECODER_INTERFACE::BEQ_FN3:
					BEQ_E();
					break;
...
void EXECUTOR::BEQ_E()
{
	auto offset = instruction_decoder->get_imm_b();
	auto rs1 = instruction_decoder->get_rs1();
	auto rs2 = instruction_decoder->get_rs2();

	new_pc = register_file->get_pc() +
	         (register_file->get_value_integer(rs1) == register_file->get_value_integer(rs1) ?
	          offset : 4);
}
...

上一篇
RISC-V: Jump 指令
下一篇
RISC-V: Memory Fence 指令
系列文
猴子都寫得出來的 RISC-V CPU Emulator31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言