aboutsummaryrefslogtreecommitdiff
path: root/accel/tcg
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2024-04-02 22:10:50 -1000
committerRichard Henderson <richard.henderson@linaro.org>2024-05-15 08:55:18 +0200
commit3a247368e6fc12304e73451c63254313e2ebd60e (patch)
treed77335d1b5e9dd8247bfc631173f14d81d8a2105 /accel/tcg
parent4abc892362f8282450f18c4e45c5b0534461d01e (diff)
downloadqemu-3a247368e6fc12304e73451c63254313e2ebd60e.zip
qemu-3a247368e6fc12304e73451c63254313e2ebd60e.tar.gz
qemu-3a247368e6fc12304e73451c63254313e2ebd60e.tar.bz2
accel/tcg: Implement translator_st
Copy data out of a completed translation. This will be used for both plugins and disassembly. Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'accel/tcg')
-rw-r--r--accel/tcg/translator.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
index aa9f36a..01e1f09 100644
--- a/accel/tcg/translator.c
+++ b/accel/tcg/translator.c
@@ -354,6 +354,61 @@ static void record_save(DisasContextBase *db, vaddr pc,
memcpy(db->record + (offset - db->record_start), from, size);
}
+size_t translator_st_len(const DisasContextBase *db)
+{
+ return db->fake_insn ? db->record_len : db->tb->size;
+}
+
+bool translator_st(const DisasContextBase *db, void *dest,
+ vaddr addr, size_t len)
+{
+ size_t offset, offset_end;
+
+ if (addr < db->pc_first) {
+ return false;
+ }
+ offset = addr - db->pc_first;
+ offset_end = offset + len;
+ if (offset_end > translator_st_len(db)) {
+ return false;
+ }
+
+ if (!db->fake_insn) {
+ size_t offset_page1 = -(db->pc_first | TARGET_PAGE_MASK);
+
+ /* Get all the bytes from the first page. */
+ if (db->host_addr[0]) {
+ if (offset_end <= offset_page1) {
+ memcpy(dest, db->host_addr[0] + offset, len);
+ return true;
+ }
+ if (offset < offset_page1) {
+ size_t len0 = offset_page1 - offset;
+ memcpy(dest, db->host_addr[0] + offset, len0);
+ offset += len0;
+ dest += len0;
+ }
+ }
+
+ /* Get any bytes from the second page. */
+ if (db->host_addr[1] && offset >= offset_page1) {
+ memcpy(dest, db->host_addr[1] + (offset - offset_page1),
+ offset_end - offset);
+ return true;
+ }
+ }
+
+ /* Else get recorded bytes. */
+ if (db->record_len != 0 &&
+ offset >= db->record_start &&
+ offset_end <= db->record_start + db->record_len) {
+ memcpy(dest, db->record + (offset - db->record_start),
+ offset_end - offset);
+ return true;
+ }
+ return false;
+}
+
static void plugin_insn_append(vaddr pc, const void *from, size_t size)
{
#ifdef CONFIG_PLUGIN