From 82884b3ef726889f837542d2b5e98e2cd8246c00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karel=20Ko=C4=8D=C3=AD?= Date: Thu, 31 Aug 2017 00:18:53 +0200 Subject: Handle endianness in memory correctly --- qtmips_machine/memory.cpp | 29 ++++++++++++++++++++++++++++- qtmips_machine/programmemory.cpp | 1 - qtmips_machine/tests/testmemory.cpp | 22 ++++++++++++++++++++++ qtmips_machine/tests/tst_machine.h | 1 + 4 files changed, 51 insertions(+), 2 deletions(-) diff --git a/qtmips_machine/memory.cpp b/qtmips_machine/memory.cpp index 25deab0..2540035 100644 --- a/qtmips_machine/memory.cpp +++ b/qtmips_machine/memory.cpp @@ -1,30 +1,57 @@ #include "memory.h" +// Note about endianness: Current memory implementation is expected to be a big endian. +// But we can be running on little endian so we should do conversion from bytes to word according that. + void MemoryAccess::write_hword(std::uint32_t offset, std::uint16_t value) { +#if __BYTE_ORDER == __LITTLE_ENDIAN + this->write_byte(offset++, (std::uint8_t)(value >> 8)); + this->write_byte(offset, (std::uint8_t)value); +#else this->write_byte(offset++, (std::uint8_t)value); this->write_byte(offset, (std::uint8_t)(value >> 8)); +#endif } void MemoryAccess::write_word(std::uint32_t offset, std::uint32_t value) { +#if __BYTE_ORDER == __LITTLE_ENDIAN + this->write_byte(offset++, (std::uint8_t)(value >> 24)); + this->write_byte(offset++, (std::uint8_t)(value >> 16)); + this->write_byte(offset++, (std::uint8_t)(value >> 8)); + this->write_byte(offset, (std::uint8_t)value); +#else this->write_byte(offset++, (std::uint8_t)value); this->write_byte(offset++, (std::uint8_t)(value >> 8)); this->write_byte(offset++, (std::uint8_t)(value >> 16)); - this->write_byte(offset++, (std::uint8_t)(value >> 24)); + this->write_byte(offset, (std::uint8_t)(value >> 24)); +#endif } std::uint16_t MemoryAccess::read_hword(std::uint32_t offset) { std::uint16_t dt = 0; +#if __BYTE_ORDER == __LITTLE_ENDIAN + dt |= (this->read_byte(offset++) << 8); + dt |= this->read_byte(offset); +#else dt |= this->read_byte(offset++); dt |= (this->read_byte(offset) << 8); +#endif return dt; } std::uint32_t MemoryAccess::read_word(std::uint32_t offset) { std::uint32_t dt = 0; +#if __BYTE_ORDER == __LITTLE_ENDIAN + dt |= (this->read_byte(offset++) << 24); + dt |= (this->read_byte(offset++) << 16); + dt |= (this->read_byte(offset++) << 8); + dt |= this->read_byte(offset); +#else dt |= this->read_byte(offset++); dt |= (this->read_byte(offset++) << 8); dt |= (this->read_byte(offset++) << 16); dt |= (this->read_byte(offset) << 24); +#endif return dt; } diff --git a/qtmips_machine/programmemory.cpp b/qtmips_machine/programmemory.cpp index 6759842..1ff3bca 100644 --- a/qtmips_machine/programmemory.cpp +++ b/qtmips_machine/programmemory.cpp @@ -40,7 +40,6 @@ Instruction *ProgramMemory::at(std::uint32_t address) { } } -// TODO implement #define I_UNKNOWN(DATA) throw QTMIPS_EXCEPTION(UnsupportedInstruction, "Unknown instruction, can't decode", to_string_hex(DATA)) #define I_UNSUPPORTED(INST) throw QTMIPS_EXCEPTION(UnsupportedInstruction, "Decoded unsupported unstruction", #INST) diff --git a/qtmips_machine/tests/testmemory.cpp b/qtmips_machine/tests/testmemory.cpp index 991e1f1..eac7dd6 100644 --- a/qtmips_machine/tests/testmemory.cpp +++ b/qtmips_machine/tests/testmemory.cpp @@ -59,3 +59,25 @@ void MachineTests::memory_section() { // Read trough memory QCOMPARE(m.read_byte(address), (std::uint8_t)0x66); } + +void MachineTests::memory_endian() { + Memory m; + + // Memory should be bit endian so write bytes from most significant byte + m.write_byte(0x00, 0x12); + m.write_byte(0x01, 0x34); + m.write_byte(0x02, 0x56); + m.write_byte(0x03, 0x78); + QCOMPARE(m.read_hword(0x00), (std::uint16_t)0x1234); + QCOMPARE(m.read_word(0x00), (std::uint32_t)0x12345678); + + m.write_hword(0x80, 0x1234); + QCOMPARE(m.read_byte(0x80), (std::uint8_t)0x12); + QCOMPARE(m.read_byte(0x81), (std::uint8_t)0x34); + + m.write_word(0xF0, 0x12345678); + QCOMPARE(m.read_byte(0xF0), (std::uint8_t)0x12); + QCOMPARE(m.read_byte(0xF1), (std::uint8_t)0x34); + QCOMPARE(m.read_byte(0xF2), (std::uint8_t)0x56); + QCOMPARE(m.read_byte(0xF3), (std::uint8_t)0x78); +} diff --git a/qtmips_machine/tests/tst_machine.h b/qtmips_machine/tests/tst_machine.h index 214ab88..e5137c4 100644 --- a/qtmips_machine/tests/tst_machine.h +++ b/qtmips_machine/tests/tst_machine.h @@ -16,6 +16,7 @@ private Q_SLOTS: void memory_data(); void memory_section(); void memory_section_data(); + void memory_endian(); }; #endif // TST_MACHINE_H -- cgit v1.2.3