diff --git a/Processors/68000/Implementation/68000Implementation.hpp b/Processors/68000/Implementation/68000Implementation.hpp index 18c1c26f5..cc0828eb8 100644 --- a/Processors/68000/Implementation/68000Implementation.hpp +++ b/Processors/68000/Implementation/68000Implementation.hpp @@ -767,6 +767,28 @@ template void Processor: #undef set_flags_w #undef set_flags_l + /* + TSTs: compare to zero. + */ + + case Operation::TSTb: + carry_flag_ = overflow_flag_ = 0; + zero_result_ = active_program_->source->halves.low.halves.low; + negative_flag_ = zero_result_ & 0x80; + break; + + case Operation::TSTw: + carry_flag_ = overflow_flag_ = 0; + zero_result_ = active_program_->source->halves.low.full; + negative_flag_ = zero_result_ & 0x8000; + break; + + case Operation::TSTl: + carry_flag_ = overflow_flag_ = 0; + zero_result_ = active_program_->source->full; + negative_flag_ = zero_result_ & 0x80000000; + break; + /* Development period debugging. */ diff --git a/Processors/68000/Implementation/68000Storage.cpp b/Processors/68000/Implementation/68000Storage.cpp index 366a6ee07..ca6f858b2 100644 --- a/Processors/68000/Implementation/68000Storage.cpp +++ b/Processors/68000/Implementation/68000Storage.cpp @@ -326,6 +326,8 @@ struct ProcessorStorageConstructor { MOVEM, // Maps a mode and register as they were a 'destination' and sets up bus steps with a suitable // hole for the runtime part to install proper MOVEM activity. + + TST, // Mapsa mode and register to a TST. }; using Operation = ProcessorStorage::Operation; @@ -467,6 +469,10 @@ struct ProcessorStorageConstructor { {0xffc0, 0x4880, Operation::MOVEMtoMw, Decoder::MOVEM}, // 4-128 (p232) {0xffc0, 0x4cc0, Operation::MOVEMtoRl, Decoder::MOVEM}, // 4-128 (p232) {0xffc0, 0x4c80, Operation::MOVEMtoRw, Decoder::MOVEM}, // 4-128 (p232) + + {0xffc0, 0x4a00, Operation::TSTb, Decoder::TST}, // 4-192 (p296) + {0xffc0, 0x4a40, Operation::TSTw, Decoder::TST}, // 4-192 (p296) + {0xffc0, 0x4a80, Operation::TSTl, Decoder::TST}, // 4-192 (p296) }; #ifndef NDEBUG @@ -2168,6 +2174,40 @@ struct ProcessorStorageConstructor { op(Action::None, seq("nn _ np")); break; + case Decoder::TST: { + storage_.instructions[instruction].set_source(storage_, ea_mode, ea_register); + + const int mode = combined_mode(ea_mode, ea_register); + const bool is_byte_access = operation == Operation::TSTb; + const bool is_long_word_access = operation == Operation::TSTl; + switch(is_long_word_access ? l(mode) : bw(mode)) { + default: continue; + + case bw(Dn): + case l(Dn): + op(Action::PerformOperation, seq("np")); + break; + + case bw(Ind): + case bw(PostInc): + op(Action::None, seq("nr", { a(ea_register) }, !is_byte_access)); + op(Action::PerformOperation, seq("np")); + if(mode == PostInc) { + op(int(is_byte_access ? Action::Increment1 : Action::Increment2) | MicroOp::SourceMask); + } + break; + + case l(Ind): + case l(PostInc): + op(int(Action::CopyToEffectiveAddress) | MicroOp::SourceMask, seq("nR+ nr", { ea(0), ea(0) })); + op(Action::PerformOperation, seq("np")); + if(mode == PostInc) { + op(int(Action::Increment4) | MicroOp::SourceMask); + } + break; + } + } break; + default: std::cerr << "Unhandled decoder " << int(mapping.decoder) << std::endl; continue; diff --git a/Processors/68000/Implementation/68000Storage.hpp b/Processors/68000/Implementation/68000Storage.hpp index d2cac60d7..aca3b63ce 100644 --- a/Processors/68000/Implementation/68000Storage.hpp +++ b/Processors/68000/Implementation/68000Storage.hpp @@ -82,6 +82,8 @@ class ProcessorStorage { MOVEMtoMl, MOVEMtoMw, Scc, + + TSTb, TSTw, TSTl, }; /*!