Skip to content

Commit

Permalink
feat: implement funct decoding for r and i fmt
Browse files Browse the repository at this point in the history
  • Loading branch information
BenMcAvoy committed Apr 29, 2024
1 parent d3826f6 commit 6e6b1b9
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 17 deletions.
1 change: 1 addition & 0 deletions include/cpu.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class CPU {
~CPU();

void fetch(); // Fetches the instruction from memory.
void decode(uint32_t ins); // Decodes the instruction.

// Registers
uint32_t x0 = 0; // Zero constant
Expand Down
144 changes: 127 additions & 17 deletions src/cpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@ inline static uint32_t extractBits(uint32_t *ins, int amount) {
return value;
}

// TODO: Move decoding to separate function
void CPU::fetch() {
// Fetch the instruction from memory
uint32_t ins = this->memory->read32(this->pc);
void CPU::decode(uint32_t ins) {
iFMT fmt = getFormat(ins);

// Print the format
Expand All @@ -29,12 +26,51 @@ void CPU::fetch() {
uint32_t rs2 = extractBits(&ins, 5);
uint32_t funct7 = extractBits(&ins, 7);

// Combination: funct7 | funct3
uint32_t funct = (funct7 << 3) | funct3;

LOG_DEBUG("Instruction (%s): %s %02X %02X %02X %02X %02X",
"R", std::bitset<7>(opcode).to_string().c_str(),
rd, funct3, rs1, rs2, funct7
);

switch (funct) {
case 0x0: // 0x0 0x0
LOG_DEBUG("ADD");
break;
case (0x20 << 3): // 0x20 0x0
LOG_DEBUG("SUB");
break;
case 0x4: // 0x0 0x4
LOG_DEBUG("XOR");
break;
case 0x6: // 0x0 0x6
LOG_DEBUG("OR");
break;
case 0x7: // 0x0 0x7
LOG_DEBUG("AND");
break;
case 0x1: // 0x0 0x1
LOG_DEBUG("SLL");
break;
case 0x5: // 0x0 0x5
LOG_DEBUG("SRL");
break;
case (0x20 << 3) | 0x5: // 0x20 0x5
LOG_DEBUG("SRA");
break;
case 0x2: // 0x0 0x2
LOG_DEBUG("SLT");
break;
case 0x3: // 0x0 0x3
LOG_DEBUG("SLTU");
break;
default:
LOG_WARN("Unknown instruction with funct %02X", funct);
}

} // End of scope for variables

break;
case I:
{ // Scope for variables to allow stack allocation in a switch statement
Expand All @@ -48,22 +84,96 @@ void CPU::fetch() {
"I", std::bitset<7>(opcode).to_string().c_str(),
rd, funct3, rs1, imm
);

uint32_t imm_breakout = imm & 0xFE; // Get [5:11] bits

if (opcode == 0b00000011) {
switch (funct3) {
case 0x0:
LOG_DEBUG("LB");
break;
case 0x1:
LOG_DEBUG("LH");
break;
case 0x2:
LOG_DEBUG("LW");
break;
case 0x4:
LOG_DEBUG("LBU");
break;
case 0x5:
LOG_DEBUG("LHU");
break;
}

return;
}

break;
case S:
LOG_WARN("Instruction format S not implemented");
break;
case B:
LOG_WARN("Instruction format B not implemented");
break;
case U:
LOG_WARN("Instruction format U not implemented");
break;
case J:
LOG_WARN("Instruction format J not implemented");
break;
if (opcode == 0b01100011 && funct3 == 0x0) {
LOG_DEBUG("LW");
return;
}

if (opcode == 0b01110011) {
switch (funct3) {
case 0x0:
LOG_DEBUG("FLW");
break;
case 0x1:
LOG_DEBUG("FLD");
break;
default:
LOG_WARN("Unknown instruction with funct3 %02X", funct3);
}

return;
}

switch (funct3) {
case 0x0: // 0x0
LOG_DEBUG("ADDI");
break;
case 0x4: // 0x4
LOG_DEBUG("XORI");
break;
case 0x6: // 0x6
LOG_DEBUG("ORI");
break;
case 0x7: // 0x7
LOG_DEBUG("ANDI");
break;
case 0x1: // 0x1
if (imm_breakout == 0x0)
LOG_DEBUG("SLLI");

break;
case 0x5: // 0x5
if (imm_breakout == 0x0)
LOG_DEBUG("SRLI");

if (imm_breakout == 0x20)
LOG_DEBUG("SRAI");

break;
case 0x2: // 0x2
LOG_DEBUG("SLTI");
break;
case 0x3: // 0x3
LOG_DEBUG("SLTIU");
break;
default:
LOG_WARN("Unknown instruction with funct3 %02X", funct3);
}

} // End of scope for variables
}
}

// TODO: Move decoding to separate function
void CPU::fetch() {
// Fetch the instruction from memory
uint32_t ins = this->memory->read32(this->pc);
this->decode(ins);

// Increment the program counter
this->pc += 4;
Expand Down

0 comments on commit 6e6b1b9

Please sign in to comment.