From 8f8428ea493c60c7fe2d86c0f3a38330480bdcd8 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Tue, 22 Dec 2020 15:38:04 +0100 Subject: [PATCH] DAA implemented --- src/zvm_m65/z80_instr_general.s | 53 +++++++++++++-- src/zvm_m65/z80_tables.s | 68 +++++++++++++++++++ src/zvm_m65/zvm_banking.s | 112 +------------------------------- src/zvm_m65/zvm_core.s | 1 - tools/generate_z80_tables.cc | 96 +++++++++++++++++++++++++-- 5 files changed, 209 insertions(+), 121 deletions(-) diff --git a/src/zvm_m65/z80_instr_general.s b/src/zvm_m65/z80_instr_general.s index 9cae0afa..ed2f4aeb 100644 --- a/src/zvm_m65/z80_instr_general.s +++ b/src/zvm_m65/z80_instr_general.s @@ -4,7 +4,48 @@ ; -Z80_instr_2F: ; CPL +!macro Z80_DAA_TAB .OTAB, .FTAB { + ldx REG_A + lda .OTAB,x + sta REG_A + lda .FTAB,x + sta REG_F + jmp ZVM_next +} + +Z80_instr_27: ; DAA + + bbs1 REG_F, @N1 +@N0: + bbs0 REG_F, @N0C1 +@N0C0: + bbs4 REG_F, @N0C0H1 +@N0C0H0: + +Z80_DAA_TAB z80_otable_DAA_N0C0H0, z80_ftable_DAA_N0C0H0 +@N0C0H1: + +Z80_DAA_TAB z80_otable_DAA_N0C0H1, z80_ftable_DAA_N0C0H1 +@N0C1: + bbs4 REG_F, @N0C1H1 +@N0C1H0: + +Z80_DAA_TAB z80_otable_DAA_N0C1H0, z80_ftable_DAA_N0C1H0 +@N0C1H1: + +Z80_DAA_TAB z80_otable_DAA_N0C1H1, z80_ftable_DAA_N0C1H1 +@N1: + bbs0 REG_F, @N1C1 +@N1C0: + bbs4 REG_F, @N1C0H1 +@N1C0H0: + +Z80_DAA_TAB z80_otable_DAA_N1C0H0, z80_ftable_DAA_N1C0H0 +@N1C0H1: + +Z80_DAA_TAB z80_otable_DAA_N1C0H1, z80_ftable_DAA_N1C0H1 +@N1C1: + bbs4 REG_F, @N1C1H1 +@N1C1H0: + +Z80_DAA_TAB z80_otable_DAA_N1C1H0, z80_ftable_DAA_N1C1H0 +@N1C1H1: + +Z80_DAA_TAB z80_otable_DAA_N1C1H1, z80_ftable_DAA_N1C1H1 + +Z80_instr_2F: ; CPL lda REG_A eor #$FF @@ -17,7 +58,7 @@ Z80_instr_2F: ; CPL ; XXX put NEG here -Z80_instr_3F: ; CCF +Z80_instr_3F: ; CCF +Z80_PUT_0_NF bbs0 REG_F,@1 @@ -30,14 +71,14 @@ Z80_instr_3F: ; CCF +Z80_PUT_0_CF jmp ZVM_next -Z80_instr_37: ; SCF +Z80_instr_37: ; SCF +Z80_PUT_0_HF +Z80_PUT_0_NF +Z80_PUT_1_CF jmp ZVM_next -Z80_instr_76: ; HALT +Z80_instr_76: ; HALT ; Used to call BIOS routines ; XXX probably not the besta idea, GENCPC seems to do some relocations @@ -59,14 +100,14 @@ Z80_instr_76: ; HALT tax jmp (zvm_BIOS_vectable,x) -Z80_instr_F3: ; DI +Z80_instr_F3: ; DI lda #$00 sta REG_IFF1 sta REG_IFF2 jmp ZVM_next -Z80_instr_FB: ; EI +Z80_instr_FB: ; EI lda #Z80_PF sta REG_IFF1 diff --git a/src/zvm_m65/z80_tables.s b/src/zvm_m65/z80_tables.s index ea049522..b7545b59 100644 --- a/src/zvm_m65/z80_tables.s +++ b/src/zvm_m65/z80_tables.s @@ -28,3 +28,71 @@ z80_ftable_AND: z80_ftable_IN_OR_XOR: +PUT_Z80_FTABLE_IN_OR_XOR + +; +; That horrific DAA instruction +; + +z80_otable_DAA_N0C0H0: + + +PUT_Z80_OTABLE_DAA_N0C0H0 + +z80_otable_DAA_N0C0H1: + + +PUT_Z80_OTABLE_DAA_N0C0H1 + +z80_otable_DAA_N0C1H0: + + +PUT_Z80_OTABLE_DAA_N0C1H0 + +z80_otable_DAA_N0C1H1: + + +PUT_Z80_OTABLE_DAA_N0C1H1 + +z80_otable_DAA_N1C0H0: + + +PUT_Z80_OTABLE_DAA_N1C0H0 + +z80_otable_DAA_N1C0H1: + + +PUT_Z80_OTABLE_DAA_N1C0H1 + +z80_otable_DAA_N1C1H0: + + +PUT_Z80_OTABLE_DAA_N1C1H0 + +z80_otable_DAA_N1C1H1: + + +PUT_Z80_OTABLE_DAA_N1C1H1 + +z80_ftable_DAA_N0C0H0: + + +PUT_Z80_FTABLE_DAA_N0C0H0 + +z80_ftable_DAA_N0C0H1: + + +PUT_Z80_FTABLE_DAA_N0C0H1 + +z80_ftable_DAA_N0C1H0: + + +PUT_Z80_FTABLE_DAA_N0C1H0 + +z80_ftable_DAA_N0C1H1: + + +PUT_Z80_FTABLE_DAA_N0C1H1 + +z80_ftable_DAA_N1C0H0: + + +PUT_Z80_FTABLE_DAA_N1C0H0 + +z80_ftable_DAA_N1C0H1: + + +PUT_Z80_FTABLE_DAA_N1C0H1 + +z80_ftable_DAA_N1C1H0: + + +PUT_Z80_FTABLE_DAA_N1C1H0 + +z80_ftable_DAA_N1C1H1: + + +PUT_Z80_FTABLE_DAA_N1C1H1 diff --git a/src/zvm_m65/zvm_banking.s b/src/zvm_m65/zvm_banking.s index d7baa80d..3403d769 100644 --- a/src/zvm_m65/zvm_banking.s +++ b/src/zvm_m65/zvm_banking.s @@ -6,121 +6,13 @@ ZVM_set_bank_0: - ; XXX consider switchink banks using DMA list - - lda #ZVM_fetch_value_bank_0 - sta VEC_fetch_value+1 - - lda #ZVM_fetch_stack_bank_0 - sta VEC_fetch_stack+1 - - lda #ZVM_store_stack_bank_0 - sta VEC_store_stack+1 - - lda #ZVM_fetch_via_HL_bank_0 - sta VEC_fetch_via_HL+1 - - lda #ZVM_store_via_HL_bank_0 - sta VEC_store_via_HL+1 - - lda #ZVM_fetch_via_IX_d_bank_0 - sta VEC_fetch_via_IX_d+1 - - lda #ZVM_fetch_via_IY_d_bank_0 - sta VEC_fetch_via_IY_d+1 - - lda #ZVM_store_via_IX_d_bank_0 - sta VEC_store_via_IX_d+1 - - lda #ZVM_store_via_IY_d_bank_0 - sta VEC_store_via_IY_d+1 - - lda #ZVM_fetch_via_nn_bank_0 - sta VEC_fetch_via_nn+1 - - lda #ZVM_store_via_nn_bank_0 - sta VEC_store_via_nn+1 + ; XXX use DMAgic to switch banks (vectors on zeropage) rts ZVM_set_bank_1: - lda #ZVM_fetch_value_bank_1 - sta VEC_fetch_value+1 - - lda #ZVM_fetch_stack_bank_1 - sta VEC_fetch_stack+1 - - lda #ZVM_store_stack_bank_1 - sta VEC_store_stack+1 - - lda #ZVM_fetch_via_HL_bank_1 - sta VEC_fetch_via_HL+1 - - lda #ZVM_store_via_HL_bank_1 - sta VEC_store_via_HL+1 - - lda #ZVM_fetch_via_IX_d_bank_1 - sta VEC_fetch_via_IX_d+1 - - lda #ZVM_fetch_via_IY_d_bank_1 - sta VEC_fetch_via_IY_d+1 - - lda #ZVM_store_via_IX_d_bank_1 - sta VEC_store_via_IX_d+1 - - lda #ZVM_store_via_IY_d_bank_1 - sta VEC_store_via_IY_d+1 - - lda #ZVM_fetch_via_nn_bank_1 - sta VEC_fetch_via_nn+1 - - lda #ZVM_store_via_nn_bank_1 - sta VEC_store_via_nn+1 + ; XXX use DMAgic to switch banks (vectors on zeropage) rts diff --git a/src/zvm_m65/zvm_core.s b/src/zvm_m65/zvm_core.s index 5c08f384..addeb42a 100644 --- a/src/zvm_m65/zvm_core.s +++ b/src/zvm_m65/zvm_core.s @@ -107,7 +107,6 @@ Z80_instr_12: ; LD (DE),A Z80_instr_19: ; ADD HL,DE Z80_instr_1A: ; LD A,(DE) Z80_instr_22: ; LD (nn),HL -Z80_instr_27: ; DAA Z80_instr_29: ; ADD HL,HL Z80_instr_2A: ; LD HL,(nn) Z80_instr_32: ; LD (nn),A diff --git a/tools/generate_z80_tables.cc b/tools/generate_z80_tables.cc index df0ee434..db236721 100644 --- a/tools/generate_z80_tables.cc +++ b/tools/generate_z80_tables.cc @@ -210,14 +210,102 @@ std::string generateInOrXorTable(void) return outStr.str() + "}\n\n\n"; } + + +typedef struct FlagsDAA +{ + uint8_t N = 0; // input/output + uint8_t C = 0; // input/output + uint8_t H = 0; // input/output + uint8_t S = 0; // output + uint8_t Z = 0; // output + uint8_t P = 0; // output + uint8_t X = 0; // output + uint8_t Y = 0; // output + +} Flags; + + +uint8_t calculateDAA(FlagsDAA &flags, uint8_t A) +{ + // Based on code by Rui Ribeiro, see the discussion here: + // https://stackoverflow.com/questions/8119577/z80-daa-instruction + + int t = 0; + + if (flags.H || ((A & 0xF) > 9)) t++; + + if (flags.C || (A > 0x99)) + { + t += 2; + flags.C = 1; + } + + if (flags.N && !flags.H) + { + flags.H = 0; + } + else + { + if (flags.N && flags.H) + flags.H = (((A & 0x0F)) < 6); + else + flags.H = ((A & 0x0F) >= 0x0A); + } + + switch (t) + { + case 1: A += (flags.N) ? 0xFA : 0x06; break; // -6:6 + case 2: A += (flags.N) ? 0xA0 : 0x60; break; // -0x60:0x60 + case 3: A += (flags.N) ? 0x9A : 0x66; break; // -0x66:0x66 + } + + flags.S = (A & 0x80); + flags.Z = !A; + flags.P = GLOBAL_Parity[A]; + flags.X = A & 0x20; + flags.Y = A & 0x08; + + return A; +} + std::string generateDaaTables() { std::string outStr; - // iterate by SF, HF, CF flags + for (uint8_t NF : {0, 1}) for (uint8_t CF : {0, 1}) for (uint8_t HF : {0, 1}) + { + std::string keyStr = std::string("_") + (NF ? "N1" : "N0") + (CF ? "C1" : "C0") + (HF ? "H1" : "H0"); - // XXX - // Check code by Rui Ribeiro, see https://stackoverflow.com/questions/8119577/z80-daa-instruction + std::stringstream outStrF; + outStrF << "!macro PUT_Z80_FTABLE_DAA" << keyStr << " {\n"; + + std::stringstream outStrO; + outStrO << "!macro PUT_Z80_OTABLE_DAA" << keyStr << " {\n"; + + for (uint16_t idx = 0; idx < 0x100; idx++) + { + FlagsDAA flags; + if (NF) flags.N = 1; + if (CF) flags.C = 1; + if (HF) flags.H = 1; + + outStrO << "\t!byte $" << std::hex << std::setw(2) << std::setfill('0') << (int) calculateDAA(flags, idx) << "\n"; + + int fResult = (flags.N ? Z80_NF : 0) + + (flags.C ? Z80_CF : 0) + + (flags.H ? Z80_HF : 0) + + (flags.S ? Z80_SF : 0) + + (flags.P ? Z80_PF : 0) + + (flags.Z ? Z80_ZF : 0) + + (flags.X ? Z80_XF : 0) + + (flags.Y ? Z80_YF : 0); + + outStrF << "\t!byte $" << std::hex << std::setw(2) << std::setfill('0') << fResult << "\n"; + } + + outStr += outStrF.str() + "}\n\n\n" + outStrO.str() + "}\n\n\n"; + } return outStr; } @@ -239,7 +327,7 @@ void writeTables() // Write tables - outFile << generateParityTable(); // always put it first! + outFile << generateParityTable(); // always put this one first! outFile << generateDisplacementTable(); outFile << generateIncTable(); outFile << generateDecTable();