📄 z80.c
字号:
#define ENTER_HALT { \
_PC--; \
_HALT = 1; \
if( !after_EI ) \
z80_burn( z80_ICount ); \
}
/***************************************************************
* Leave HALT state; write 0 to fake port
***************************************************************/
#define LEAVE_HALT { \
if( _HALT ) \
{ \
_HALT = 0; \
_PC++; \
} \
}
/***************************************************************
* Input a byte from given I/O port
***************************************************************/
#define PORT_IN(port) ((UINT8)cpu_readport(port))
/***************************************************************
* Output a byte to given I/O port
***************************************************************/
#define PORT_OUT(port,value) cpu_writeport(port,value)
/***************************************************************
* Read a byte from given memory location
***************************************************************/
#define RM(addr) (UINT8)cpu_readmem16(addr)
/***************************************************************
* Read a word from given memory location
***************************************************************/
static __inline void RM16( UINT32 addr, PAIR *r )
{
r->b.l = RM(addr);
r->b.h = RM((addr+1)&0xffff);
}
/***************************************************************
* Write a byte to given memory location
***************************************************************/
#define WM(addr,value) cpu_writemem16(addr,value)
/***************************************************************
* Write a word to given memory location
***************************************************************/
static __inline void WM16( UINT32 addr, PAIR *r )
{
WM(addr,r->b.l);
WM((addr+1)&0xffff,r->b.h);
}
/***************************************************************
* ROP() is identical to RM() except it is used for
* reading opcodes. In case of system with memory mapped I/O,
* this function can be used to greatly speed up emulation
***************************************************************/
static __inline UINT8 ROP(void)
{
unsigned pc = _PCD;
_PC++;
return cpu_readop(pc);
}
/****************************************************************
* ARG() is identical to ROP() except it is used
* for reading opcode arguments. This difference can be used to
* support systems that use different encoding mechanisms for
* opcodes and opcode arguments
***************************************************************/
static __inline UINT8 ARG(void)
{
unsigned pc = _PCD;
_PC++;
return cpu_readop_arg(pc);
}
static __inline UINT32 ARG16(void)
{
unsigned pc = _PCD;
_PC += 2;
return cpu_readop_arg(pc) | (cpu_readop_arg((pc+1)&0xffff) << 8);
}
/***************************************************************
* Calculate the effective address EA of an opcode using
* IX+offset resp. IY+offset addressing.
***************************************************************/
#define EAX EA = (UINT32)(UINT16)(_IX+(INT8)ARG())
#define EAY EA = (UINT32)(UINT16)(_IY+(INT8)ARG())
/***************************************************************
* POP
***************************************************************/
#define POP(DR) { RM16( _SPD, &Z80.DR ); _SP += 2; }
/***************************************************************
* PUSH
***************************************************************/
#define PUSH(SR) { _SP -= 2; WM16( _SPD, &Z80.SR ); }
/***************************************************************
* JP
***************************************************************/
#if BUSY_LOOP_HACKS
#define JP { \
unsigned oldpc = _PCD-1; \
_PCD = ARG16(); \
/* speed up busy loop */ \
if( _PCD == oldpc ) \
{ \
if( !after_EI ) \
BURNODD( z80_ICount, 1, 10 ); \
} \
else \
{ \
UINT8 op = cpu_readop(_PCD); \
if( _PCD == oldpc-1 ) \
{ \
/* NOP - JP $-1 or EI - JP $-1 */ \
if ( op == 0x00 || op == 0xfb ) \
{ \
if( !after_EI ) \
BURNODD( z80_ICount-4, 2, 4+10 ); \
} \
} \
else \
/* LD SP,#xxxx - JP $-3 (Galaga) */ \
if( _PCD == oldpc-3 && op == 0x31 ) \
{ \
if( !after_EI ) \
BURNODD( z80_ICount-10, 2, 10+10 ); \
} \
} \
}
#else
#define JP { \
_PCD = ARG16(); \
}
#endif
/***************************************************************
* JP_COND
***************************************************************/
#define JP_COND(cond) \
if( cond ) \
{ \
_PCD = ARG16(); \
} \
else \
{ \
_PC += 2; \
}
/***************************************************************
* JR
***************************************************************/
#define JR() \
{ \
unsigned oldpc = _PCD-1; \
INT8 arg = (INT8)ARG(); /* ARG() also increments _PC */ \
_PC += arg; /* so don't do _PC += ARG() */ \
/* speed up busy loop */ \
if( _PCD == oldpc ) \
{ \
if( !after_EI ) \
BURNODD( z80_ICount, 1, 12 ); \
} \
else \
{ \
UINT8 op = cpu_readop(_PCD); \
if( _PCD == oldpc-1 ) \
{ \
/* NOP - JR $-1 or EI - JR $-1 */ \
if ( op == 0x00 || op == 0xfb ) \
{ \
if( !after_EI ) \
BURNODD( z80_ICount-4, 2, 4+12 ); \
} \
} \
else \
/* LD SP,#xxxx - JR $-3 */ \
if( _PCD == oldpc-3 && op == 0x31 ) \
{ \
if( !after_EI ) \
BURNODD( z80_ICount-12, 2, 10+12 ); \
} \
} \
}
/***************************************************************
* JR_COND
***************************************************************/
#define JR_COND(cond) \
if( cond ) \
{ \
INT8 arg = (INT8)ARG(); /* ARG() also increments _PC */ \
_PC += arg; /* so don't do _PC += ARG() */ \
CY(5); \
} \
else _PC++; \
/***************************************************************
* CALL
***************************************************************/
#define CALL(cond) \
if( cond ) \
{ \
EA = ARG16(); \
PUSH( PC ); \
_PCD = EA; \
CY(7); \
} \
else \
{ \
_PC+=2; \
}
/***************************************************************
* RET
***************************************************************/
#define RET(cond) \
if( cond ) \
{ \
POP(PC); \
CY(6); \
}
/***************************************************************
* RETN
***************************************************************/
#define RETN { \
RET(1); \
if( _IFF1 == 0 && _IFF2 == 1 ) \
{ \
_IFF1 = 1; \
if( Z80.irq_state != CLEAR_LINE || \
Z80.request_irq >= 0 ) \
{ \
take_interrupt(); \
} \
} \
else _IFF1 = _IFF2; \
}
/***************************************************************
* RETI
***************************************************************/
#define RETI { \
int device = Z80.service_irq; \
RET(1); \
/* according to http://www.msxnet.org/tech/Z80/z80undoc.txt */ \
/* _IFF1 = _IFF2; */ \
if( device >= 0 ) \
{ \
Z80.irq[device].interrupt_reti(Z80.irq[device].irq_param); \
} \
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -