diff --git a/target/e2k/cpu-dump.c b/target/e2k/cpu-dump.c new file mode 100644 index 0000000000..a6add4485b --- /dev/null +++ b/target/e2k/cpu-dump.c @@ -0,0 +1,182 @@ +/* + * e2k CPU dump to file + * + * Copyright (c) 2021 Denis Drakhnya + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "helper-tcg.h" +#include "qemu/qemu-print.h" + +static inline const char *indent(int width, int max_width) +{ + static const char s[] = " "; + + assert(width < sizeof(s) && max_width < sizeof(s)); + return s + sizeof(s) - 1 - max_width + width; +} + +static void dump_psp(FILE *f, int flags, const char *name, E2KPsp *psp, + bool newline) +{ + qemu_fprintf(f, "%s %016" PRIx64 " base %016" PRIx64 " index %08" PRIx32 + " size %08" PRIx32 " %c%c itag=%x%s", + name, + (uint64_t) psp->base + psp->index, + (uint64_t) psp->base, + (uint32_t) psp->index, + (uint32_t) psp->size, + psp->is_readable ? 'R' : ' ', + psp->is_writable ? 'W' : ' ', + (int) psp->itag, + newline ? "\n" : ""); +} + +static void dump_rwap(FILE *f, int flags, const char *name, E2KRwap *rwap, + bool newline) +{ + qemu_fprintf(f, "%s %016" PRIx64 " base %016" PRIx64 " curptr %08" PRIx32 + " size %08" PRIx32 " %c%c%c%s", + name, + (uint64_t) rwap->base + rwap->curptr, + (uint64_t) rwap->base, + (uint32_t) rwap->curptr, + (uint32_t) rwap->size, + rwap->protected ? 'P' : ' ', + rwap->read ? 'R' : ' ', + rwap->write ? 'W' : ' ', + newline ? "\n" : ""); +} + +static void dump_lsr(CPUE2KState *env, FILE *f, int flags) +{ + qemu_fprintf(f, + " lcnt %016" PRIx64 " pcnt=%02x ecnt=%02x vlc=%d ldmc=%d ldovl=%02x\n" + "ilcnt %016" PRIx64 " ipcnt=%02x iecnt=%02x over=%d semc=%d strmd=%02x\n", + env->lsr_lcnt, + (int) env->lsr_pcnt, + (int) env->lsr_ecnt, + (int) env->lsr_vlc, + (int) extract32(env->lsr, LSR_LDMC_OFF - 32, 1), + (int) extract32(env->lsr, LSR_LDOVL_OFF - 32, LSR_LDOVL_LEN), + env->ilcr_lcnt, + (int) extract32(env->ilcr, LSR_PCNT_OFF - 32, LSR_PCNT_LEN), + (int) extract32(env->ilcr, LSR_ECNT_OFF - 32, LSR_ECNT_LEN), + (int) env->lsr_over, + (int) extract32(env->lsr, LSR_SEMC_OFF - 32, 1), + (int) env->lsr_strmd + ); +} + +static void dump_predicate_regs(CPUE2KState *env, FILE *f, int flags) +{ + int i; + + qemu_fprintf(f, "pred"); + for (i = 0; i < 32; i++) { + qemu_fprintf(f, "%s%d", indent(i > 9, 2), i); + } + qemu_fprintf(f, "\n "); + for (i = 0; i < 32; i++) { + int index = i < env->bp.size ? (i + env->bp.cur) % env->bp.size : i; + int preg = (env->pregs >> (index * 2)) & 3; + qemu_fprintf(f, " %c%d", preg >> 1 ? '*' : ' ', preg & 1); + } + qemu_fprintf(f, "\n"); +} + +static inline void dump_reg(FILE *f, char mnemonic, int index, + uint8_t tag, E2KReg reg) +{ + int width = (index > 9) + (index > 99); + const char *prefix = indent(width, 3 - ((index & 3) == 0)); + uint8_t tag_lo = tag & 3; + uint8_t tag_hi = (tag >> 2) & 3; + + qemu_fprintf(f, "%s%c%d <%d%d>%016" PRIx64, prefix, mnemonic, index, + tag_hi, tag_lo, reg.lo); + if ((index & 3) == 3) { + qemu_fprintf(f, "\n"); + } +} + +static void dump_regs(CPUE2KState *env, FILE *f, int flags) +{ + int i; + + for (i = 0; i < env->wd.size; i++) { + dump_reg(f, 'r', i, env->tags[i], env->regs[i]); + } + if (env->wd.size & 3) { + qemu_fprintf(f, "\n"); + } + + if ((env->wd.size - env->bn.base) >= env->bn.size) { + for (i = 0; i < env->bn.size; i++) { + int index = env->bn.base + (i + env->bn.cur) % env->bn.size; + dump_reg(f, 'b', i, env->tags[index], env->regs[index]); + } + if (env->bn.size & 3) { + qemu_fprintf(f, "\n"); + } + } + + for (i = 0; i < 32; i++) { + int index = E2K_NR_COUNT + i; + dump_reg(f, 'g', i, env->tags[index], env->regs[index]); + } +} + +void e2k_cpu_dump_state(CPUState *cs, FILE *f, int flags) +{ + E2KCPU *cpu = E2K_CPU(cs); + CPUE2KState *env = &cpu->env; + + + qemu_fprintf(f, + " ip %016" PRIx64 " ctpr1 %016" PRIx64 " ctpr2 %016" PRIx64 " ctpr3 %016" PRIx64 "\n" + " sbr %016" PRIx64 " osr0 %016" PRIx64 " psr=%02x upsr=%04x\n", + (uint64_t) env->ip, + env->ctprs[0].raw, + env->ctprs[1].raw, + env->ctprs[2].raw, + env->sbr, + env->osr0, + (int) env->psr, + (int) env->upsr + ); + dump_rwap(f, flags, " usd", &env->usd, true); + dump_psp(f, flags, " pcsp", &env->pcsp, true); + dump_psp(f, flags, " psp", &env->psp, true); + dump_rwap(f, flags, "oscud", &env->oscud, true); + dump_rwap(f, flags, " osgd", &env->osgd, true); + dump_rwap(f, flags, " cud", &env->cud, true); + dump_rwap(f, flags, " gd", &env->gd, true); + dump_lsr(env, f, flags); + qemu_fprintf(f, " wsz=%d wbdl=%d rbs=%d rsz=%d rcur=%d psz=%d pcur=%d\n", + (int) env->wd.size, + (int) env->wdbl, + (int) env->bn.base, + (int) env->bn.size, + (int) env->bn.cur, + (int) env->bp.size, + (int) env->bp.cur + ); + dump_predicate_regs(env, f, flags); + dump_regs(env, f, flags); +} + diff --git a/target/e2k/cpu.c b/target/e2k/cpu.c index 9886d095bf..b60b553726 100644 --- a/target/e2k/cpu.c +++ b/target/e2k/cpu.c @@ -31,8 +31,6 @@ //#define DEBUG_FEATURES -void e2k_cpu_dump_state(CPUState *cs, FILE *f, int flags); - static void e2k_cpu_reset(DeviceState *dev) { CPUState *cs = CPU(dev); @@ -135,51 +133,6 @@ static const struct e2k_def_t e2k_defs[] = { }, }; -static inline void cpu_dump_state_br(CPUE2KState *env, FILE *f, int flags) -{ - uint32_t br = env_br_get(env); - E2KBnState *bn = &env->bn; - E2KBpState *bp = &env->bp; - - qemu_fprintf(f, "br 0x%x\n", br); - qemu_fprintf(f, " rbs %d\n", bn->base / 2); - qemu_fprintf(f, " rsz %d\n", bn->size / 2 - 1); - qemu_fprintf(f, " rcur %d\n", bn->cur / 2); - qemu_fprintf(f, " psz %d\n", bp->size); - qemu_fprintf(f, " pcur %d\n", bp->cur); -} - -void e2k_cpu_dump_state(CPUState *cs, FILE *f, int flags) -{ - E2KCPU *cpu = E2K_CPU(cs); - CPUE2KState *env = &cpu->env; - unsigned int i; - - qemu_fprintf(f, " ip = " TARGET_FMT_lx "\n", env->ip); - qemu_fprintf(f, " pregs = 0x%016lx\n", env->pregs); - qemu_fprintf(f, " pcsp_lo = 0x%016lx\n", env->pcsp.lo); - qemu_fprintf(f, " pcsp_hi = 0x%016lx\n", env->pcsp.hi); - qemu_fprintf(f, " psp_lo = 0x%016lx\n", env->psp.lo); - qemu_fprintf(f, " psp_hi = 0x%016lx\n", env->psp.hi); - qemu_fprintf(f, " usd_lo = 0x%016lx\n", env->usd.lo); - qemu_fprintf(f, " usd_hi = 0x%016lx\n", env->usd.hi); - qemu_fprintf(f, " lsr = 0x%016lx\n", env->lsr); - cpu_dump_state_br(env, f, flags); - - for (i = 0; i < E2K_REG_COUNT; i++) { - char name = i < E2K_NR_COUNT ? 'r' : 'g'; - int tag = env->tags[i]; - qemu_fprintf(f, "%%%c%d\t<%d%d> 0x%lx\n", name, i, tag >> 2, tag & 3, - env->regs[i].lo); - } - - for (i = 0; i < 32; i++) { - int preg = (env->pregs >> (i * 2)) & 3; - qemu_fprintf(f, "pred%d\t<%d> %s\n", i, preg >> 1, - preg & 1 ? "true" : "false"); - } -} - static void e2k_cpu_set_pc(CPUState *cs, vaddr value) { E2KCPU *cpu = E2K_CPU(cs); diff --git a/target/e2k/cpu.h b/target/e2k/cpu.h index dc6164b567..d5ab23a24b 100644 --- a/target/e2k/cpu.h +++ b/target/e2k/cpu.h @@ -942,6 +942,7 @@ static inline int cpu_mmu_index(CPUE2KState *env, bool ifetch) #endif } +void e2k_cpu_dump_state(CPUState *cs, FILE *f, int flags); void e2k_cpu_do_interrupt(CPUState *cs); void e2k_cpu_list(void); int e2k_cpu_signal_handler(int host_signum, void *pinfo, void *puc); diff --git a/target/e2k/meson.build b/target/e2k/meson.build index 94d89dd5eb..2a49b03c94 100644 --- a/target/e2k/meson.build +++ b/target/e2k/meson.build @@ -1,6 +1,7 @@ e2k_ss = ss.source_set() e2k_ss.add(files( 'cpu.c', + 'cpu-dump.c', 'gdbstub.c', 'helper.c', 'helper_aau.c',