aboutsummaryrefslogtreecommitdiff
path: root/SrcShared/Hardware/EmMemory.h
diff options
context:
space:
mode:
Diffstat (limited to 'SrcShared/Hardware/EmMemory.h')
-rw-r--r--SrcShared/Hardware/EmMemory.h457
1 files changed, 457 insertions, 0 deletions
diff --git a/SrcShared/Hardware/EmMemory.h b/SrcShared/Hardware/EmMemory.h
new file mode 100644
index 0000000..f10b749
--- /dev/null
+++ b/SrcShared/Hardware/EmMemory.h
@@ -0,0 +1,457 @@
+/* -*- 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.
+\* ===================================================================== */
+
+#ifndef EmMemory_h
+#define EmMemory_h
+
+// Normally, I'd assume that these includes were pulled in
+// by EmCommon.h. However, EmMemory.h gets included by UAE,
+// which doesn't pull in EmCommon.h. So I have to explicitly
+// make sure they're included.
+
+#include "Switches.h" // WORDSWAP_MEMORY, UNALIGNED_LONG_ACCESS
+#include "EmTypes.h" // uint32, etc.
+#include "EmAssert.h" // EmAssert
+
+#include "sysconfig.h" // STATIC_INLINE
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ---------------------------------------------------------------------------
+// ¥ EmAddressBank
+// ---------------------------------------------------------------------------
+
+typedef uint32 (*EmMemGetFunc) (emuptr);
+typedef void (*EmMemPutFunc) (emuptr, uint32);
+typedef uint8* (*EmMemTranslateFunc) (emuptr);
+typedef int (*EmMemCheckFunc) (emuptr, uint32);
+typedef void (*EmMemCycleFunc) (void);
+typedef uint8* (*EmMemTranslateMetaFunc) (emuptr);
+
+typedef struct EmAddressBank
+{
+ /* These ones should be self-explanatory... */
+ EmMemGetFunc lget, wget, bget;
+ EmMemPutFunc lput, wput, bput;
+
+ /* Use xlateaddr to translate an Amiga address to a uae_u8 * that can
+ * be used to address memory without calling the wget/wput functions.
+ * This doesn't work for all memory banks, so this function may call
+ * abort(). */
+ EmMemTranslateFunc xlateaddr;
+
+ /* To prevent calls to abort(), use check before calling xlateaddr.
+ * It checks not only that the memory bank can do xlateaddr, but also
+ * that the pointer points to an area of at least the specified size.
+ * This is used for example to translate bitplane pointers in custom.c */
+ EmMemCheckFunc checkaddr;
+
+ EmMemTranslateMetaFunc xlatemetaaddr;
+ EmMemCycleFunc EmMemAddOpcodeCycles;
+} EmAddressBank;
+
+
+#ifndef ECM_DYNAMIC_PATCH
+
+ extern EmAddressBank* gEmMemBanks[65536];
+
+#else // ECM_DYNAMIC_PATCH
+
+ extern EmAddressBank** gDynEmMemBanksP;
+
+#endif // ECM_DYNAMIC_PATCH
+
+
+// ---------------------------------------------------------------------------
+// ¥ Support macros
+// ---------------------------------------------------------------------------
+
+#ifndef ECM_DYNAMIC_PATCH
+
+ #define EmMemBankIndex(addr) (((emuptr)(addr)) >> 16)
+
+ #define EmMemGetBank(addr) (*gEmMemBanks[EmMemBankIndex(addr)])
+ #define EmMemPutBank(addr, b) (gEmMemBanks[EmMemBankIndex(addr)] = (b))
+
+#else // ECM_DYNAMIC_PATCH
+
+ #define EmMemBankIndex(addr) (((unsigned long)(addr)) >> 16)
+
+ #define EmMemGetBank(addr) (*((gDynEmMemBanksP)[EmMemBankIndex(addr)]))
+ #define EmMemPutBank(addr, b) ((gDynEmMemBanksP)[EmMemBankIndex(addr)] = (b))
+
+#endif // ECM_DYNAMIC_PATCH
+
+#define EmMemCallGetFunc(func, addr) ((*EmMemGetBank(addr).func)(addr))
+#define EmMemCallPutFunc(func, addr, v) ((*EmMemGetBank(addr).func)(addr, v))
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemGet32
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE uint32 EmMemGet32(emuptr addr)
+{
+ return EmMemCallGetFunc(lget, addr);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemGet16
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE uint32 EmMemGet16(emuptr addr)
+{
+ return EmMemCallGetFunc(wget, addr);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemGet8
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE uint32 EmMemGet8(emuptr addr)
+{
+ return EmMemCallGetFunc(bget, addr);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemPut32
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE void EmMemPut32(emuptr addr, uint32 l)
+{
+ EmMemCallPutFunc(lput, addr, l);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemPut16
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE void EmMemPut16(emuptr addr, uint32 w)
+{
+ EmMemCallPutFunc(wput, addr, w);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemPut8
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE void EmMemPut8(emuptr addr, uint32 b)
+{
+ EmMemCallPutFunc(bput, addr, b);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemGetRealAddress
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE uint8* EmMemGetRealAddress(emuptr addr)
+{
+ return EmMemGetBank(addr).xlateaddr(addr);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemCheckAddress
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE int EmMemCheckAddress(emuptr addr, uint32 size)
+{
+ return EmMemGetBank(addr).checkaddr(addr, size);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemAddOpcodeCycles
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE void EmMemAddOpcodeCycles(emuptr addr)
+{
+ EmAssert (EmMemGetBank(addr).EmMemAddOpcodeCycles);
+ EmMemGetBank(addr).EmMemAddOpcodeCycles();
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemGetMetaAddress
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE uint8* EmMemGetMetaAddress(emuptr addr)
+{
+ EmAssert(EmMemGetBank(addr).xlatemetaaddr);
+ return EmMemGetBank(addr).xlatemetaaddr(addr);
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemDoGet32
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE uint32 EmMemDoGet32 (void* a)
+{
+#if WORDSWAP_MEMORY || !UNALIGNED_LONG_ACCESS
+ return (((uint32) *(((uint16*) a) + 0)) << 16) |
+ (((uint32) *(((uint16*) a) + 1)));
+#else
+ return *(uint32*) a;
+#endif
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemDoGet16
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE uint16 EmMemDoGet16 (void* a)
+{
+ return *(uint16*) a;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemDoGet8
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE uint8 EmMemDoGet8 (void* a)
+{
+#if WORDSWAP_MEMORY
+ return *(uint8*) ((long) a ^ 1);
+#else
+ return *(uint8*) a;
+#endif
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemDoPut32
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE void EmMemDoPut32 (void* a, uint32 v)
+{
+#if WORDSWAP_MEMORY || !UNALIGNED_LONG_ACCESS
+ *(((uint16*) a) + 0) = (uint16) (v >> 16);
+ *(((uint16*) a) + 1) = (uint16) (v);
+#else
+ *(uint32*) a = v;
+#endif
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemDoPut16
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE void EmMemDoPut16 (void* a, uint16 v)
+{
+ *(uint16*) a = v;
+}
+
+// ---------------------------------------------------------------------------
+// ¥ EmMemDoPut8
+// ---------------------------------------------------------------------------
+
+STATIC_INLINE void EmMemDoPut8 (void* a, uint8 v)
+{
+#if WORDSWAP_MEMORY
+ *(uint8*) ((long) a ^ 1) = v;
+#else
+ *(uint8*) a = v;
+#endif
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#ifdef __cplusplus
+
+class EmStream;
+
+
+// Types.
+
+// This struct is used to control access to memory. The first set of fields
+// are booleans which, when set to true, turn on address validation for the
+// various ranges of memory. The second second set of fields are booleans
+// which, when set to true, prevent access by user applications to the various
+// ranges of memory.
+
+struct MemAccessFlags
+{
+ Bool fValidate_DummyGet;
+ Bool fValidate_DummySet;
+ Bool fValidate_RegisterGet;
+ Bool fValidate_RegisterSet;
+ Bool fValidate_DRAMGet;
+ Bool fValidate_DRAMSet;
+ Bool fValidate_SRAMGet;
+ Bool fValidate_SRAMSet;
+ Bool fValidate_ROMGet;
+ Bool fValidate_ROMSet;
+
+// Bool fProtect_LowMemGet;
+// Bool fProtect_LowMemSet;
+// Bool fProtect_GlobalGet;
+// Bool fProtect_GlobalSet;
+// Bool fProtect_ScreenGet;
+// Bool fProtect_ScreenSet;
+ Bool fProtect_SRAMGet;
+ Bool fProtect_SRAMSet;
+ Bool fProtect_ROMGet;
+ Bool fProtect_ROMSet;
+ Bool fProtect_RegisterGet;
+ Bool fProtect_RegisterSet;
+
+// Bool fCheck_UserChunkGet;
+// Bool fCheck_UserChunkSet;
+// Bool fCheck_SysChunkGet;
+// Bool fCheck_SysChunkSet;
+
+// Bool fProtect_SysLowMemGet;
+// Bool fProtect_SysLowMemSet;
+// Bool fProtect_SysGlobalGet;
+// Bool fProtect_SysGlobalSet;
+// Bool fProtect_SysScreenGet;
+// Bool fProtect_SysScreenSet;
+// Bool fProtect_SysSRAMGet;
+// Bool fProtect_SysSRAMSet;
+ Bool fProtect_SysROMGet;
+ Bool fProtect_SysROMSet;
+// Bool fProtect_SysRegisterGet;
+// Bool fProtect_SysRegisterSet;
+};
+
+
+// Globals.
+
+extern MemAccessFlags gMemAccessFlags;
+extern Bool gPCInRAM;
+extern Bool gPCInROM;
+
+#if PROFILE_MEMORY
+enum
+{
+ kDRAMLongRead, kDRAMLongRead2, kDRAMWordRead, kDRAMByteRead,
+ kDRAMLongWrite, kDRAMLongWrite2, kDRAMWordWrite, kDRAMByteWrite,
+ kSRAMLongRead, kSRAMLongRead2, kSRAMWordRead, kSRAMByteRead,
+ kSRAMLongWrite, kSRAMLongWrite2, kSRAMWordWrite, kSRAMByteWrite,
+ kROMLongRead, kROMLongRead2, kROMWordRead, kROMByteRead,
+ kROMLongWrite, kROMLongWrite2, kROMWordWrite, kROMByteWrite,
+ kREGLongRead, kREGLongRead2, kREGWordRead, kREGByteRead,
+ kREGLongWrite, kREGLongWrite2, kREGWordWrite, kREGByteWrite,
+
+ kSED1375LongRead, kSED1375LongRead2, kSED1375WordRead, kSED1375ByteRead,
+ kSED1375LongWrite, kSED1375LongWrite2, kSED1375WordWrite, kSED1375ByteWrite,
+
+ kLastEnum
+};
+extern long gMemoryAccess[];
+#endif
+
+struct EmAddressBank;
+class SessionFile;
+
+// Function prototypes.
+
+class Memory
+{
+ public:
+ static void Initialize (EmStream& hROM,
+ RAMSizeType ramSize);
+ static void Reset (Bool hardwareReset);
+ static void Save (SessionFile&);
+ static void Load (SessionFile&);
+ static void Dispose (void);
+
+ static void InitializeBanks (EmAddressBank& iBankInitializer,
+ int32 iStartingBankIndex,
+ int32 iNumberOfBanks);
+
+ static void ResetBankHandlers (void);
+
+ static void MapPhysicalMemory (const void*, uint32);
+ static void UnmapPhysicalMemory (const void*);
+ static void GetMappingInfo (emuptr, void**, uint32*);
+
+ static void CheckNewPC (emuptr newPC);
+ static int IsPCInRAM (void) { return gPCInRAM; }
+ static int IsPCInROM (void) { return gPCInROM; }
+};
+
+typedef Memory EmMemory;
+
+
+// There are places within the emulator where we'd like to access low-memory
+// and/or Dragonball registers. If the PC happens to be in RAM, then
+// the checks implied by the above booleans and switches will flag our
+// access as an error. Before making such accesses, create an instance
+// of CEnableFullAccess to suspend and restore the checks.
+//
+// Since such accesses are typically "meta" accesses where the emulator is
+// accessing memory outside the normal execution of an opcode, we also
+// turn off the profiling variable that controls whether or not cycles
+// spent accessing memory are counted.
+
+class CEnableFullAccess
+{
+ public:
+ CEnableFullAccess (void);
+ ~CEnableFullAccess (void);
+
+ static Bool AccessOK (void);
+
+ private:
+ MemAccessFlags fOldMemAccessFlags;
+
+#if HAS_PROFILING
+ Bool fOldProfilingCounted;
+#endif
+
+ static long fgAccessCount;
+};
+
+
+// Std C Library-ish routines for manipulating data
+// in emulated memory.
+
+emuptr EmMem_memset(emuptr dst, int val, size_t len);
+
+emuptr EmMem_memchr(emuptr src, int val, size_t len);
+
+template <class T1, class T2>
+int EmMem_memcmp(T1 src1, T2 src2, size_t len);
+
+template <class T1, class T2>
+T1 EmMem_memcpy (T1 dst, T2 src, size_t len);
+
+template <class T1, class T2>
+T1 EmMem_memmove (T1 dst, T2 src, size_t len);
+
+size_t EmMem_strlen(emuptr str);
+
+template <class T1, class T2>
+T1 EmMem_strcpy(T1 dst, T2 src);
+
+template <class T1, class T2>
+T1 EmMem_strncpy(T1 dst, T2 src, size_t len);
+
+template <class T1, class T2>
+T1 EmMem_strcat(T1 dst, T2 src);
+
+template <class T1, class T2>
+T1 EmMem_strncat(T1 dst, T2 src, size_t len);
+
+template <class T1, class T2>
+int EmMem_strcmp(T1 dst, T2 src);
+
+template <class T1, class T2>
+int EmMem_strncmp(T1 dst, T2 src, size_t len);
+
+#endif // __cplusplus
+
+#endif /* EmMemory_h */