📄 cpu.c
字号:
if(OPARG_F_NC(Opcode)) return &FlagNC; if(OPARG_F_C(Opcode)) return &FlagC; if(OPARG_F_PO(Opcode)) return &FlagPO; if(OPARG_F_PE(Opcode)) return &FlagPE; if(OPARG_F_P(Opcode)) return &FlagP; if(OPARG_F_M(Opcode)) return &FlagM; return NULL;}// As per OperandF(), but works with those opcode that only accept one// of four flags instead of eight in bits 3 and 4logic* OperandSF(byte Opcode) { if(OPARG_SF_NZ(Opcode)) return &FlagNZ; if(OPARG_SF_Z(Opcode)) return &FlagZ; if(OPARG_SF_NC(Opcode)) return &FlagNC; if(OPARG_SF_C(Opcode)) return &FlagC; return NULL;}// Store a string in Name containing the human-readable name of the flag// which is a Flag* variable at address *Flag.void NameFlag(logic* Flag, char* Name) { if(Flag==&FlagNZ) strcpy(Name, "nz"); else if(Flag==&FlagZ) strcpy(Name, "z"); else if(Flag==&FlagNC) strcpy(Name, "nc"); else if(Flag==&FlagC) strcpy(Name, "c"); else if(Flag==&FlagPO) strcpy(Name, "po"); else if(Flag==&FlagPE) strcpy(Name, "pe"); else if(Flag==&FlagP) strcpy(Name, "p"); else if(Flag==&FlagM) strcpy(Name, "m"); else strcpy(Name, "?f");}// Store a string in Name containing the human-readable name of the (byte)// register at address *Register.void NameRegister(byte* Register, char* Name) { if(Register==&AF.Bytes.H) strcpy(Name, "a"); else if(Register==&AF.Bytes.L) strcpy(Name, "f"); else if(Register==&BC.Bytes.H) strcpy(Name, "b"); else if(Register==&BC.Bytes.L) strcpy(Name, "c"); else if(Register==&DE.Bytes.H) strcpy(Name, "d"); else if(Register==&DE.Bytes.L) strcpy(Name, "e"); else if(Register==&HL.Bytes.H) strcpy(Name, "h"); else if(Register==&HL.Bytes.L) strcpy(Name, "l"); else if(Register==&MemoryData) { if(PointerReg==&HL) strcpy(Name, "(hl)"); else if(PointerReg==&IX) strcpy(Name, "(ix)"); else if(PointerReg==&IY) strcpy(Name, "(iy)"); else strcpy(Name, "?i"); } else strcpy(Name, "?r");}// Store a string in Name containing the human-readable name of the// register pair at address *Register.void NameRegisterPair(word* Register, char* Name) { if(Register==&AF.Word) strcpy(Name, "af"); else if(Register==&BC.Word) strcpy(Name, "bc"); else if(Register==&DE.Word) strcpy(Name, "de"); else if(Register==&HL.Word) strcpy(Name, "hl"); else if(Register==&SP.Word) strcpy(Name, "sp"); else if(Register==&IX.Word) strcpy(Name, "ix"); else if(Register==&IY.Word) strcpy(Name, "iy"); else strcpy(Name, "?p");}// Return the contents of cell number Address in main memory.inline byte ReadMemory(word Address) { MemoryAddress=Address; if(Protections[Address]&PROTECT_READ) Exception=TRAP_MEMORY; MemoryData=Memory[Address]; return MemoryData;}// Write the contents of Value to cell number Address in main memory,// if this is allowed.void WriteMemory(word Address, byte Value) { MemoryAddress=Address; MemoryData=Value; MemoryWrite=TRUE; if(Protections[Address]&PROTECT_WRITE) { Exception=TRAP_MEMORY; } else { Memory[Address]=Value; }}inline byte ReadIO(byte Port) { return 0;}void WriteIO(byte Port, byte Value) { fprintf(stdout, "WARNING: Writing %02x into port %02x\n", Value, Port);}// Initialize the Z80 simulation.void Init() { int i; AF.Word=BC.Word=DE.Word=HL.Word=IX.Word=IY.Word=SP.Word=PC.Word=AF1.Word=BC1.Word=DE1.Word=HL1.Word=0x0000; FlagNZ=!(FlagZ=0); FlagNC=!(FlagC=0); FlagPO=!(FlagPE=0); FlagP=!(FlagM=0); Flag3=0; Flag5=0; FlagN=0; FlagH=0; TStates=0; InstructionsExecuted=0; for(i=0; i<0x1000; i++) { Memory[i]=0x00; // rand(); } //ProtectRange(0x0000, 0x3fff, PROTECT_WRITE); ProtectRange(0x0000, 0xffff, 0); fprintf(stdout, "Z80 initialized\n");}void LoadROM(FILE* Handle) { fread(Memory, 1, 0x10000, Handle);}void MetaCall(byte Number) { switch(Number) { case METACALL_ENTER: // to be implemented break; case METACALL_EXIT: // to be implemented break; case METACALL_PUTCHARACTER: fprintf(stderr, "%c", HL.Bytes.L); fflush(stderr); break; case METACALL_PUTWORD: fprintf(stderr, "%04x", HL.Word); fflush(stderr); break; case METACALL_WRITEPROTECT: ProtectRange(HL.Word, DE.Word, PROTECT_WRITE); break; case METACALL_READPROTECT: ProtectRange(HL.Word, DE.Word, PROTECT_READ); break; case METACALL_RWPROTECT: ProtectRange(HL.Word, DE.Word, PROTECT_WRITE|PROTECT_READ); break; case METACALL_UNPROTECT: ProtectRange(HL.Word, DE.Word, 0); break; default: fprintf(stdout, "WARNING: Unimplemented metacall %02x\n", Number); Exception=TRAP_METACALL; } UsefulInstruction=TRUE;}void SnapshotState(FILE* Handle) { char Mnemonic[MAX_NAME]; word InstructionAddress; InstructionAddress=PC.Word; fprintf(Handle, "Frame %ld Begin\n", InstructionsExecuted); fprintf(Handle, "\tPC <0x%04x> SP <0x%04x>\n", PC.Word, SP.Word); fprintf(Handle, "\tA <0x%02x>\n", AF.Bytes.H); fprintf(Handle, "\tfS <%d> fZ <%d> f5 <%d> fH <%d> f3 <%d> fP <%d> fN <%d> fC <%d>\n", ((AF.Bytes.L>>7)&1), ((AF.Bytes.L>>6)&1), ((AF.Bytes.L>>5)&1), ((AF.Bytes.L>>4)&1), ((AF.Bytes.L>>3)&1), ((AF.Bytes.L>>2)&1), ((AF.Bytes.L>>1)&1), ((AF.Bytes.L>>7)&0)); fprintf(Handle, "\tHL <0x%04x>\n", HL.Word); fprintf(Handle, "\tIX <0x%04x> IY <0x%04x>\n", IX.Word, IY.Word), fprintf(Handle, "\tBC <0x%04x> DE <0x%04x>\n", BC.Word, DE.Word); fprintf(Handle, "\tMAR <0x%04x> MDR <0x%02x>\n", MemoryAddress, MemoryData); if(MemoryWrite) fprintf(Handle, "\tStore <TRUE>\n"); else fprintf(Handle, "\tStore <FALSE>\n"); fprintf(Handle, "\tStack <0x%02x%02x>\n", Memory[(word)(SP.Word+1)], Memory[(word)(SP.Word+0)]); Disassemble(&InstructionAddress, Mnemonic); fprintf(Handle, "\tMnemonic <%s>\n", Mnemonic); fprintf(Handle, "End\n");}void PrintRegisters(FILE *Handle) { fprintf(Handle, "SP:%04x AF:%04x BC:%04x DE:%04x HL:%04x IX:%04x IY:%04x", SP.Word, AF.Word, BC.Word, DE.Word, HL.Word, IX.Word, IY.Word);}inline word FetchAddress(word* Address) { return Memory[(*Address)++] | (Memory[(*Address)++]<<8);}// Disassemble the Z80 instruction starting at Address.void Disassemble(word* Address, char* Mnemonic) { char NameR[MAX_NAME], NameS[MAX_NAME], NameP[MAX_NAME], NameI[MAX_NAME], NameF[MAX_NAME], Symbol[MAX_NAME]; byte Opcode; Opcode=Memory[(*Address)++]; if(OP_IXPREFIX(Opcode)) { Opcode=ReadMemory((*Address)++); PointerReg=&IX; Indexing=TRUE; } else if(OP_IYPREFIX(Opcode)) { Opcode=ReadMemory((*Address)++); PointerReg=&IY; Indexing=TRUE; } else { PointerReg=&HL; Indexing=FALSE; } if(OP_HLT(Opcode)) { sprintf(Mnemonic, "halt"); } else if(OP_LD_R_S(Opcode)) { NameRegister(OperandR(Opcode), NameR); NameRegister(OperandS(Opcode), NameS); if(Indexing) { if(OPARG_R_PHL(Opcode)) sprintf(Mnemonic, "ld #%02x %s, %s", Memory[(*Address)++], NameR, NameS); else if(OPARG_S_PHL(Opcode)) sprintf(Mnemonic, "ld %s, #%02x %s", NameR, Memory[(*Address)++], NameS); } else sprintf(Mnemonic, "ld %s, %s", NameR, NameS); } else if(OP_LD_R_B(Opcode)) { NameRegister(OperandR(Opcode), NameR); if(Indexing) sprintf(Mnemonic, "ld #%02x %s, #%02x", Memory[(*Address)++], NameR, Memory[(*Address)++]); else sprintf(Mnemonic, "ld %s, #%02x", NameR, Memory[(*Address)++]); } else if(OP_LD_P_W(Opcode)) { NameRegisterPair(OperandP(Opcode), NameP); sprintf(Mnemonic, "ld %s, #%02x%02x", NameP, Memory[(*Address)++], Memory[(*Address)++]); } else if(OP_LD_SP_HL(Opcode)) { NameRegisterPair(&PointerReg->Word, NameI); sprintf(Mnemonic, "ld sp, %s", NameI); } else if(OP_LD_A_PBC(Opcode)) { sprintf(Mnemonic, "ld a, (bc)"); } else if(OP_LD_A_PDE(Opcode)) { sprintf(Mnemonic, "ld a, (de)"); } else if(OP_LD_A_PW(Opcode)) { sprintf(Mnemonic, "ld a, (%02x%02x)", Memory[(*Address)++], Memory[(*Address)++]); } else if(OP_LD_PW_A(Opcode)) { sprintf(Mnemonic, "ld (%02x%02x), a", Memory[(*Address)++], Memory[(*Address)++]); } else if(OP_LD_HL_PW(Opcode)) { sprintf(Mnemonic, "ld hl, (%02x%02x)", Memory[(*Address)++], Memory[(*Address)++]); } else if(OP_LD_PBC_A(Opcode)) { sprintf(Mnemonic, "ld (bc), a"); } else if(OP_LD_PDE_A(Opcode)) { sprintf(Mnemonic, "ld (de), a"); } else if(OP_ADD_S(Opcode)) { NameRegister(OperandS(Opcode), NameS); if(OPMOD_CARRYIN(Opcode)) sprintf(Mnemonic, "adc a, %s", NameS); else sprintf(Mnemonic, "add a, %s", NameS); } else if(OP_ADD_B(Opcode)) { if(OPMOD_CARRYIN(Opcode)) sprintf(Mnemonic, "adc a, #%02x", Memory[(*Address)++]); else sprintf(Mnemonic, "add a, #%02x", Memory[(*Address)++]); } else if(OP_SUB_S(Opcode)) { NameRegister(OperandS(Opcode), NameS); if(OPMOD_CARRYIN(Opcode)) sprintf(Mnemonic, "sbc a, %s", NameS); else sprintf(Mnemonic, "sub a, %s", NameS); } else if(OP_SUB_B(Opcode)) { if(OPMOD_CARRYIN(Opcode)) sprintf(Mnemonic, "sbc a, #%02x", Memory[(*Address)++]); else sprintf(Mnemonic, "sub a, #%02x", Memory[(*Address)++]); } else if(OP_ADD_HL_P(Opcode)) { NameRegisterPair(&PointerReg->Word, NameI); NameRegisterPair(OperandP(Opcode), NameP); sprintf(Mnemonic, "add %s, %s", NameI, NameP); } else if(OP_INC_R(Opcode)) { NameRegister(OperandR(Opcode), NameR); sprintf(Mnemonic, "inc %s", NameR); } else if(OP_DEC_R(Opcode)) { NameRegister(OperandR(Opcode), NameR); sprintf(Mnemonic, "dec %s", NameR); } else if(OP_INC_P(Opcode)) { NameRegisterPair(OperandP(Opcode), NameP); sprintf(Mnemonic, "inc %s", NameP); } else if(OP_DEC_P(Opcode)) { NameRegisterPair(OperandP(Opcode), NameP); sprintf(Mnemonic, "dec %s", NameP); } else if(OP_AND_S(Opcode)) { NameRegister(OperandS(Opcode), NameS); sprintf(Mnemonic, "and a, %s", NameS); } else if(OP_AND_B(Opcode)) { sprintf(Mnemonic, "and a, #%02x", Memory[(*Address)++]); } else if(OP_XOR_S(Opcode)) { NameRegister(OperandS(Opcode), NameS); sprintf(Mnemonic, "xor a, %s", NameS); } else if(OP_XOR_B(Opcode)) { sprintf(Mnemonic, "xor a, #%02x", Memory[(*Address)++]); } else if(OP_OR_S(Opcode)) { NameRegister(OperandS(Opcode), NameS); sprintf(Mnemonic, "or a, %s", NameS); } else if(OP_OR_B(Opcode)) { sprintf(Mnemonic, "or a, #%02x", Memory[(*Address)++]); } else if(OP_CP_S(Opcode)) { NameRegister(OperandS(Opcode), NameS); sprintf(Mnemonic, "cp a, %s", NameS); } else if(OP_CP_B(Opcode)) { sprintf(Mnemonic, "cp a, #%02x", Memory[(*Address)++]); } else if(OP_JP_W(Opcode)) { LookupSymbol(FetchAddress(Address), Symbol); sprintf(Mnemonic, "jp %s", Symbol); } else if(OP_JP_F_W(Opcode)) { NameFlag(OperandF(Opcode), NameF); LookupSymbol(FetchAddress(Address), Symbol); sprintf(Mnemonic, "jp %s, %s", NameF, Symbol); } else if(OP_JP_PHL(Opcode)) { sprintf(Mnemonic, "jp (HL)"); } else if(OP_JR_B(Opcode)) { sprintf(Mnemonic, "jr %02x", Memory[(*Address)++]); } else if(OP_JR_SF_B(Opcode)) { NameFlag(OperandF(Opcode), NameF); sprintf(Mnemonic, "jr %s, %02x", NameF, Memory[(*Address)++]); } else if(OP_DJNZ_B(Opcode)) { sprintf(Mnemonic, "djnz %02x", Memory[(*Address)++]); } else if(OP_CPL(Opcode)) { sprintf(Mnemonic, "cpl"); } else if(OP_DI(Opcode)) { sprintf(Mnemonic, "di"); } else if(OP_EI(Opcode)) { sprintf(Mnemonic, "ei"); } else if(OP_CALL_W(Opcode)) { LookupSymbol(FetchAddress(Address), Symbol); sprintf(Mnemonic, "call %s", Symbol); } else if(OP_CALL_F_W(Opcode)) { NameFlag(OperandF(Opcode), NameF); LookupSymbol(FetchAddress(Address), Symbol); sprintf(Mnemonic, "call %s, %s", NameF, Symbol); } else if(OP_RET(Opcode)) { sprintf(Mnemonic, "ret"); } else if(OP_RET_F(Opcode)) { NameFlag(OperandF(Opcode), NameF); sprintf(Mnemonic, "ret %s", NameF); } else if(OP_EXDEHL(Opcode)) { sprintf(Mnemonic, "ex de, HL"); } else if(OP_EXPSPHL(Opcode)) { sprintf(Mnemonic, "ex (sp), HL"); } else if(OP_EXAFAF1(Opcode)) { sprintf(Mnemonic, "ex af, af'"); } else if(OP_EXX(Opcode)) { sprintf(Mnemonic, "exx"); } else if(OP_PUSH_P(Opcode)) { if(OperandP(Opcode)==&SP.Word) strcpy(NameP, "AF"); else NameRegisterPair(OperandP(Opcode), NameP); sprintf(Mnemonic, "push %s", NameP); } else if(OP_POP_P(Opcode)) { if(OperandP(Opcode)==&SP.Word) strcpy(NameP, "AF"); else NameRegisterPair(OperandP(Opcode), NameP); sprintf(Mnemonic, "pop %s", NameP); } else if(OP_RLA(Opcode)) { sprintf(Mnemonic, "rla"); } else if(OP_RLCA(Opcode)) { sprintf(Mnemonic, "rlca"); } else if(OP_RRCA(Opcode)) { sprintf(Mnemonic, "rrca"); } else if(OP_RRA(Opcode)) { sprintf(Mnemonic, "rra"); } else if(OP_IN_B(Opcode)) { sprintf(Mnemonic, "in a, %02x", Memory[(*Address)++]); } else if(OP_OUT_B(Opcode)) { sprintf(Mnemonic, "out %02x, a", Memory[(*Address)++]); } else if(OP_RST00(Opcode)) { sprintf(Mnemonic, "rst 0x00"); } else if(OP_RST08(Opcode)) { sprintf(Mnemonic, "rst 0x08 (META)"); } else if(OP_RST10(Opcode)) { sprintf(Mnemonic, "rst 0x10"); } else if(OP_RST18(Opcode)) { sprintf(Mnemonic, "rst 0x18"); } else if(OP_RST20(Opcode)) { sprintf(Mnemonic, "rst 0x20"); } else if(OP_RST28(Opcode)) { sprintf(Mnemonic, "rst 0x28"); } else if(OP_RST30(Opcode)) { sprintf(Mnemonic, "rst 0x30"); } else if(OP_RST38(Opcode)) { sprintf(Mnemonic, "rst 0x38"); } else if(OP_NOP(Opcode)) { sprintf(Mnemonic, "nop"); } else if(OP_CB(Opcode)) { Opcode=Memory[(*Address)++]; if(OP_CB_RLC(Opcode)) { NameRegister(OperandS(Opcode), NameS); sprintf(Mnemonic, "rlc %s", NameS); } else if(OP_CB_RL(Opcode)) { NameRegister(OperandS(Opcode), NameS); sprintf(Mnemonic, "rl %s", NameS); } else if(OP_CB_RRC(Opcode)) { NameRegister(OperandS(Opcode), NameS); sprintf(Mnemonic, "rrc %s", NameS); } else if(OP_CB_SLA(Opcode)) { NameRegister(OperandS(Opcode), NameS); sprintf(Mnemonic, "sla %s", NameS); } else if(OP_CB_BIT_N_S(Opcode)) { NameRegister(OperandS(Opcode), NameS); sprintf(Mnemonic, "bit %d, %s", OPPARM_N(Opcode), NameS); } else { sprintf(Mnemonic, "???"); } } else if(OP_ED(Opcode)) { Opcode=Memory[(*Address)++]; if(OP_ED_LD_P_PW(Opcode)) { NameRegisterPair(OperandP(Opcode), NameP); LookupSymbol(FetchAddress(Address), Symbol); sprintf(Mnemonic, "ld %s, (%s)", NameP, Symbol); } else if(OP_ED_LD_PW_SP(Opcode)) { LookupSymbol(FetchAddress(Address), Symbol);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -