2013-04-17 22:43:11 -04:00
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
2008-12-08 04:46:09 +00:00
# ifndef _POWERPC_H
# define _POWERPC_H
# include "Common.h"
2010-08-26 17:44:13 +00:00
# include "CPUCoreBase.h"
2008-12-08 04:46:09 +00:00
# include "Gekko.h"
2009-06-28 12:15:31 +00:00
# include "BreakPoints.h"
# include "../Debugger/PPCDebugInterface.h"
2009-10-03 12:29:27 +00:00
# include "PPCCache.h"
2008-12-08 04:46:09 +00:00
class PointerWrap ;
2010-08-26 17:44:13 +00:00
extern CPUCoreBase * cpu_core_base ;
2008-12-08 04:46:09 +00:00
namespace PowerPC
{
2008-12-15 19:22:34 +00:00
enum CoreMode
{
MODE_INTERPRETER ,
MODE_JIT ,
} ;
// This contains the entire state of the emulated PowerPC "Gekko" CPU.
struct GC_ALIGNED64 ( PowerPCState )
{
u32 mojs [ 128 ] ; // Try to isolate the regs from other variables in the cache.
u32 gpr [ 32 ] ; // General purpose registers. r1 = stack pointer.
// The paired singles are strange : PS0 is stored in the full 64 bits of each FPR
// but ps calculations are only done in 32-bit precision, and PS1 is only 32 bits.
// Since we want to use SIMD, SSE2 is the only viable alternative - 2x double.
u64 ps [ 32 ] [ 2 ] ;
u32 pc ; // program counter
u32 npc ;
2010-07-25 17:54:03 +00:00
u32 cr ; // flags
u8 cr_fast [ 8 ] ; // Possibly reorder to 0, 2, 4, 8, 1, 3, 5, 7 so that we can make Compact and Expand super fast?
2008-12-15 20:41:59 +00:00
2008-12-15 19:22:34 +00:00
u32 msr ; // machine specific register
u32 fpscr ; // floating point flags/status bits
// Exception management.
2010-09-01 22:03:51 +00:00
volatile u32 Exceptions ;
2008-12-15 19:22:34 +00:00
2010-07-05 02:05:47 +00:00
u32 sr [ 16 ] ; // Segment registers.
2008-12-15 19:22:34 +00:00
u32 DebugCount ;
2013-10-29 01:23:17 -04:00
2010-07-05 02:05:47 +00:00
// special purpose registers - controls quantizers, DMA, and lots of other misc extensions.
2008-12-15 19:22:34 +00:00
// also for power management, but we don't care about that.
u32 spr [ 1024 ] ;
2010-01-15 14:39:27 +00:00
2010-07-29 12:17:47 +00:00
u32 dtlb_last ;
u32 dtlb_va [ 128 ] ;
u32 dtlb_pa [ 128 ] ;
u32 itlb_last ;
u32 itlb_va [ 128 ] ;
u32 itlb_pa [ 128 ] ;
2010-01-15 14:39:27 +00:00
2013-05-19 17:14:29 +02:00
u32 pagetable_base ;
u32 pagetable_hashmask ;
2009-10-03 12:29:27 +00:00
InstructionCache iCache ;
2008-12-15 19:22:34 +00:00
} ;
enum CPUState
{
CPU_RUNNING = 0 ,
CPU_STEPPING = 2 ,
CPU_POWERDOWN = 3 ,
} ;
extern PowerPCState ppcState ;
2009-06-28 11:47:39 +00:00
extern BreakPoints breakpoints ;
extern MemChecks memchecks ;
2009-06-28 12:15:31 +00:00
extern PPCDebugInterface debug_interface ;
2009-06-28 11:47:39 +00:00
2010-01-19 19:28:27 +00:00
void Init ( int cpu_core ) ;
2008-12-15 19:22:34 +00:00
void Shutdown ( ) ;
void DoState ( PointerWrap & p ) ;
2011-12-31 15:18:48 +11:00
CoreMode GetMode ( ) ;
2008-12-15 19:22:34 +00:00
void SetMode ( CoreMode _coreType ) ;
2013-10-29 01:23:17 -04:00
void SingleStep ( ) ;
2008-12-15 19:22:34 +00:00
void CheckExceptions ( ) ;
2012-04-15 21:34:15 +10:00
void CheckExternalExceptions ( ) ;
2010-07-05 02:05:47 +00:00
void CheckBreakPoints ( ) ;
2008-12-15 19:22:34 +00:00
void RunLoop ( ) ;
void Start ( ) ;
void Pause ( ) ;
void Stop ( ) ;
2009-02-17 22:48:16 +00:00
CPUState GetState ( ) ;
volatile CPUState * GetStatePtr ( ) ; // this oddity is here instead of an extern declaration to easily be able to find all direct accesses throughout the code.
2008-12-15 19:22:34 +00:00
2008-12-15 20:41:59 +00:00
void CompactCR ( ) ;
void ExpandCR ( ) ;
2008-12-15 19:22:34 +00:00
void OnIdle ( u32 _uThreadAddr ) ;
2009-05-31 09:22:29 +00:00
void OnIdleIL ( ) ;
2008-12-15 19:22:34 +00:00
2012-04-28 20:42:45 +10:00
void UpdatePerformanceMonitor ( u32 cycles , u32 num_load_stores , u32 num_fp_inst ) ;
2008-12-15 19:22:34 +00:00
// Easy register access macros.
2009-10-03 12:29:27 +00:00
# define HID0 ((UReg_HID0&)PowerPC::ppcState.spr[SPR_HID0])
2008-12-08 04:46:09 +00:00
# define HID2 ((UReg_HID2&)PowerPC::ppcState.spr[SPR_HID2])
2010-09-11 02:34:51 +00:00
# define HID4 ((UReg_HID4&)PowerPC::ppcState.spr[SPR_HID4])
2008-12-08 04:46:09 +00:00
# define DMAU (*(UReg_DMAU*)&PowerPC::ppcState.spr[SPR_DMAU])
# define DMAL (*(UReg_DMAL*)&PowerPC::ppcState.spr[SPR_DMAL])
2012-04-28 20:42:45 +10:00
# define MMCR0 ((UReg_MMCR0&)PowerPC::ppcState.spr[SPR_MMCR0])
# define MMCR1 ((UReg_MMCR1&)PowerPC::ppcState.spr[SPR_MMCR1])
2008-12-08 04:46:09 +00:00
# define PC PowerPC::ppcState.pc
# define NPC PowerPC::ppcState.npc
# define FPSCR ((UReg_FPSCR&)PowerPC::ppcState.fpscr)
# define MSR PowerPC::ppcState.msr
# define GPR(n) PowerPC::ppcState.gpr[n]
# define rGPR PowerPC::ppcState.gpr
# define rSPR(i) PowerPC::ppcState.spr[i]
# define LR PowerPC::ppcState.spr[SPR_LR]
# define CTR PowerPC::ppcState.spr[SPR_CTR]
# define rDEC PowerPC::ppcState.spr[SPR_DEC]
# define SRR0 PowerPC::ppcState.spr[SPR_SRR0]
# define SRR1 PowerPC::ppcState.spr[SPR_SRR1]
2013-10-29 01:23:17 -04:00
# define SPRG0 PowerPC::ppcState.spr[SPR_SPRG0]
2008-12-08 04:46:09 +00:00
# define SPRG1 PowerPC::ppcState.spr[SPR_SPRG1]
# define SPRG2 PowerPC::ppcState.spr[SPR_SPRG2]
# define SPRG3 PowerPC::ppcState.spr[SPR_SPRG3]
# define GQR(x) PowerPC::ppcState.spr[SPR_GQR0+x]
# define TL PowerPC::ppcState.spr[SPR_TL]
# define TU PowerPC::ppcState.spr[SPR_TU]
# define rPS0(i) (*(double*)(&PowerPC::ppcState.ps[i][0]))
# define rPS1(i) (*(double*)(&PowerPC::ppcState.ps[i][1]))
# define riPS0(i) (*(u64*)(&PowerPC::ppcState.ps[i][0]))
# define riPS1(i) (*(u64*)(&PowerPC::ppcState.ps[i][1]))
2008-12-15 19:22:34 +00:00
} // namespace
2008-12-08 04:46:09 +00:00
2009-06-13 14:10:10 +00:00
// Fast CR system - store them in single bytes instead of nibbles to not have to
// mask/shift them out.
2008-12-08 04:46:09 +00:00
2008-12-15 19:22:34 +00:00
// These are intended to stay fast, probably become faster, and are not likely to slow down much if at all.
2008-12-08 04:46:09 +00:00
inline void SetCRField ( int cr_field , int value ) {
2008-12-15 20:41:59 +00:00
PowerPC : : ppcState . cr_fast [ cr_field ] = value ;
2008-12-08 04:46:09 +00:00
}
inline u32 GetCRField ( int cr_field ) {
2008-12-15 20:41:59 +00:00
return PowerPC : : ppcState . cr_fast [ cr_field ] ;
2008-12-08 04:46:09 +00:00
}
inline u32 GetCRBit ( int bit ) {
2008-12-15 20:41:59 +00:00
return ( PowerPC : : ppcState . cr_fast [ bit > > 2 ] > > ( 3 - ( bit & 3 ) ) ) & 1 ;
2008-12-08 04:46:09 +00:00
}
2008-12-19 22:46:28 +00:00
inline void SetCRBit ( int bit , int value ) {
if ( value & 1 )
PowerPC : : ppcState . cr_fast [ bit > > 2 ] | = 0x8 > > ( bit & 3 ) ;
else
PowerPC : : ppcState . cr_fast [ bit > > 2 ] & = ~ ( 0x8 > > ( bit & 3 ) ) ;
}
2008-12-15 21:05:37 +00:00
// SetCR and GetCR are fairly slow. Should be avoided if possible.
2008-12-08 04:46:09 +00:00
inline void SetCR ( u32 new_cr ) {
2010-07-25 17:54:03 +00:00
PowerPC : : ppcState . cr = new_cr ;
PowerPC : : ExpandCR ( ) ;
2008-12-08 04:46:09 +00:00
}
inline u32 GetCR ( ) {
2010-07-25 17:54:03 +00:00
PowerPC : : CompactCR ( ) ;
return PowerPC : : ppcState . cr ;
2008-12-08 04:46:09 +00:00
}
2008-12-15 19:22:34 +00:00
// SetCarry/GetCarry may speed up soon.
2008-12-08 04:46:09 +00:00
inline void SetCarry ( int ca ) {
2008-12-15 19:22:34 +00:00
( ( UReg_XER & ) PowerPC : : ppcState . spr [ SPR_XER ] ) . CA = ca ;
2008-12-08 04:46:09 +00:00
}
inline int GetCarry ( ) {
2008-12-15 19:22:34 +00:00
return ( ( UReg_XER & ) PowerPC : : ppcState . spr [ SPR_XER ] ) . CA ;
}
inline UReg_XER GetXER ( ) {
return ( ( UReg_XER & ) PowerPC : : ppcState . spr [ SPR_XER ] ) ;
}
inline void SetXER ( UReg_XER new_xer ) {
( ( UReg_XER & ) PowerPC : : ppcState . spr [ SPR_XER ] ) = new_xer ;
}
inline int GetXER_SO ( ) {
return ( ( UReg_XER & ) PowerPC : : ppcState . spr [ SPR_XER ] ) . SO ;
}
inline void SetXER_SO ( int value ) {
( ( UReg_XER & ) PowerPC : : ppcState . spr [ SPR_XER ] ) . SO = value ;
2008-12-08 04:46:09 +00:00
}
2009-06-13 14:10:10 +00:00
void UpdateFPRF ( double dvalue ) ;
2009-11-15 22:26:39 +00:00
# endif