diff options
Diffstat (limited to 'SrcShared/Hardware/EmBankSRAM.cpp')
-rw-r--r-- | SrcShared/Hardware/EmBankSRAM.cpp | 640 |
1 files changed, 640 insertions, 0 deletions
diff --git a/SrcShared/Hardware/EmBankSRAM.cpp b/SrcShared/Hardware/EmBankSRAM.cpp new file mode 100644 index 0000000..4553131 --- /dev/null +++ b/SrcShared/Hardware/EmBankSRAM.cpp @@ -0,0 +1,640 @@ +/* -*- mode: C++; tab-width: 4 -*- */ +/* ===================================================================== *\ + Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries. + All rights reserved. + + This file is part of the Palm OS Emulator. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +\* ===================================================================== */ + +#include "EmCommon.h" +#include "EmBankSRAM.h" + +#include "Byteswapping.h" // ByteswapWords +#include "DebugMgr.h" // Debug::CheckStepSpy +#include "EmCPU68K.h" // gCPU68K +#include "EmMemory.h" // gRAMBank_Size, gRAM_Memory, gMemoryAccess +#include "EmScreen.h" // EmScreen::MarkDirty +#include "EmSession.h" // GetDevice +#include "MetaMemory.h" // MetaMemory:: +#include "Miscellaneous.h" // StWordSwapper +#include "Profiling.h" // WAITSTATES_SRAM +#include "SessionFile.h" // WriteRAMImage + + +// =========================================================================== +// ¥ SRAM Bank Accessors +// =========================================================================== +// These functions provide fetch and store access to the emulator's random +// access memory. + +static EmAddressBank gAddressBank = +{ + EmBankSRAM::GetLong, + EmBankSRAM::GetWord, + EmBankSRAM::GetByte, + EmBankSRAM::SetLong, + EmBankSRAM::SetWord, + EmBankSRAM::SetByte, + EmBankSRAM::GetRealAddress, + EmBankSRAM::ValidAddress, + EmBankSRAM::GetMetaAddress, + EmBankSRAM::AddOpcodeCycles +}; + + // Note: I'd've used hwrCardBase0 here, except that that + // changes on different hardware. It's 0x10000000 in some + // cases, 0x00000000 in others. + +static const emuptr kMemoryStart = 0x10000000; +static const emuptr kMemoryStartEZ = 0x00000000; +static const emuptr kMemoryStartVZ = 0x00000000; + +emuptr gMemoryStart; + +uint32 gRAMBank_Size; +uint32 gRAMBank_Mask; +uint8* gRAM_Memory; +uint8* gRAM_MetaMemory; + +#if defined (_DEBUG) + + // In debug mode, define a global variable that points to the + // Palm ROM's low-memory globals. That makes it easier to find + // out what's going wrong when something goes wrong. + // + // Keep in mind that on Windows, all values are "wordswapped" + // (each pair of bytes is byteswapped). + + LowMemHdrType* gLowMemory; + +#endif + + +static inline uint8* InlineGetMetaAddress (emuptr address) +{ + return (uint8*) &(gRAM_MetaMemory[address]); +} + +static inline void PrvScreenCheck (uint8* metaAddress, emuptr address, size_t size) +{ +#if defined (macintosh) + + if (size == 1 && !MetaMemory::IsScreenBuffer8 (metaAddress)) + return; + + if (size == 2 && !MetaMemory::IsScreenBuffer16 (metaAddress)) + return; + + if (size == 4 && !MetaMemory::IsScreenBuffer32 (metaAddress)) + return; + +#else + + if (MetaMemory::IsScreenBuffer (metaAddress, size)) + +#endif + + { + EmScreen::MarkDirty (address, size); + } +} + + +/*********************************************************************** + * + * FUNCTION: EmBankSRAM::Initialize + * + * DESCRIPTION: Standard initialization function. Responsible for + * initializing this sub-system when a new session is + * created. Will be followed by at least one call to + * Reset or Load. + * + * PARAMETERS: None. + * + * RETURNED: Nothing. + * + ***********************************************************************/ + +void EmBankSRAM::Initialize (RAMSizeType ramSize) +{ + EmAssert (gRAM_Memory == NULL); + EmAssert (gRAM_MetaMemory == NULL); + + if (ramSize > 0) + { + gRAMBank_Size = ramSize * 1024; + gRAMBank_Mask = gRAMBank_Size - 1; + gRAM_Memory = (uint8*) Platform::AllocateMemoryClear (gRAMBank_Size); + gRAM_MetaMemory = (uint8*) Platform::AllocateMemoryClear (gRAMBank_Size); + +#if defined (_DEBUG) + // In debug mode, define a global variable that points to the + // Palm ROM's low-memory globals. That makes it easier to find + // out what's going wrong when something goes wrong. + + gLowMemory = (LowMemHdrType*) gRAM_Memory; +#endif + } + + EmAssert (gSession); + + if (gSession->GetDevice ().Supports68EZ328 ()) + { + gMemoryStart = kMemoryStartEZ; + } + else if (gSession->GetDevice ().Supports68VZ328 ()) + { + gMemoryStart = kMemoryStartVZ; + } + else + { + gMemoryStart = kMemoryStart; + } +} + + +/*********************************************************************** + * + * FUNCTION: EmBankSRAM::Reset + * + * DESCRIPTION: Standard reset function. Sets the sub-system to a + * default state. This occurs not only on a Reset (as + * from the menu item), but also when the sub-system + * is first initialized (Reset is called after Initialize) + * as well as when the system is re-loaded from an + * insufficient session file. + * + * PARAMETERS: None. + * + * RETURNED: Nothing. + * + ***********************************************************************/ + +void EmBankSRAM::Reset (Bool /*hardwareReset*/) +{ + memset (gRAM_MetaMemory, 0, gRAMBank_Size); +} + + +/*********************************************************************** + * + * FUNCTION: EmBankSRAM::Save + * + * DESCRIPTION: Standard save function. Saves any sub-system state to + * the given session file. + * + * PARAMETERS: None. + * + * RETURNED: Nothing. + * + ***********************************************************************/ + +void EmBankSRAM::Save (SessionFile& f) +{ + StWordSwapper swapper1 (gRAM_Memory, gRAMBank_Size); + f.WriteRAMImage (gRAM_Memory, gRAMBank_Size); + + StWordSwapper swapper2 (gRAM_MetaMemory, gRAMBank_Size); + f.WriteMetaRAMImage (gRAM_MetaMemory, gRAMBank_Size); +} + + +/*********************************************************************** + * + * FUNCTION: EmBankSRAM::Load + * + * DESCRIPTION: Standard load function. Loads any sub-system state + * from the given session file. + * + * PARAMETERS: None. + * + * RETURNED: Nothing. + * + ***********************************************************************/ + +void EmBankSRAM::Load (SessionFile& f) +{ + EmAssert (gRAM_Memory); + EmAssert (gRAM_MetaMemory); + + if (f.ReadRAMImage (gRAM_Memory)) + { + ByteswapWords (gRAM_Memory, gRAMBank_Size); + } + else + { + f.SetCanReload (false); + } + + if (f.ReadMetaRAMImage (gRAM_MetaMemory)) + { + ByteswapWords (gRAM_MetaMemory, gRAMBank_Size); + } + else + { + f.SetCanReload (false); + } +} + + +/*********************************************************************** + * + * FUNCTION: EmBankSRAM::Dispose + * + * DESCRIPTION: Standard dispose function. Completely release any + * resources acquired or allocated in Initialize and/or + * Load. + * + * PARAMETERS: None. + * + * RETURNED: Nothing. + * + ***********************************************************************/ + +void EmBankSRAM::Dispose (void) +{ + Platform::DisposeMemory (gRAM_Memory); + Platform::DisposeMemory (gRAM_MetaMemory); +} + + +/*********************************************************************** + * + * FUNCTION: EmBankSRAM::SetBankHandlers + * + * DESCRIPTION: Set the bank handlers UAE uses to dispatch memory + * access operations. + * + * PARAMETERS: None + * + * RETURNED: Nothing + * + ***********************************************************************/ + +void EmBankSRAM::SetBankHandlers (void) +{ + // Memory banks 0x1000 to <mumble> are managed by the functions + // in EmBankSRAM. <mumble> is based on the amount of RAM being emulated. + + long numBanks = EmMemBankIndex (gMemoryStart + gRAMBank_Size - 1) - + EmMemBankIndex (gMemoryStart) + 1; + Memory::InitializeBanks (gAddressBank, EmMemBankIndex (gMemoryStart), numBanks); +} + + +// --------------------------------------------------------------------------- +// ¥ EmBankSRAM::GetLong +// --------------------------------------------------------------------------- + +uint32 EmBankSRAM::GetLong (emuptr address) +{ +#if PROFILE_MEMORY + gMemoryAccess[kSRAMLongRead]++; + if (address & 2) + gMemoryAccess[kSRAMLongRead2]++; +#endif + +#if (CHECK_FOR_ADDRESS_ERROR) + if ((address & 1) != 0) + { + AddressError (address, sizeof (uint32), true); + } +#endif + +#if (PREVENT_USER_SRAM_GET) + if (gMemAccessFlags.fProtect_SRAMGet) + { + ProtectedAccess (address, sizeof (uint32), true); + } +#endif + +#if (VALIDATE_SRAM_GET) + if (gMemAccessFlags.fValidate_SRAMGet && !ValidAddress (address, sizeof (uint32))) + { + InvalidAccess (address, sizeof (uint32), true); + } +#endif + +#if HAS_PROFILING + CYCLE_GETLONG (WAITSTATES_SRAM); +#endif + + address &= gRAMBank_Mask; + + return EmMemDoGet32 (gRAM_Memory + address); +} + + +// --------------------------------------------------------------------------- +// ¥ EmBankSRAM::GetWord +// --------------------------------------------------------------------------- + +uint32 EmBankSRAM::GetWord (emuptr address) +{ +#if PROFILE_MEMORY + gMemoryAccess[kSRAMWordRead]++; +#endif + +#if (CHECK_FOR_ADDRESS_ERROR) + if ((address & 1) != 0) + { + AddressError (address, sizeof (uint16), true); + } +#endif + +#if (PREVENT_USER_SRAM_GET) + if (gMemAccessFlags.fProtect_SRAMGet) + { + ProtectedAccess (address, sizeof (uint16), true); + } +#endif + +#if (VALIDATE_SRAM_GET) + if (gMemAccessFlags.fValidate_SRAMGet && !ValidAddress (address, sizeof (uint16))) + { + InvalidAccess (address, sizeof (uint16), true); + } +#endif + +#if HAS_PROFILING + CYCLE_GETWORD (WAITSTATES_SRAM); +#endif + + address &= gRAMBank_Mask; + + return EmMemDoGet16 (gRAM_Memory + address); +} + + +// --------------------------------------------------------------------------- +// ¥ EmBankSRAM::GetByte +// --------------------------------------------------------------------------- + +uint32 EmBankSRAM::GetByte (emuptr address) +{ +#if PROFILE_MEMORY + gMemoryAccess[kSRAMByteRead]++; +#endif + +#if (PREVENT_USER_SRAM_GET) + if (gMemAccessFlags.fProtect_SRAMGet) + { + ProtectedAccess (address, sizeof (uint8), true); + } +#endif + +#if (VALIDATE_SRAM_GET) + if (gMemAccessFlags.fValidate_SRAMGet && !ValidAddress (address, sizeof (uint8))) + { + InvalidAccess (address, sizeof (uint8), true); + } +#endif + +#if HAS_PROFILING + CYCLE_GETBYTE (WAITSTATES_SRAM); +#endif + + address &= gRAMBank_Mask; + + return EmMemDoGet8 (gRAM_Memory + address); +} + + +// --------------------------------------------------------------------------- +// ¥ EmBankSRAM::SetLong +// --------------------------------------------------------------------------- + +void EmBankSRAM::SetLong (emuptr address, uint32 value) +{ +#if PROFILE_MEMORY + gMemoryAccess[kSRAMLongWrite]++; + if (address & 2) + gMemoryAccess[kSRAMLongWrite2]++; +#endif + +#if (CHECK_FOR_ADDRESS_ERROR) + if ((address & 1) != 0) + { + AddressError (address, sizeof (uint32), false); + } +#endif + +#if (PREVENT_USER_SRAM_SET) + if (gMemAccessFlags.fProtect_SRAMSet) + { + ProtectedAccess (address, sizeof (uint32), false); + } +#endif + +#if (VALIDATE_SRAM_SET) + if (gMemAccessFlags.fValidate_SRAMSet && !ValidAddress (address, sizeof (uint32))) + { + InvalidAccess (address, sizeof (uint32), false); + } +#endif + +#if HAS_PROFILING + CYCLE_PUTLONG (WAITSTATES_SRAM); +#endif + + emuptr phyAddress = address; + phyAddress &= gRAMBank_Mask; + + register uint8* metaAddress = InlineGetMetaAddress (phyAddress); +// META_CHECK (metaAddress, address, SetLong, uint32, false); + ::PrvScreenCheck (metaAddress, address, sizeof (uint32)); + + EmMemDoPut32 (gRAM_Memory + phyAddress, value); + + // See if any interesting memory locations have changed. If so, + // CheckStepSpy will report it. + + Debug::CheckStepSpy (address, sizeof (uint32)); +} + + +// --------------------------------------------------------------------------- +// ¥ EmBankSRAM::SetWord +// --------------------------------------------------------------------------- + +void EmBankSRAM::SetWord (emuptr address, uint32 value) +{ +#if PROFILE_MEMORY + gMemoryAccess[kSRAMWordWrite]++; +#endif + +#if (CHECK_FOR_ADDRESS_ERROR) + if ((address & 1) != 0) + { + AddressError (address, sizeof (uint16), false); + } +#endif + +#if (PREVENT_USER_SRAM_SET) + if (gMemAccessFlags.fProtect_SRAMSet) + { + ProtectedAccess (address, sizeof (uint16), false); + } +#endif + +#if (VALIDATE_SRAM_SET) + if (gMemAccessFlags.fValidate_SRAMSet && !ValidAddress (address, sizeof (uint16))) + { + InvalidAccess (address, sizeof (uint16), false); + } +#endif + +#if HAS_PROFILING + CYCLE_PUTWORD (WAITSTATES_SRAM); +#endif + + emuptr phyAddress = address; + phyAddress &= gRAMBank_Mask; + + register uint8* metaAddress = InlineGetMetaAddress (phyAddress); +// META_CHECK (metaAddress, address, SetLong, uint16, false); + ::PrvScreenCheck (metaAddress, address, sizeof (uint16)); + + EmMemDoPut16 (gRAM_Memory + phyAddress, value); + + // See if any interesting memory locations have changed. If so, + // CheckStepSpy will report it. + + Debug::CheckStepSpy (address, sizeof (uint16)); +} + + +// --------------------------------------------------------------------------- +// ¥ EmBankSRAM::SetByte +// --------------------------------------------------------------------------- + +void EmBankSRAM::SetByte (emuptr address, uint32 value) +{ +#if PROFILE_MEMORY + gMemoryAccess[kSRAMByteWrite]++; +#endif + +#if (PREVENT_USER_SRAM_SET) + if (gMemAccessFlags.fProtect_SRAMSet) + { + ProtectedAccess (address, sizeof (uint8), false); + } +#endif + +#if (VALIDATE_SRAM_SET) + if (gMemAccessFlags.fValidate_SRAMSet && !ValidAddress (address, sizeof (uint8))) + { + InvalidAccess (address, sizeof (uint8), false); + } +#endif + +#if HAS_PROFILING + CYCLE_PUTBYTE (WAITSTATES_SRAM); +#endif + + emuptr phyAddress = address; + phyAddress &= gRAMBank_Mask; + + register uint8* metaAddress = InlineGetMetaAddress (phyAddress); +// META_CHECK (metaAddress, address, SetLong, uint8, false); + ::PrvScreenCheck (metaAddress, address, sizeof (uint8)); + + EmMemDoPut8 (gRAM_Memory + phyAddress, value); + + // See if any interesting memory locations have changed. If so, + // CheckStepSpy will report it. + + Debug::CheckStepSpy (address, sizeof (uint8)); +} + + +// --------------------------------------------------------------------------- +// ¥ EmBankSRAM::ValidAddress +// --------------------------------------------------------------------------- + +int EmBankSRAM::ValidAddress (emuptr address, uint32 size) +{ + address -= gMemoryStart; + int result = (address + size) <= (gMemoryStart + gRAMBank_Size); + + return result; +} + + +// --------------------------------------------------------------------------- +// ¥ EmBankSRAM::GetRealAddress +// --------------------------------------------------------------------------- + +uint8* EmBankSRAM::GetRealAddress (emuptr address) +{ + // Strip the uppermost bit of the address. + + address &= gRAMBank_Mask; + + return (uint8*) &(gRAM_Memory[address]); +} + + +// --------------------------------------------------------------------------- +// ¥ EmBankSRAM::GetMetaAddress +// --------------------------------------------------------------------------- + +uint8* EmBankSRAM::GetMetaAddress (emuptr address) +{ + // Strip the uppermost bit of the address. + + address &= gRAMBank_Mask; + + return (uint8*) &(gRAM_MetaMemory[address]); +} + + +// --------------------------------------------------------------------------- +// ¥ EmBankSRAM::AddOpcodeCycles +// --------------------------------------------------------------------------- + +void EmBankSRAM::AddOpcodeCycles (void) +{ +#if (HAS_PROFILING) + CYCLE_GETWORD (WAITSTATES_SRAM); +#endif +} + + +// --------------------------------------------------------------------------- +// ¥ EmBankSRAM::AddressError +// --------------------------------------------------------------------------- + +void EmBankSRAM::AddressError (emuptr address, long size, Bool forRead) +{ + EmAssert (gCPU68K); + gCPU68K->AddressError (address, size, forRead); +} + + +// --------------------------------------------------------------------------- +// ¥ EmBankSRAM::InvalidAccess +// --------------------------------------------------------------------------- + +void EmBankSRAM::InvalidAccess (emuptr address, long size, Bool forRead) +{ + EmAssert (gCPU68K); + gCPU68K->BusError (address, size, forRead); +} + + +// --------------------------------------------------------------------------- +// ¥ EmBankSRAM::ProtectedAccess +// --------------------------------------------------------------------------- + +void EmBankSRAM::ProtectedAccess (emuptr address, long size, Bool forRead) +{ + EmAssert (gCPU68K); + gCPU68K->BusError (address, size, forRead); +} + |