diff --git a/PSEMU/Bus.h b/PSEMU/Bus.h index 69cae3f..3745bad 100644 --- a/PSEMU/Bus.h +++ b/PSEMU/Bus.h @@ -5,6 +5,7 @@ #include "Bios.h" #include "Range.h" #include "RAM.h" +#include "DMA.h" class Bus { public: @@ -20,7 +21,7 @@ class Bus { const Range EXPANSION_1 = Range(0x1f000000, 512 * 1024); const Range IRQ_CONTROL = Range(0x1f801070, 8); const Range TIMERS = Range(0x1f801100, 0x30); - const Range DMA = Range(0x1f801080, 0x80); + const Range _DMA = Range(0x1f801080, 0x80); const Range GPU = Range(0x1f801810, 8); const Range MEM_CONTROL = Range(0x1f801000, 36); @@ -28,25 +29,29 @@ class Bus { // Index address space in 512MB chunks uint32_t index = (addr >> 29); - return addr & region_mask[index]; + return (addr & region_mask[index]); } // Load and Store functions uint32_t load32(uint32_t addr) { + + if (addr % 4 != 0) { + throw std::runtime_error("[Bus] ERROR: Unaligned load32 address " + std::to_string(addr)); + } + uint32_t abs_addr = mask_region(addr); - if (RAM_.contains(abs_addr)) { - return ram.load32(RAM_.offset(abs_addr)); - } else if (BIOS.contains(abs_addr)) { - return bios.load32(BIOS.offset(abs_addr)); - } else if (IRQ_CONTROL.contains(abs_addr)) { - std::cout << "[BUS] WARNING: IRQ CONTROL NOT IMPLEMENTED. IRQ control read " << std::to_string(IRQ_CONTROL.offset(abs_addr)) << "\n"; - return 0; - } else if (DMA.contains(abs_addr)) { - std::cout << "[BUS] WARNING: DMA NOT IMPLEMENTED. DMA read: " << std::to_string(DMA.offset(abs_addr)) << "\n"; + if (auto offset = RAM_.contains(abs_addr); offset.has_value()) { + return ram.load32(offset.value()); + } else if (auto offset = BIOS.contains(abs_addr); offset.has_value()) { + return bios.load32(offset.value()); + } else if (auto offset = IRQ_CONTROL.contains(abs_addr); offset.has_value()) { + std::cout << "[BUS] WARNING: IRQ CONTROL NOT IMPLEMENTED. IRQ control read " << std::to_string(offset.value()) << "\n"; return 0; - } else if (GPU.contains(abs_addr)) { - std::cout << "[BUS] WARNING: GPU NOT IMPLEMENTED. GPU read " << std::to_string(GPU.offset(abs_addr)) << "\n"; - switch (GPU.offset(abs_addr)) { + } else if (auto offset = _DMA.contains(abs_addr); offset.has_value()) { + dma_reg(offset.value()); + } else if (auto offset = GPU.contains(abs_addr); offset.has_value()) { + std::cout << "[BUS] WARNING: GPU NOT IMPLEMENTED. GPU read " << std::to_string(offset.value()) << "\n"; + switch (offset.value()) { case 4: return 0x1c000000; break; @@ -56,38 +61,34 @@ class Bus { } } - if (addr % 4 != 0) { - throw std::runtime_error("[Bus] ERROR: Unaligned load32 address " + std::to_string(addr)); - } - throw std::runtime_error("[Bus] ERROR: Unhandled fetch32 at address " + std::to_string(addr)); } void store32(uint32_t addr, uint32_t value) { uint32_t abs_addr = mask_region(addr); - if (RAM_.contains(abs_addr)) { - ram.store32(RAM_.offset(abs_addr), value); + if (auto offset = RAM_.contains(abs_addr); offset.has_value()) { + ram.store32(offset.value(), value); return; - } else if (BIOS.contains(abs_addr)) { - bios.store32(BIOS.offset(abs_addr), value); + } else if (auto offset = BIOS.contains(abs_addr); offset.has_value()) { + bios.store32(offset.value(), value); return; - } else if (IRQ_CONTROL.contains(abs_addr)) { - std::cout << "[BUS] WARNING: IRQ CONTROL NOT IMPLEMENTED. IRQ control: " << std::to_string(IRQ_CONTROL.offset(abs_addr)) << " " << std::to_string(value) << "\n"; + } else if (auto offset = IRQ_CONTROL.contains(abs_addr); offset.has_value()) { + std::cout << "[BUS] WARNING: IRQ CONTROL NOT IMPLEMENTED. IRQ control: " << std::to_string(offset.value()) << " " << std::to_string(value) << "\n"; return; - } else if (DMA.contains(abs_addr)) { + } else if (auto offset = _DMA.contains(abs_addr); offset.has_value()) { std::cout << "[BUS] WARNING: DMA NOT IMPLEMENTED. DMA write: " << std::to_string(abs_addr) << std::to_string(value) << "\n"; return; - } else if (GPU.contains(abs_addr)) { - std::cout << "[BUS] WARNING: GPU NOT IMPLEMENTED. GPU write " << std::to_string(GPU.offset(abs_addr)) << " " << std::to_string(value) << "\n"; + } else if (auto offset = GPU.contains(abs_addr); offset.has_value()) { + std::cout << "[BUS] WARNING: GPU NOT IMPLEMENTED. GPU write " << std::to_string(offset.value()) << " " << std::to_string(value) << "\n"; return; - } else if (TIMERS.contains(abs_addr)) { - std::cout << "[BUS] WARNING: Timer NOT IMPLEMENTED. Timer write register" << std::to_string(TIMERS.offset(abs_addr)) << " " << std::to_string(value) << "\n"; + } else if (auto offset = TIMERS.contains(abs_addr); offset.has_value()) { + std::cout << "[BUS] WARNING: Timer NOT IMPLEMENTED. Timer write register" << std::to_string(offset.value()) << " " << std::to_string(value) << "\n"; return; - } else if (CACHE_CONTROL.contains(abs_addr)) { - std::cout << "[Bus] WARNING: Cache Control not implemented. Cache Control read " << std::to_string(IRQ_CONTROL.offset(abs_addr)) << " " << std::to_string(value) << "\n"; + } else if (auto offset = CACHE_CONTROL.contains(abs_addr); offset.has_value()) { + std::cout << "[Bus] WARNING: Cache Control not implemented. Cache Control read " << std::to_string(offset.value()) << " " << std::to_string(value) << "\n"; return; - } else if (MEM_CONTROL.contains(abs_addr)) { - switch (MEM_CONTROL.offset(abs_addr)) { + } else if (auto offset = MEM_CONTROL.contains(abs_addr); offset.has_value()) { + switch (offset.value()) { case 0: if (value != 0x1f000000) { std::cout << "[Bus] ERROR: Bad Expansion 1 base address: " << std::to_string(value) << "\n"; @@ -99,11 +100,11 @@ class Bus { } break; default: - std::cout << "[Bus] ERROR: Unhandled write to MEM Control " << std::to_string(IRQ_CONTROL.offset(abs_addr)) << " " << std::to_string(value) << "\n"; + std::cout << "[Bus] ERROR: Unhandled write to MEM Control " << std::to_string(offset.value()) << " " << std::to_string(value) << "\n"; break; } return; - } else if (RAM_SIZE.contains(abs_addr)) { + } else if (auto offset = RAM_SIZE.contains(abs_addr); offset.has_value()) { return; } @@ -117,17 +118,17 @@ class Bus { void store16(uint32_t addr, uint16_t value) { uint32_t abs_addr = mask_region(addr); - if (RAM_.contains(abs_addr)) { - ram.store16(RAM_.offset(abs_addr), value); + if (auto offset = RAM_.contains(abs_addr); offset.has_value()) { + ram.store16(offset.value(), value); return; - } else if (SPU.contains(abs_addr)) { - std::cout << "[BUS] WARNING: SPU NOT IMPLEMENTED. SPU write register " << std::to_string(SPU.offset(abs_addr)) << "\n"; + } else if (auto offset = SPU.contains(abs_addr); offset.has_value()) { + std::cout << "[BUS] WARNING: SPU NOT IMPLEMENTED. SPU write register " << std::to_string(offset.value()) << "\n"; return; - } else if (TIMERS.contains(abs_addr)) { - std::cout << "[BUS] WARNING: TIMER NOT IMPLEMENTED. Timer write register " << std::to_string(TIMERS.offset(abs_addr)) << "\n"; + } else if (auto offset = TIMERS.contains(abs_addr); offset.has_value()) { + std::cout << "[BUS] WARNING: TIMER NOT IMPLEMENTED. Timer write register " << std::to_string(offset.value()) << "\n"; return; - } else if (IRQ_CONTROL.contains(abs_addr)) { - std::cout << "[BUS] WARNING: IRQ CONTROL NOT IMPLEMENTED. IRQ control write " << std::to_string(IRQ_CONTROL.offset(abs_addr)) << " " << std::to_string(value) << "\n"; + } else if (auto offset = IRQ_CONTROL.contains(abs_addr); offset.has_value()) { + std::cout << "[BUS] WARNING: IRQ CONTROL NOT IMPLEMENTED. IRQ control write " << std::to_string(offset.value()) << " " << std::to_string(value) << "\n"; return; } @@ -141,11 +142,11 @@ class Bus { void store8(uint32_t addr, uint8_t value) { uint32_t abs_addr = mask_region(addr); - if (RAM_.contains(abs_addr)) { - ram.store8(RAM_.offset(abs_addr), value); + if (auto offset = RAM_.contains(abs_addr); offset.has_value()) { + ram.store8(offset.value(), value); return; - } else if (EXPANSION_2.contains(abs_addr)) { - std::cout << "[BUS] WARNING: Expansion 2 NOT IMPLEMENTED. Expansion 2 read register " << std::to_string(EXPANSION_2.offset(abs_addr)) << "\n"; + } else if (auto offset = EXPANSION_2.contains(abs_addr); offset.has_value()) { + std::cout << "[BUS] WARNING: Expansion 2 NOT IMPLEMENTED. Expansion 2 read register " << std::to_string(offset.value()) << "\n"; return; } @@ -160,12 +161,12 @@ class Bus { uint8_t load8(uint32_t addr) { uint32_t abs_addr = mask_region(addr); - if (RAM_.contains(abs_addr)) { - return ram.load8(RAM_.offset(abs_addr)); - } else if (BIOS.contains(abs_addr)) { - return bios.load8(BIOS.offset(abs_addr)); - } else if (EXPANSION_1.contains(abs_addr)) { - std::cout << "[BUS] WARNING: Expansion 1 NOT IMPLEMENTED. Expansion 1 read register " << std::to_string(EXPANSION_1.offset(abs_addr)) << "\n"; + if (auto offset = RAM_.contains(abs_addr); offset.has_value()) { + return ram.load8(offset.value()); + } else if (auto offset = BIOS.contains(abs_addr); offset.has_value()) { + return bios.load8(offset.value()); + } else if (auto offset = EXPANSION_1.contains(abs_addr); offset.has_value()) { + std::cout << "[BUS] WARNING: Expansion 1 NOT IMPLEMENTED. Expansion 1 read register " << std::to_string(offset.value()) << "\n"; return 0; } @@ -175,21 +176,35 @@ class Bus { uint16_t load16(uint8_t addr) { uint32_t abs_addr = mask_region(addr); - if (RAM_.contains(abs_addr)) { - return ram.load16(RAM_.offset(abs_addr)); - } else if (SPU.contains(abs_addr)) { - std::cout << "[BUS] WARNING: SPU NOT IMPLEMENTED. SPU read register " << std::to_string(SPU.offset(abs_addr)) << "\n"; + if (auto offset = RAM_.contains(abs_addr); offset.has_value()) { + return ram.load16(offset.value()); + } else if (auto offset = SPU.contains(abs_addr); offset.has_value()) { + std::cout << "[BUS] WARNING: SPU NOT IMPLEMENTED. SPU read register " << std::to_string(offset.value()) << "\n"; return 0; - } else if (IRQ_CONTROL.contains(abs_addr)) { - std::cout << "[BUS] WARNING: IRQ CONTROL NOT IMPLEMENTED. IRQ control read " << std::to_string(IRQ_CONTROL.offset(abs_addr)) << "\n"; + } else if (auto offset = IRQ_CONTROL.contains(abs_addr); offset.has_value()) { + std::cout << "[BUS] WARNING: IRQ CONTROL NOT IMPLEMENTED. IRQ control read " << std::to_string(offset.value()) << "\n"; return 0; } throw std::runtime_error("[Bus] ERROR: Unhandled load16 into address " + std::to_string(addr)); } + uint32_t dma_reg(uint32_t offset) { + switch (offset){ + case 0x70: + return dma.get_control(); + break; + + default: + std::cout << "[BUS] Unhandled DMA access\n"; + return 0; + break; + } + } + Bios bios; RAM ram; + DMA dma; const uint32_t region_mask[8] = { 0xffffffff, 0xffffffff, diff --git a/PSEMU/CPU.cpp b/PSEMU/CPU.cpp index 394c407..70e3d60 100644 --- a/PSEMU/CPU.cpp +++ b/PSEMU/CPU.cpp @@ -13,6 +13,8 @@ void CPU::reset() { regs[i] = 0xdeadbeef; out_regs[i] = 0xdeadbeef; } + out_regs[0] = 0; + regs[0] = 0; load = std::make_tuple(0, 0); sr = 0; cause = 0; @@ -50,7 +52,7 @@ void CPU::fetch() { } void CPU::decode_execute(Instruction instruction) { - std::cout << "instruction: " << instruction.instruction << "\n"; + std::cout << "PC: " << pc << "\n"; switch (instruction.opcode()) { case (0b000000): switch (instruction.function()) { diff --git a/PSEMU/DMA.cpp b/PSEMU/DMA.cpp new file mode 100644 index 0000000..e7ef967 --- /dev/null +++ b/PSEMU/DMA.cpp @@ -0,0 +1 @@ +#include "DMA.h" diff --git a/PSEMU/DMA.h b/PSEMU/DMA.h new file mode 100644 index 0000000..d690ddf --- /dev/null +++ b/PSEMU/DMA.h @@ -0,0 +1,15 @@ +#pragma once +#include + +class DMA { +public: + DMA() { + control = 0x07654321; + } + + uint32_t get_control() { return control; } + +private: + uint32_t control; +}; + diff --git a/PSEMU/PSEMU.cpp b/PSEMU/PSEMU.cpp index a5744d1..52e1e89 100644 --- a/PSEMU/PSEMU.cpp +++ b/PSEMU/PSEMU.cpp @@ -18,5 +18,8 @@ int main() { while (true) { cpu.tick(); } + for (int i = 0; i < 2 * 1024 * 1024; i++) { + std::cout << bus.ram.load32(i) << "\n"; + } return 0; } diff --git a/PSEMU/PSEMU.vcxproj b/PSEMU/PSEMU.vcxproj index 945571e..9cafa2b 100644 --- a/PSEMU/PSEMU.vcxproj +++ b/PSEMU/PSEMU.vcxproj @@ -132,6 +132,7 @@ + @@ -144,6 +145,7 @@ + diff --git a/PSEMU/PSEMU.vcxproj.filters b/PSEMU/PSEMU.vcxproj.filters index accdfbb..847af09 100644 --- a/PSEMU/PSEMU.vcxproj.filters +++ b/PSEMU/PSEMU.vcxproj.filters @@ -28,6 +28,9 @@ {8524c40f-742d-4742-baa0-fa4732042965} + + {3dcc3f34-d96f-4c55-abea-df2abfcfccee} + @@ -45,6 +48,9 @@ Source Files\Bus\RAM + + Source Files\Bus\DMA + @@ -70,5 +76,8 @@ Source Files\Bus\RAM + + Source Files\Bus\DMA + \ No newline at end of file diff --git a/PSEMU/RAM.cpp b/PSEMU/RAM.cpp index f09da68..96eb9f8 100644 --- a/PSEMU/RAM.cpp +++ b/PSEMU/RAM.cpp @@ -2,7 +2,7 @@ void RAM::newl() { for (int i = 0; i < (2 * 1024 * 1024); i++) { - ram[i] = 0x0; + ram[i] = 0xca; } } diff --git a/PSEMU/Range.h b/PSEMU/Range.h index 712ed21..52d0b87 100644 --- a/PSEMU/Range.h +++ b/PSEMU/Range.h @@ -10,11 +10,10 @@ struct Range { Range(uint32_t s, uint32_t l) : start(s), length(l) {} - inline bool contains(uint32_t addr) const { - return (addr >= start && addr < start + length); - } - - inline uint32_t offset(uint32_t addr) const { - return addr - start; + std::optional contains(uint32_t addr) const { + if (addr >= start && addr < start + length) + return (addr - start); + else + return std::nullopt; } }; diff --git a/PSEMU/x64/Debug/CPU.obj b/PSEMU/x64/Debug/CPU.obj index 138243a..76c9d20 100644 Binary files a/PSEMU/x64/Debug/CPU.obj and b/PSEMU/x64/Debug/CPU.obj differ diff --git a/PSEMU/x64/Debug/PSEMU.ilk b/PSEMU/x64/Debug/PSEMU.ilk index d0fa773..8f06be7 100644 Binary files a/PSEMU/x64/Debug/PSEMU.ilk and b/PSEMU/x64/Debug/PSEMU.ilk differ diff --git a/PSEMU/x64/Debug/PSEMU.log b/PSEMU/x64/Debug/PSEMU.log index 84cd62b..3ad9565 100644 --- a/PSEMU/x64/Debug/PSEMU.log +++ b/PSEMU/x64/Debug/PSEMU.log @@ -3,9 +3,10 @@ C:\Users\ronit\Desktop\PSEMU\PSEMU\CPU.h(114,1): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence C:\Users\ronit\Desktop\PSEMU\PSEMU\CPU.h(123,1): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence C:\Users\ronit\Desktop\PSEMU\PSEMU\CPU.h(132,1): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence -C:\Users\ronit\Desktop\PSEMU\PSEMU\CPU.cpp(826,53): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence -C:\Users\ronit\Desktop\PSEMU\PSEMU\CPU.cpp(1102,16): warning C4244: 'initializing': conversion from 'uint64_t' to 'uint32_t', possible loss of data -C:\Users\ronit\Desktop\PSEMU\PSEMU\CPU.cpp(1104,23): warning C4293: '>>': shift count negative or too big, undefined behavior +C:\Users\ronit\Desktop\PSEMU\PSEMU\CPU.cpp(828,53): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence +C:\Users\ronit\Desktop\PSEMU\PSEMU\CPU.cpp(1104,16): warning C4244: 'initializing': conversion from 'uint64_t' to 'uint32_t', possible loss of data +C:\Users\ronit\Desktop\PSEMU\PSEMU\CPU.cpp(1106,23): warning C4293: '>>': shift count negative or too big, undefined behavior + DMA.cpp PSEMU.cpp C:\Users\ronit\Desktop\PSEMU\PSEMU\CPU.h(114,1): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence C:\Users\ronit\Desktop\PSEMU\PSEMU\CPU.h(123,1): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence diff --git a/PSEMU/x64/Debug/PSEMU.obj b/PSEMU/x64/Debug/PSEMU.obj index 6d7e6c9..04a91e3 100644 Binary files a/PSEMU/x64/Debug/PSEMU.obj and b/PSEMU/x64/Debug/PSEMU.obj differ diff --git a/PSEMU/x64/Debug/PSEMU.tlog/CL.command.1.tlog b/PSEMU/x64/Debug/PSEMU.tlog/CL.command.1.tlog index 2d1f443..e5b6768 100644 Binary files a/PSEMU/x64/Debug/PSEMU.tlog/CL.command.1.tlog and b/PSEMU/x64/Debug/PSEMU.tlog/CL.command.1.tlog differ diff --git a/PSEMU/x64/Debug/PSEMU.tlog/CL.read.1.tlog b/PSEMU/x64/Debug/PSEMU.tlog/CL.read.1.tlog index 5de48c1..6f9aeec 100644 Binary files a/PSEMU/x64/Debug/PSEMU.tlog/CL.read.1.tlog and b/PSEMU/x64/Debug/PSEMU.tlog/CL.read.1.tlog differ diff --git a/PSEMU/x64/Debug/PSEMU.tlog/CL.write.1.tlog b/PSEMU/x64/Debug/PSEMU.tlog/CL.write.1.tlog index f061f7b..136e026 100644 Binary files a/PSEMU/x64/Debug/PSEMU.tlog/CL.write.1.tlog and b/PSEMU/x64/Debug/PSEMU.tlog/CL.write.1.tlog differ diff --git a/PSEMU/x64/Debug/PSEMU.tlog/Cl.items.tlog b/PSEMU/x64/Debug/PSEMU.tlog/Cl.items.tlog index d9fdd3f..e8c3608 100644 --- a/PSEMU/x64/Debug/PSEMU.tlog/Cl.items.tlog +++ b/PSEMU/x64/Debug/PSEMU.tlog/Cl.items.tlog @@ -1,5 +1,6 @@ C:\Users\ronit\Desktop\PSEMU\PSEMU\Bios.cpp;C:\Users\ronit\Desktop\PSEMU\PSEMU\x64\Debug\Bios.obj C:\Users\ronit\Desktop\PSEMU\PSEMU\Bus.cpp;C:\Users\ronit\Desktop\PSEMU\PSEMU\x64\Debug\Bus.obj C:\Users\ronit\Desktop\PSEMU\PSEMU\CPU.cpp;C:\Users\ronit\Desktop\PSEMU\PSEMU\x64\Debug\CPU.obj +C:\Users\ronit\Desktop\PSEMU\PSEMU\DMA.cpp;C:\Users\ronit\Desktop\PSEMU\PSEMU\x64\Debug\DMA.obj C:\Users\ronit\Desktop\PSEMU\PSEMU\PSEMU.cpp;C:\Users\ronit\Desktop\PSEMU\PSEMU\x64\Debug\PSEMU.obj C:\Users\ronit\Desktop\PSEMU\PSEMU\RAM.cpp;C:\Users\ronit\Desktop\PSEMU\PSEMU\x64\Debug\RAM.obj diff --git a/PSEMU/x64/Debug/PSEMU.tlog/link.command.1.tlog b/PSEMU/x64/Debug/PSEMU.tlog/link.command.1.tlog index dffabcf..c81e7e1 100644 Binary files a/PSEMU/x64/Debug/PSEMU.tlog/link.command.1.tlog and b/PSEMU/x64/Debug/PSEMU.tlog/link.command.1.tlog differ diff --git a/PSEMU/x64/Debug/PSEMU.tlog/link.read.1.tlog b/PSEMU/x64/Debug/PSEMU.tlog/link.read.1.tlog index 860ea9e..6c78b48 100644 Binary files a/PSEMU/x64/Debug/PSEMU.tlog/link.read.1.tlog and b/PSEMU/x64/Debug/PSEMU.tlog/link.read.1.tlog differ diff --git a/PSEMU/x64/Debug/PSEMU.tlog/link.write.1.tlog b/PSEMU/x64/Debug/PSEMU.tlog/link.write.1.tlog index 22fbdc6..756aa94 100644 Binary files a/PSEMU/x64/Debug/PSEMU.tlog/link.write.1.tlog and b/PSEMU/x64/Debug/PSEMU.tlog/link.write.1.tlog differ diff --git a/PSEMU/x64/Debug/vc143.idb b/PSEMU/x64/Debug/vc143.idb index dd66a40..a9df04a 100644 Binary files a/PSEMU/x64/Debug/vc143.idb and b/PSEMU/x64/Debug/vc143.idb differ diff --git a/PSEMU/x64/Debug/vc143.pdb b/PSEMU/x64/Debug/vc143.pdb index d404e17..8ec0535 100644 Binary files a/PSEMU/x64/Debug/vc143.pdb and b/PSEMU/x64/Debug/vc143.pdb differ diff --git a/x64/Debug/PSEMU.exe b/x64/Debug/PSEMU.exe index e24793a..e8eb773 100644 Binary files a/x64/Debug/PSEMU.exe and b/x64/Debug/PSEMU.exe differ diff --git a/x64/Debug/PSEMU.pdb b/x64/Debug/PSEMU.pdb index 168ee60..9af0bf9 100644 Binary files a/x64/Debug/PSEMU.pdb and b/x64/Debug/PSEMU.pdb differ