DAA implemented
This commit is contained in:
1 parent
4f39173705
commit
8f8428ea49
5 files changed
+209
-121
No files matched your search
@@ -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
|
lda REG_A
|
||||||
eor #$FF
|
eor #$FF
|
||||||
@@ -17,7 +58,7 @@ Z80_instr_2F: ; CPL
|
|||||||
|
|
||||||
; XXX put NEG here
|
; XXX put NEG here
|
||||||
|
|
||||||
Z80_instr_3F: ; CCF
|
Z80_instr_3F: ; CCF
|
||||||
|
|
||||||
+Z80_PUT_0_NF
|
+Z80_PUT_0_NF
|
||||||
bbs0 REG_F,@1
|
bbs0 REG_F,@1
|
||||||
@@ -30,14 +71,14 @@ Z80_instr_3F: ; CCF
|
|||||||
+Z80_PUT_0_CF
|
+Z80_PUT_0_CF
|
||||||
jmp ZVM_next
|
jmp ZVM_next
|
||||||
|
|
||||||
Z80_instr_37: ; SCF
|
Z80_instr_37: ; SCF
|
||||||
|
|
||||||
+Z80_PUT_0_HF
|
+Z80_PUT_0_HF
|
||||||
+Z80_PUT_0_NF
|
+Z80_PUT_0_NF
|
||||||
+Z80_PUT_1_CF
|
+Z80_PUT_1_CF
|
||||||
jmp ZVM_next
|
jmp ZVM_next
|
||||||
|
|
||||||
Z80_instr_76: ; HALT
|
Z80_instr_76: ; HALT
|
||||||
|
|
||||||
; Used to call BIOS routines
|
; Used to call BIOS routines
|
||||||
; XXX probably not the besta idea, GENCPC seems to do some relocations
|
; XXX probably not the besta idea, GENCPC seems to do some relocations
|
||||||
@@ -59,14 +100,14 @@ Z80_instr_76: ; HALT
|
|||||||
tax
|
tax
|
||||||
jmp (zvm_BIOS_vectable,x)
|
jmp (zvm_BIOS_vectable,x)
|
||||||
|
|
||||||
Z80_instr_F3: ; DI
|
Z80_instr_F3: ; DI
|
||||||
|
|
||||||
lda #$00
|
lda #$00
|
||||||
sta REG_IFF1
|
sta REG_IFF1
|
||||||
sta REG_IFF2
|
sta REG_IFF2
|
||||||
jmp ZVM_next
|
jmp ZVM_next
|
||||||
|
|
||||||
Z80_instr_FB: ; EI
|
Z80_instr_FB: ; EI
|
||||||
|
|
||||||
lda #Z80_PF
|
lda #Z80_PF
|
||||||
sta REG_IFF1
|
sta REG_IFF1
|
||||||
|
|||||||
@@ -28,3 +28,71 @@ z80_ftable_AND:
|
|||||||
z80_ftable_IN_OR_XOR:
|
z80_ftable_IN_OR_XOR:
|
||||||
|
|
||||||
+PUT_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
|
||||||
+2
-110
@@ -6,121 +6,13 @@
|
|||||||
|
|
||||||
ZVM_set_bank_0:
|
ZVM_set_bank_0:
|
||||||
|
|
||||||
; XXX consider switchink banks using DMA list
|
; XXX use DMAgic to switch banks (vectors on zeropage)
|
||||||
|
|
||||||
lda #<ZVM_fetch_value_bank_0
|
|
||||||
sta VEC_fetch_value+0
|
|
||||||
lda #>ZVM_fetch_value_bank_0
|
|
||||||
sta VEC_fetch_value+1
|
|
||||||
|
|
||||||
lda #<ZVM_fetch_stack_bank_0
|
|
||||||
sta VEC_fetch_stack+0
|
|
||||||
lda #>ZVM_fetch_stack_bank_0
|
|
||||||
sta VEC_fetch_stack+1
|
|
||||||
|
|
||||||
lda #<ZVM_store_stack_bank_0
|
|
||||||
sta VEC_store_stack+0
|
|
||||||
lda #>ZVM_store_stack_bank_0
|
|
||||||
sta VEC_store_stack+1
|
|
||||||
|
|
||||||
lda #<ZVM_fetch_via_HL_bank_0
|
|
||||||
sta VEC_fetch_via_HL+0
|
|
||||||
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+0
|
|
||||||
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+0
|
|
||||||
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+0
|
|
||||||
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+0
|
|
||||||
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+0
|
|
||||||
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+0
|
|
||||||
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+0
|
|
||||||
lda #>ZVM_store_via_nn_bank_0
|
|
||||||
sta VEC_store_via_nn+1
|
|
||||||
|
|
||||||
rts
|
rts
|
||||||
|
|
||||||
ZVM_set_bank_1:
|
ZVM_set_bank_1:
|
||||||
|
|
||||||
lda #<ZVM_fetch_value_bank_1
|
; XXX use DMAgic to switch banks (vectors on zeropage)
|
||||||
sta VEC_fetch_value+0
|
|
||||||
lda #>ZVM_fetch_value_bank_1
|
|
||||||
sta VEC_fetch_value+1
|
|
||||||
|
|
||||||
lda #<ZVM_fetch_stack_bank_1
|
|
||||||
sta VEC_fetch_stack+0
|
|
||||||
lda #>ZVM_fetch_stack_bank_1
|
|
||||||
sta VEC_fetch_stack+1
|
|
||||||
|
|
||||||
lda #<ZVM_store_stack_bank_1
|
|
||||||
sta VEC_store_stack+0
|
|
||||||
lda #>ZVM_store_stack_bank_1
|
|
||||||
sta VEC_store_stack+1
|
|
||||||
|
|
||||||
lda #<ZVM_fetch_via_HL_bank_1
|
|
||||||
sta VEC_fetch_via_HL+0
|
|
||||||
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+0
|
|
||||||
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+0
|
|
||||||
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+0
|
|
||||||
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+0
|
|
||||||
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+0
|
|
||||||
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+0
|
|
||||||
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+0
|
|
||||||
lda #>ZVM_store_via_nn_bank_1
|
|
||||||
sta VEC_store_via_nn+1
|
|
||||||
|
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
|||||||
@@ -107,7 +107,6 @@ Z80_instr_12: ; LD (DE),A
|
|||||||
Z80_instr_19: ; ADD HL,DE
|
Z80_instr_19: ; ADD HL,DE
|
||||||
Z80_instr_1A: ; LD A,(DE)
|
Z80_instr_1A: ; LD A,(DE)
|
||||||
Z80_instr_22: ; LD (nn),HL
|
Z80_instr_22: ; LD (nn),HL
|
||||||
Z80_instr_27: ; DAA
|
|
||||||
Z80_instr_29: ; ADD HL,HL
|
Z80_instr_29: ; ADD HL,HL
|
||||||
Z80_instr_2A: ; LD HL,(nn)
|
Z80_instr_2A: ; LD HL,(nn)
|
||||||
Z80_instr_32: ; LD (nn),A
|
Z80_instr_32: ; LD (nn),A
|
||||||
|
|||||||
@@ -210,14 +210,102 @@ std::string generateInOrXorTable(void)
|
|||||||
return outStr.str() + "}\n\n\n";
|
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 generateDaaTables()
|
||||||
{
|
{
|
||||||
std::string outStr;
|
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
|
std::stringstream outStrF;
|
||||||
// Check code by Rui Ribeiro, see https://stackoverflow.com/questions/8119577/z80-daa-instruction
|
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;
|
return outStr;
|
||||||
}
|
}
|
||||||
@@ -239,7 +327,7 @@ void writeTables()
|
|||||||
|
|
||||||
// Write tables
|
// Write tables
|
||||||
|
|
||||||
outFile << generateParityTable(); // always put it first!
|
outFile << generateParityTable(); // always put this one first!
|
||||||
outFile << generateDisplacementTable();
|
outFile << generateDisplacementTable();
|
||||||
outFile << generateIncTable();
|
outFile << generateIncTable();
|
||||||
outFile << generateDecTable();
|
outFile << generateDecTable();
|
||||||
|
|||||||
Reference in new issue
Block a user