Skip to content

Commit

Permalink
Clean up memory and some other classes
Browse files Browse the repository at this point in the history
  • Loading branch information
Hydr8gon committed Jun 7, 2024
1 parent 668e8aa commit c081555
Show file tree
Hide file tree
Showing 20 changed files with 1,247 additions and 1,351 deletions.
2 changes: 1 addition & 1 deletion src/bios.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ int Bios::execute(uint8_t vector, uint32_t **registers)
void Bios::checkWaitFlags()
{
// Read the BIOS interrupt flags from memory
uint32_t address = arm7 ? 0x3FFFFF8 : (core->cp15.getDtcmAddr() + 0x3FF8);
uint32_t address = arm7 ? 0x3FFFFF8 : (core->cp15.dtcmAddr + 0x3FF8);
uint32_t flags = core->memory.read<uint32_t>(arm7, address);

// If a flag being waited for is set, clear it and stop waiting
Expand Down
2 changes: 1 addition & 1 deletion src/cartridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1110,7 +1110,7 @@ bool CartridgeGba::loadRom()
core->rtc.enableGpRtc();

// Update the memory maps at the GBA ROM locations
core->memory.updateMap9<false>(0x08000000, 0x0A000000);
core->memory.updateMap9(0x08000000, 0x0A000000);
core->memory.updateMap7(0x08000000, 0x0D000000);

// If the save size is unknown, try to detect it
Expand Down
2 changes: 1 addition & 1 deletion src/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ Core::Core(std::string ndsRom, std::string gbaRom, int id, int ndsRomFd,
schedule(NDS_SPU_SAMPLE, 512 * 2);

// Initialize the memory and CPUs
memory.updateMap9<false>(0x00000000, 0xFFFFFFFF);
memory.updateMap9(0x00000000, 0xFFFFFFFF);
memory.updateMap7(0x00000000, 0xFFFFFFFF);
interpreter[0].init();
interpreter[1].init();
Expand Down
72 changes: 27 additions & 45 deletions src/cp15.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,91 +42,73 @@ void Cp15::loadState(FILE *file)
write(9, 1, 1, itcm);
}

uint32_t Cp15::read(int cn, int cm, int cp)
uint32_t Cp15::read(uint8_t cn, uint8_t cm, uint8_t cp)
{
// Read a value from a CP15 register
switch ((cn << 16) | (cm << 8) | (cp << 0))
{
case 0x000000: return 0x41059461; // Main ID
case 0x000001: return 0x0F0D2112; // Cache type
case 0x010000: return ctrlReg; // Control
case 0x090100: return dtcmReg; // Data TCM base/size
case 0x090101: return itcmReg; // Instruction TCM size
case 0x010000: return ctrlReg; // Control
case 0x090100: return dtcmReg; // Data TCM base/size
case 0x090101: return itcmReg; // Instruction TCM size

default:
{
LOG("Unknown CP15 register read: C%d,C%d,%d\n", cn, cm, cp);
return 0;
}
}
}

void Cp15::write(int cn, int cm, int cp, uint32_t value)
void Cp15::write(uint8_t cn, uint8_t cm, uint8_t cp, uint32_t value)
{
// Write a value to a CP15 register
uint32_t oldAddr, oldSize;
switch ((cn << 16) | (cm << 8) | (cp << 0))
{
case 0x010000: // Control
{
// Some control bits are read only, so only set the writeable ones
ctrlReg = (ctrlReg & ~0x000FF085) | (value & 0x000FF085);
// Set writable control bits and update their state values
ctrlReg = (ctrlReg & ~0xFF085) | (value & 0xFF085);
exceptionAddr = (ctrlReg & BIT(13)) ? 0xFFFF0000 : 0x00000000;
dtcmReadEnabled = (ctrlReg & BIT(16)) && !(ctrlReg & BIT(17));
dtcmWriteEnabled = (ctrlReg & BIT(16));
itcmReadEnabled = (ctrlReg & BIT(18)) && !(ctrlReg & BIT(19));
itcmWriteEnabled = (ctrlReg & BIT(18));
dtcmCanRead = (ctrlReg & BIT(16)) && !(ctrlReg & BIT(17));
dtcmCanWrite = (ctrlReg & BIT(16));
itcmCanRead = (ctrlReg & BIT(18)) && !(ctrlReg & BIT(19));
itcmCanWrite = (ctrlReg & BIT(18));

// Update the memory map at the current TCM locations
core->memory.updateMap9<true>(dtcmAddr, dtcmAddr + dtcmSize);
core->memory.updateMap9<true>(0x00000000, itcmSize);

core->memory.updateMap9(dtcmAddr, dtcmAddr + dtcmSize, true);
core->memory.updateMap9(0x00000000, itcmSize, true);
return;
}

case 0x090100: // Data TCM base/size
{
uint32_t dtcmAddrOld = dtcmAddr;
uint32_t dtcmSizeOld = dtcmSize;

// DTCM size is calculated as 512 shifted left N bits, with a minimum of 4KB
// Set the DTCM register and update its address and size
dtcmReg = value;
oldAddr = dtcmAddr;
oldSize = dtcmSize;
dtcmAddr = dtcmReg & 0xFFFFF000;
dtcmSize = 0x200 << ((dtcmReg & 0x0000003E) >> 1);
if (dtcmSize < 0x1000) dtcmSize = 0x1000;

// Update the memory map at the old and new DTCM locations
core->memory.updateMap9<true>(dtcmAddrOld, dtcmAddrOld + dtcmSizeOld);
core->memory.updateMap9<true>(dtcmAddr, dtcmAddr + dtcmSize);
dtcmSize = std::max(0x1000, 0x200 << ((dtcmReg >> 1) & 0x1F)); // Min 4KB

// Update the memory map at the old and new DTCM areas
core->memory.updateMap9(oldAddr, oldAddr + oldSize, true);
core->memory.updateMap9(dtcmAddr, dtcmAddr + dtcmSize, true);
return;
}

case 0x070004: case 0x070802: // Wait for interrupt
{
// Halt the CPU
core->interpreter[0].halt(0);
return;
}

case 0x090101: // Instruction TCM size
{
uint32_t itcmSizeOld = itcmSize;

// ITCM base is fixed, so that part of the value is unused
// ITCM size is calculated as 512 shifted left N bits, with a minimum of 4KB
// Set the ITCM register and update its size
itcmReg = value;
itcmSize = 0x200 << ((itcmReg & 0x0000003E) >> 1);
if (itcmSize < 0x1000) itcmSize = 0x1000;

// Update the memory map at the old and new ITCM locations
core->memory.updateMap9<true>(0x00000000, std::max(itcmSizeOld, itcmSize));
oldSize = itcmSize;
itcmSize = std::max(0x1000, 0x200 << ((itcmReg >> 1) & 0x1F)); // Min 4KB

// Update the memory map at the old and new ITCM areas
core->memory.updateMap9(0x00000000, std::max(oldSize, itcmSize), true);
return;
}

default:
{
LOG("Unknown CP15 register write: C%d,C%d,%d\n", cn, cm, cp);
return;
}
}
}
32 changes: 11 additions & 21 deletions src/cp15.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,34 +28,24 @@ class Core;
class Cp15
{
public:
uint32_t exceptionAddr = 0;
bool dtcmCanRead = false, dtcmCanWrite = false;
bool itcmCanRead = false, itcmCanWrite = false;
uint32_t dtcmAddr = 0, dtcmSize = 0;
uint32_t itcmSize = 0;

Cp15(Core *core): core(core) {}
void saveState(FILE *file);
void loadState(FILE *file);

uint32_t read(int cn, int cm, int cp);
void write(int cn, int cm, int cp, uint32_t value);

uint32_t getExceptionAddr() { return exceptionAddr; }
bool getDtcmReadEnabled() { return dtcmReadEnabled; }
bool getDtcmWriteEnabled() { return dtcmWriteEnabled; }
bool getItcmReadEnabled() { return itcmReadEnabled; }
bool getItcmWriteEnabled() { return itcmWriteEnabled; }
uint32_t getDtcmAddr() { return dtcmAddr; }
uint32_t getDtcmSize() { return dtcmSize; }
uint32_t getItcmSize() { return itcmSize; }
uint32_t read(uint8_t cn, uint8_t cm, uint8_t cp);
void write(uint8_t cn, uint8_t cm, uint8_t cp, uint32_t value);

private:
Core *core;

uint32_t ctrlReg = 0x00000078;
uint32_t dtcmReg = 0x00000000;
uint32_t itcmReg = 0x00000000;

uint32_t exceptionAddr = 0;
bool dtcmReadEnabled = false, dtcmWriteEnabled = false;
bool itcmReadEnabled = false, itcmWriteEnabled = false;
uint32_t dtcmAddr = 0, dtcmSize = 0;
uint32_t itcmSize = 0;
uint32_t ctrlReg = 0x78;
uint32_t dtcmReg = 0x00;
uint32_t itcmReg = 0x00;
};

#endif // CP15_H
51 changes: 21 additions & 30 deletions src/div_sqrt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,28 +50,27 @@ void DivSqrt::loadState(FILE *file)

void DivSqrt::divide()
{
// Set the division by zero error bit
// The bit only gets set if the full 64-bit denominator is zero, even in 32-bit mode
if (divDenom == 0) divCnt |= BIT(14); else divCnt &= ~BIT(14);
// Set the division by zero bit based on the full 64-bit denominator, even in 32-bit mode
divDenom ? (divCnt &= ~BIT(14)) : (divCnt |= BIT(14));

// Calculate the division result and remainder
switch (divCnt & 0x0003) // Division mode
switch (divCnt & 0x3) // Division mode
{
case 0: // 32-bit / 32-bit
{
if ((int32_t)divNumer == INT32_MIN && (int32_t)divDenom == -1) // Overflow
{
divResult = (int32_t)divNumer ^ (0xFFFFFFFFULL << 32);
divResult = (int32_t)divNumer ^ (0xFFFFFFFFULL << 32);
divRemResult = 0;
}
else if ((int32_t)divDenom != 0)
{
divResult = (int32_t)divNumer / (int32_t)divDenom;
divResult = (int32_t)divNumer / (int32_t)divDenom;
divRemResult = (int32_t)divNumer % (int32_t)divDenom;
}
else // Division by 0
{
divResult = (((int32_t)divNumer < 0) ? 1 : -1) ^ (0xFFFFFFFFULL << 32);
divResult = (((int32_t)divNumer < 0) ? 1 : -1) ^ (0xFFFFFFFFULL << 32);
divRemResult = (int32_t)divNumer;
}
break;
Expand All @@ -81,17 +80,17 @@ void DivSqrt::divide()
{
if (divNumer == INT64_MIN && (int32_t)divDenom == -1) // Overflow
{
divResult = divNumer;
divResult = divNumer;
divRemResult = 0;
}
else if ((int32_t)divDenom != 0)
{
divResult = divNumer / (int32_t)divDenom;
divResult = divNumer / (int32_t)divDenom;
divRemResult = divNumer % (int32_t)divDenom;
}
else // Division by 0
{
divResult = (divNumer < 0) ? 1 : -1;
divResult = (divNumer < 0) ? 1 : -1;
divRemResult = divNumer;
}
break;
Expand All @@ -101,17 +100,17 @@ void DivSqrt::divide()
{
if (divNumer == INT64_MIN && divDenom == -1) // Overflow
{
divResult = divNumer;
divResult = divNumer;
divRemResult = 0;
}
else if (divDenom != 0)
{
divResult = divNumer / divDenom;
divResult = divNumer / divDenom;
divRemResult = divNumer % divDenom;
}
else // Division by 0
{
divResult = (divNumer < 0) ? 1 : -1;
divResult = (divNumer < 0) ? 1 : -1;
divRemResult = divNumer;
}
break;
Expand All @@ -122,7 +121,7 @@ void DivSqrt::divide()
void DivSqrt::squareRoot()
{
// Calculate the square root result
switch (sqrtCnt & 0x0001) // Square root mode
switch (sqrtCnt & 0x1) // Square root mode
{
case 0: // 32-bit
sqrtResult = sqrt((uint32_t)sqrtParam);
Expand All @@ -136,66 +135,58 @@ void DivSqrt::squareRoot()

void DivSqrt::writeDivCnt(uint16_t mask, uint16_t value)
{
// Write to the DIVCNT register
// Write to the DIVCNT register and update the division result
mask &= 0x0003;
divCnt = (divCnt & ~mask) | (value & mask);

divide();
}

void DivSqrt::writeDivNumerL(uint32_t mask, uint32_t value)
{
// Write to the DIVNUMER register
// Write to the DIVNUMER register and update the division result
divNumer = (divNumer & ~((uint64_t)mask)) | (value & mask);

divide();
}

void DivSqrt::writeDivNumerH(uint32_t mask, uint32_t value)
{
// Write to the DIVNUMER register
// Write to the DIVNUMER register and update the division result
divNumer = (divNumer & ~((uint64_t)mask << 32)) | ((uint64_t)(value & mask) << 32);

divide();
}

void DivSqrt::writeDivDenomL(uint32_t mask, uint32_t value)
{
// Write to the DIVDENOM register
// Write to the DIVDENOM register and update the division result
divDenom = (divDenom & ~((uint64_t)mask)) | (value & mask);

divide();
}

void DivSqrt::writeDivDenomH(uint32_t mask, uint32_t value)
{
// Write to the DIVDENOM register
// Write to the DIVDENOM register and update the division result
divDenom = (divDenom & ~((uint64_t)mask << 32)) | ((uint64_t)(value & mask) << 32);

divide();
}

void DivSqrt::writeSqrtCnt(uint16_t mask, uint16_t value)
{
// Write to the SQRTCNT register
// Write to the SQRTCNT register and update the square root result
mask &= 0x0001;
sqrtCnt = (sqrtCnt & ~mask) | (value & mask);

squareRoot();
}

void DivSqrt::writeSqrtParamL(uint32_t mask, uint32_t value)
{
// Write to the DIVDENOM register
// Write to the DIVDENOM register and update the square root result
sqrtParam = (sqrtParam & ~((uint64_t)mask)) | (value & mask);

squareRoot();
}

void DivSqrt::writeSqrtParamH(uint32_t mask, uint32_t value)
{
// Write to the SQRTPARAM register
// Write to the SQRTPARAM register and update the square root result
sqrtParam = (sqrtParam & ~((uint64_t)mask << 32)) | ((uint64_t)(value & mask) << 32);

squareRoot();
}
24 changes: 12 additions & 12 deletions src/div_sqrt.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,19 @@ class DivSqrt
void saveState(FILE *file);
void loadState(FILE *file);

uint16_t readDivCnt() { return divCnt; }
uint32_t readDivNumerL() { return divNumer; }
uint32_t readDivNumerH() { return divNumer >> 32; }
uint32_t readDivDenomL() { return divDenom; }
uint32_t readDivDenomH() { return divDenom >> 32; }
uint32_t readDivResultL() { return divResult; }
uint32_t readDivResultH() { return divResult >> 32; }
uint32_t readDivRemResultL() { return divRemResult; }
uint16_t readDivCnt() { return divCnt; }
uint32_t readDivNumerL() { return divNumer; }
uint32_t readDivNumerH() { return divNumer >> 32; }
uint32_t readDivDenomL() { return divDenom; }
uint32_t readDivDenomH() { return divDenom >> 32; }
uint32_t readDivResultL() { return divResult; }
uint32_t readDivResultH() { return divResult >> 32; }
uint32_t readDivRemResultL() { return divRemResult; }
uint32_t readDivRemResultH() { return divRemResult >> 32; }
uint16_t readSqrtCnt() { return sqrtCnt; }
uint32_t readSqrtResult() { return sqrtResult; }
uint32_t readSqrtParamL() { return sqrtParam; }
uint32_t readSqrtParamH() { return sqrtParam >> 32; }
uint16_t readSqrtCnt() { return sqrtCnt; }
uint32_t readSqrtResult() { return sqrtResult; }
uint32_t readSqrtParamL() { return sqrtParam; }
uint32_t readSqrtParamH() { return sqrtParam >> 32; }

void writeDivCnt(uint16_t mask, uint16_t value);
void writeDivNumerL(uint32_t mask, uint32_t value);
Expand Down
Loading

0 comments on commit c081555

Please sign in to comment.