diff options
Diffstat (limited to 'SrcShared/Hardware/EmCPU68K.h')
-rw-r--r-- | SrcShared/Hardware/EmCPU68K.h | 334 |
1 files changed, 334 insertions, 0 deletions
diff --git a/SrcShared/Hardware/EmCPU68K.h b/SrcShared/Hardware/EmCPU68K.h new file mode 100644 index 0000000..1cdfa08 --- /dev/null +++ b/SrcShared/Hardware/EmCPU68K.h @@ -0,0 +1,334 @@ +/* -*- mode: C++; tab-width: 4 -*- */ +/* ===================================================================== *\ + Copyright (c) 2000-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 EmCPU68K_h +#define EmCPU68K_h + +#include "EmCPU.h" // EmCPU + +#include <vector> // vector + +#if REGISTER_HISTORY +#include "UAE.h" // regstruct +#else +struct regstruct; +#endif + +const uint16 kATrapReturnTrapNum = 0x0C; + +/*--------------------------------------------------------------------- + * Register numbering for 68K. Each register must have a unique + * non-zero register number. + *--------------------------------------------------------------------*/ +enum EmCPU68KRegID +{ + e68KRegID_Invalid = 0, /* Zero is an invalid register number */ + e68KRegID_D0 = 1, + e68KRegID_D1 = 2, + e68KRegID_D2 = 3, + e68KRegID_D3 = 4, + e68KRegID_D4 = 5, + e68KRegID_D5 = 6, + e68KRegID_D6 = 7, + e68KRegID_D7 = 8, + e68KRegID_A0 = 9, + e68KRegID_A1 = 10, + e68KRegID_A2 = 11, + e68KRegID_A3 = 12, + e68KRegID_A4 = 13, + e68KRegID_A5 = 14, + e68KRegID_A6 = 15, + e68KRegID_USP = 16, + e68KRegID_SSP = 17, + e68KRegID_PC = 18, + e68KRegID_SR = 19 +}; + + +enum ExceptionNumber +{ + kException_BusErr = 2, // 08 / 2 + kException_AddressErr, // 0C / 3 + kException_IllegalInstr, // 10 / 4 + kException_DivideByZero, // 14 / 5 + kException_Chk, // 18 / 6 + kException_Trap, // 1C / 7 + kException_Privilege, // 20 / 8 + kException_Trace, // 24 / 9 + kException_ATrap, // 28 / A + kException_FTrap, // 2C / B + kException_Reseved12, // 30 / C + kException_Coproc, // 34 / D + kException_FormatErr, // 38 / E + kException_UninitializedInt, // 3C / F + + kException_Reserved0, // 40-5C / 10-17 + kException_Reserved1, + kException_Reserved2, + kException_Reserved3, + kException_Reserved4, + kException_Reserved5, + kException_Reserved6, + kException_Reserved7, + + kException_SpuriousInt, // 60 / 18 + kException_AutoVec1, // 64 / 19 + kException_AutoVec2, // 68 / 1A + kException_AutoVec3, // 6C / 1B + kException_AutoVec4, // 70 / 1C + kException_AutoVec5, // 74 / 1D + kException_AutoVec6, // 78 / 1E + kException_AutoVec7, // 7C / 1F + + kException_Trap0, // 80 - BC / 20 - 2F // For soft breakpoints + kException_Trap1, + kException_Trap2, + kException_Trap3, + kException_Trap4, + kException_Trap5, + kException_Trap6, + kException_Trap7, + kException_Trap8, // For compiled breakpoints + kException_Trap9, + kException_Trap10, + kException_Trap11, + kException_Trap12, + kException_Trap13, // ATrap returns (emulator convention) + kException_Trap14, + kException_Trap15, // Trap dispatcher + + kException_Unassigned0, // C0 - FC / 30 - 3F + kException_Unassigned1, + kException_Unassigned2, + kException_Unassigned3, + kException_Unassigned4, + kException_Unassigned5, + kException_Unassigned6, + kException_Unassigned7, + kException_Unassigned8, + kException_Unassigned9, + kException_Unassigned10, + kException_Unassigned11, + kException_Unassigned12, + kException_Unassigned13, + kException_Unassigned14, + kException_Unassigned15, + + kException_LastException, + + kException_SoftBreak = kException_Trap0 + sysDbgBreakpointTrapNum, + kException_HardBreak = kException_Trap0 + sysDbgTrapNum, + kException_SysCall = kException_Trap0 + sysDispatchTrapNum, + kException_ATrapReturn = kException_Trap0 + kATrapReturnTrapNum +}; + +/* + Grr...this function doesn't appear to be "seen" by VC++. Even in its + presence, an expression involving an ExceptionNumber and an int + results in the message "error C2440: 'initializing' : cannot convert + from 'const int' to 'const enum ExceptionNumber'" + +inline ExceptionNumber operator+ (ExceptionNumber left, int right) +{ + // NB: cast "left" to an integer, or this routine will recurse! + return (ExceptionNumber) ((int) left + right); +} +*/ + +#if EXCEPTION_HISTORY + +struct ExceptionHistoryType +{ + const char* name; + uint32 pc; + uint32 sp; +}; + +#endif + +// Using uint32 instead of uint16 generates slightly better code. +typedef uint32 EmOpcode68K; + +enum EmStackChangeType +{ + kStackPointerChanged, + kStackPointerIncremented, + kStackPointerDecremented, + kStackPointerKernelStackHack +}; + +class EmCPU68K; +typedef Bool (*Hook68KException) (ExceptionNumber); +typedef Bool (*Hook68KJSR) (emuptr oldPC, emuptr dest); +typedef Bool (*Hook68KJSR_Ind) (emuptr oldPC, emuptr dest); +typedef void (*Hook68KLINK) (int linkSize); +typedef Bool (*Hook68KRTE) (emuptr dest); +typedef Bool (*Hook68KRTS) (emuptr dest); +typedef void (*Hook68KNewPC) (emuptr dest); +typedef void (*Hook68KNewSP) (EmStackChangeType); + +typedef vector<Hook68KException> Hook68KExceptionList; +typedef vector<Hook68KJSR> Hook68KJSRList; +typedef vector<Hook68KJSR_Ind> Hook68KJSR_IndList; +typedef vector<Hook68KLINK> Hook68KLINKList; +typedef vector<Hook68KRTE> Hook68KRTEList; +typedef vector<Hook68KRTS> Hook68KRTSList; +typedef vector<Hook68KNewPC> Hook68KNewPCList; +typedef vector<Hook68KNewSP> Hook68KNewSPList; + +class EmCPU68K; +extern EmCPU68K* gCPU68K; + +// These variables should strictly be in a sub-system that implements +// the stack overflow checking, etc. However, for performance reasons, +// we need to expose them to UAE (see the CHECK_STACK_POINTER_ASSIGNMENT, +// et al macros), so define them here. +// +// Similar comments for the CheckKernelStack function. + +extern "C" uint32 gStackHigh; +extern "C" uint32 gStackLowWarn; +extern "C" uint32 gStackLow; +extern "C" uint32 gKernelStackOverflowed; + + +class EmCPU68K : public EmCPU +{ + public: + // ----------------------------------------------------------------------------- + // constructor / destructor + // ----------------------------------------------------------------------------- + + EmCPU68K (EmSession*); + virtual ~EmCPU68K (void); + + // ----------------------------------------------------------------------------- + // public methods + // ----------------------------------------------------------------------------- + + // Standard sub-system methods: + // Reset: Resets the state. Called on hardware resets or on + // calls to SysReset. Also called from constructor. + // Save: Saves the state to the given file. + // Load: Loads the state from the given file. Can assume that + // Reset has been called first. + + virtual void Reset (Bool hardwareReset); + virtual void Save (SessionFile&); + virtual void Load (SessionFile&); + + // Execute the main CPU loop until asked to stop. + + virtual void Execute (void); + virtual void CheckAfterCycle (void); + + // Low-level access to CPU state. + + virtual emuptr GetPC (void); + virtual emuptr GetSP (void); + virtual uint32 GetRegister (int); + + virtual void SetPC (emuptr); + virtual void SetSP (emuptr); + virtual void SetRegister (int, uint32); + + virtual Bool Stopped (void); + + // Called from routines in EmUAEGlue.cpp + + void ProcessException (ExceptionNumber); + void ProcessIllegalInstruction (EmOpcode68K opcode); + int ProcessJSR (emuptr oldPC, emuptr dest); + int ProcessJSR_Ind (emuptr oldPC, emuptr dest); + void ProcessLINK (int linkSize); + int ProcessRTE (emuptr dest); + int ProcessRTS (emuptr dest); + void CheckNewPC (emuptr dest); + void CheckNewSP (EmStackChangeType); + + // Called by CPU clients who need to be notified when certain + // actions occur. + + void InstallHookException (ExceptionNumber, + Hook68KException); + + void InstallHookJSR (Hook68KJSR); + void InstallHookJSR_Ind (Hook68KJSR_Ind); + void InstallHookLINK (Hook68KLINK); + void InstallHookRTS (Hook68KRTE); + void InstallHookRTE (Hook68KRTS); + void InstallHookNewPC (Hook68KNewPC); + void InstallHookNewSP (Hook68KNewSP); + + void RemoveHookException (ExceptionNumber, + Hook68KException); + + void RemoveHookJSR (Hook68KJSR); + void RemoveHookJSR_Ind (Hook68KJSR_Ind); + void RemoveHookLINK (Hook68KLINK); + void RemoveHookRTS (Hook68KRTE); + void RemoveHookRTE (Hook68KRTS); + void RemoveHookNewPC (Hook68KNewPC); + void RemoveHookNewSP (Hook68KNewSP); + + // Register management. Clients should call Get/SetRegisters for + // the most part. UpdateXFromY are here so that MakeSR and + // MakeFromSR (UAE glue functions) can call them. + + void GetRegisters (regstruct& registers); + void SetRegisters (regstruct& registers); + void UpdateSRFromRegisters (void); + void UpdateRegistersFromSR (void); + + uint32 GetCycleCount (void); + + void BusError (emuptr address, long size, Bool forRead); + void AddressError (emuptr address, long size, Bool forRead); + + private: + Bool ExecuteSpecial (void); + Bool ExecuteStoppedLoop (void); + + void CycleSlowly (Bool sleeping); + Bool CheckForBreak (void); + + void ProcessInterrupt (int32 interrupt); + + void InitializeUAETables (void); + + private: + emuptr fLastTraceAddress; + uint32 fCycleCount; + Hook68KExceptionList fExceptionHandlers[kException_LastException]; + Hook68KJSRList fHookJSR; + Hook68KJSR_IndList fHookJSR_Ind; + Hook68KLINKList fHookLINK; + Hook68KRTEList fHookRTE; + Hook68KRTSList fHookRTS; + Hook68KNewPCList fHookNewPC; + Hook68KNewSPList fHookNewSP; + +#if REGISTER_HISTORY + #define kRegHistorySize 512 + long fRegHistoryIndex; + struct regstruct fRegHistory[kRegHistorySize]; +#endif + +#if EXCEPTION_HISTORY + #define kExceptionHistorySize 512 + long fExceptionHistoryIndex; + struct ExceptionHistoryType fExceptionHistory[kExceptionHistorySize]; +#endif +}; + +#endif // EmCPU68K_h |