Implement Ecall OpCodes
MODIFY
src/defines.h
src/defines.h
@@ -13,12 +13,20 @@ enum instrType {
STORE = 0b0100011,
OP_IMM = 0b0010011,
OP = 0b0110011,
+ ECALL = 0b1110011,
INVALID = 0b0
};
typedef std::vector<uint8_t> memory;
-enum instrState { ERR_BFUNCT3, ERR_NULLLOAD, EXEC_ERR, SUCCESS = 0 };
+enum instrState {
+ ERR_BFUNCT3,
+ ERR_NULLLOAD,
+ EXEC_ERR,
+ SUCCESS = 0,
+ DONE,
+ ERR_ECALL
+};
typedef struct {
instrType type = INVALID;

MODIFY
src/runner.cpp
src/runner.cpp
@@ -33,7 +33,12 @@ int Runner::exec() {
// unsuccesfully parses an instruction.
instrState err;
while (getInstruction(m_pc)) {
- if ((err = execInstruction(m_currentInstruction)) != SUCCESS) {
+ switch ((err = execInstruction(m_currentInstruction))) {
+ case SUCCESS:
+ break;
+ case DONE:
+ return 0;
+ default:
handleError(err);
return 1;
}
@@ -69,6 +74,8 @@ instrState Runner::execInstruction(Instruction instr) {
return execOpImmInstr(instr);
case OP:
return execOpInstr(instr);
+ case ECALL:
+ return execEcallInstr();
default:
return instrState::EXEC_ERR;
break;
@@ -223,24 +230,32 @@ instrState Runner::execOpInstr(Instruction instr) {
case 0b000: // ADD and SUB
if (fields[0] == 0) {
m_reg[fields[4]] = m_reg[fields[2]] + m_reg[fields[1]]; // ADD
+ break;
} else if (fields[0] == 0b0100000) {
m_reg[fields[4]] = m_reg[fields[2]] - m_reg[fields[1]]; // SUB
+ break;
}
case 0b001: // SLL
m_reg[fields[4]] = (int32_t)m_reg[fields[2]] << (m_reg[fields[1]] & 0x1F);
+ break;
case 0b010: // SLT
m_reg[fields[4]] =
(int32_t)m_reg[fields[2]] < (int32_t)m_reg[fields[1]] ? 1 : 0;
+ break;
case 0b011: // SLTU
m_reg[fields[4]] = m_reg[fields[2]] < m_reg[fields[1]] ? 1 : 0;
+ break;
case 0b100: // XOR
m_reg[fields[4]] = m_reg[fields[2]] ^ m_reg[fields[1]];
+ break;
case 0b101: // SRL and SRA
if (fields[0] == 0) {
m_reg[fields[4]] = m_reg[fields[2]] >> (m_reg[fields[1]] & 0x1F); // SRL
+ break;
} else if (fields[0] == 0b0100000) {
m_reg[fields[4]] =
(int32_t)m_reg[fields[2]] >> (m_reg[fields[1]] & 0x1F); // SRA
+ break;
}
case 0b110: // OR
m_reg[fields[4]] = m_reg[fields[2]] | m_reg[fields[1]];
@@ -252,6 +267,16 @@ instrState Runner::execOpInstr(Instruction instr) {
return SUCCESS;
}
+instrState Runner::execEcallInstr() {
+ switch (m_reg[10]) // a0
+ {
+ case 10:
+ return DONE;
+ default:
+ return ERR_ECALL;
+ }
+}
+
void Runner::handleError(instrState err) const {
// handle error and print program counter + current instruction
}

MODIFY
src/runner.h
src/runner.h
@@ -44,6 +44,7 @@ private:
instrState execStoreInstr(Instruction instr);
instrState execOpImmInstr(Instruction instr);
instrState execOpInstr(Instruction instr);
+ instrState execEcallInstr();
// Instruction decode functions; generated programmatically
decode_functor generateWordParser(std::vector<int> bitFields);

Implement Ecall OpCodes