diff --git a/src/gui/ui/hexlineedit.cpp b/src/gui/ui/hexlineedit.cpp index 01f7efff..ad2c783b 100644 --- a/src/gui/ui/hexlineedit.cpp +++ b/src/gui/ui/hexlineedit.cpp @@ -48,7 +48,7 @@ HexLineEdit::HexLineEdit( set_value(0); } -void HexLineEdit::set_value(uint32_t value) { +void HexLineEdit::set_value(uint64_t value) { QString s, t = ""; last_set = value; s = QString::number(value, base); @@ -60,8 +60,8 @@ void HexLineEdit::set_value(uint32_t value) { void HexLineEdit::on_edit_finished() { bool ok; - uint32_t val; - val = text().toULong(&ok, 16); + uint64_t val; + val = text().toULongLong(&ok, 16); if (!ok) { set_value(last_set); return; diff --git a/src/gui/ui/hexlineedit.h b/src/gui/ui/hexlineedit.h index 6ad859ce..e56ed4e8 100644 --- a/src/gui/ui/hexlineedit.h +++ b/src/gui/ui/hexlineedit.h @@ -17,10 +17,10 @@ class HexLineEdit : public QLineEdit { const QString &prefix = "0x"); public slots: - void set_value(uint32_t value); + void set_value(uint64_t value); signals: - void value_edit_finished(uint32_t value); + void value_edit_finished(uint64_t value); private slots: void on_edit_finished(); diff --git a/src/gui/windows/memory/memorydock.cpp b/src/gui/windows/memory/memorydock.cpp index 07fd4d69..004a9625 100644 --- a/src/gui/windows/memory/memorydock.cpp +++ b/src/gui/windows/memory/memorydock.cpp @@ -32,7 +32,7 @@ MemoryDock::MemoryDock(QWidget *parent, QSettings *settings) : Super(parent) { memory_content->verticalHeader()->hide(); // memory_content->setHorizontalHeader(memory_model->); - auto *go_edit = new HexLineEdit(nullptr, 8, 16, "0x"); + auto *go_edit = new HexLineEdit(nullptr, 16, 16, "0x"); auto *layout_top = new QHBoxLayout; layout_top->addWidget(cell_size); @@ -57,7 +57,7 @@ MemoryDock::MemoryDock(QWidget *parent, QSettings *settings) : Super(parent) { memory_model, &MemoryModel::cached_access); connect( go_edit, &HexLineEdit::value_edit_finished, memory_content, - [memory_content](uint32_t value) { + [memory_content](uint64_t value) { memory_content->go_to_address(machine::Address(value)); }); connect( diff --git a/src/machine/machine.cpp b/src/machine/machine.cpp index 50d56355..67afbf4f 100644 --- a/src/machine/machine.cpp +++ b/src/machine/machine.cpp @@ -15,14 +15,18 @@ Machine::Machine(MachineConfig config, bool load_symtab, bool load_executable) if (load_executable) { ProgramLoader program(machine_config.elf()); this->machine_config.set_simulated_endian(program.get_endian()); - mem_program_only = new Memory(machine_config.get_simulated_endian()); - program.to_memory(mem_program_only); if (program.get_architecture_type() == ARCH64) this->machine_config.set_simulated_xlen(Xlen::_64); else this->machine_config.set_simulated_xlen(Xlen::_32); + if (this->machine_config.get_simulated_xlen() == Xlen::_64) + mem_program_only = new Memory(machine_config.get_simulated_endian(), 64); + else + mem_program_only = new Memory(machine_config.get_simulated_endian(), 32); + program.to_memory(mem_program_only); + if (load_symtab) { symtab = program.get_symbol_table(); } @@ -33,12 +37,16 @@ Machine::Machine(MachineConfig config, bool load_symtab, bool load_executable) } mem = new Memory(*mem_program_only); } else { - mem = new Memory(machine_config.get_simulated_endian()); + mem = (this->machine_config.get_simulated_xlen() == Xlen::_64 ? new Memory(machine_config.get_simulated_endian(), 64) : new Memory(machine_config.get_simulated_endian(), 32)); } data_bus = new MemoryDataBus(machine_config.get_simulated_endian()); - data_bus->insert_device_to_range( - mem, 0x00000000_addr, 0xefffffff_addr, false); + if (this->machine_config.get_simulated_xlen() == Xlen::_32) + data_bus->insert_device_to_range( + mem, 0x00000000_addr, 0xefffffff_addr, false); + else + data_bus->insert_device_to_range( + mem, 0x00000000_addr, 0xefffffffffffffff_addr, false); setup_serial_port(); setup_perip_spi_led(); @@ -112,18 +120,34 @@ Machine::Machine(MachineConfig config, bool load_symtab, bool load_executable) } void Machine::setup_lcd_display() { perip_lcd_display = new LcdDisplay(machine_config.get_simulated_endian()); - memory_bus_insert_range( - perip_lcd_display, 0xffe00000_addr, 0xffe4afff_addr, true); + if(this->machine_config.get_simulated_xlen() == Xlen::_64){ + memory_bus_insert_range( + perip_lcd_display, 0xffffffffffe00000_addr, 0xffffffffffe4afff_addr, true); + } + else + memory_bus_insert_range( + perip_lcd_display, 0xffe00000_addr, 0xffe4afff_addr, true); } void Machine::setup_perip_spi_led() { perip_spi_led = new PeripSpiLed(machine_config.get_simulated_endian()); - memory_bus_insert_range( - perip_spi_led, 0xffffc100_addr, 0xffffc1ff_addr, true); + if(this->machine_config.get_simulated_xlen() == Xlen::_64){ + memory_bus_insert_range( + perip_spi_led, 0xffffffffffffc100_addr, 0xffffffffffffc1ff_addr, true); + } + else + memory_bus_insert_range( + perip_spi_led, 0xffffc100_addr, 0xffffc1ff_addr, true); } void Machine::setup_serial_port() { ser_port = new SerialPort(machine_config.get_simulated_endian()); - memory_bus_insert_range(ser_port, 0xffffc000_addr, 0xffffc03f_addr, true); - memory_bus_insert_range(ser_port, 0xffff0000_addr, 0xffff003f_addr, false); + if(this->machine_config.get_simulated_xlen() == Xlen::_64){ + memory_bus_insert_range(ser_port, 0xffffffffffffc000_addr, 0xffffffffffffc03f_addr, true); + memory_bus_insert_range(ser_port, 0xffffffffffff0000_addr, 0xffffffffffff003f_addr, false); + } + else{ + memory_bus_insert_range(ser_port, 0xffffc000_addr, 0xffffc03f_addr, true); + memory_bus_insert_range(ser_port, 0xffff0000_addr, 0xffff003f_addr, false); + } connect( ser_port, &SerialPort::signal_interrupt, this, &Machine::set_interrupt_signal); diff --git a/src/machine/memory/backend/memory.cpp b/src/machine/memory/backend/memory.cpp index 9d618ada..6a6aeca5 100644 --- a/src/machine/memory/backend/memory.cpp +++ b/src/machine/memory/backend/memory.cpp @@ -102,22 +102,22 @@ static_assert( * ```address & generate_mask(8, 0)``` */ constexpr uint64_t generate_mask(size_t section_size, size_t unit_size) { - return ((1U << section_size) - 1) << unit_size; + return ((1ULL << section_size) - 1) << unit_size; } /** * Get index in row for given offset and row number i */ -constexpr size_t tree_row_bit_offset(size_t i) { - return 32 - MEMORY_TREE_BITS - i * MEMORY_TREE_BITS; +constexpr uint64_t tree_row_bit_offset(size_t i, size_t xlen) { + return xlen - MEMORY_TREE_BITS - i * MEMORY_TREE_BITS; } /* * Select branch index from memory tree. */ -constexpr size_t get_tree_row(size_t offset, size_t i) { - return (offset & generate_mask(MEMORY_TREE_BITS, tree_row_bit_offset(i))) - >> tree_row_bit_offset(i); +constexpr uint64_t get_tree_row(uint64_t offset, size_t i, size_t xlen) { + return (offset & generate_mask(MEMORY_TREE_BITS, tree_row_bit_offset(i, xlen))) + >> tree_row_bit_offset(i, xlen); } Memory::Memory() : BackendMemory(BIG) { @@ -128,27 +128,61 @@ Memory::Memory() : BackendMemory(BIG) { Memory::Memory(Endian simulated_machine_endian) : BackendMemory(simulated_machine_endian) { this->mt_root = allocate_section_tree(); + this->xlen = 32; +} + +Memory::Memory(Endian simulated_machine_endian, size_t xlen) + : BackendMemory(simulated_machine_endian) { + this->mt_root = allocate_section_tree(); + this->xlen = xlen; } Memory::Memory(const Memory &other) : BackendMemory(other.simulated_machine_endian) { - this->mt_root = copy_section_tree(other.get_memory_tree_root(), 0); + this->xlen = other.xlen; + this->mt_root = copy_section_tree(other.get_memory_tree_root(), 0, ((this->xlen - MEMORY_SECTION_BITS) / MEMORY_TREE_BITS)); } Memory::~Memory() { - free_section_tree(this->mt_root, 0); + free_section_tree(this->mt_root, 0, ((this->xlen - MEMORY_SECTION_BITS) / MEMORY_TREE_BITS)); delete[] this->mt_root; } void Memory::reset() { - free_section_tree(this->mt_root, 0); + free_section_tree(this->mt_root, 0, ((this->xlen - MEMORY_SECTION_BITS) / MEMORY_TREE_BITS)); delete[] this->mt_root; this->mt_root = allocate_section_tree(); } void Memory::reset(const Memory &m) { - free_section_tree(this->mt_root, 0); - this->mt_root = copy_section_tree(m.get_memory_tree_root(), 0); + free_section_tree(this->mt_root, 0, ((this->xlen - MEMORY_SECTION_BITS) / MEMORY_TREE_BITS)); + if(this->xlen > m.xlen) { + union MemoryTree *cmt = allocate_section_tree(); + const union MemoryTree *mt = m.get_memory_tree_root(); + this->xlen = m.xlen; + for(size_t i = 0; i < MEMORY_TREE_ROW_SIZE; i++) { + if (mt[i].subtree != nullptr) { + size_t index = i >> 3 ? 15 : 0; + union MemoryTree *temp = cmt; + for (size_t j = 0; j < 8; j++, temp = temp[index].subtree) { + if (temp[index].subtree == nullptr) { + temp[index].subtree = allocate_section_tree(); + } + } + temp[i].subtree = copy_section_tree(mt[i].subtree, 1, ((this->xlen - MEMORY_SECTION_BITS) / MEMORY_TREE_BITS)); + } + } + delete[] this->mt_root; + this->mt_root = cmt; + this->xlen = 64; + } + else if (this->xlen < m.xlen) { + delete[] this->mt_root; + this->mt_root = allocate_section_tree(); + } + else + this->mt_root = copy_section_tree(m.get_memory_tree_root(), 0, ((this->xlen - MEMORY_SECTION_BITS) / MEMORY_TREE_BITS)); + } MemorySection *Memory::get_section(size_t offset, bool create) const { @@ -156,8 +190,9 @@ MemorySection *Memory::get_section(size_t offset, bool create) const { size_t row_num; // Walk memory tree branch from root to leaf and create new nodes when // needed and requested (`create` flag). - for (size_t i = 0; i < (MEMORY_TREE_DEPTH - 1); i++) { - row_num = get_tree_row(offset, i); + size_t memory_tree_depth = ((this->xlen - MEMORY_SECTION_BITS) / MEMORY_TREE_BITS); + for (size_t i = 0; i < (memory_tree_depth - 1); i++) { + row_num = get_tree_row(offset, i, this->xlen); if (w[row_num].subtree == nullptr) { // We don't have this tree so allocate it. if (!create) { @@ -168,7 +203,7 @@ MemorySection *Memory::get_section(size_t offset, bool create) const { } w = w[row_num].subtree; } - row_num = get_tree_row(offset, MEMORY_TREE_DEPTH - 1); + row_num = get_tree_row(offset, memory_tree_depth - 1, this->xlen); if (w[row_num].sec == nullptr) { if (!create) { return nullptr; @@ -227,7 +262,7 @@ uint32_t Memory::get_change_counter() const { } bool Memory::operator==(const Memory &m) const { - return compare_section_tree(this->mt_root, m.get_memory_tree_root(), 0); + return compare_section_tree(this->mt_root, m.get_memory_tree_root(), 0 , ((this->xlen - MEMORY_SECTION_BITS) / MEMORY_TREE_BITS)); } bool Memory::operator!=(const Memory &m) const { @@ -244,11 +279,11 @@ union machine::MemoryTree *Memory::allocate_section_tree() { return mt; } -void Memory::free_section_tree(union MemoryTree *mt, size_t depth) { - if (depth < (MEMORY_TREE_DEPTH - 1)) { // Following level is memory tree +void Memory::free_section_tree(union MemoryTree *mt, size_t depth, size_t memory_tree_depth) { + if (depth < (memory_tree_depth - 1)) { // Following level is memory tree for (size_t i = 0; i < MEMORY_TREE_ROW_SIZE; i++) { if (mt[i].subtree != nullptr) { - free_section_tree(mt[i].subtree, depth + 1); + free_section_tree(mt[i].subtree, depth + 1, memory_tree_depth); delete[] mt[i].subtree; } } @@ -262,14 +297,15 @@ void Memory::free_section_tree(union MemoryTree *mt, size_t depth) { bool Memory::compare_section_tree( const union MemoryTree *mt1, const union MemoryTree *mt2, - size_t depth) { - if (depth < (MEMORY_TREE_DEPTH - 1)) { // Following level is memory tree + size_t depth, + size_t memory_tree_depth) { + if (depth < (memory_tree_depth - 1)) { // Following level is memory tree for (size_t i = 0; i < MEMORY_TREE_ROW_SIZE; i++) { if (((mt1[i].subtree == nullptr || mt2[i].subtree == nullptr) && mt1[i].subtree != mt2[i].subtree) || (mt1[i].subtree != nullptr && mt2[i].subtree != nullptr && !compare_section_tree( - mt1[i].subtree, mt2[i].subtree, depth + 1))) { + mt1[i].subtree, mt2[i].subtree, depth + 1, memory_tree_depth))) { return false; } } @@ -287,12 +323,12 @@ bool Memory::compare_section_tree( } union machine::MemoryTree * -Memory::copy_section_tree(const union MemoryTree *mt, size_t depth) { +Memory::copy_section_tree(const union MemoryTree *mt, size_t depth, size_t memory_tree_depth) { union MemoryTree *nmt = allocate_section_tree(); - if (depth < (MEMORY_TREE_DEPTH - 1)) { // Following level is memory tree + if (depth < (memory_tree_depth - 1)) { // Following level is memory tree for (size_t i = 0; i < MEMORY_TREE_ROW_SIZE; i++) { if (mt[i].subtree != nullptr) { - nmt[i].subtree = copy_section_tree(mt[i].subtree, depth + 1); + nmt[i].subtree = copy_section_tree(mt[i].subtree, depth + 1, memory_tree_depth); } } } else { // Following level is memory section diff --git a/src/machine/memory/backend/memory.h b/src/machine/memory/backend/memory.h index 0199afd9..8371e06c 100644 --- a/src/machine/memory/backend/memory.h +++ b/src/machine/memory/backend/memory.h @@ -78,6 +78,7 @@ class Memory final : public BackendMemory { // This is dummy constructor for qt internal uses only. Memory(); explicit Memory(Endian simulated_machine_endian); + Memory(Endian simulated_machine_endian, size_t xlen); Memory(const Memory &); ~Memory() override; void reset(); // Reset whole content of memory (removes old tree and creates @@ -109,14 +110,16 @@ class Memory final : public BackendMemory { private: union MemoryTree *mt_root; uint32_t change_counter = 0; + size_t xlen; static union MemoryTree *allocate_section_tree(); - static void free_section_tree(union MemoryTree *, size_t depth); + static void free_section_tree(union MemoryTree *, size_t depth , size_t memory_tree_depth); static bool compare_section_tree( const union MemoryTree *, const union MemoryTree *, - size_t depth); + size_t depth, + size_t memory_tree_depth); static union MemoryTree * - copy_section_tree(const union MemoryTree *, size_t depth); + copy_section_tree(const union MemoryTree *, size_t depth , size_t memory_tree_depth); [[nodiscard]] uint32_t get_change_counter() const; }; } // namespace machine