From cf39f0dd388a26e27cd27f126557a8b720104f86 Mon Sep 17 00:00:00 2001 From: Tim Nibert Date: Sun, 3 Nov 2019 19:38:37 +1100 Subject: [PATCH] conditional branching decoding --- decoder.cpp | 64 +++++++++++++++++++++++++++++++++++++------ decoder.h | 2 ++ tests/systemtests.h | 1 + tests/testdecoder.cpp | 16 +++++++++++ 4 files changed, 74 insertions(+), 9 deletions(-) diff --git a/decoder.cpp b/decoder.cpp index 3fc8c3f..2f62dc0 100644 --- a/decoder.cpp +++ b/decoder.cpp @@ -20,7 +20,7 @@ InstructionDecoder::InstructionDecoder(cpustate * c, Memory * m) /** * Decode an opcode and execute it * form aaabbbcc or xxy10000 - * bbb and ccc match ups depends on cc + * bbb and aaa match ups depends on cc * return number of cycles used */ int InstructionDecoder::decode_and_execute(uint8_t opcode) @@ -30,20 +30,67 @@ int InstructionDecoder::decode_and_execute(uint8_t opcode) // todo: single byte instructions // The conditional branch instructions all have the form xxy10000. - // The flag indicated by xx is compared with y, and the branch is taken if they are equal. if((opcode | 0b11100000) == 0b11110000) { - uint8_t xx = opcode & 0b11000000; - bool y = (opcode & 0b00100000) >> 5; - // todo: finish this + // todo: BRK, JSR abs, RTI, RTS + bool to_jump = decode_branch(opcode); - /*switch(xx) + if(to_jump) { + // these can use relative (all branch instructions) or absolute addressing + // need to differentiate + // the following won't cut it + // relative - signed 8 bit relative offset (e.g. -128 to +127) - }*/ + // relative, todo: account for sign (is this two's comp?) + //cpu->pc += mem->readmem(cpu->pc + mem->readmem(cpu->pc+1)); + // absolute: + //cpu->pc = mem->readmem(revlendianbytes(cpu->pc+2, cpu->pc+1)); + } } - else // form aaabbbcc instruction + else + { + decode_aaabbbcc(opcode); + } + + return 1; // replace this with cycles used? +} + +bool InstructionDecoder::decode_branch(uint8_t opcode) +{ + // The flag indicated by xx is compared with y, and the branch is taken if they are equal. + // this gives us: BPL, BMI, BVC, BVS, BCC, BCS, BNE, BEQ + uint8_t xx = (opcode & 0b11000000) >> 6; + int flag; + bool y = (opcode & 0b00100000) >> 5; + bool to_jump = false; + + // determine the flag to evaluate + switch(xx) + { + case 0b00: // test negative flag + flag = FLAG_NEGATIVE; + break; + case 0b01: // test overflow flag + flag = FLAG_OVERFLOW; + break; + case 0b10: // test carry flag + flag = FLAG_CARRY; + break; + case 0b11: // test zero flag + flag = FLAG_ZERO; + break; + } + + // compare the flag with y + to_jump = (getflag(cpu, flag) == y); + + return to_jump; +} + +void InstructionDecoder::decode_aaabbbcc(uint8_t opcode) +{ { uint8_t cc = opcode & 0b00000011; // control code uint8_t bbb = opcode & 0b00011100; // addressing mode @@ -200,5 +247,4 @@ int InstructionDecoder::decode_and_execute(uint8_t opcode) // case 0b11 only used for illegal opcodes } } - return 1; // replace this with cycles used? } \ No newline at end of file diff --git a/decoder.h b/decoder.h index 3df35c8..f8bed9c 100644 --- a/decoder.h +++ b/decoder.h @@ -14,6 +14,8 @@ class InstructionDecoder public: InstructionDecoder(cpustate *, Memory *); int decode_and_execute(uint8_t); + void decode_aaabbbcc(uint8_t); + bool decode_branch(uint8_t); }; diff --git a/tests/systemtests.h b/tests/systemtests.h index bd22b48..8266b55 100644 --- a/tests/systemtests.h +++ b/tests/systemtests.h @@ -109,6 +109,7 @@ class TestDecoder : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( TestDecoder ); CPPUNIT_TEST( test_aaabbbcc ); + CPPUNIT_TEST( test_branching ); CPPUNIT_TEST_SUITE_END(); private: diff --git a/tests/testdecoder.cpp b/tests/testdecoder.cpp index 89b90ff..133fdfa 100644 --- a/tests/testdecoder.cpp +++ b/tests/testdecoder.cpp @@ -26,3 +26,19 @@ void TestDecoder::test_aaabbbcc() CPPUNIT_ASSERT(cpu->a == 0b11111111); } +void TestDecoder::test_branching() +{ + cpu->pc = 0; + cpu->p = 0b00000010; + //mem->writemem(0, 0xf0); + mem->writemem(1, 3); // branch +3 bytes + + bool test = decoder->decode_branch(0xf0); // decode BEQ + CPPUNIT_ASSERT(test); + + cpu->p = 0b0; + test = decoder->decode_branch(0xf0); + CPPUNIT_ASSERT(!test); + + // todo: test the jumping +} \ No newline at end of file