今天一樣是簡單的 AND、OR、XOR指令實作,
多出來的時間就來還摸索期留下來的債,
讓整個專案變得更完整和容易維護,
這次補上 JUMP/BRANCH Exception 和 LOAD/STORE Exception。
指令格式如下:
|31 25|24 20|19 15|14 12|11 7|6 0|
+---------------------------------------------------+
| func7 | rs2 | rs1 | funct3 | rd | opcode |
+---------------------------------------------------+
rd = rs1 & rs2
|31 25|24 20|19 15|14 12|11 7|6 0|
+-------------------------------------------------------+
| 0000000 | rs2 | rs1 | 111 | rd | 0110011 |
+-------------------------------------------------------+
rd = rs1 | rs2
|31 25|24 20|19 15|14 12|11 7|6 0|
+-------------------------------------------------------+
| 0000000 | rs2 | rs1 | 110 | rd | 0110011 |
+-------------------------------------------------------+
rd = rs1 ^ rs2
|31 25|24 20|19 15|14 12|11 7|6 0|
+-------------------------------------------------------+
| 0000000 | rs2 | rs1 | 100 | rd | 0110011 |
+-------------------------------------------------------+
github 頁面 Tag: ITDay23
JUMP/BRANCH Exception 的條件會取決於是否支援 Compress Extension,
詳細內容可以看前面的文章,
這次先在 Executor 做了一個簡單的判斷和處理,
未來實做 CSR 再改掉。
LOAD/STORE Exception 的條件會取決於存取的大小和 EEI 的設計,
詳細內容在前面的文章有提到,
因為目前沒有實做其他裝置與判斷機制,
這邊先當作 address misalignment 處理。
//executor.cpp
...
#define INSTRUCTION_ALIGNMENT 4
#define LOAD_STORE_ALIGNMENT_W 4
#define LOAD_STORE_ALIGNMENT_HW 4
bool isAlignment(uint32_t address, unsigned int baseNumber)
{
if(0 == address % baseNumber) {
return true;
} else {
return false;
}
}
...
void EXECUTOR::LH_E()
{
auto rs1 = instruction_decoder->get_rs1();
auto rd = instruction_decoder->get_rd();
auto addr = register_file->get_value_integer(rs1) + (uint32_t) instruction_decoder->get_imm(31, 20);
if(!isAlignment(addr, LOAD_STORE_ALIGNMENT_HW)) {
cpu->raise_exception(CPU_INTERFACE::LOAD_ADDRESS_MISALIGNED_EXCEPTION_CAUSE);
}
...
void EXECUTOR::JALR_E()
{
auto offset = instruction_decoder->get_imm(31, 20);
auto rs1 = instruction_decoder->get_rs1();
auto rd = instruction_decoder->get_rd();
auto addr = (register_file->get_value_integer(rs1) + offset) & ~0x1;
if(!isAlignment(addr, INSTRUCTION_ALIGNMENT)) {
cpu->raise_exception(CPU_INTERFACE::INSTRUCTION_ADDRESS_MISALIGNED_EXCEPTION_CAUSE);
}
...
指令部分相對單純,
這次用 AND 當範例,實作如下:
//executor.cpp
...
case INSTRUCTION_DECODER_INTERFACE::AND_FN3:
AND_E();
//do not check FN7 for readibility, refactor in future
break;
...
void EXECUTOR::AND_E()
{
auto rd = instruction_decoder->get_rd();
auto rs1 = instruction_decoder->get_rs1();
auto rs2 = instruction_decoder->get_rs2();
auto value = register_file->get_value_integer(rs1) & register_file->get_value_integer(rs2);
register_file->set_value_integer(rd, value);
}
//instructionDecodetInterface.h
...
AND_FN3 = 0b111,
...
AND_FN7 = 0b0000000,
...