From bea8959e252557b852ea47f1a791021bd50e201a Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 11 Oct 2020 23:59:30 -0700 Subject: [PATCH 1/4] GB: Disallow skipping BIOS with no ROM loaded --- src/gb/gb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gb/gb.c b/src/gb/gb.c index bc7221957..d2b750aae 100644 --- a/src/gb/gb.c +++ b/src/gb/gb.c @@ -469,7 +469,7 @@ void GBReset(struct SM83Core* cpu) { GBVideoReset(&gb->video); GBTimerReset(&gb->timer); GBIOReset(gb); - if (!gb->biosVf) { + if (!gb->biosVf && gb->memory.rom) { GBSkipBIOS(gb); } else { mTimingSchedule(&gb->timing, &gb->timer.event, 0); From 29a30920d28f11af7b97161161c14f7e4de969c8 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 12 Oct 2020 00:12:25 -0700 Subject: [PATCH 2/4] Qt: Start adding support for GB to the frame view --- src/platform/qt/FrameView.cpp | 66 +++++++++++++++++++++++++++++------ src/platform/qt/FrameView.h | 6 ++-- 2 files changed, 59 insertions(+), 13 deletions(-) diff --git a/src/platform/qt/FrameView.cpp b/src/platform/qt/FrameView.cpp index c32e1f9c8..9e32d692d 100644 --- a/src/platform/qt/FrameView.cpp +++ b/src/platform/qt/FrameView.cpp @@ -186,7 +186,7 @@ void FrameView::updateTilesGBA(bool) { { LayerId::SPRITE, sprite }, !m_disabled.contains({ LayerId::SPRITE, sprite }), QPixmap::fromImage(obj), - {}, offset, false + {}, offset, false, false }); if (m_queue.back().image.hasAlpha()) { m_queue.back().mask = QRegion(m_queue.back().image.mask()); @@ -212,7 +212,7 @@ void FrameView::updateTilesGBA(bool) { { LayerId::BACKGROUND, bg }, !m_disabled.contains({ LayerId::BACKGROUND, bg }), QPixmap::fromImage(compositeMap(bg, m_mapStatus[bg])), - {}, offset, true + {}, offset, true, false }); if (m_queue.back().image.hasAlpha()) { m_queue.back().mask = QRegion(m_queue.back().image.mask()); @@ -228,7 +228,7 @@ void FrameView::updateTilesGBA(bool) { { LayerId::BACKDROP }, !m_disabled.contains({ LayerId::BACKDROP }), QPixmap::fromImage(backdropImage), - {}, {0, 0}, false + {}, {0, 0}, false, true }); updateRendered(); } @@ -237,7 +237,6 @@ void FrameView::updateTilesGBA(bool) { void FrameView::injectGBA() { mVideoLogger* logger = m_vl->videoLogger; - mVideoLoggerInjectionPoint(logger, LOGGER_INJECTION_FIRST_SCANLINE); GBA* gba = static_cast(m_vl->board); gba->video.renderer->highlightBG[0] = false; gba->video.renderer->highlightBG[1] = false; @@ -276,11 +275,6 @@ void FrameView::injectGBA() { if (m_overrideBackdrop.isValid()) { mVideoLoggerInjectPalette(logger, 0, M_RGB8_TO_RGB5(m_overrideBackdrop.rgb())); } - if (m_ui.disableScanline->checkState() == Qt::Checked) { - mVideoLoggerIgnoreAfterInjection(logger, (1 << DIRTY_PALETTE) | (1 << DIRTY_OAM) | (1 << DIRTY_REGISTER)); - } else { - mVideoLoggerIgnoreAfterInjection(logger, 0); - } } #endif @@ -292,13 +286,49 @@ void FrameView::updateTilesGB(bool) { m_queue.clear(); { CoreController::Interrupter interrupter(m_controller); + for (int sprite = 0; sprite < 40; ++sprite) { + ObjInfo info; + lookupObj(sprite, &info); + + if (!info.enabled) { + continue; + } + + QPointF offset(info.x, info.y); + QImage obj(compositeObj(info)); + if (info.hflip || info.vflip) { + obj = obj.mirrored(info.hflip, info.vflip); + } + m_queue.append({ + { LayerId::SPRITE, sprite }, + !m_disabled.contains({ LayerId::SPRITE, sprite }), + QPixmap::fromImage(obj), + {}, offset, false, false + }); + if (m_queue.back().image.hasAlpha()) { + m_queue.back().mask = QRegion(m_queue.back().image.mask()); + } else { + m_queue.back().mask = QRegion(0, 0, m_queue.back().image.width(), m_queue.back().image.height()); + } + } + updateRendered(); } invalidateQueue(m_controller->screenDimensions()); } void FrameView::injectGB() { + mVideoLogger* logger = m_vl->videoLogger; + + m_vl->reset(m_vl); for (const Layer& layer : m_queue) { + switch (layer.id.type) { + case LayerId::SPRITE: + if (!layer.enabled) { + mVideoLoggerInjectOAM(logger, layer.id.index << 2, 0); + } + break; + } } } #endif @@ -310,6 +340,8 @@ void FrameView::invalidateQueue(const QSize& dims) { bool blockSignals = m_ui.queue->blockSignals(true); QMutexLocker locker(&m_mutex); if (m_vl) { + mVideoLogger* logger = m_vl->videoLogger; + mVideoLoggerInjectionPoint(logger, LOGGER_INJECTION_FIRST_SCANLINE); switch (m_controller->platform()) { #ifdef M_CORE_GBA case PLATFORM_GBA: @@ -322,6 +354,11 @@ void FrameView::invalidateQueue(const QSize& dims) { break; #endif } + if (m_ui.disableScanline->checkState() == Qt::Checked) { + mVideoLoggerIgnoreAfterInjection(logger, (1 << DIRTY_PALETTE) | (1 << DIRTY_OAM) | (1 << DIRTY_REGISTER)); + } else { + mVideoLoggerIgnoreAfterInjection(logger, 0); + } m_vl->runFrame(m_vl); } @@ -335,7 +372,7 @@ void FrameView::invalidateQueue(const QSize& dims) { item = m_ui.queue->item(i); } item->setText(layer.id.readable()); - item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); + item->setFlags(Qt::ItemIsSelectable | (layer.fixed ? Qt::NoItemFlags : Qt::ItemIsUserCheckable) | Qt::ItemIsEnabled); item->setCheckState(layer.enabled ? Qt::Checked : Qt::Unchecked); item->setData(Qt::UserRole, i); item->setSelected(layer.id == m_active); @@ -351,8 +388,12 @@ void FrameView::invalidateQueue(const QSize& dims) { updateRendered(); composited = m_rendered; } else { + QImage framebuffer(m_framebuffer); m_ui.exportButton->setEnabled(true); - composited.convertFromImage(m_framebuffer); + if (framebuffer.size() != m_dims) { + framebuffer = framebuffer.copy({QPoint(), m_dims}); + } + composited.convertFromImage(framebuffer); } m_composited = composited.scaled(m_dims * m_ui.magnification->value()); m_ui.compositedView->setPixmap(m_composited); @@ -461,6 +502,9 @@ QString FrameView::LayerId::readable() const { case BACKDROP: typeStr = tr("Backdrop"); break; + case FRAME: + typeStr = tr("Frame"); + break; } if (index < 0) { return typeStr; diff --git a/src/platform/qt/FrameView.h b/src/platform/qt/FrameView.h index e47e82054..5074a42bf 100644 --- a/src/platform/qt/FrameView.h +++ b/src/platform/qt/FrameView.h @@ -66,7 +66,8 @@ private: BACKGROUND, WINDOW, SPRITE, - BACKDROP + BACKDROP, + FRAME } type = NONE; int index = -1; @@ -82,6 +83,7 @@ private: QRegion mask; QPointF location; bool repeats; + bool fixed; }; bool lookupLayer(const QPointF& coord, Layer*&); @@ -117,4 +119,4 @@ private: std::shared_ptr m_callbackLocker{std::make_shared(true)}; }; -} \ No newline at end of file +} From 67d3eed8fbdfadfce9c3f5c0ac1c6b4ad323b9e4 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 12 Oct 2020 18:07:11 -0700 Subject: [PATCH 3/4] ARM Decoder: Revamp load/store interface, readability cleanup --- include/mgba/internal/arm/decoder.h | 3 + src/arm/decoder-arm.c | 143 +++++++++++++++------------- src/arm/decoder-thumb.c | 76 ++++++++------- 3 files changed, 118 insertions(+), 104 deletions(-) diff --git a/include/mgba/internal/arm/decoder.h b/include/mgba/internal/arm/decoder.h index 1a3f9e7e9..f29c15aad 100644 --- a/include/mgba/internal/arm/decoder.h +++ b/include/mgba/internal/arm/decoder.h @@ -66,6 +66,9 @@ CXX_GUARD_START #define ARM_MEMORY_DECREMENT_BEFORE 0x0200 #define ARM_MEMORY_INCREMENT_BEFORE 0x0300 #define ARM_MEMORY_SPSR_SWAP 0x0400 +#define ARM_MEMORY_STORE 0x1000 +#define ARM_MEMORY_LOAD 0x2000 +#define ARM_MEMORY_SWAP 0x3000 #define ARM_PSR_C 1 #define ARM_PSR_X 2 diff --git a/src/arm/decoder-arm.c b/src/arm/decoder-arm.c index abfff5335..cf75d8881 100644 --- a/src/arm/decoder-arm.c +++ b/src/arm/decoder-arm.c @@ -192,61 +192,68 @@ } \ CYCLES;) -#define DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME, MNEMONIC, ADDRESSING_MODE, CYCLES, TYPE, OTHER_AFFECTED) \ +#define DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME, MNEMONIC, ADDRESSING_MODE, TYPE, FORMAT, OTHER_AFFECTED) \ DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME, MNEMONIC, \ ARM_MEMORY_POST_INCREMENT | \ ARM_MEMORY_WRITEBACK | \ - ARM_MEMORY_OFFSET_SUBTRACT, \ - ADDRESSING_MODE, CYCLES, TYPE, OTHER_AFFECTED) \ + ARM_MEMORY_OFFSET_SUBTRACT | \ + ARM_MEMORY_ ## FORMAT, \ + ADDRESSING_MODE, FORMAT ## _CYCLES, ARM_ACCESS_ ## TYPE, OTHER_AFFECTED) \ DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME ## U, MNEMONIC, \ ARM_MEMORY_POST_INCREMENT | \ - ARM_MEMORY_WRITEBACK, \ - ADDRESSING_MODE, CYCLES, TYPE, OTHER_AFFECTED) \ + ARM_MEMORY_WRITEBACK | \ + ARM_MEMORY_ ## FORMAT, \ + ADDRESSING_MODE, FORMAT ## _CYCLES, ARM_ACCESS_ ## TYPE, OTHER_AFFECTED) \ DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME ## P, MNEMONIC, \ - ARM_MEMORY_OFFSET_SUBTRACT, \ - ADDRESSING_MODE, CYCLES, TYPE, OTHER_AFFECTED) \ + ARM_MEMORY_OFFSET_SUBTRACT | \ + ARM_MEMORY_ ## FORMAT, \ + ADDRESSING_MODE, FORMAT ## _CYCLES, ARM_ACCESS_ ## TYPE, OTHER_AFFECTED) \ DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME ## PW, MNEMONIC, \ ARM_MEMORY_PRE_INCREMENT | \ ARM_MEMORY_WRITEBACK | \ - ARM_MEMORY_OFFSET_SUBTRACT, \ - ADDRESSING_MODE, CYCLES, TYPE, OTHER_AFFECTED) \ + ARM_MEMORY_OFFSET_SUBTRACT | \ + ARM_MEMORY_ ## FORMAT, \ + ADDRESSING_MODE, FORMAT ## _CYCLES, ARM_ACCESS_ ## TYPE, OTHER_AFFECTED) \ DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME ## PU, MNEMONIC, \ - 0, \ - ADDRESSING_MODE, CYCLES, TYPE, OTHER_AFFECTED) \ + ARM_MEMORY_ ## FORMAT, \ + ADDRESSING_MODE, FORMAT ## _CYCLES, ARM_ACCESS_ ## TYPE, OTHER_AFFECTED) \ DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME ## PUW, MNEMONIC, \ - ARM_MEMORY_WRITEBACK, \ - ADDRESSING_MODE, CYCLES, TYPE, OTHER_AFFECTED) \ + ARM_MEMORY_WRITEBACK | \ + ARM_MEMORY_ ## FORMAT, \ + ADDRESSING_MODE, FORMAT ## _CYCLES, ARM_ACCESS_ ## TYPE, OTHER_AFFECTED) \ -#define DEFINE_LOAD_STORE_MODE_2_DECODER_ARM(NAME, MNEMONIC, CYCLES, TYPE, OTHER_AFFECTED) \ - DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME ## _LSL_, MNEMONIC, ADDR_MODE_2_LSL, CYCLES, TYPE, OTHER_AFFECTED) \ - DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME ## _LSR_, MNEMONIC, ADDR_MODE_2_LSR, CYCLES, TYPE, OTHER_AFFECTED) \ - DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME ## _ASR_, MNEMONIC, ADDR_MODE_2_ASR, CYCLES, TYPE, OTHER_AFFECTED) \ - DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME ## _ROR_, MNEMONIC, ADDR_MODE_2_ROR, CYCLES, TYPE, OTHER_AFFECTED) \ - DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME ## I, MNEMONIC, ADDR_MODE_2_IMM, CYCLES, TYPE, OTHER_AFFECTED) +#define DEFINE_LOAD_STORE_MODE_2_DECODER_ARM(NAME, MNEMONIC, FORMAT, TYPE, OTHER_AFFECTED) \ + DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME ## _LSL_, MNEMONIC, ADDR_MODE_2_LSL, TYPE, FORMAT, OTHER_AFFECTED) \ + DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME ## _LSR_, MNEMONIC, ADDR_MODE_2_LSR, TYPE, FORMAT, OTHER_AFFECTED) \ + DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME ## _ASR_, MNEMONIC, ADDR_MODE_2_ASR, TYPE, FORMAT, OTHER_AFFECTED) \ + DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME ## _ROR_, MNEMONIC, ADDR_MODE_2_ROR, TYPE, FORMAT, OTHER_AFFECTED) \ + DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME ## I, MNEMONIC, ADDR_MODE_2_IMM, TYPE, FORMAT, OTHER_AFFECTED) -#define DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(NAME, MNEMONIC, CYCLES, TYPE, OTHER_AFFECTED) \ - DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME, MNEMONIC, ADDR_MODE_3_REG, CYCLES, TYPE, OTHER_AFFECTED) \ - DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME ## I, MNEMONIC, ADDR_MODE_3_IMM, CYCLES, TYPE, OTHER_AFFECTED) +#define DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(NAME, MNEMONIC, FORMAT, TYPE, OTHER_AFFECTED) \ + DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME, MNEMONIC, ADDR_MODE_3_REG, TYPE, FORMAT, OTHER_AFFECTED) \ + DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME ## I, MNEMONIC, ADDR_MODE_3_IMM, TYPE, FORMAT, OTHER_AFFECTED) -#define DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME, MNEMONIC, ADDRESSING_MODE, CYCLES, TYPE, OTHER_AFFECTED) \ +#define DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME, MNEMONIC, ADDRESSING_MODE, TYPE, FORMAT, OTHER_AFFECTED) \ DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME, MNEMONIC, \ ARM_MEMORY_POST_INCREMENT | \ ARM_MEMORY_WRITEBACK | \ - ARM_MEMORY_OFFSET_SUBTRACT, \ - ADDRESSING_MODE, CYCLES, TYPE, OTHER_AFFECTED) \ + ARM_MEMORY_OFFSET_SUBTRACT | \ + ARM_MEMORY_ ## FORMAT, \ + ADDRESSING_MODE, FORMAT ## _CYCLES, ARM_ACCESS_ ## TYPE, OTHER_AFFECTED) \ DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME ## U, MNEMONIC, \ ARM_MEMORY_POST_INCREMENT | \ - ARM_MEMORY_WRITEBACK, \ - ADDRESSING_MODE, CYCLES, TYPE, OTHER_AFFECTED) + ARM_MEMORY_WRITEBACK | \ + ARM_MEMORY_ ## FORMAT, \ + ADDRESSING_MODE, FORMAT ## _CYCLES, ARM_ACCESS_ ## TYPE, OTHER_AFFECTED) -#define DEFINE_LOAD_STORE_T_DECODER_ARM(NAME, MNEMONIC, CYCLES, TYPE, OTHER_AFFECTED) \ - DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME ## _LSL_, MNEMONIC, ADDR_MODE_2_LSL, CYCLES, TYPE, OTHER_AFFECTED) \ - DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME ## _LSR_, MNEMONIC, ADDR_MODE_2_LSR, CYCLES, TYPE, OTHER_AFFECTED) \ - DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME ## _ASR_, MNEMONIC, ADDR_MODE_2_ASR, CYCLES, TYPE, OTHER_AFFECTED) \ - DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME ## _ROR_, MNEMONIC, ADDR_MODE_2_ROR, CYCLES, TYPE, OTHER_AFFECTED) \ - DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME ## I, MNEMONIC, ADDR_MODE_2_IMM, CYCLES, TYPE, OTHER_AFFECTED) +#define DEFINE_LOAD_STORE_T_DECODER_ARM(NAME, MNEMONIC, FORMAT, TYPE, OTHER_AFFECTED) \ + DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME ## _LSL_, MNEMONIC, ADDR_MODE_2_LSL, TYPE, FORMAT, OTHER_AFFECTED) \ + DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME ## _LSR_, MNEMONIC, ADDR_MODE_2_LSR, TYPE, FORMAT, OTHER_AFFECTED) \ + DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME ## _ASR_, MNEMONIC, ADDR_MODE_2_ASR, TYPE, FORMAT, OTHER_AFFECTED) \ + DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME ## _ROR_, MNEMONIC, ADDR_MODE_2_ROR, TYPE, FORMAT, OTHER_AFFECTED) \ + DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME ## I, MNEMONIC, ADDR_MODE_2_IMM, TYPE, FORMAT, OTHER_AFFECTED) -#define DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME, MNEMONIC, DIRECTION, WRITEBACK) \ +#define DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME, MNEMONIC, DIRECTION, FORMAT) \ DEFINE_DECODER_ARM(NAME, MNEMONIC, \ info->memory.baseReg = (opcode >> 16) & 0xF; \ info->op1.immediate = opcode & 0x0000FFFF; \ @@ -255,27 +262,27 @@ } \ info->operandFormat = ARM_OPERAND_MEMORY_1; \ info->memory.format = ARM_MEMORY_REGISTER_BASE | \ - WRITEBACK | \ + FORMAT | \ ARM_MEMORY_ ## DIRECTION;) -#define DEFINE_LOAD_STORE_MULTIPLE_DECODER_ARM(NAME) \ - DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## DA, NAME, DECREMENT_AFTER, 0) \ - DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## DAW, NAME, DECREMENT_AFTER, ARM_MEMORY_WRITEBACK) \ - DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## DB, NAME, DECREMENT_BEFORE, 0) \ - DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## DBW, NAME, DECREMENT_BEFORE, ARM_MEMORY_WRITEBACK) \ - DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## IA, NAME, INCREMENT_AFTER, 0) \ - DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## IAW, NAME, INCREMENT_AFTER, ARM_MEMORY_WRITEBACK) \ - DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## IB, NAME, INCREMENT_BEFORE, 0) \ - DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## IBW, NAME, INCREMENT_BEFORE, ARM_MEMORY_WRITEBACK) \ - DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SDA, NAME, DECREMENT_AFTER, ARM_MEMORY_SPSR_SWAP) \ - DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SDAW, NAME, DECREMENT_AFTER, ARM_MEMORY_WRITEBACK | ARM_MEMORY_SPSR_SWAP) \ - DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SDB, NAME, DECREMENT_BEFORE, ARM_MEMORY_SPSR_SWAP) \ - DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SDBW, NAME, DECREMENT_BEFORE, ARM_MEMORY_WRITEBACK | ARM_MEMORY_SPSR_SWAP) \ - DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SIA, NAME, INCREMENT_AFTER, ARM_MEMORY_SPSR_SWAP) \ - DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SIAW, NAME, INCREMENT_AFTER, ARM_MEMORY_WRITEBACK | ARM_MEMORY_SPSR_SWAP) \ - DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SIB, NAME, INCREMENT_BEFORE, ARM_MEMORY_SPSR_SWAP) \ - DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SIBW, NAME, INCREMENT_BEFORE, ARM_MEMORY_WRITEBACK | ARM_MEMORY_SPSR_SWAP) +#define DEFINE_LOAD_STORE_MULTIPLE_DECODER_ARM(NAME, FORMAT) \ + DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## DA, NAME, DECREMENT_AFTER, ARM_MEMORY_ ## FORMAT) \ + DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## DAW, NAME, DECREMENT_AFTER, ARM_MEMORY_WRITEBACK | ARM_MEMORY_ ## FORMAT) \ + DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## DB, NAME, DECREMENT_BEFORE, ARM_MEMORY_ ## FORMAT) \ + DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## DBW, NAME, DECREMENT_BEFORE, ARM_MEMORY_WRITEBACK | ARM_MEMORY_ ## FORMAT) \ + DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## IA, NAME, INCREMENT_AFTER, ARM_MEMORY_ ## FORMAT) \ + DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## IAW, NAME, INCREMENT_AFTER, ARM_MEMORY_WRITEBACK | ARM_MEMORY_ ## FORMAT) \ + DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## IB, NAME, INCREMENT_BEFORE, ARM_MEMORY_ ## FORMAT) \ + DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## IBW, NAME, INCREMENT_BEFORE, ARM_MEMORY_WRITEBACK | ARM_MEMORY_ ## FORMAT) \ + DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SDA, NAME, DECREMENT_AFTER, ARM_MEMORY_SPSR_SWAP | ARM_MEMORY_ ## FORMAT) \ + DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SDAW, NAME, DECREMENT_AFTER, ARM_MEMORY_WRITEBACK | ARM_MEMORY_SPSR_SWAP | ARM_MEMORY_ ## FORMAT) \ + DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SDB, NAME, DECREMENT_BEFORE, ARM_MEMORY_SPSR_SWAP | ARM_MEMORY_ ## FORMAT) \ + DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SDBW, NAME, DECREMENT_BEFORE, ARM_MEMORY_WRITEBACK | ARM_MEMORY_SPSR_SWAP | ARM_MEMORY_ ## FORMAT) \ + DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SIA, NAME, INCREMENT_AFTER, ARM_MEMORY_SPSR_SWAP | ARM_MEMORY_ ## FORMAT) \ + DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SIAW, NAME, INCREMENT_AFTER, ARM_MEMORY_WRITEBACK | ARM_MEMORY_SPSR_SWAP | ARM_MEMORY_ ## FORMAT) \ + DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SIB, NAME, INCREMENT_BEFORE, ARM_MEMORY_SPSR_SWAP | ARM_MEMORY_ ## FORMAT) \ + DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SIBW, NAME, INCREMENT_BEFORE, ARM_MEMORY_WRITEBACK | ARM_MEMORY_SPSR_SWAP | ARM_MEMORY_ ## FORMAT) #define DEFINE_SWP_DECODER_ARM(NAME, TYPE) \ DEFINE_DECODER_ARM(NAME, SWP, \ @@ -285,8 +292,8 @@ info->operandFormat = ARM_OPERAND_REGISTER_1 | \ ARM_OPERAND_AFFECTED_1 | \ ARM_OPERAND_REGISTER_2 | \ - ARM_OPERAND_MEMORY_3; \ - info->memory.format = ARM_MEMORY_REGISTER_BASE; \ + ARM_OPERAND_MEMORY_3 | ARM_OPERAND_AFFECTED_3; \ + info->memory.format = ARM_MEMORY_REGISTER_BASE | ARM_MEMORY_SWAP; \ info->memory.width = TYPE;) DEFINE_ALU_DECODER_ARM(ADD, 0) @@ -317,22 +324,22 @@ DEFINE_LONG_MULTIPLY_DECODER_ARM(UMULL) // Begin load/store definitions -DEFINE_LOAD_STORE_MODE_2_DECODER_ARM(LDR, LDR, LOAD_CYCLES, ARM_ACCESS_WORD, ARM_OPERAND_AFFECTED_1) -DEFINE_LOAD_STORE_MODE_2_DECODER_ARM(LDRB, LDR, LOAD_CYCLES, ARM_ACCESS_BYTE, ARM_OPERAND_AFFECTED_1) -DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(LDRH, LDR, LOAD_CYCLES, ARM_ACCESS_HALFWORD, ARM_OPERAND_AFFECTED_1) -DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(LDRSB, LDR, LOAD_CYCLES, ARM_ACCESS_SIGNED_BYTE, ARM_OPERAND_AFFECTED_1) -DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(LDRSH, LDR, LOAD_CYCLES, ARM_ACCESS_SIGNED_HALFWORD, ARM_OPERAND_AFFECTED_1) -DEFINE_LOAD_STORE_MODE_2_DECODER_ARM(STR, STR, STORE_CYCLES, ARM_ACCESS_WORD, ARM_OPERAND_NONE) -DEFINE_LOAD_STORE_MODE_2_DECODER_ARM(STRB, STR, STORE_CYCLES, ARM_ACCESS_BYTE, ARM_OPERAND_NONE) -DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(STRH, STR, STORE_CYCLES, ARM_ACCESS_HALFWORD, ARM_OPERAND_NONE) +DEFINE_LOAD_STORE_MODE_2_DECODER_ARM(LDR, LDR, LOAD, WORD, ARM_OPERAND_AFFECTED_1) +DEFINE_LOAD_STORE_MODE_2_DECODER_ARM(LDRB, LDR, LOAD, BYTE, ARM_OPERAND_AFFECTED_1) +DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(LDRH, LDR, LOAD, HALFWORD, ARM_OPERAND_AFFECTED_1) +DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(LDRSB, LDR, LOAD, SIGNED_BYTE, ARM_OPERAND_AFFECTED_1) +DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(LDRSH, LDR, LOAD, SIGNED_HALFWORD, ARM_OPERAND_AFFECTED_1) +DEFINE_LOAD_STORE_MODE_2_DECODER_ARM(STR, STR, STORE, WORD, ARM_OPERAND_AFFECTED_2) +DEFINE_LOAD_STORE_MODE_2_DECODER_ARM(STRB, STR, STORE, BYTE, ARM_OPERAND_AFFECTED_2) +DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(STRH, STR, STORE, HALFWORD, ARM_OPERAND_AFFECTED_2) -DEFINE_LOAD_STORE_T_DECODER_ARM(LDRBT, LDR, LOAD_CYCLES, ARM_ACCESS_TRANSLATED_BYTE, ARM_OPERAND_AFFECTED_1) -DEFINE_LOAD_STORE_T_DECODER_ARM(LDRT, LDR, LOAD_CYCLES, ARM_ACCESS_TRANSLATED_WORD, ARM_OPERAND_AFFECTED_1) -DEFINE_LOAD_STORE_T_DECODER_ARM(STRBT, STR, STORE_CYCLES, ARM_ACCESS_TRANSLATED_BYTE, ARM_OPERAND_NONE) -DEFINE_LOAD_STORE_T_DECODER_ARM(STRT, STR, STORE_CYCLES, ARM_ACCESS_TRANSLATED_WORD, ARM_OPERAND_NONE) +DEFINE_LOAD_STORE_T_DECODER_ARM(LDRBT, LDR, LOAD, TRANSLATED_BYTE, ARM_OPERAND_AFFECTED_1) +DEFINE_LOAD_STORE_T_DECODER_ARM(LDRT, LDR, LOAD, TRANSLATED_WORD, ARM_OPERAND_AFFECTED_1) +DEFINE_LOAD_STORE_T_DECODER_ARM(STRBT, STR, STORE, TRANSLATED_BYTE, ARM_OPERAND_AFFECTED_2) +DEFINE_LOAD_STORE_T_DECODER_ARM(STRT, STR, STORE, TRANSLATED_WORD, ARM_OPERAND_AFFECTED_2) -DEFINE_LOAD_STORE_MULTIPLE_DECODER_ARM(LDM) -DEFINE_LOAD_STORE_MULTIPLE_DECODER_ARM(STM) +DEFINE_LOAD_STORE_MULTIPLE_DECODER_ARM(LDM, LOAD) +DEFINE_LOAD_STORE_MULTIPLE_DECODER_ARM(STM, STORE) DEFINE_SWP_DECODER_ARM(SWP, ARM_ACCESS_WORD) DEFINE_SWP_DECODER_ARM(SWPB, ARM_ACCESS_BYTE) diff --git a/src/arm/decoder-thumb.c b/src/arm/decoder-thumb.c index a53da00e9..e96ae8396 100644 --- a/src/arm/decoder-thumb.c +++ b/src/arm/decoder-thumb.c @@ -27,7 +27,7 @@ ARM_OPERAND_REGISTER_2 | \ ARM_OPERAND_IMMEDIATE_3;) -#define DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(NAME, MNEMONIC, CYCLES, WIDTH, AFFECTED) \ +#define DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(NAME, MNEMONIC, FORMAT, WIDTH, AFFECTED) \ DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ info->op1.reg = opcode & 0x0007; \ info->memory.baseReg = (opcode >> 3) & 0x0007; \ @@ -37,18 +37,19 @@ ARM_OPERAND_AFFECTED_ ## AFFECTED | \ ARM_OPERAND_MEMORY_2; \ info->memory.format = ARM_MEMORY_REGISTER_BASE | \ - ARM_MEMORY_IMMEDIATE_OFFSET; \ - CYCLES) + ARM_MEMORY_IMMEDIATE_OFFSET | \ + ARM_MEMORY_ ## FORMAT; \ + FORMAT ## _CYCLES) DEFINE_IMMEDIATE_5_DECODER_DATA_THUMB(LSL1, LSL) DEFINE_IMMEDIATE_5_DECODER_DATA_THUMB(LSR1, LSR) DEFINE_IMMEDIATE_5_DECODER_DATA_THUMB(ASR1, ASR) -DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(LDR1, LDR, LOAD_CYCLES, 4, 1) -DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(LDRB1, LDR, LOAD_CYCLES, 1, 1) -DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(LDRH1, LDR, LOAD_CYCLES, 2, 1) -DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(STR1, STR, STORE_CYCLES, 4, 2) -DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(STRB1, STR, STORE_CYCLES, 1, 2) -DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(STRH1, STR, STORE_CYCLES, 2, 2) +DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(LDR1, LDR, LOAD, 4, 1) +DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(LDRB1, LDR, LOAD, 1, 1) +DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(LDRH1, LDR, LOAD, 2, 1) +DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(STR1, STR, STORE, 4, 2) +DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(STRB1, STR, STORE, 1, 2) +DEFINE_IMMEDIATE_5_DECODER_MEM_THUMB(STRH1, STR, STORE, 2, 2) #define DEFINE_DATA_FORM_1_DECODER_THUMB(NAME, MNEMONIC) \ DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ @@ -151,7 +152,7 @@ DEFINE_DECODER_WITH_HIGH_THUMB(MOV3, MOV, ARM_OPERAND_AFFECTED_1, 0) ARM_OPERAND_REGISTER_2 | \ ARM_OPERAND_IMMEDIATE_3;) -#define DEFINE_IMMEDIATE_WITH_REGISTER_MEM_THUMB(NAME, MNEMONIC, REG, CYCLES, AFFECTED) \ +#define DEFINE_IMMEDIATE_WITH_REGISTER_MEM_THUMB(NAME, MNEMONIC, REG, FORMAT, AFFECTED) \ DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ info->op1.reg = (opcode >> 8) & 0x0007; \ info->memory.baseReg = REG; \ @@ -161,40 +162,42 @@ DEFINE_DECODER_WITH_HIGH_THUMB(MOV3, MOV, ARM_OPERAND_AFFECTED_1, 0) ARM_OPERAND_AFFECTED_ ## AFFECTED | \ ARM_OPERAND_MEMORY_2; \ info->memory.format = ARM_MEMORY_REGISTER_BASE | \ - ARM_MEMORY_IMMEDIATE_OFFSET; \ - CYCLES;) + ARM_MEMORY_IMMEDIATE_OFFSET | \ + ARM_MEMORY_ ## FORMAT; \ + FORMAT ## _CYCLES;) -DEFINE_IMMEDIATE_WITH_REGISTER_MEM_THUMB(LDR3, LDR, ARM_PC, LOAD_CYCLES, 1) -DEFINE_IMMEDIATE_WITH_REGISTER_MEM_THUMB(LDR4, LDR, ARM_SP, LOAD_CYCLES, 1) -DEFINE_IMMEDIATE_WITH_REGISTER_MEM_THUMB(STR3, STR, ARM_SP, STORE_CYCLES, 2) +DEFINE_IMMEDIATE_WITH_REGISTER_MEM_THUMB(LDR3, LDR, ARM_PC, LOAD, 1) +DEFINE_IMMEDIATE_WITH_REGISTER_MEM_THUMB(LDR4, LDR, ARM_SP, LOAD, 1) +DEFINE_IMMEDIATE_WITH_REGISTER_MEM_THUMB(STR3, STR, ARM_SP, STORE, 2) DEFINE_IMMEDIATE_WITH_REGISTER_DATA_THUMB(ADD5, ADD, ARM_PC) DEFINE_IMMEDIATE_WITH_REGISTER_DATA_THUMB(ADD6, ADD, ARM_SP) -#define DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(NAME, MNEMONIC, CYCLES, TYPE, AFFECTED) \ +#define DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(NAME, MNEMONIC, FORMAT, TYPE, AFFECTED) \ DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ info->memory.offset.reg = (opcode >> 6) & 0x0007; \ info->op1.reg = opcode & 0x0007; \ info->memory.baseReg = (opcode >> 3) & 0x0007; \ - info->memory.width = TYPE; \ + info->memory.width = ARM_ACCESS_ ## TYPE; \ info->operandFormat = ARM_OPERAND_REGISTER_1 | \ ARM_OPERAND_AFFECTED_ ## AFFECTED | \ ARM_OPERAND_MEMORY_2; \ info->memory.format = ARM_MEMORY_REGISTER_BASE | \ - ARM_MEMORY_REGISTER_OFFSET; \ - CYCLES;) + ARM_MEMORY_REGISTER_OFFSET | \ + ARM_MEMORY_ ## FORMAT; \ + FORMAT ## _CYCLES;) -DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDR2, LDR, LOAD_CYCLES, ARM_ACCESS_WORD, 1) -DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRB2, LDR, LOAD_CYCLES, ARM_ACCESS_BYTE, 1) -DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRH2, LDR, LOAD_CYCLES, ARM_ACCESS_HALFWORD, 1) -DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSB, LDR, LOAD_CYCLES, ARM_ACCESS_SIGNED_BYTE, 1) -DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSH, LDR, LOAD_CYCLES, ARM_ACCESS_SIGNED_HALFWORD, 1) -DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STR2, STR, STORE_CYCLES, ARM_ACCESS_WORD, 2) -DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRB2, STR, STORE_CYCLES, ARM_ACCESS_BYTE, 2) -DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRH2, STR, STORE_CYCLES, ARM_ACCESS_HALFWORD, 2) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDR2, LDR, LOAD, WORD, 1) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRB2, LDR, LOAD, BYTE, 1) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRH2, LDR, LOAD, HALFWORD, 1) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSB, LDR, LOAD, SIGNED_BYTE, 1) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(LDRSH, LDR, LOAD, SIGNED_HALFWORD, 1) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STR2, STR, STORE, WORD, 2) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRB2, STR, STORE, BYTE, 2) +DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRH2, STR, STORE, HALFWORD, 2) // TODO: Estimate memory cycles -#define DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(NAME, RN, MNEMONIC, DIRECTION, ADDITIONAL_REG) \ +#define DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(NAME, RN, MNEMONIC, DIRECTION, FORMAT, ADDITIONAL_REG) \ DEFINE_THUMB_DECODER(NAME, MNEMONIC, \ info->memory.baseReg = RN; \ info->op1.immediate = (opcode & 0xFF) | ADDITIONAL_REG; \ @@ -204,13 +207,14 @@ DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRH2, STR, STORE_CYCLES, ARM_ACCESS_HALFW info->operandFormat = ARM_OPERAND_MEMORY_1 | ARM_OPERAND_AFFECTED_1; \ info->memory.format = ARM_MEMORY_REGISTER_BASE | \ ARM_MEMORY_WRITEBACK | \ + ARM_MEMORY_ ## FORMAT | \ DIRECTION;) -#define DEFINE_LOAD_STORE_MULTIPLE_THUMB(NAME) \ - DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(NAME ## IA, (opcode >> 8) & 0x0007, NAME, ARM_MEMORY_INCREMENT_AFTER, 0) +#define DEFINE_LOAD_STORE_MULTIPLE_THUMB(NAME, FORMAT) \ + DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(NAME ## IA, (opcode >> 8) & 0x0007, NAME, ARM_MEMORY_INCREMENT_AFTER, FORMAT, 0) -DEFINE_LOAD_STORE_MULTIPLE_THUMB(LDM) -DEFINE_LOAD_STORE_MULTIPLE_THUMB(STM) +DEFINE_LOAD_STORE_MULTIPLE_THUMB(LDM, LOAD) +DEFINE_LOAD_STORE_MULTIPLE_THUMB(STM, STORE) #define DEFINE_CONDITIONAL_BRANCH_THUMB(COND) \ DEFINE_THUMB_DECODER(B ## COND, B, \ @@ -246,10 +250,10 @@ DEFINE_CONDITIONAL_BRANCH_THUMB(LE) DEFINE_SP_MODIFY_THUMB(ADD7, ADD) DEFINE_SP_MODIFY_THUMB(SUB4, SUB) -DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POP, ARM_SP, LDM, ARM_MEMORY_INCREMENT_AFTER, 0) -DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POPR, ARM_SP, LDM, ARM_MEMORY_INCREMENT_AFTER, 1 << ARM_PC) -DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSH, ARM_SP, STM, ARM_MEMORY_DECREMENT_BEFORE, 0) -DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSHR, ARM_SP, STM, ARM_MEMORY_DECREMENT_BEFORE, 1 << ARM_LR) +DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POP, ARM_SP, LDM, ARM_MEMORY_INCREMENT_AFTER, LOAD, 0) +DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POPR, ARM_SP, LDM, ARM_MEMORY_INCREMENT_AFTER, LOAD, 1 << ARM_PC) +DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSH, ARM_SP, STM, ARM_MEMORY_DECREMENT_BEFORE, STORE, 0) +DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSHR, ARM_SP, STM, ARM_MEMORY_DECREMENT_BEFORE, STORE, 1 << ARM_LR) DEFINE_THUMB_DECODER(ILL, ILL, info->operandFormat = ARM_OPERAND_NONE; From c7a147598167b237530dedd924443f3144501cbe Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 12 Oct 2020 18:08:13 -0700 Subject: [PATCH 4/4] ARM Decoder: Only print PC-relative register contents in loads (fixes #1908) --- src/arm/decoder.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/arm/decoder.c b/src/arm/decoder.c index 81bf9f483..59b3b7f1c 100644 --- a/src/arm/decoder.c +++ b/src/arm/decoder.c @@ -164,17 +164,20 @@ static int _decodeMemory(struct ARMMemoryAccess memory, struct ARMCore* cpu, con } int total = 0; bool elideClose = false; + char comment[64]; int written; + comment[0] = '\0'; if (memory.format & ARM_MEMORY_REGISTER_BASE) { if (memory.baseReg == ARM_PC && memory.format & ARM_MEMORY_IMMEDIATE_OFFSET) { uint32_t addrBase = memory.format & ARM_MEMORY_OFFSET_SUBTRACT ? -memory.offset.immediate : memory.offset.immediate; - if (!cpu) { + if (!cpu || memory.format & ARM_MEMORY_STORE) { strlcpy(buffer, "[", blen); ADVANCE(1); written = _decodePCRelative(addrBase, symbols, pc & 0xFFFFFFFC, false, buffer, blen); ADVANCE(written); } else { uint32_t value; + _decodePCRelative(addrBase, symbols, pc & 0xFFFFFFFC, false, comment, sizeof(comment)); addrBase += pc & 0xFFFFFFFC; // Thumb does not have PC-relative LDRH/LDRB switch (memory.width & 7) { case 1: @@ -247,6 +250,10 @@ static int _decodeMemory(struct ARMMemoryAccess memory, struct ARMCore* cpu, con strlcpy(buffer, "!", blen); ADVANCE(1); } + if (comment[0]) { + written = snprintf(buffer, blen, " @ %s", comment); + ADVANCE(written); + } return total; }