1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-10-01 13:58:20 +00:00

Add remaining acceptable error cases.

This commit is contained in:
Thomas Harte 2023-11-09 12:26:40 -05:00
parent ed3922e458
commit e78e5c8101
2 changed files with 35 additions and 4 deletions

View File

@ -470,6 +470,9 @@ enum class Source: uint8_t {
/// getter is used).
IndirectNoBase = Indirect - 1,
};
constexpr bool is_register(Source source) {
return source < Source::None;
}
enum class Repetition: uint8_t {
None, RepE, RepNE, Rep,

View File

@ -658,11 +658,10 @@ struct FailedExecution {
failure_list = &permitted_failures;
}
// IDIV_REP has a couple of cases...
if(decoded.second.operation() == Operation::IDIV_REP) {
// For reasons I don't understand, sometimes the test set doesn't increment the IP
// across a REP_IDIV. I don't think (?) this correlates to real 8086 behaviour.
// IDIV_REP: for reasons I don't understand, sometimes the test set doesn't increment
// the IP across a REP_IDIV. I don't think (?) this correlates to real 8086 behaviour.
// More research required, but for now I'm not treating this as a roadblock.
if(decoded.second.operation() == Operation::IDIV_REP) {
Registers advanced_registers = intended_registers;
advanced_registers.ip_ += decoded.first;
if(advanced_registers == execution_support.registers && ramEqual && flagsEqual) {
@ -670,6 +669,35 @@ struct FailedExecution {
}
}
// IDIV[_REP] byte: the test cases sometimes throw even when I can't see why they should,
// and other x86 emulations also don't throw. I guess — guess! — an 8086-specific oddity
// deviates from the x86 average here. So I'm also permitting these for now.
if(
decoded.second.operation_size() == InstructionSet::x86::DataSize::Byte &&
(decoded.second.operation() == Operation::IDIV_REP || decoded.second.operation() == Operation::IDIV)
) {
if(intended_registers.sp() == execution_support.registers.sp() - 6) {
Registers non_exception_registers = intended_registers;
non_exception_registers.ip() = execution_support.registers.ip();
non_exception_registers.sp() = execution_support.registers.sp();
non_exception_registers.ax() = execution_support.registers.ax();
non_exception_registers.cs() = execution_support.registers.cs();
if(non_exception_registers == execution_support.registers) {
failure_list = &permitted_failures;
}
}
}
// LEA from a register is undefined behaviour and throws on processors beyond the 8086.
if(decoded.second.operation() == Operation::LEA && InstructionSet::x86::is_register(decoded.second.source().source())) {
failure_list = &permitted_failures;
}
if(failure_list == &execution_failures) {
printf("Fail: %d\n", int(decoded.second.operation()));
}
// Record a failure.
FailedExecution failure;
failure.instruction = decoded.second;