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

Implement first FPU instruction

* Since we have encountered our first FPU register, add the 32 floating
point registers to the CPU.

* In addition solve a small bug in the JAL instruction related to the
return link address. See previous commit for details
parent 2c622b24
No related branches found
No related tags found
No related merge requests found
......@@ -11,7 +11,7 @@ include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()
# Create executable target
add_executable(${PROJECT_NAME} src/main.cpp src/common/manager.cpp src/cpu/ee.cpp)
add_executable(${PROJECT_NAME} src/main.cpp src/common/manager.cpp src/cpu/ee.cpp )
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)
# Link to all the required conan libs
......
......@@ -60,5 +60,6 @@ void ComponentManager::write(uint32_t addr, T data)
/* Template definitions. */
template uint32_t ComponentManager::read<uint32_t>(uint32_t);
template uint64_t ComponentManager::read<uint64_t>(uint32_t);
template uint8_t ComponentManager::read<uint8_t>(uint32_t);
template void ComponentManager::write<uint32_t>(uint32_t, uint32_t);
template void ComponentManager::write<uint64_t>(uint32_t, uint64_t);
\ No newline at end of file
......@@ -74,6 +74,12 @@ void EmotionEngine::fetch_instruction()
case 0b010100: op_beql(); break;
case 0b001011: op_sltiu(); break;
case 0b010101: op_bnel(); break;
case 0b100000: op_lb(); break;
case 0b111001: op_swc1(); break;
case 0b100100: op_lbu(); break;
case 0b110111: op_ld(); break;
case 0b000010: op_j(); break;
case 0b100011: op_lw(); break;
default:
fmt::print("[ERROR] Unimplemented opcode: {:#06b}\n", instr.opcode & 0x3F);
std::abort();
......@@ -205,7 +211,7 @@ void EmotionEngine::op_sll()
gpr[rd].dword[0] = (uint64_t)(int32_t)(gpr[rt].word[0] << sa);
if (instr.value == 0) fmt::print("NOP\n");
else fmt::print("SLL: GPR[{:d}] = GPR[{:d}] ({:#x}) << {:d}\n", rd, rt, gpr[rd].dword[0], sa);
else fmt::print("SLL: GPR[{:d}] = GPR[{:d}] ({:#x}) << {:d}\n", rd, rt, gpr[rt].dword[0], sa);
}
void EmotionEngine::op_slti()
......@@ -291,6 +297,82 @@ void EmotionEngine::op_sync()
fmt::print("SYNC\n");
}
void EmotionEngine::op_lb()
{
uint16_t rt = instr.i_type.rt;
uint16_t base = instr.i_type.rs;
int16_t offset = (int16_t)instr.i_type.immediate;
uint32_t vaddr = offset + gpr[base].word[0];
gpr[rt].dword[0] = (int64_t)read<uint8_t>(vaddr);
fmt::print("LB: GPR[{:d}] = {:#x} from address {:#x} = GPR[{:d}] ({:#x}) + {:#x}\n", rt, gpr[rt].dword[0], vaddr, base, gpr[base].word[0], offset);
}
void EmotionEngine::op_swc1()
{
uint16_t base = instr.i_type.rs;
uint16_t ft = instr.i_type.rt;
int16_t offset = (int16_t)instr.i_type.immediate;
uint32_t vaddr = offset + gpr[base].word[0];
uint32_t data = fpr[ft].word[0];
fmt::print("SWC1: Writing FPR[{:d}] ({:#x}) to address {:#x} = GPR[{:d}] ({:#x}) + {:d}\n", ft, data, vaddr, base, gpr[base].word[0], offset);
if ((vaddr & 0b11) != 0)
{
fmt::print("[ERROR] SW: Address {:#x} is not aligned\n", vaddr);
std::exit(1); /* NOTE: SignalException (AddressError) */
}
else
write<uint32_t>(vaddr, data);
}
void EmotionEngine::op_lbu()
{
uint16_t rt = instr.i_type.rt;
uint16_t base = instr.i_type.rs;
int16_t offset = (int16_t)instr.i_type.immediate;
uint32_t vaddr = offset + gpr[base].word[0];
gpr[rt].dword[0] = read<uint8_t>(vaddr);
fmt::print("LBU: GPR[{:d}] = {:#x} from address {:#x} = GPR[{:d}] ({:#x}) + {:#x}\n", rt, gpr[rt].dword[0], vaddr, base, gpr[base].word[0], offset);
}
void EmotionEngine::op_ld()
{
uint16_t rt = instr.i_type.rt;
uint16_t base = instr.i_type.rs;
int16_t offset = (int16_t)instr.i_type.immediate;
uint32_t vaddr = offset + gpr[base].word[0];
gpr[rt].dword[0] = read<uint64_t>(vaddr);
fmt::print("LD: GPR[{:d}] = {:#x} from address {:#x} = GPR[{:d}] ({:#x}) + {:#x}\n", rt, gpr[rt].dword[0], vaddr, base, gpr[base].word[0], offset);
}
void EmotionEngine::op_j()
{
uint32_t instr_index = instr.j_type.target;
pc = (pc & 0xF0000000) | (instr_index << 2);
fmt::print("J: Jumping to PC = {:#x}\n", pc);
}
void EmotionEngine::op_lw()
{
uint16_t rt = instr.i_type.rt;
uint16_t base = instr.i_type.rs;
int16_t offset = (int16_t)instr.i_type.immediate;
uint32_t vaddr = offset + gpr[base].word[0];
gpr[rt].dword[0] = (int32_t)read<uint32_t>(vaddr);
fmt::print("LW: GPR[{:d}] = {:#x} from address {:#x} = GPR[{:d}] ({:#x}) + {:#x}\n", rt, gpr[rt].dword[0], vaddr, base, gpr[base].word[0], offset);
}
void EmotionEngine::op_addiu()
{
uint16_t rt = instr.i_type.rt;
......@@ -379,7 +461,7 @@ void EmotionEngine::op_jal()
{
uint32_t instr_index = instr.j_type.target;
gpr[31].dword[0] = pc + 4;
gpr[31].dword[0] = pc;
pc = (pc & 0xF0000000) | (instr_index << 2);
fmt::print("JAL: Jumping to PC = {:#x}\n", pc);
......@@ -550,5 +632,6 @@ void EmotionEngine::op_bnel()
/* Template definitions. */
template uint32_t EmotionEngine::read<uint32_t>(uint32_t);
template uint64_t EmotionEngine::read<uint64_t>(uint32_t);
template uint8_t EmotionEngine::read<uint8_t>(uint32_t);
template void EmotionEngine::write<uint32_t>(uint32_t, uint32_t);
template void EmotionEngine::write<uint64_t>(uint32_t, uint64_t);
\ No newline at end of file
......@@ -88,7 +88,8 @@ public:
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(); void op_sync();
void op_sltiu(); void op_bnel(); void op_sync(); void op_lb();
void op_swc1(); void op_lbu(); void op_ld(); void op_j();
protected:
ComponentManager* manager;
......@@ -100,6 +101,10 @@ protected:
uint32_t sa;
Instruction instr, next_instr;
/* FPU (COP1) registers */
Register fpr[32];
uint64_t fcr0, fcr31;
bool skip_branch_delay = false;
/* Scratchpad */
......
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