summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author hap <happppp@users.noreply.github.com>2023-01-04 23:06:31 +0100
committer hap <happppp@users.noreply.github.com>2023-01-04 23:06:31 +0100
commitf44b3ca90c1329b6a9cc9db08013840fd1ab736b (patch)
tree3c48c76fe7a892a9e01ce4ce9f5aa6f522e9d814 /src
parenta0bbc5cf9f6b5ea582adaf1bfc48f2266b76f41d (diff)
i8085: fix problem with daa opcode
Diffstat (limited to 'src')
-rw-r--r--src/devices/cpu/i8085/i8085.cpp100
-rw-r--r--src/devices/cpu/i8085/i8085.h13
2 files changed, 60 insertions, 53 deletions
diff --git a/src/devices/cpu/i8085/i8085.cpp b/src/devices/cpu/i8085/i8085.cpp
index f08f24ab6f0..c29ae4a684c 100644
--- a/src/devices/cpu/i8085/i8085.cpp
+++ b/src/devices/cpu/i8085/i8085.cpp
@@ -9,8 +9,8 @@
* Partially based on information out of Z80Em by Marcel De Kogel
*
* TODO:
- * - 8085 DAA fails on 8080/8085 CPU Exerciser
* - not sure if 8085 DSUB H flag is correct
+ * - accurate 8085 undocumented V/K flags
* - most of those is_8085 can probably be done better, like function overrides
*
* ---------------------------------------------------------------------------
@@ -102,8 +102,8 @@
* October 2012, hap
* - fixed H flag on subtraction opcodes
* - on 8080, don't push the unsupported flags(X5, X3, V) to stack
- * - 8080 passes on 8080/8085 CPU Exerciser, 8085 errors only on the DAA test
- * (ref: http://www.idb.me.uk/sunhillow/8080.html - tests only 8080 opcodes)
+ * - it passes on 8080/8085 CPU Exerciser (ref: http://www.idb.me.uk/sunhillow/8080.html
+ * tests only 8080 opcodes, link is dead so go via archive.org)
*
*****************************************************************************/
@@ -121,7 +121,7 @@
constexpr u8 SF = 0x80;
constexpr u8 ZF = 0x40;
-constexpr u8 X5F = 0x20;
+constexpr u8 KF = 0x20;
constexpr u8 HF = 0x10;
constexpr u8 X3F = 0x08;
constexpr u8 PF = 0x04;
@@ -456,12 +456,11 @@ void i8085a_cpu_device::state_string_export(const device_state_entry &entry, std
switch (entry.index())
{
case STATE_GENFLAGS:
- str = string_format("%c%c%c%c%c%c%c%c",
+ str = string_format("%c%c%c%c.%c%c%c",
m_AF.b.l & 0x80 ? 'S':'.',
m_AF.b.l & 0x40 ? 'Z':'.',
- m_AF.b.l & 0x20 ? 'X':'.', // X5
+ m_AF.b.l & 0x20 ? 'K':'.', // X5
m_AF.b.l & 0x10 ? 'H':'.',
- m_AF.b.l & 0x08 ? '?':'.',
m_AF.b.l & 0x04 ? 'P':'.',
m_AF.b.l & 0x02 ? 'V':'.',
m_AF.b.l & 0x01 ? 'C':'.');
@@ -469,6 +468,21 @@ void i8085a_cpu_device::state_string_export(const device_state_entry &entry, std
}
}
+void i8080_cpu_device::state_string_export(const device_state_entry &entry, std::string &str) const
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ str = string_format("%c%c.%c.%c.%c",
+ m_AF.b.l & 0x80 ? 'S':'.',
+ m_AF.b.l & 0x40 ? 'Z':'.',
+ m_AF.b.l & 0x10 ? 'H':'.',
+ m_AF.b.l & 0x04 ? 'P':'.',
+ m_AF.b.l & 0x01 ? 'C':'.');
+ break;
+ }
+}
+
std::unique_ptr<util::disasm_interface> i8085a_cpu_device::create_disassembler()
{
return std::make_unique<i8085_disassembler>();
@@ -819,7 +833,7 @@ void i8085a_cpu_device::op_jmp(int cond)
if (cond)
{
m_PC = read_arg16();
- m_icount -= extra_jmp();
+ m_icount -= jmp_taken();
}
else
{
@@ -832,7 +846,7 @@ void i8085a_cpu_device::op_call(int cond)
if (cond)
{
PAIR p = read_arg16();
- m_icount -= extra_call();
+ m_icount -= call_taken();
op_push(m_PC);
m_PC = p;
}
@@ -847,7 +861,7 @@ void i8085a_cpu_device::op_ret(int cond)
// conditional RET only
if (cond)
{
- m_icount -= extra_ret();
+ m_icount -= ret_taken();
m_PC = op_pop();
}
}
@@ -904,9 +918,9 @@ void i8085a_cpu_device::execute_one(int opcode)
if (is_8085())
{
if (m_BC.w.l == 0x0000)
- m_AF.b.l |= X5F;
+ m_AF.b.l |= KF;
else
- m_AF.b.l &= ~X5F;
+ m_AF.b.l &= ~KF;
}
break;
case 0x04: // INR B
@@ -946,9 +960,9 @@ void i8085a_cpu_device::execute_one(int opcode)
if (is_8085())
{
if (m_BC.w.l == 0xffff)
- m_AF.b.l |= X5F;
+ m_AF.b.l |= KF;
else
- m_AF.b.l &= ~X5F;
+ m_AF.b.l &= ~KF;
}
break;
case 0x0c: // INR C
@@ -983,9 +997,9 @@ void i8085a_cpu_device::execute_one(int opcode)
if (is_8085())
{
if (m_DE.w.l == 0x0000)
- m_AF.b.l |= X5F;
+ m_AF.b.l |= KF;
else
- m_AF.b.l &= ~X5F;
+ m_AF.b.l &= ~KF;
}
break;
case 0x14: // INR D
@@ -1025,9 +1039,9 @@ void i8085a_cpu_device::execute_one(int opcode)
if (is_8085())
{
if (m_DE.w.l == 0xffff)
- m_AF.b.l |= X5F;
+ m_AF.b.l |= KF;
else
- m_AF.b.l &= ~X5F;
+ m_AF.b.l &= ~KF;
}
break;
case 0x1c: // INR E
@@ -1072,9 +1086,9 @@ void i8085a_cpu_device::execute_one(int opcode)
if (is_8085())
{
if (m_HL.w.l == 0x0000)
- m_AF.b.l |= X5F;
+ m_AF.b.l |= KF;
else
- m_AF.b.l &= ~X5F;
+ m_AF.b.l &= ~KF;
}
break;
case 0x24: // INR H
@@ -1088,22 +1102,12 @@ void i8085a_cpu_device::execute_one(int opcode)
break;
case 0x27: // DAA
m_WZ.b.h = m_AF.b.h;
- if (is_8085() && m_AF.b.l & VF)
- {
- if ((m_AF.b.l & HF) || ((m_AF.b.h & 0xf) > 9))
- m_WZ.b.h -= 6;
- if ((m_AF.b.l & CF) || (m_AF.b.h > 0x99))
- m_WZ.b.h -= 0x60;
- }
- else
- {
- if ((m_AF.b.l & HF) || ((m_AF.b.h & 0xf) > 9))
- m_WZ.b.h += 6;
- if ((m_AF.b.l & CF) || (m_AF.b.h > 0x99))
- m_WZ.b.h += 0x60;
- }
+ if ((m_AF.b.l & HF) || ((m_AF.b.h & 0xf) > 9))
+ m_WZ.b.h += 6;
+ if ((m_AF.b.l & CF) || (m_AF.b.h > 0x99))
+ m_WZ.b.h += 0x60;
- m_AF.b.l = (m_AF.b.l & 3) | (m_AF.b.h & 0x28) | ((m_AF.b.h > 0x99) ? 1 : 0) | ((m_AF.b.h ^ m_WZ.b.h) & 0x10) | lut_zsp[m_WZ.b.h];
+ m_AF.b.l = (m_AF.b.l & 0x23) | ((m_AF.b.h > 0x99) ? 1 : 0) | ((m_AF.b.h ^ m_WZ.b.h) & 0x10) | lut_zsp[m_WZ.b.h];
m_AF.b.h = m_WZ.b.h;
break;
@@ -1128,9 +1132,9 @@ void i8085a_cpu_device::execute_one(int opcode)
if (is_8085())
{
if (m_HL.w.l == 0xffff)
- m_AF.b.l |= X5F;
+ m_AF.b.l |= KF;
else
- m_AF.b.l &= ~X5F;
+ m_AF.b.l &= ~KF;
}
break;
case 0x2c: // INR L
@@ -1145,7 +1149,7 @@ void i8085a_cpu_device::execute_one(int opcode)
case 0x2f: // CMA
m_AF.b.h ^= 0xff;
if (is_8085())
- m_AF.b.l |= HF | VF;
+ m_AF.b.l |= VF;
break;
case 0x30: // 8085: SIM, otherwise undocumented NOP
@@ -1188,9 +1192,9 @@ void i8085a_cpu_device::execute_one(int opcode)
if (is_8085())
{
if (m_SP.w.l == 0x0000)
- m_AF.b.l |= X5F;
+ m_AF.b.l |= KF;
else
- m_AF.b.l &= ~X5F;
+ m_AF.b.l &= ~KF;
}
break;
case 0x34: // INR M
@@ -1228,9 +1232,9 @@ void i8085a_cpu_device::execute_one(int opcode)
if (is_8085())
{
if (m_SP.w.l == 0xffff)
- m_AF.b.l |= X5F;
+ m_AF.b.l |= KF;
else
- m_AF.b.l &= ~X5F;
+ m_AF.b.l &= ~KF;
}
break;
case 0x3c: // INR A
@@ -1437,7 +1441,7 @@ void i8085a_cpu_device::execute_one(int opcode)
if (m_AF.b.l & VF)
{
// RST taken = 6 more cycles
- m_icount -= extra_ret();
+ m_icount -= ret_taken();
op_rst(8);
}
}
@@ -1513,7 +1517,7 @@ void i8085a_cpu_device::execute_one(int opcode)
break;
case 0xdd: // 8085: JNX nnnn, otherwise undocumented CALL nnnn
if (is_8085())
- op_jmp(!(m_AF.b.l & X5F));
+ op_jmp(!(m_AF.b.l & KF));
else
op_call(1);
break;
@@ -1605,9 +1609,11 @@ void i8085a_cpu_device::execute_one(int opcode)
op_call(!(m_AF.b.l & SF));
break;
case 0xf5: // PUSH A
- // on 8080, VF=1 and X3F=0 and X5F=0 always! (we don't have to check for it elsewhere)
+ // X3F is always 0, and on 8080, VF=1 and KF=0
+ // (we don't have to check for it elsewhere)
+ m_AF.b.l &= ~X3F;
if (!is_8085())
- m_AF.b.l = (m_AF.b.l & ~(X3F | X5F)) | VF;
+ m_AF.b.l = (m_AF.b.l & ~KF) | VF;
op_push(m_AF);
break;
case 0xf6: // ORI nn
@@ -1636,7 +1642,7 @@ void i8085a_cpu_device::execute_one(int opcode)
break;
case 0xfd: // 8085: JX nnnn, otherwise undocumented CALL nnnn
if (is_8085())
- op_jmp(m_AF.b.l & X5F);
+ op_jmp(m_AF.b.l & KF);
else
op_call(1);
break;
diff --git a/src/devices/cpu/i8085/i8085.h b/src/devices/cpu/i8085/i8085.h
index 6dde029576c..711f6add7ff 100644
--- a/src/devices/cpu/i8085/i8085.h
+++ b/src/devices/cpu/i8085/i8085.h
@@ -91,7 +91,6 @@ protected:
// device_disasm_interface overrides
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
-private:
address_space_config m_program_config;
address_space_config m_io_config;
address_space_config m_opcode_config;
@@ -131,9 +130,9 @@ private:
u8 lut_zs[256];
u8 lut_zsp[256];
- virtual int extra_ret() { return 6; }
- virtual int extra_jmp() { return 3; }
- virtual int extra_call() { return 9; }
+ virtual int ret_taken() { return 6; }
+ virtual int jmp_taken() { return 3; }
+ virtual int call_taken() { return 9; }
virtual bool is_8085() { return true; }
void set_sod(int state);
@@ -182,8 +181,10 @@ protected:
virtual u64 execute_clocks_to_cycles(u64 clocks) const noexcept override { return clocks; }
virtual u64 execute_cycles_to_clocks(u64 cycles) const noexcept override { return cycles; }
- virtual int extra_jmp() override { return 0; }
- virtual int extra_call() override { return 6; }
+ virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
+
+ virtual int jmp_taken() override { return 0; }
+ virtual int call_taken() override { return 6; }
virtual bool is_8085() override { return false; }
};