namespace SA1100 {
-Emulator::Emulator() : EmuBase(false) {}
+Emulator::Emulator() : EmuBase(false) {
+ mOsTimer = new OsTimer();
+ mLcdController = new LCDController();
+ mGpioController = new GPIOController();
+ mUart = new Uart(getSerialOutput());
+ mResetController = new ResetController();
+ mRtc = new RTC(getClockSpeed());
+ mIntController =
+ new IntController(mLcdController, mOsTimer, mGpioController, mUart, mRtc);
+ mPowerManager = new PowerManager();
+
+ MemoryBlockC0 = new uint8_t[MemoryBlockMask + 1];
+ MemoryBlockC8 = new uint8_t[MemoryBlockMask + 1];
+ ROM = new uint8_t[0x1000000];
+}
+
+Emulator::~Emulator() {
+ delete mOsTimer;
+ delete mLcdController;
+ delete mGpioController;
+ delete mIntController;
+ delete mPowerManager;
+ delete mResetController;
+ delete mRtc;
+ delete[] MemoryBlockC0;
+ delete[] MemoryBlockC8;
+ delete[] ROM;
+}
uint32_t Emulator::getRTC() { return 0; }
configured = true;
srand(1000);
nextTickAt = Series7::TICK_INTERVAL;
+ setProcessorID(0x4401A111);
+
+ mMemoryController.reset();
+ mPowerManager->reset();
+ mOsTimer->reset();
+ mLcdController->reset();
+ mIntController->reset();
+ mGpioController->reset();
+ mRtc->reset();
reset();
}
if (!configured)
configure();
+ if (mResetController->resetRequested()) {
+ mResetController->reset();
+ mMemoryController.reset();
+ mPowerManager->reset();
+ mOsTimer->reset();
+ mLcdController->reset();
+ mIntController->reset();
+ mGpioController->reset();
+ mRtc->reset();
+ reset();
+ }
+
while (!asleep && passedCycles < cycles) {
if (passedCycles >= nextTickAt) {
// increment RTCDIV
nextTickAt += Series7::TICK_INTERVAL;
}
+ mRtc->run(passedCycles);
+ mGpioController->run();
+ mUart->run(passedCycles);
+ mIntController->run();
+ mOsTimer->tick();
+
+ if (mIntController->havePendingFiq() && canAcceptFIQ()) {
+ requestFIQ();
+ halted = false;
+ }
+ if (mIntController->havePendingIrq() && canAcceptIRQ()) {
+ requestIRQ();
+ halted = false;
+ }
+
// what's running?
if (halted) {
// keep the clock moving
#include "emubase.h"
#include "series7_defs.h"
+#include "gpio_controller.h"
+#include "interrupt_controller.h"
+#include "lcd_controller.h"
+#include "memory_controller.h"
+#include "os_timer.h"
+#include "power_manager.h"
+#include "reset_controller.h"
+#include "rtc.h"
+#include "uart.h"
+
namespace SA1100 {
// Relatively simple implementation of a StrongARM SA-1100 CPU
class Emulator : public EmuBase {
public:
- // 16MB ROM
- uint8_t ROM[0x1000000];
- // 16MB RAM/bank0, mapped at base addr 0xC0000000
- uint8_t MemoryBlockC0[0x1000000];
- // 16MB RAM/bank1, mapped at base addr 0xC8000000
+ uint8_t* ROM;
+ // RAM/bank0, mapped at base addr 0xC0000000
+ uint8_t* MemoryBlockC0;
+ // RAM/bank1, mapped at base addr 0xC8000000
// On the netBook, the OS.img minus the 256-byte wrapper is copied to this RAM
// See the bookboot README file (linked above)
- uint8_t MemoryBlockC8[0x1000000];
- enum { MemoryBlockMask = 0x0FFFFFF };
+ uint8_t* MemoryBlockC8;
+ const uint32_t MemoryBlockMask = 0x0FFFFFF;
private:
uint32_t pwrsr = 0x00002000; // cold start flag
bool halted = false, asleep = false;
uint32_t getRTC();
+ MemoryController mMemoryController;
+ GPIOController* mGpioController;
+ LCDController* mLcdController;
+ OsTimer* mOsTimer;
+ IntController* mIntController;
+ PowerManager* mPowerManager;
+ ResetController* mResetController;
+ RTC* mRtc;
+ Uart* mUart;
+
public:
MaybeU32 readPhysical(uint32_t physAddr, ValueSize valueSize) override;
bool writePhysical(uint32_t value, uint32_t physAddr,
public:
Emulator();
+ virtual ~Emulator();
+
uint8_t* getROMBuffer() override;
size_t getROMSize() override;
void loadROM(uint8_t* buffer, size_t size) override;
bool Emulator::writePCM8(uint8_t value, uint32_t physAddr) { return true; }
uint32_t Emulator::readPCM32(uint32_t physAddr) {
- // Peripheral Control Modules
- return 0x0;
+ uint16_t region = (physAddr >> 16) & 0xFFFF;
+
+ switch (region) {
+ case 0x8005:
+ // UART
+ return mUart->read32(physAddr);
+ default:
+ return 0x0;
+ }
}
-bool Emulator::writePCM32(uint32_t value, uint32_t physAddr) { return true; }
+bool Emulator::writePCM32(uint32_t value, uint32_t physAddr) {
+ uint16_t region = (physAddr >> 16) & 0xFFFF;
+ switch (region) {
+ case 0x8005:
+ // UART
+ mUart->write32(physAddr, value);
+ return true;
+ default:
+ return true;
+ }
+}
uint8_t Emulator::readSCM8(uint32_t physAddr) {
// System Control Modules
return 0x0;
bool Emulator::writeSCM8(uint8_t value, uint32_t physAddr) { return true; }
uint32_t Emulator::readSCM32(uint32_t physAddr) {
- // System Control Modules
- return 0x0;
+ uint16_t region = (physAddr >> 16) & 0xFFFF;
+
+ switch (region) {
+ case 0x9000:
+ // OS Timer
+ return mOsTimer->read32(physAddr);
+ case 0x9001:
+ // RTC
+ return mRtc->read32(physAddr);
+ case 0x9002:
+ // Power manager
+ return mPowerManager->read32(physAddr);
+ case 0x9003:
+ // Reset controller
+ return mResetController->read32(physAddr);
+ case 0x9004:
+ // GPIO
+ return mGpioController->read32(physAddr);
+ case 0x9005:
+ // Interrupt Controller
+ return mIntController->read32(physAddr);
+ case 0x9006:
+ // PPC
+ return 0;
+ default:
+ printf("Tried to read %08x\n", physAddr);
+ return 0x0;
+ }
}
-bool Emulator::writeSCM32(uint32_t value, uint32_t physAddr) { return true; }
+bool Emulator::writeSCM32(uint32_t value, uint32_t physAddr) {
+ uint16_t region = (physAddr >> 16) & 0xFFFF;
+
+ switch (region) {
+ case 0x9000:
+ // OS Timer
+ mOsTimer->write32(physAddr, value);
+ return true;
+ case 0x9001:
+ // RTC
+ mRtc->write32(physAddr, value);
+ return true;
+ case 0x9002:
+ // Power manager
+ mPowerManager->write32(physAddr, value);
+ return true;
+ case 0x9003:
+ // Reset controller
+ mResetController->write32(physAddr, value);
+ return true;
+ case 0x9004:
+ // GPIO
+ mGpioController->write32(physAddr, value);
+ return true;
+ case 0x9005:
+ // Interrupt Controller
+ mIntController->write32(physAddr, value);
+ return true;
+ case 0x9006:
+ // PPC
+ return true;
+ default:
+ LOG_REG_W("Unknown", physAddr, value);
+ return true;
+ }
+}
uint8_t Emulator::readPhysical8(uint32_t physAddr) {
uint8_t region = (physAddr >> 24) & 0xFF;
break;
case 0xA0:
// Memory Control Registers
- result = 0x0;
+ result = mMemoryController.read32(physAddr);
break;
case 0xB0:
// LCD/DMA Control Registers
- result = 0x0;
+ result = mLcdController->read32(physAddr);
break;
case 0xC0:
case 0xC1:
case 0x00:
// Read-only
return false;
- break;
case 0x20:
case 0x21:
case 0x22:
return writeSCM32(value, physAddr);
case 0xA0:
// Memory Control Registers
- return false;
+ mMemoryController.write32(physAddr, value);
+ return true;
case 0xB0:
// LCD/DMA Control Registers
+ mLcdController->write32(physAddr, value);
return true;
case 0xC0:
case 0xC1: