⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpu.c

📁 A Zilog Z80 simulator, debugger and profiler tailored for ZX Spectrum development (but generic enoug
💻 C
📖 第 1 页 / 共 3 页
字号:
/*   Z80Sim - A simulator/debugger for the Zilog Z80 processor   Copyright (C) 2003 Lorenzo J. Lucchini   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. This program is distributed in the hope that it   will be useful, but WITHOUT ANY WARRANTY; without even the   implied warranty of MERCHANTABILITY or FITNESS FOR A   PARTICULAR PURPOSE. See the GNU General Public License for   more details. You should have received a copy of the GNU   General Public License along with this program; if not,   write to the Free Software Foundation, Inc., 59 Temple   Place, Suite 330, Boston, MA 02111-1307 USA*/#include "types.h"#include "sizes.h"#include "cpu.h"#include "opcodes.h"#include "symbols.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#define METACALL_QUIT		0x00#define METACALL_PUTCHARACTER	0x01#define METACALL_GETCLOCK	0x02#define METACALL_ENTER		0x03#define METACALL_EXIT		0x04#define METACALL_ENTERLEAF	0x05#define METACALL_DUMPREGS	0x06#define METACALL_PUTWORD	0x07#define METACALL_WRITEPROTECT	0x08#define METACALL_READPROTECT	0x09#define METACALL_RWPROTECT	0x0a#define METACALL_UNPROTECT	0x0b#define PROTECT_WRITE		1<<0#define PROTECT_READ		1<<1typedef union {	word Word;	struct {		byte L;		byte H;	} Bytes;} reg;inline byte ReadMemory(word Address);void WriteMemory(word Address, byte Value);void Push(word);void Pop(word*);byte Memory[SIZE_MEMORY];short Protections[SIZE_MEMORY];byte IR;reg AF, SP, PC;reg BC, DE;reg HL, IX, IY;reg AF1;reg BC1, DE1;reg HL1;logic InterruptRequest;logic EnableInterrupts;logic IFF1, IFF2;logic FlagZ, FlagNZ;logic FlagC, FlagNC;logic FlagPO, FlagPE;logic FlagM, FlagP;logic FlagN, FlagH;logic Flag3, Flag5;unsigned long TStates;unsigned long InstructionsExecuted;logic UsefulInstruction;logic Indexing;logic IndirectMemoryWrite;logic MemoryWrite;byte MemoryData;word MemoryAddress;reg* PointerReg;byte Index;trap Exception;#warning FIXME: DOES NOT GIVE THE RIGHT T-STATES, SHOULD BE MOVED OUT OF OperandR AND THE RESTint PHLOverhead;// Protect a zone of the main memory as specified by Flagsvoid ProtectRange(word Start, word End, short Flags) {	int i;	for(i=Start; i<=End; i++) {		Protections[i]=Flags;	}}// Return the bit specifying the sign in a 2's complement value of type 'byte'.inline logic SignBit(byte Value) {	if(Value&0x80) return TRUE; else return FALSE;}// Return TRUE if the parity of Byte is even, otherwise FALSE.inline logic Parity(byte Byte) {        byte Temp;	Temp=Byte;        Temp=Temp^(Temp>>4);        Temp=Temp^(Temp>>2);        Temp=Temp^(Temp>>1);        return ((Temp&1)!=0?FALSE:TRUE);}// Copy the contents of the Flag* logic variables into the actual F register.void StoreFlags() {	assert(FlagZ==!FlagNZ);	assert(FlagC==!FlagNC);	assert(FlagPE==!FlagPO);	assert(FlagP==!FlagM);	AF.Bytes.L=(		(FlagC?(1<<0):0) |		(FlagN?(1<<1):0) |		(FlagPE?(1<<2):0)|		(Flag3?(1<<3):0) |		(FlagH?(1<<4):0) |		(Flag5?(1<<5):0) |		(FlagZ?(1<<6):0) |		(FlagM?(1<<7):0)	);}// Set the Flag* variables depending on the contents of Datum, except those// that cannot be inferred from it alone. Don't set the actual F register.// Also calculate parity and store it into FlagPE/FlagPO if GiveParity==TRUE.void SetFlags(byte Datum) {	Flag3=(Datum&0x08)!=0;	Flag5=(Datum&0x20)!=0;	if(Datum==0) FlagZ=1; else FlagZ=0;	FlagNZ=!FlagZ;	FlagP=!SignBit(Datum);        FlagM=!FlagP;	FlagPE=Parity(Datum);	FlagPO=!FlagPE;}// Add Operand to *Register, and store the result into *Register. Set the Flag*// variables accordingly.void AddByte(byte* Register, byte Operand) {	byte Op1=*Register, Op2=Operand;        long Sum;        Sum=Op1+Op2;        *Register=(byte)Sum;        SetFlags(*Register);        if((Op1&0x08)^(Op2&0x08)^(Sum&0x08)) FlagH=1; else FlagH=0;        if(Sum>(word)0xFF) FlagNC=!(FlagC=1); else FlagC=!(FlagNC=1);	if(SignBit(Op1)==SignBit(Op2) && SignBit(Sum)!=SignBit(Op1)) FlagPO=!(FlagPE=1); else FlagPO=!(FlagPE=0);        FlagN=0;        TStates+=4;}// Subtract Operand from *Register, and store the result into *Register. Set the Flag*// variables accordingly.void SubByte(byte* Register, byte Operand) {        byte Op1=*Register, Op2=-Operand;        long Sum;        Sum=Op1+Op2;        *Register=(byte)Sum;        SetFlags(*Register);        if((Op1&0x08)^(Op2&0x08)^(Sum&0x08)) FlagH=0; else FlagH=1;        if(Sum>(word)0xFF) FlagNC=!(FlagC=0); else FlagC=!(FlagNC=0);        if(SignBit(Op1)==SignBit(Op2) && SignBit(Sum)!=SignBit(Op1)) FlagPO=!(FlagPE=1); else FlagPO=!(FlagPE=0);        FlagN=0;        TStates+=4;}// As per AddByte(), but do it for two words, and only set the flags required by// a word addition.void AddWord(word* Register, word Operand) {	long Sum;	Sum=*Register+Operand;        if(((*Register)&0x0F00)+(Operand&0x0F00)>0x0F00) FlagH=1; else FlagH=0;	*Register=(word)Sum;	if(Sum>0xFFFF) FlagNC=!(FlagC=1); else FlagC=!(FlagNC=1);	FlagN=0;	TStates+=11;}// Logical And of two bytes, store result into *Register and set the Flag*s.void And(byte* Register, byte Operand) {	*Register=*Register&Operand;	// Flags should be correct	SetFlags(*Register);	FlagNC=!(FlagC=0);	FlagN=0;	//StoreFlags();	TStates+=4;}// Logical exclusive Or of two bytes, store result into *Register and set the Flag*s.void XOr(byte* Register, byte Operand) {	*Register=*Register^Operand;	// Flags should be correct, but aren't	SetFlags(*Register);	FlagNC=!(FlagC=0);	FlagN=0;	FlagH=0;	//StoreFlags();	TStates+=4;}// Logical Or of two bytes, store result into *Register and set the Flag*s.void Or(byte* Register, byte Operand) {	*Register=*Register|Operand;	// Flags should be correct	SetFlags(*Register);	FlagNC=!(FlagC=0);	FlagN=0;	//StoreFlags();	TStates+=4;}// Subtract Operand to *Register; don't store the result anywhere, only set the Flag*s.void Compare(byte* Register, byte Operand) {	byte Temp=*Register;	SubByte(&Temp, Operand);        FlagN=1;	TStates+=4;}// Fetch a direct operand of the length of a word (16 bits).word GetWordOperand() {	reg WordOperand;        WordOperand.Bytes.L=ReadMemory(PC.Word++);        WordOperand.Bytes.H=ReadMemory(PC.Word++);	return WordOperand.Word;}// Branch to NewAddress.void JumpAbsolute(word NewAddress) {	PC.Word=NewAddress;	TStates+=10;	UsefulInstruction=TRUE;}// Branch to PC+Index.void JumpRelative(byte Index) {        PC.Word+=(word)(sbyte)Index;	TStates+=12;	UsefulInstruction=TRUE;}// Store PC into the stack, then branch to ProcAddress.void Call(word ProcAddress) {        Push(PC.Word);	JumpAbsolute(ProcAddress);	TStates-=4;}// Push Register into the stack.void Push(word Register) {	WriteMemory(SP.Word-2, (Register&0x00FF)>>0);        WriteMemory(SP.Word-1, (Register&0xFF00)>>8);	SP.Word-=2;	TStates+=11;}// Pop a value from the stack and store it into *Register.void Pop(word* Register) {	*Register=ReadMemory(SP.Word++);	(*Register)|=ReadMemory(SP.Word++)<<8;	if(Register==&AF.Word) {		FlagNC=!(FlagC=(AF.Bytes.L>>0)&1);		FlagNZ=!(FlagZ=(AF.Bytes.L>>6)&1);		FlagPO=!(FlagPE=(AF.Bytes.L>>2)&1);		FlagP=!(FlagM=(AF.Bytes.L>>7)&1);		FlagN=(AF.Bytes.L>>1)&1;		FlagH=(AF.Bytes.L>>4)&1;		Flag3=(AF.Bytes.L>>3)&1;		Flag5=(AF.Bytes.L>>5)&1;	}	TStates+=10;}// Swap two words.void Swap(word* Reg1, word* Reg2) {	word Temp;	Temp=*Reg1;	*Reg1=*Reg2;	*Reg2=Temp;}// Return the address of the register specified in Opcode, with Opcode being// a Z80 opcode whose bits 3..5 specify a register.byte* OperandR(byte Opcode) {        if(OPARG_R_A(Opcode)) return &AF.Bytes.H;	if(OPARG_R_B(Opcode)) return &BC.Bytes.H;	if(OPARG_R_C(Opcode)) return &BC.Bytes.L;	if(OPARG_R_D(Opcode)) return &DE.Bytes.H;        if(OPARG_R_E(Opcode)) return &DE.Bytes.L;        if(OPARG_R_H(Opcode)) return &HL.Bytes.H;        if(OPARG_R_L(Opcode)) return &HL.Bytes.L;        if(OPARG_R_PHL(Opcode)) {		TStates+=PHLOverhead;                IndirectMemoryWrite=TRUE;                MemoryData=ReadMemory(PointerReg->Word+(word)(sbyte)Index);                return &MemoryData;        }        fprintf(stdout, "ERROR: Unrecognized destination register\n");	return &AF.Bytes.H;}// Return the address of the register specified in Opcode, with Opcode being// a Z80 opcode whose bits 0..2 specify a register.byte* OperandS(byte Opcode) {        if(OPARG_S_A(Opcode)) return &AF.Bytes.H;        if(OPARG_S_B(Opcode)) return &BC.Bytes.H;        if(OPARG_S_C(Opcode)) return &BC.Bytes.L;        if(OPARG_S_D(Opcode)) return &DE.Bytes.H;        if(OPARG_S_E(Opcode)) return &DE.Bytes.L;        if(OPARG_S_H(Opcode)) return &HL.Bytes.H;        if(OPARG_S_L(Opcode)) return &HL.Bytes.L;        if(OPARG_S_PHL(Opcode)) {		TStates+=PHLOverhead;		MemoryData=ReadMemory(PointerReg->Word+(word)(sbyte)Index);		return &MemoryData;	}	fprintf(stdout, "ERROR: Unrecognized source register\n");	return &AF.Bytes.H;}// Return the address of the register pair specified in Opcode, with Opcode// being a Z80 opcode whose bits 4 and 5 specify a register pair.word* OperandP(byte Opcode) {        if(OPARG_P_BC(Opcode)) return &BC.Word;        if(OPARG_P_DE(Opcode)) return &DE.Word;        if(OPARG_P_HL(Opcode)) return &(PointerReg->Word);        if(OPARG_P_SP(Opcode)) return &SP.Word;	return NULL;}// Return the address of a Flag* variable as specified in Opcode, with// Opcode being a z80 opcode whose bits 3..5 specify a flag.logic* OperandF(byte Opcode) {        if(OPARG_F_NZ(Opcode)) return &FlagNZ;        if(OPARG_F_Z(Opcode)) return &FlagZ;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -