Skip to content
Snippets Groups Projects
Commit 95f02f67 authored by Geo Ster's avatar Geo Ster
Browse files

Continue going through the BIOS

* Implement more instructions as usual
* Rename instr.doubleword to instr.dword for more compat code
* Add the skip branch delay slots feature for beq* instructions
parent 5cafeb61
No related branches found
No related tags found
No related merge requests found
......@@ -36,7 +36,7 @@ union Instruction {
};
union Register {
uint64_t doubleword[2];
uint64_t dword[2];
uint32_t word[4];
};
......@@ -70,6 +70,9 @@ public:
void op_tlbwi(); void op_mtc0(); void op_lw(); void op_mmi();
void op_madd1(); void op_jalr(); void op_sd(); void op_jal();
void op_sra(); void op_regimm(); void op_bgez(); void op_addu();
void op_daddu(); void op_andi(); void op_beq(); void op_or();
void op_mult(); void op_divu(); void op_beql(); void op_mflo();
void op_sltiu(); void op_bnel();
protected:
ComponentManager* manager;
......@@ -81,6 +84,8 @@ protected:
uint32_t sa;
Instruction instr, next_instr;
bool skip_branch_delay = false;
/* Scratchpad */
uint8_t scratchpad[16 * 1024];
......
......@@ -27,7 +27,7 @@ void EmotionEngine::reset_state()
next_instr.value = 0;
/* Set this to zero */
gpr[0].doubleword[0] = gpr[0].doubleword[1] = 0;
gpr[0].dword[0] = gpr[0].dword[1] = 0;
/* Set EE pRId */
cop0.prid = 0x00002E20;
......@@ -39,8 +39,16 @@ void EmotionEngine::fetch_instruction()
instr.value = next_instr.value;
next_instr = read<uint32_t>(pc);
std::cout << "PC: " << std::hex << pc - 4 << " Instruction: 0x" << instr.value << ' ' << std::dec;
//if (pc - 4 == 0x9fc43288) __debugbreak();
pc += 4;
if (skip_branch_delay)
{
skip_branch_delay = false;
std::cout << "SKIPPED delay slot\n";
return;
}
switch(instr.opcode)
{
case COP0_OPCODE: op_cop0(); break;
......@@ -57,6 +65,11 @@ void EmotionEngine::fetch_instruction()
case 0b111111: op_sd(); break;
case 0b000011: op_jal(); break;
case 0b000001: op_regimm(); break;
case 0b001100: op_andi(); break;
case 0b000100: op_beq(); break;
case 0b010100: op_beql(); break;
case 0b001011: op_sltiu(); break;
case 0b010101: op_bnel(); break;
default:
std::cout << "Unimplemented opcode: " << std::bitset<6>(instr.opcode) << '\n';
std::abort();
......@@ -123,7 +136,7 @@ void EmotionEngine::op_mfc0()
uint16_t rd = (instr.value >> 11) & 0x1F;
uint16_t rt = (instr.value >> 16) & 0x1F;
gpr[rt].doubleword[0] = cop0.regs[rd];
gpr[rt].dword[0] = cop0.regs[rd];
std::cout << "MFC0: GPR[" << rt << "] = COP0_REG[" << rd << "] (" << cop0.regs[rd] << ")\n";
}
......@@ -138,6 +151,11 @@ void EmotionEngine::op_special()
case 0b001001: op_jalr(); break;
case 0b000011: op_sra(); break;
case 0b100001: op_addu(); break;
case 0b101101: op_daddu(); break;
case 0b100101: op_or(); break;
case 0b011000: op_mult(); break;
case 0b011011: op_divu(); break;
case 0b010010: op_mflo(); break;
default:
std::cout << "Unimplemented SPECIAL instruction: " << std::bitset<6>(instr.r_type.funct) << '\n';
std::exit(1);
......@@ -163,16 +181,18 @@ void EmotionEngine::op_sw()
int16_t offset = (int16_t)instr.i_type.immediate;
uint32_t vaddr = offset + gpr[base].word[0];
if (vaddr & 0b11 != 0)
uint32_t data = gpr[rt].word[0];
std::cout << "SW: Writing GPR[" << rt << std::hex << "] (0x" << data << ") to address: 0x" << vaddr << "(0x" << gpr[base].word[0] << " + 0x" << offset << ")";
std::cout << std::dec << " = GPR[" << base << "] (0x" << std::hex << gpr[base].word[0] << ") + " << std::dec << offset << '\n';
if ((vaddr & 0b11) != 0)
{
std::cout << "SW: Address 0x" << std::hex << vaddr << " is not aligned\n";
std::exit(1); /* NOTE: SignalException (AddressError) */
}
uint32_t data = gpr[rt].word[0];
std::cout << "SW: Writing GPR[" << rt << std::hex << "] (0x" << data << ") to address: 0x" << vaddr;
std::cout << " = GPR[" << base << "] (" << gpr[base].word[0] << ") + " << std::dec << offset << '\n';
write<uint32_t>(vaddr, data);
else
write<uint32_t>(vaddr, data);
}
void EmotionEngine::op_sll()
......@@ -184,10 +204,10 @@ void EmotionEngine::op_sll()
if (instr.value == 0)
std::cout << "NOP\n";
else
std::cout << "SLL: GPR[" << rd << "] = GPR[" << rt << "] (0x" << std::hex << gpr[rd].doubleword[0] << ") << " << sa << '\n';
std::cout << "SLL: GPR[" << rd << "] = GPR[" << rt << "] (0x" << std::hex << gpr[rd].dword[0] << ") << " << sa << '\n';
uint32_t result = gpr[rt].word[0] << sa;
gpr[rd].doubleword[0] = (uint64_t)(int32_t)result;
gpr[rd].dword[0] = (uint64_t)(int32_t)result;
}
void EmotionEngine::op_slti()
......@@ -196,8 +216,8 @@ void EmotionEngine::op_slti()
uint16_t rt = instr.i_type.rt;
int64_t imm = (int64_t)(int16_t)instr.i_type.immediate;
std::cout << "SLTI: GPR[" << rt << "] = GPR[" << rs << "] (" << (int64_t)gpr[rs].doubleword[0] << ") < " << imm << '\n';
gpr[rt].doubleword[0] = (int64_t)gpr[rs].doubleword[0] < imm;
std::cout << "SLTI: GPR[" << rt << "] = GPR[" << rs << "] (" << (int64_t)gpr[rs].dword[0] << ") < " << imm << '\n';
gpr[rt].dword[0] = (int64_t)gpr[rs].dword[0] < imm;
}
void EmotionEngine::op_bne()
......@@ -207,9 +227,9 @@ void EmotionEngine::op_bne()
int32_t imm = (int16_t)instr.i_type.immediate;
int32_t offset = imm << 2;
std::cout << "BNE: || GPR[" << rt << "] (" << gpr[rt].doubleword[0] << ") != GPR[" << rs << "] (" << gpr[rs].doubleword[0];
std::cout << "BNE: || GPR[" << rt << "] (" << gpr[rt].dword[0] << ") != GPR[" << rs << "] (" << gpr[rs].dword[0];
std::cout << ")|| -> OFFSET: " << offset << '\n';
if (gpr[rs].doubleword[0] != gpr[rt].doubleword[0])
if (gpr[rs].dword[0] != gpr[rt].dword[0])
pc += offset;
}
......@@ -217,10 +237,10 @@ void EmotionEngine::op_ori()
{
uint16_t rs = instr.i_type.rs;
uint16_t rt = instr.i_type.rt;
uint64_t imm = (uint64_t)instr.i_type.immediate;
uint16_t imm = instr.i_type.immediate;
std::cout << "ORI: GPR[" << rt << "] = GPR[" << rs << "] (0x" << std::hex << gpr[rs].doubleword[0] << ") | 0x" << imm << std::dec << '\n';
gpr[rt].doubleword[0] = gpr[rs].doubleword[0] | imm;
std::cout << "ORI: GPR[" << rt << "] = GPR[" << rs << "] (0x" << std::hex << gpr[rs].dword[0] << ") | 0x" << imm << std::dec << '\n';
gpr[rt].dword[0] = gpr[rs].dword[0] | imm;
}
void EmotionEngine::op_addi()
......@@ -230,8 +250,8 @@ void EmotionEngine::op_addi()
int16_t imm = (int16_t)instr.i_type.immediate;
/* TODO: Overflow detection */
std::cout << "ADDI: GPR[" << rt << "] = GPR[" << rs << " (0x" << std::hex << gpr[rs].doubleword[0] << ") + 0x" << imm << std::dec << '\n';
gpr[rt].doubleword[0] = gpr[rs].doubleword[0] + imm;
std::cout << "ADDI: GPR[" << rt << "] = GPR[" << rs << " (0x" << std::hex << gpr[rs].dword[0] << ") + 0x" << imm << std::dec << '\n';
gpr[rt].dword[0] = gpr[rs].dword[0] + imm;
}
void EmotionEngine::op_lq()
......@@ -240,11 +260,11 @@ void EmotionEngine::op_lq()
uint16_t base = instr.i_type.rs;
int16_t imm = (int16_t)instr.i_type.immediate;
uint32_t vaddr = (gpr[base].doubleword[0] + imm) | 0b0000;
gpr[rt].doubleword[0] = read<uint64_t>(vaddr);
gpr[rt].doubleword[1] = read<uint64_t>(vaddr + 8);
uint32_t vaddr = (gpr[base].dword[0] + imm) | 0b0000;
gpr[rt].dword[0] = read<uint64_t>(vaddr);
gpr[rt].dword[1] = read<uint64_t>(vaddr + 8);
std::cout << "LQ: GPR[" << rt << "] = 0x" << std::hex << gpr[rt].doubleword[0] << " from address 0x" << vaddr << '\n';
std::cout << "LQ: GPR[" << rt << "] = 0x" << std::hex << gpr[rt].dword[0] << " from address 0x" << vaddr << '\n';
}
void EmotionEngine::op_lui()
......@@ -253,7 +273,7 @@ void EmotionEngine::op_lui()
uint32_t imm = instr.i_type.immediate;
std::cout << "LUI: GPR[" << rt << "] = 0x" << std::hex << imm << std::dec << '\n';
gpr[rt].doubleword[0] = (int64_t)(int32_t)(imm << 16);
gpr[rt].dword[0] = (int64_t)(int32_t)(imm << 16);
}
void EmotionEngine::op_jr()
......@@ -269,9 +289,9 @@ void EmotionEngine::op_addiu()
uint16_t rs = instr.i_type.rs;
int16_t imm = (int16_t)instr.i_type.immediate;
int64_t temp = gpr[rs].doubleword[0] + (int64_t)imm;
gpr[rt].doubleword[0] = (int64_t)(temp & 0xFFFFFFFF);
std::cout << "ADDIU: GPR[" << rt << "] = GPR[" << rs << "] (0x" << std::hex << gpr[rs].doubleword[0] << ") + 0x" << imm << std::dec << '\n';
int64_t temp = gpr[rs].dword[0] + (int64_t)imm;
gpr[rt].dword[0] = (int64_t)(temp & 0xFFFFFFFF);
std::cout << "ADDIU: GPR[" << rt << "] = GPR[" << rs << "] (0x" << std::hex << gpr[rs].dword[0] << ") + 0x" << imm << std::dec << '\n';
}
void EmotionEngine::op_tlbwi()
......@@ -311,7 +331,7 @@ void EmotionEngine::op_madd1()
lo1 = (int64_t)(int32_t)(result & 0xFFFFFFFF);
hi1 = (int64_t)(int32_t)(result >> 32);
gpr[rd].doubleword[0] = (int64_t)lo1;
gpr[rd].dword[0] = (int64_t)lo1;
std::cout << "MADD1: GPR[" << rd << "] = LO1 = 0x" << std::hex << (int64_t)lo1 << "and HI1 = 0x" << hi1 << std::dec << '\n';
}
......@@ -321,10 +341,10 @@ void EmotionEngine::op_jalr()
uint16_t rs = instr.r_type.rs;
uint16_t rd = instr.r_type.rd;
gpr[rd].doubleword[0] = pc + 4; /* Normally this should be PC + 8 but we compensate for the prefetching with -4 */
gpr[rd].dword[0] = pc + 4; /* Normally this should be PC + 8 but we compensate for the prefetching with -4 */
pc = gpr[rs].word[0];
std::cout << "JALR: Jumped to PC = GPR[" << rs << "] (0x" << std::hex << pc << ") with link address 0x" << gpr[rd].doubleword[0] << std::dec << '\n';
std::cout << "JALR: Jumped to PC = GPR[" << rs << "] (0x" << std::hex << pc << ") with link address 0x" << gpr[rd].dword[0] << std::dec << '\n';
}
void EmotionEngine::op_sd()
......@@ -334,13 +354,13 @@ void EmotionEngine::op_sd()
int16_t offset = (int16_t)instr.i_type.immediate;
uint32_t vaddr = offset + gpr[base].word[0];
if (vaddr & 0b111 != 0)
if ((vaddr & 0b111) != 0)
{
std::cout << "SD: Address 0x" << std::hex << vaddr << " is not aligned\n";
std::exit(1); /* NOTE: SignalException (AddressError) */
}
uint64_t data = gpr[rt].doubleword[0];
uint64_t data = gpr[rt].dword[0];
std::cout << "SD: Writing GPR[" << rt << std::hex << "] (0x" << data << ") to address: 0x" << vaddr;
std::cout << " = GPR[" << base << "] (" << gpr[base].word[0] << ") + " << std::dec << offset << '\n';
write<uint64_t>(vaddr, data);
......@@ -350,7 +370,7 @@ void EmotionEngine::op_jal()
{
uint32_t instr_index = instr.j_type.target;
gpr[31].doubleword[0] = pc + 4;
gpr[31].dword[0] = pc + 4;
pc = (pc & 0xF0000000) + (instr_index << 2);
std::cout << "JAL: Jumped to PC = 0x" << std::hex << pc << std::dec << '\n';
}
......@@ -364,8 +384,8 @@ void EmotionEngine::op_sra()
static uint32_t mask[2] = { 0x0, 0xFFFFFFFF };
uint32_t result = (mask[gpr[rt].word[0] >> 31] << sa) | (gpr[rt].word[0] >> sa);
gpr[rd].doubleword[0] = (int64_t)(gpr[rt].word[0] >> sa);
std::cout << "SRA: GPR[" << rd << "] (0x" << std::hex << gpr[rd].doubleword[0] << ") = GPR[" << rt << "] (0x";
gpr[rd].dword[0] = (int64_t)(gpr[rt].word[0] >> sa);
std::cout << "SRA: GPR[" << rd << "] (0x" << std::hex << gpr[rd].dword[0] << ") = GPR[" << rt << "] (0x";
std::cout << gpr[rt].word[0] << ") >> " << std::dec << sa << '\n';
}
......@@ -375,7 +395,7 @@ void EmotionEngine::op_bgez()
uint16_t rs = instr.i_type.rs;
int32_t offset = (int32_t)(imm << 2);
if (gpr[rs].doubleword[0] >= 0)
if (gpr[rs].dword[0] >= 0)
pc += offset;
std::cout << "BGEZ: IF GPR[" << rs << "] (0x" << std::hex << gpr[rs].word[0] << ") > 0 THEN PC += " << offset << std::dec << '\n';
......@@ -387,11 +407,136 @@ void EmotionEngine::op_addu()
uint16_t rs = instr.r_type.rs;
uint16_t rd = instr.r_type.rd;
uint64_t result = gpr[rs].doubleword[0] + gpr[rt].doubleword[0];
gpr[rd].doubleword[0] = (int64_t)(int32_t)(result & 0xFFFFFFFF);
uint64_t result = gpr[rs].dword[0] + gpr[rt].dword[0];
gpr[rd].dword[0] = (int64_t)(int32_t)(result & 0xFFFFFFFF);
std::cout << "ADDU: GPR[" << rd << "] (0x" << std::hex << gpr[rd].dword[0] << ") = GPR[" << rs << "] (0x" << gpr[rs].dword[0] << ")";
std::cout << std::dec << " + GPR[" << rt << "] (0x" << std::hex << gpr[rt].dword[0] << std::dec << ")\n";
}
void EmotionEngine::op_daddu()
{
uint16_t rt = instr.r_type.rt;
uint16_t rs = instr.r_type.rs;
uint16_t rd = instr.r_type.rd;
gpr[rd].dword[0] = gpr[rs].dword[0] + gpr[rt].dword[0];
std::cout << "DADDU: GPR[" << rd << "] (0x" << std::hex << gpr[rd].dword[0] << ") = GPR[" << rs << "] (0x" << gpr[rs].dword[0] << ")";
std::cout << std::dec << " + GPR[" << rt << "] (0x" << std::hex << gpr[rt].dword[0] << std::dec << ")\n";
}
void EmotionEngine::op_andi()
{
uint16_t rt = instr.i_type.rt;
uint16_t rs = instr.i_type.rs;
uint16_t imm = instr.i_type.immediate;
std::cout << "ADDU: GPR[" << rd << "] (0x" << std::hex << gpr[rd].doubleword[0] << ") = GPR[" << rs << "] (0x" << gpr[rs].doubleword[0] << ")";
std::cout << std::dec << " + GPR[" << rt << "] (0x" << std::hex << gpr[rt].doubleword[0] << std::dec << ")\n";
gpr[rt].dword[0] = imm & gpr[rs].dword[0];
std::cout << "ANDI: GPR[" << rt << "] (0x" << std::hex << gpr[rt].dword[0] << ") = 0x" << imm << std::dec;
std::cout << " & GPR[" << rs << "] (0x" << std::hex << gpr[rs].dword[0] << ")\n" << std::dec;
}
void EmotionEngine::op_beq()
{
uint16_t rt = instr.i_type.rt;
uint16_t rs = instr.i_type.rs;
uint32_t imm = instr.i_type.immediate;
int32_t offset = (int32_t)(imm << 2);
if (gpr[rs].dword[0] == gpr[rt].dword[0])
pc += offset;
std::cout << "BEQ: IF GPR[" << rt << "] (0x" << std::hex << gpr[rt].dword[0] << ") == GPR[" << std::dec << rs << "] (0x";
std::cout << std::hex << gpr[rs].dword[0] << ") THEN PC += 0x" << offset << std::dec << '\n';
}
void EmotionEngine::op_or()
{
uint16_t rt = instr.r_type.rt;
uint16_t rs = instr.r_type.rs;
uint16_t rd = instr.r_type.rd;
gpr[rd].dword[0] = gpr[rs].dword[0] | gpr[rt].dword[0];
std::cout << "OR: GPR[" << rd << "] (0x" << std::hex << gpr[rd].dword[0] << ") = GPR[" << std::dec << rs << "] (0x" << std::hex;
std::cout << gpr[rs].dword[0] << ") | GPR[" << std::dec << rt << "]" << std::hex << " (0x" << gpr[rt].dword[0] << std::dec << ")\n";
}
void EmotionEngine::op_mult()
{
uint16_t rt = instr.r_type.rt;
uint16_t rs = instr.r_type.rs;
uint16_t rd = instr.r_type.rd;
int64_t result = (int64_t)gpr[rs].word[0] * (int64_t)gpr[rt].word[0];
gpr[rd].dword[0] = lo0 = (int64_t)(int32_t)(result & 0xFFFFFFFF);
hi0 = (int64_t)(int32_t)(result >> 32);
std::cout << "MULT: GPR[" << rd << "] = LO0 = 0x" << std::hex << lo0 << " and HI0 = 0x" << hi0 << std::dec << '\n';
}
void EmotionEngine::op_divu()
{
uint16_t rt = instr.i_type.rt;
uint16_t rs = instr.i_type.rs;
if (gpr[rt].word[0] != 0)
{
lo0 = gpr[rs].word[0] / gpr[rt].word[0];
hi0 = gpr[rs].word[0] % gpr[rt].word[0];
std::cout << "DIVU: LO0 = GPR[" << rs << "] (0x" << std::hex << gpr[rs].word[0] << ") / GPR[" << std::dec << rt << "] (0x" << std::hex << gpr[rt].word[0] << ")\n";
}
else
{
std::cout << "DIVU: Division by zero!\n";
std::abort();
}
}
void EmotionEngine::op_beql()
{
uint16_t rt = instr.i_type.rt;
uint16_t rs = instr.i_type.rs;
uint32_t imm = instr.i_type.immediate;
int32_t offset = (int32_t)(imm << 2);
if (gpr[rs].dword[0] == gpr[rt].dword[0])
pc += offset;
else
skip_branch_delay = true;
std::cout << "BEQL: IF GPR[" << rs << "] (0x" << std::hex << gpr[rs].dword[0] << ") == GPR[" << std::dec << rt << "] (0x" << std::hex << gpr[rt].dword[0];
std::cout << ") THEN PC += " << std::dec << offset << '\n';
}
void EmotionEngine::op_mflo()
{
uint16_t rd = instr.r_type.rd;
gpr[rd].dword[0] = lo0;
std::cout << "MFLO: GPR[" << rd << "] = LO0 (0x" << std::hex << lo0 << ")\n" << std::dec;
}
void EmotionEngine::op_sltiu()
{
uint16_t rt = instr.i_type.rt;
uint16_t rs = instr.i_type.rs;
uint64_t imm = instr.i_type.immediate;
gpr[rt].dword[0] = (gpr[rs].dword[0] < imm);
std::cout << "SLTIU: GPR[" << rt << "] = GPR[" << rs << "] (0x" << std::hex << gpr[rs].dword[0] << ") < 0x" << imm << std::dec << '\n';
}
void EmotionEngine::op_bnel()
{
uint16_t rt = instr.i_type.rt;
uint16_t rs = instr.i_type.rs;
uint32_t imm = instr.i_type.immediate;
int32_t offset = (int32_t)(imm << 2);
if (gpr[rs].dword[0] != gpr[rt].dword[0])
pc += offset;
else
skip_branch_delay = true;
}
/* Template definitions. */
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment