aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2022-10-05 10:17:02 -0400
committerStefan Hajnoczi <stefanha@redhat.com>2022-10-05 10:17:02 -0400
commit4a9c04672a875ed00ea807ea4d552c01f6440bc7 (patch)
tree5ae0c7c85d114c608cf6018b8dc50f4feaaa83b8 /target
parentfafd35a6dab8e70a7c395aaa8e1273267cf9f3c8 (diff)
parentab419fd8a035a65942de4e63effcd55ccbf1a9fe (diff)
downloadqemu-4a9c04672a875ed00ea807ea4d552c01f6440bc7.zip
qemu-4a9c04672a875ed00ea807ea4d552c01f6440bc7.tar.gz
qemu-4a9c04672a875ed00ea807ea4d552c01f6440bc7.tar.bz2
Merge tag 'pull-tcg-20221004' of https://gitlab.com/rth7680/qemu into staging
Cache CPUClass for use in hot code paths. Add CPUTLBEntryFull, probe_access_full, tlb_set_page_full. Add generic support for TARGET_TB_PCREL. tcg/ppc: Optimize 26-bit jumps using STQ for POWER 2.07 target/sh4: Fix TB_FLAG_UNALIGN # -----BEGIN PGP SIGNATURE----- # # iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmM8jXEdHHJpY2hhcmQu # aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV/oEggArAHK8FtydfQ4ZwnF # SjXfpdP50OC0SZn3uBN93FZOrxz9UYG9t1oDHs39J/+b/u2nwJYch//EH2k+NtOW # hc3iIgS9bWgs/UWZESkViKQccw7gpYlc21Br38WWwFNEFyecX0p+e9pJgld5rSv1 # mRGvCs5J2svH2tcXl/Sb/JWgcumOJoG7qy2aLyJGolR6UOfwcfFMzQXzq8qjpRKH # Jh84qusE/rLbzBsdN6snJY4+dyvUo03lT5IJ4d+FQg2tUip+Qqt7pnMbsqq6qF6H # R6fWU1JTbsh7GxXJwQJ83jLBnUsi8cy6FKrZ3jyiBq76+DIpR0PqoEe+PN/weInU # TN0z4g== # =RfXJ # -----END PGP SIGNATURE----- # gpg: Signature made Tue 04 Oct 2022 15:45:53 EDT # gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F # gpg: issuer "richard.henderson@linaro.org" # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [full] # Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A 05C0 64DF 38E8 AF7E 215F * tag 'pull-tcg-20221004' of https://gitlab.com/rth7680/qemu: target/sh4: Fix TB_FLAG_UNALIGN tcg/ppc: Optimize 26-bit jumps accel/tcg: Introduce TARGET_TB_PCREL accel/tcg: Introduce tb_pc and log_pc hw/core: Add CPUClass.get_pc include/hw/core: Create struct CPUJumpCache accel/tcg: Inline tb_flush_jmp_cache accel/tcg: Do not align tb->page_addr[0] accel/tcg: Use DisasContextBase in plugin_gen_tb_start accel/tcg: Use bool for page_find_alloc accel/tcg: Remove PageDesc code_bitmap include/exec: Introduce TARGET_PAGE_ENTRY_EXTRA accel/tcg: Introduce tlb_set_page_full accel/tcg: Introduce probe_access_full accel/tcg: Suppress auto-invalidate in probe_access_internal accel/tcg: Drop addr member from SavedIOTLB accel/tcg: Rename CPUIOTLBEntry to CPUTLBEntryFull cputlb: used cached CPUClass in our hot-paths hw/core/cpu-sysemu: used cached class in cpu_asidx_from_attrs cpu: cache CPUClass in CPUState for hot code paths Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'target')
-rw-r--r--target/alpha/cpu.c9
-rw-r--r--target/arm/cpu.c17
-rw-r--r--target/arm/mte_helper.c14
-rw-r--r--target/arm/sve_helper.c4
-rw-r--r--target/arm/translate-a64.c2
-rw-r--r--target/avr/cpu.c10
-rw-r--r--target/cris/cpu.c8
-rw-r--r--target/hexagon/cpu.c10
-rw-r--r--target/hppa/cpu.c12
-rw-r--r--target/i386/cpu.c9
-rw-r--r--target/i386/tcg/tcg-cpu.c2
-rw-r--r--target/loongarch/cpu.c11
-rw-r--r--target/m68k/cpu.c8
-rw-r--r--target/microblaze/cpu.c10
-rw-r--r--target/mips/cpu.c8
-rw-r--r--target/mips/tcg/exception.c2
-rw-r--r--target/mips/tcg/sysemu/special_helper.c2
-rw-r--r--target/nios2/cpu.c9
-rw-r--r--target/openrisc/cpu.c10
-rw-r--r--target/ppc/cpu_init.c8
-rw-r--r--target/riscv/cpu.c17
-rw-r--r--target/rx/cpu.c10
-rw-r--r--target/s390x/cpu.c8
-rw-r--r--target/s390x/tcg/mem_helper.c4
-rw-r--r--target/sh4/cpu.c18
-rw-r--r--target/sh4/cpu.h58
-rw-r--r--target/sh4/helper.c6
-rw-r--r--target/sh4/translate.c90
-rw-r--r--target/sparc/cpu.c10
-rw-r--r--target/tricore/cpu.c11
-rw-r--r--target/xtensa/cpu.c8
31 files changed, 298 insertions, 107 deletions
diff --git a/target/alpha/cpu.c b/target/alpha/cpu.c
index a8990d4..979a629 100644
--- a/target/alpha/cpu.c
+++ b/target/alpha/cpu.c
@@ -33,6 +33,14 @@ static void alpha_cpu_set_pc(CPUState *cs, vaddr value)
cpu->env.pc = value;
}
+static vaddr alpha_cpu_get_pc(CPUState *cs)
+{
+ AlphaCPU *cpu = ALPHA_CPU(cs);
+
+ return cpu->env.pc;
+}
+
+
static bool alpha_cpu_has_work(CPUState *cs)
{
/* Here we are checking to see if the CPU should wake up from HALT.
@@ -244,6 +252,7 @@ static void alpha_cpu_class_init(ObjectClass *oc, void *data)
cc->has_work = alpha_cpu_has_work;
cc->dump_state = alpha_cpu_dump_state;
cc->set_pc = alpha_cpu_set_pc;
+ cc->get_pc = alpha_cpu_get_pc;
cc->gdb_read_register = alpha_cpu_gdb_read_register;
cc->gdb_write_register = alpha_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 7ec3281..94ca6f1 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -60,6 +60,18 @@ static void arm_cpu_set_pc(CPUState *cs, vaddr value)
}
}
+static vaddr arm_cpu_get_pc(CPUState *cs)
+{
+ ARMCPU *cpu = ARM_CPU(cs);
+ CPUARMState *env = &cpu->env;
+
+ if (is_a64(env)) {
+ return env->pc;
+ } else {
+ return env->regs[15];
+ }
+}
+
#ifdef CONFIG_TCG
void arm_cpu_synchronize_from_tb(CPUState *cs,
const TranslationBlock *tb)
@@ -72,9 +84,9 @@ void arm_cpu_synchronize_from_tb(CPUState *cs,
* never possible for an AArch64 TB to chain to an AArch32 TB.
*/
if (is_a64(env)) {
- env->pc = tb->pc;
+ env->pc = tb_pc(tb);
} else {
- env->regs[15] = tb->pc;
+ env->regs[15] = tb_pc(tb);
}
}
#endif /* CONFIG_TCG */
@@ -2172,6 +2184,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
cc->has_work = arm_cpu_has_work;
cc->dump_state = arm_cpu_dump_state;
cc->set_pc = arm_cpu_set_pc;
+ cc->get_pc = arm_cpu_get_pc;
cc->gdb_read_register = arm_cpu_gdb_read_register;
cc->gdb_write_register = arm_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
index d11a8c7..fdd23ab 100644
--- a/target/arm/mte_helper.c
+++ b/target/arm/mte_helper.c
@@ -106,7 +106,7 @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
return tags + index;
#else
uintptr_t index;
- CPUIOTLBEntry *iotlbentry;
+ CPUTLBEntryFull *full;
int in_page, flags;
ram_addr_t ptr_ra;
hwaddr ptr_paddr, tag_paddr, xlat;
@@ -129,7 +129,7 @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
assert(!(flags & TLB_INVALID_MASK));
/*
- * Find the iotlbentry for ptr. This *must* be present in the TLB
+ * Find the CPUTLBEntryFull for ptr. This *must* be present in the TLB
* because we just found the mapping.
* TODO: Perhaps there should be a cputlb helper that returns a
* matching tlb entry + iotlb entry.
@@ -144,10 +144,10 @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
g_assert(tlb_hit(comparator, ptr));
}
# endif
- iotlbentry = &env_tlb(env)->d[ptr_mmu_idx].iotlb[index];
+ full = &env_tlb(env)->d[ptr_mmu_idx].fulltlb[index];
/* If the virtual page MemAttr != Tagged, access unchecked. */
- if (!arm_tlb_mte_tagged(&iotlbentry->attrs)) {
+ if (!arm_tlb_mte_tagged(&full->attrs)) {
return NULL;
}
@@ -181,7 +181,7 @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
int wp = ptr_access == MMU_DATA_LOAD ? BP_MEM_READ : BP_MEM_WRITE;
assert(ra != 0);
cpu_check_watchpoint(env_cpu(env), ptr, ptr_size,
- iotlbentry->attrs, wp, ra);
+ full->attrs, wp, ra);
}
/*
@@ -202,11 +202,11 @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
tag_paddr = ptr_paddr >> (LOG2_TAG_GRANULE + 1);
/* Look up the address in tag space. */
- tag_asi = iotlbentry->attrs.secure ? ARMASIdx_TagS : ARMASIdx_TagNS;
+ tag_asi = full->attrs.secure ? ARMASIdx_TagS : ARMASIdx_TagNS;
tag_as = cpu_get_address_space(env_cpu(env), tag_asi);
mr = address_space_translate(tag_as, tag_paddr, &xlat, NULL,
tag_access == MMU_DATA_STORE,
- iotlbentry->attrs);
+ full->attrs);
/*
* Note that @mr will never be NULL. If there is nothing in the address
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
index d6f7ef9..9cae8fd 100644
--- a/target/arm/sve_helper.c
+++ b/target/arm/sve_helper.c
@@ -5384,8 +5384,8 @@ bool sve_probe_page(SVEHostPage *info, bool nofault, CPUARMState *env,
g_assert(tlb_hit(comparator, addr));
# endif
- CPUIOTLBEntry *iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index];
- info->attrs = iotlbentry->attrs;
+ CPUTLBEntryFull *full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
+ info->attrs = full->attrs;
}
#endif
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 9bed336..78b2d91 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -14624,7 +14624,7 @@ static bool is_guarded_page(CPUARMState *env, DisasContext *s)
* table entry even for that case.
*/
return (tlb_hit(entry->addr_code, addr) &&
- arm_tlb_bti_gp(&env_tlb(env)->d[mmu_idx].iotlb[index].attrs));
+ arm_tlb_bti_gp(&env_tlb(env)->d[mmu_idx].fulltlb[index].attrs));
#endif
}
diff --git a/target/avr/cpu.c b/target/avr/cpu.c
index 05b992f..0d28611 100644
--- a/target/avr/cpu.c
+++ b/target/avr/cpu.c
@@ -32,6 +32,13 @@ static void avr_cpu_set_pc(CPUState *cs, vaddr value)
cpu->env.pc_w = value / 2; /* internally PC points to words */
}
+static vaddr avr_cpu_get_pc(CPUState *cs)
+{
+ AVRCPU *cpu = AVR_CPU(cs);
+
+ return cpu->env.pc_w * 2;
+}
+
static bool avr_cpu_has_work(CPUState *cs)
{
AVRCPU *cpu = AVR_CPU(cs);
@@ -47,7 +54,7 @@ static void avr_cpu_synchronize_from_tb(CPUState *cs,
AVRCPU *cpu = AVR_CPU(cs);
CPUAVRState *env = &cpu->env;
- env->pc_w = tb->pc / 2; /* internally PC points to words */
+ env->pc_w = tb_pc(tb) / 2; /* internally PC points to words */
}
static void avr_cpu_reset(DeviceState *ds)
@@ -214,6 +221,7 @@ static void avr_cpu_class_init(ObjectClass *oc, void *data)
cc->has_work = avr_cpu_has_work;
cc->dump_state = avr_cpu_dump_state;
cc->set_pc = avr_cpu_set_pc;
+ cc->get_pc = avr_cpu_get_pc;
dc->vmsd = &vms_avr_cpu;
cc->sysemu_ops = &avr_sysemu_ops;
cc->disas_set_info = avr_cpu_disas_set_info;
diff --git a/target/cris/cpu.c b/target/cris/cpu.c
index ed6c781..22f5c70 100644
--- a/target/cris/cpu.c
+++ b/target/cris/cpu.c
@@ -35,6 +35,13 @@ static void cris_cpu_set_pc(CPUState *cs, vaddr value)
cpu->env.pc = value;
}
+static vaddr cris_cpu_get_pc(CPUState *cs)
+{
+ CRISCPU *cpu = CRIS_CPU(cs);
+
+ return cpu->env.pc;
+}
+
static bool cris_cpu_has_work(CPUState *cs)
{
return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
@@ -297,6 +304,7 @@ static void cris_cpu_class_init(ObjectClass *oc, void *data)
cc->has_work = cris_cpu_has_work;
cc->dump_state = cris_cpu_dump_state;
cc->set_pc = cris_cpu_set_pc;
+ cc->get_pc = cris_cpu_get_pc;
cc->gdb_read_register = cris_cpu_gdb_read_register;
cc->gdb_write_register = cris_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index fa9bd70..fa6d722 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -251,12 +251,19 @@ static void hexagon_cpu_set_pc(CPUState *cs, vaddr value)
env->gpr[HEX_REG_PC] = value;
}
+static vaddr hexagon_cpu_get_pc(CPUState *cs)
+{
+ HexagonCPU *cpu = HEXAGON_CPU(cs);
+ CPUHexagonState *env = &cpu->env;
+ return env->gpr[HEX_REG_PC];
+}
+
static void hexagon_cpu_synchronize_from_tb(CPUState *cs,
const TranslationBlock *tb)
{
HexagonCPU *cpu = HEXAGON_CPU(cs);
CPUHexagonState *env = &cpu->env;
- env->gpr[HEX_REG_PC] = tb->pc;
+ env->gpr[HEX_REG_PC] = tb_pc(tb);
}
static bool hexagon_cpu_has_work(CPUState *cs)
@@ -337,6 +344,7 @@ static void hexagon_cpu_class_init(ObjectClass *c, void *data)
cc->has_work = hexagon_cpu_has_work;
cc->dump_state = hexagon_dump_state;
cc->set_pc = hexagon_cpu_set_pc;
+ cc->get_pc = hexagon_cpu_get_pc;
cc->gdb_read_register = hexagon_gdb_read_register;
cc->gdb_write_register = hexagon_gdb_write_register;
cc->gdb_num_core_regs = TOTAL_PER_THREAD_REGS + NUM_VREGS + NUM_QREGS;
diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
index a6f52ca..e677ca0 100644
--- a/target/hppa/cpu.c
+++ b/target/hppa/cpu.c
@@ -36,13 +36,20 @@ static void hppa_cpu_set_pc(CPUState *cs, vaddr value)
cpu->env.iaoq_b = value + 4;
}
+static vaddr hppa_cpu_get_pc(CPUState *cs)
+{
+ HPPACPU *cpu = HPPA_CPU(cs);
+
+ return cpu->env.iaoq_f;
+}
+
static void hppa_cpu_synchronize_from_tb(CPUState *cs,
const TranslationBlock *tb)
{
HPPACPU *cpu = HPPA_CPU(cs);
#ifdef CONFIG_USER_ONLY
- cpu->env.iaoq_f = tb->pc;
+ cpu->env.iaoq_f = tb_pc(tb);
cpu->env.iaoq_b = tb->cs_base;
#else
/* Recover the IAOQ values from the GVA + PRIV. */
@@ -52,7 +59,7 @@ static void hppa_cpu_synchronize_from_tb(CPUState *cs,
int32_t diff = cs_base;
cpu->env.iasq_f = iasq_f;
- cpu->env.iaoq_f = (tb->pc & ~iasq_f) + priv;
+ cpu->env.iaoq_f = (tb_pc(tb) & ~iasq_f) + priv;
if (diff) {
cpu->env.iaoq_b = cpu->env.iaoq_f + diff;
}
@@ -168,6 +175,7 @@ static void hppa_cpu_class_init(ObjectClass *oc, void *data)
cc->has_work = hppa_cpu_has_work;
cc->dump_state = hppa_cpu_dump_state;
cc->set_pc = hppa_cpu_set_pc;
+ cc->get_pc = hppa_cpu_get_pc;
cc->gdb_read_register = hppa_cpu_gdb_read_register;
cc->gdb_write_register = hppa_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 1db1278..ad623d9 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -6824,6 +6824,14 @@ static void x86_cpu_set_pc(CPUState *cs, vaddr value)
cpu->env.eip = value;
}
+static vaddr x86_cpu_get_pc(CPUState *cs)
+{
+ X86CPU *cpu = X86_CPU(cs);
+
+ /* Match cpu_get_tb_cpu_state. */
+ return cpu->env.eip + cpu->env.segs[R_CS].base;
+}
+
int x86_cpu_pending_interrupt(CPUState *cs, int interrupt_request)
{
X86CPU *cpu = X86_CPU(cs);
@@ -7106,6 +7114,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
cc->has_work = x86_cpu_has_work;
cc->dump_state = x86_cpu_dump_state;
cc->set_pc = x86_cpu_set_pc;
+ cc->get_pc = x86_cpu_get_pc;
cc->gdb_read_register = x86_cpu_gdb_read_register;
cc->gdb_write_register = x86_cpu_gdb_write_register;
cc->get_arch_id = x86_cpu_get_arch_id;
diff --git a/target/i386/tcg/tcg-cpu.c b/target/i386/tcg/tcg-cpu.c
index d3c2b8f..6cf14c8 100644
--- a/target/i386/tcg/tcg-cpu.c
+++ b/target/i386/tcg/tcg-cpu.c
@@ -51,7 +51,7 @@ static void x86_cpu_synchronize_from_tb(CPUState *cs,
{
X86CPU *cpu = X86_CPU(cs);
- cpu->env.eip = tb->pc - tb->cs_base;
+ cpu->env.eip = tb_pc(tb) - tb->cs_base;
}
#ifndef CONFIG_USER_ONLY
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 941e277..1722ed2 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -82,6 +82,14 @@ static void loongarch_cpu_set_pc(CPUState *cs, vaddr value)
env->pc = value;
}
+static vaddr loongarch_cpu_get_pc(CPUState *cs)
+{
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+ CPULoongArchState *env = &cpu->env;
+
+ return env->pc;
+}
+
#ifndef CONFIG_USER_ONLY
#include "hw/loongarch/virt.h"
@@ -309,7 +317,7 @@ static void loongarch_cpu_synchronize_from_tb(CPUState *cs,
LoongArchCPU *cpu = LOONGARCH_CPU(cs);
CPULoongArchState *env = &cpu->env;
- env->pc = tb->pc;
+ env->pc = tb_pc(tb);
}
#endif /* CONFIG_TCG */
@@ -680,6 +688,7 @@ static void loongarch_cpu_class_init(ObjectClass *c, void *data)
cc->has_work = loongarch_cpu_has_work;
cc->dump_state = loongarch_cpu_dump_state;
cc->set_pc = loongarch_cpu_set_pc;
+ cc->get_pc = loongarch_cpu_get_pc;
#ifndef CONFIG_USER_ONLY
dc->vmsd = &vmstate_loongarch_cpu;
cc->sysemu_ops = &loongarch_sysemu_ops;
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
index 25d610d..1e902e1 100644
--- a/target/m68k/cpu.c
+++ b/target/m68k/cpu.c
@@ -31,6 +31,13 @@ static void m68k_cpu_set_pc(CPUState *cs, vaddr value)
cpu->env.pc = value;
}
+static vaddr m68k_cpu_get_pc(CPUState *cs)
+{
+ M68kCPU *cpu = M68K_CPU(cs);
+
+ return cpu->env.pc;
+}
+
static bool m68k_cpu_has_work(CPUState *cs)
{
return cs->interrupt_request & CPU_INTERRUPT_HARD;
@@ -540,6 +547,7 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data)
cc->has_work = m68k_cpu_has_work;
cc->dump_state = m68k_cpu_dump_state;
cc->set_pc = m68k_cpu_set_pc;
+ cc->get_pc = m68k_cpu_get_pc;
cc->gdb_read_register = m68k_cpu_gdb_read_register;
cc->gdb_write_register = m68k_cpu_gdb_write_register;
#if defined(CONFIG_SOFTMMU)
diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c
index aed200d..c10b8ac 100644
--- a/target/microblaze/cpu.c
+++ b/target/microblaze/cpu.c
@@ -84,12 +84,19 @@ static void mb_cpu_set_pc(CPUState *cs, vaddr value)
cpu->env.iflags = 0;
}
+static vaddr mb_cpu_get_pc(CPUState *cs)
+{
+ MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
+
+ return cpu->env.pc;
+}
+
static void mb_cpu_synchronize_from_tb(CPUState *cs,
const TranslationBlock *tb)
{
MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
- cpu->env.pc = tb->pc;
+ cpu->env.pc = tb_pc(tb);
cpu->env.iflags = tb->flags & IFLAGS_TB_MASK;
}
@@ -391,6 +398,7 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data)
cc->dump_state = mb_cpu_dump_state;
cc->set_pc = mb_cpu_set_pc;
+ cc->get_pc = mb_cpu_get_pc;
cc->gdb_read_register = mb_cpu_gdb_read_register;
cc->gdb_write_register = mb_cpu_gdb_write_register;
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index c15c955..da58eb8 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -128,6 +128,13 @@ static void mips_cpu_set_pc(CPUState *cs, vaddr value)
mips_env_set_pc(&cpu->env, value);
}
+static vaddr mips_cpu_get_pc(CPUState *cs)
+{
+ MIPSCPU *cpu = MIPS_CPU(cs);
+
+ return cpu->env.active_tc.PC;
+}
+
static bool mips_cpu_has_work(CPUState *cs)
{
MIPSCPU *cpu = MIPS_CPU(cs);
@@ -557,6 +564,7 @@ static void mips_cpu_class_init(ObjectClass *c, void *data)
cc->has_work = mips_cpu_has_work;
cc->dump_state = mips_cpu_dump_state;
cc->set_pc = mips_cpu_set_pc;
+ cc->get_pc = mips_cpu_get_pc;
cc->gdb_read_register = mips_cpu_gdb_read_register;
cc->gdb_write_register = mips_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
diff --git a/target/mips/tcg/exception.c b/target/mips/tcg/exception.c
index 2bd77a6..96e6117 100644
--- a/target/mips/tcg/exception.c
+++ b/target/mips/tcg/exception.c
@@ -82,7 +82,7 @@ void mips_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb)
MIPSCPU *cpu = MIPS_CPU(cs);
CPUMIPSState *env = &cpu->env;
- env->active_tc.PC = tb->pc;
+ env->active_tc.PC = tb_pc(tb);
env->hflags &= ~MIPS_HFLAG_BMASK;
env->hflags |= tb->flags & MIPS_HFLAG_BMASK;
}
diff --git a/target/mips/tcg/sysemu/special_helper.c b/target/mips/tcg/sysemu/special_helper.c
index f4f8fe8..3c5f35c 100644
--- a/target/mips/tcg/sysemu/special_helper.c
+++ b/target/mips/tcg/sysemu/special_helper.c
@@ -94,7 +94,7 @@ bool mips_io_recompile_replay_branch(CPUState *cs, const TranslationBlock *tb)
CPUMIPSState *env = &cpu->env;
if ((env->hflags & MIPS_HFLAG_BMASK) != 0
- && env->active_tc.PC != tb->pc) {
+ && env->active_tc.PC != tb_pc(tb)) {
env->active_tc.PC -= (env->hflags & MIPS_HFLAG_B16 ? 2 : 4);
env->hflags &= ~MIPS_HFLAG_BMASK;
return true;
diff --git a/target/nios2/cpu.c b/target/nios2/cpu.c
index 19b2409..2b28429 100644
--- a/target/nios2/cpu.c
+++ b/target/nios2/cpu.c
@@ -34,6 +34,14 @@ static void nios2_cpu_set_pc(CPUState *cs, vaddr value)
env->pc = value;
}
+static vaddr nios2_cpu_get_pc(CPUState *cs)
+{
+ Nios2CPU *cpu = NIOS2_CPU(cs);
+ CPUNios2State *env = &cpu->env;
+
+ return env->pc;
+}
+
static bool nios2_cpu_has_work(CPUState *cs)
{
return cs->interrupt_request & CPU_INTERRUPT_HARD;
@@ -362,6 +370,7 @@ static void nios2_cpu_class_init(ObjectClass *oc, void *data)
cc->has_work = nios2_cpu_has_work;
cc->dump_state = nios2_cpu_dump_state;
cc->set_pc = nios2_cpu_set_pc;
+ cc->get_pc = nios2_cpu_get_pc;
cc->disas_set_info = nios2_cpu_disas_set_info;
#ifndef CONFIG_USER_ONLY
cc->sysemu_ops = &nios2_sysemu_ops;
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
index cb9f35f..f6fd437 100644
--- a/target/openrisc/cpu.c
+++ b/target/openrisc/cpu.c
@@ -31,12 +31,19 @@ static void openrisc_cpu_set_pc(CPUState *cs, vaddr value)
cpu->env.dflag = 0;
}
+static vaddr openrisc_cpu_get_pc(CPUState *cs)
+{
+ OpenRISCCPU *cpu = OPENRISC_CPU(cs);
+
+ return cpu->env.pc;
+}
+
static void openrisc_cpu_synchronize_from_tb(CPUState *cs,
const TranslationBlock *tb)
{
OpenRISCCPU *cpu = OPENRISC_CPU(cs);
- cpu->env.pc = tb->pc;
+ cpu->env.pc = tb_pc(tb);
}
@@ -218,6 +225,7 @@ static void openrisc_cpu_class_init(ObjectClass *oc, void *data)
cc->has_work = openrisc_cpu_has_work;
cc->dump_state = openrisc_cpu_dump_state;
cc->set_pc = openrisc_cpu_set_pc;
+ cc->get_pc = openrisc_cpu_get_pc;
cc->gdb_read_register = openrisc_cpu_gdb_read_register;
cc->gdb_write_register = openrisc_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 6e080eb..763a843 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -7214,6 +7214,13 @@ static void ppc_cpu_set_pc(CPUState *cs, vaddr value)
cpu->env.nip = value;
}
+static vaddr ppc_cpu_get_pc(CPUState *cs)
+{
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+
+ return cpu->env.nip;
+}
+
static bool ppc_cpu_has_work(CPUState *cs)
{
PowerPCCPU *cpu = POWERPC_CPU(cs);
@@ -7472,6 +7479,7 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
cc->has_work = ppc_cpu_has_work;
cc->dump_state = ppc_cpu_dump_state;
cc->set_pc = ppc_cpu_set_pc;
+ cc->get_pc = ppc_cpu_get_pc;
cc->gdb_read_register = ppc_cpu_gdb_read_register;
cc->gdb_write_register = ppc_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index b29c88b..e6d9c70 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -462,6 +462,18 @@ static void riscv_cpu_set_pc(CPUState *cs, vaddr value)
}
}
+static vaddr riscv_cpu_get_pc(CPUState *cs)
+{
+ RISCVCPU *cpu = RISCV_CPU(cs);
+ CPURISCVState *env = &cpu->env;
+
+ /* Match cpu_get_tb_cpu_state. */
+ if (env->xl == MXL_RV32) {
+ return env->pc & UINT32_MAX;
+ }
+ return env->pc;
+}
+
static void riscv_cpu_synchronize_from_tb(CPUState *cs,
const TranslationBlock *tb)
{
@@ -470,9 +482,9 @@ static void riscv_cpu_synchronize_from_tb(CPUState *cs,
RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
if (xl == MXL_RV32) {
- env->pc = (int32_t)tb->pc;
+ env->pc = (int32_t)tb_pc(tb);
} else {
- env->pc = tb->pc;
+ env->pc = tb_pc(tb);
}
}
@@ -1154,6 +1166,7 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data)
cc->has_work = riscv_cpu_has_work;
cc->dump_state = riscv_cpu_dump_state;
cc->set_pc = riscv_cpu_set_pc;
+ cc->get_pc = riscv_cpu_get_pc;
cc->gdb_read_register = riscv_cpu_gdb_read_register;
cc->gdb_write_register = riscv_cpu_gdb_write_register;
cc->gdb_num_core_regs = 33;
diff --git a/target/rx/cpu.c b/target/rx/cpu.c
index fb30080..2f28099 100644
--- a/target/rx/cpu.c
+++ b/target/rx/cpu.c
@@ -32,12 +32,19 @@ static void rx_cpu_set_pc(CPUState *cs, vaddr value)
cpu->env.pc = value;
}
+static vaddr rx_cpu_get_pc(CPUState *cs)
+{
+ RXCPU *cpu = RX_CPU(cs);
+
+ return cpu->env.pc;
+}
+
static void rx_cpu_synchronize_from_tb(CPUState *cs,
const TranslationBlock *tb)
{
RXCPU *cpu = RX_CPU(cs);
- cpu->env.pc = tb->pc;
+ cpu->env.pc = tb_pc(tb);
}
static bool rx_cpu_has_work(CPUState *cs)
@@ -208,6 +215,7 @@ static void rx_cpu_class_init(ObjectClass *klass, void *data)
cc->has_work = rx_cpu_has_work;
cc->dump_state = rx_cpu_dump_state;
cc->set_pc = rx_cpu_set_pc;
+ cc->get_pc = rx_cpu_get_pc;
#ifndef CONFIG_USER_ONLY
cc->sysemu_ops = &rx_sysemu_ops;
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
index c31bb23..df00040 100644
--- a/target/s390x/cpu.c
+++ b/target/s390x/cpu.c
@@ -88,6 +88,13 @@ static void s390_cpu_set_pc(CPUState *cs, vaddr value)
cpu->env.psw.addr = value;
}
+static vaddr s390_cpu_get_pc(CPUState *cs)
+{
+ S390CPU *cpu = S390_CPU(cs);
+
+ return cpu->env.psw.addr;
+}
+
static bool s390_cpu_has_work(CPUState *cs)
{
S390CPU *cpu = S390_CPU(cs);
@@ -297,6 +304,7 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
cc->has_work = s390_cpu_has_work;
cc->dump_state = s390_cpu_dump_state;
cc->set_pc = s390_cpu_set_pc;
+ cc->get_pc = s390_cpu_get_pc;
cc->gdb_read_register = s390_cpu_gdb_read_register;
cc->gdb_write_register = s390_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c
index fc52aa1..3758b9e 100644
--- a/target/s390x/tcg/mem_helper.c
+++ b/target/s390x/tcg/mem_helper.c
@@ -148,10 +148,6 @@ static int s390_probe_access(CPUArchState *env, target_ulong addr, int size,
#else
int flags;
- /*
- * For !CONFIG_USER_ONLY, we cannot rely on TLB_INVALID_MASK or haddr==NULL
- * to detect if there was an exception during tlb_fill().
- */
env->tlb_fill_exc = 0;
flags = probe_access_flags(env, addr, access_type, mmu_idx, nonfault, phost,
ra);
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
index 06b2691..56c5053 100644
--- a/target/sh4/cpu.c
+++ b/target/sh4/cpu.c
@@ -34,13 +34,20 @@ static void superh_cpu_set_pc(CPUState *cs, vaddr value)
cpu->env.pc = value;
}
+static vaddr superh_cpu_get_pc(CPUState *cs)
+{
+ SuperHCPU *cpu = SUPERH_CPU(cs);
+
+ return cpu->env.pc;
+}
+
static void superh_cpu_synchronize_from_tb(CPUState *cs,
const TranslationBlock *tb)
{
SuperHCPU *cpu = SUPERH_CPU(cs);
- cpu->env.pc = tb->pc;
- cpu->env.flags = tb->flags & TB_FLAG_ENVFLAGS_MASK;
+ cpu->env.pc = tb_pc(tb);
+ cpu->env.flags = tb->flags;
}
#ifndef CONFIG_USER_ONLY
@@ -50,10 +57,10 @@ static bool superh_io_recompile_replay_branch(CPUState *cs,
SuperHCPU *cpu = SUPERH_CPU(cs);
CPUSH4State *env = &cpu->env;
- if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0
- && env->pc != tb->pc) {
+ if ((env->flags & (TB_FLAG_DELAY_SLOT | TB_FLAG_DELAY_SLOT_COND))
+ && env->pc != tb_pc(tb)) {
env->pc -= 2;
- env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
+ env->flags &= ~(TB_FLAG_DELAY_SLOT | TB_FLAG_DELAY_SLOT_COND);
return true;
}
return false;
@@ -261,6 +268,7 @@ static void superh_cpu_class_init(ObjectClass *oc, void *data)
cc->has_work = superh_cpu_has_work;
cc->dump_state = superh_cpu_dump_state;
cc->set_pc = superh_cpu_set_pc;
+ cc->get_pc = superh_cpu_get_pc;
cc->gdb_read_register = superh_cpu_gdb_read_register;
cc->gdb_write_register = superh_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
diff --git a/target/sh4/cpu.h b/target/sh4/cpu.h
index 9f15ef9..727b829 100644
--- a/target/sh4/cpu.h
+++ b/target/sh4/cpu.h
@@ -78,26 +78,33 @@
#define FPSCR_RM_NEAREST (0 << 0)
#define FPSCR_RM_ZERO (1 << 0)
-#define DELAY_SLOT_MASK 0x7
-#define DELAY_SLOT (1 << 0)
-#define DELAY_SLOT_CONDITIONAL (1 << 1)
-#define DELAY_SLOT_RTE (1 << 2)
-
-#define TB_FLAG_PENDING_MOVCA (1 << 3)
-#define TB_FLAG_UNALIGN (1 << 4)
-
-#define GUSA_SHIFT 4
-#ifdef CONFIG_USER_ONLY
-#define GUSA_EXCLUSIVE (1 << 12)
-#define GUSA_MASK ((0xff << GUSA_SHIFT) | GUSA_EXCLUSIVE)
-#else
-/* Provide dummy versions of the above to allow tests against tbflags
- to be elided while avoiding ifdefs. */
-#define GUSA_EXCLUSIVE 0
-#define GUSA_MASK 0
-#endif
-
-#define TB_FLAG_ENVFLAGS_MASK (DELAY_SLOT_MASK | GUSA_MASK)
+#define TB_FLAG_DELAY_SLOT (1 << 0)
+#define TB_FLAG_DELAY_SLOT_COND (1 << 1)
+#define TB_FLAG_DELAY_SLOT_RTE (1 << 2)
+#define TB_FLAG_PENDING_MOVCA (1 << 3)
+#define TB_FLAG_GUSA_SHIFT 4 /* [11:4] */
+#define TB_FLAG_GUSA_EXCLUSIVE (1 << 12)
+#define TB_FLAG_UNALIGN (1 << 13)
+#define TB_FLAG_SR_FD (1 << SR_FD) /* 15 */
+#define TB_FLAG_FPSCR_PR FPSCR_PR /* 19 */
+#define TB_FLAG_FPSCR_SZ FPSCR_SZ /* 20 */
+#define TB_FLAG_FPSCR_FR FPSCR_FR /* 21 */
+#define TB_FLAG_SR_RB (1 << SR_RB) /* 29 */
+#define TB_FLAG_SR_MD (1 << SR_MD) /* 30 */
+
+#define TB_FLAG_DELAY_SLOT_MASK (TB_FLAG_DELAY_SLOT | \
+ TB_FLAG_DELAY_SLOT_COND | \
+ TB_FLAG_DELAY_SLOT_RTE)
+#define TB_FLAG_GUSA_MASK ((0xff << TB_FLAG_GUSA_SHIFT) | \
+ TB_FLAG_GUSA_EXCLUSIVE)
+#define TB_FLAG_FPSCR_MASK (TB_FLAG_FPSCR_PR | \
+ TB_FLAG_FPSCR_SZ | \
+ TB_FLAG_FPSCR_FR)
+#define TB_FLAG_SR_MASK (TB_FLAG_SR_FD | \
+ TB_FLAG_SR_RB | \
+ TB_FLAG_SR_MD)
+#define TB_FLAG_ENVFLAGS_MASK (TB_FLAG_DELAY_SLOT_MASK | \
+ TB_FLAG_GUSA_MASK)
typedef struct tlb_t {
uint32_t vpn; /* virtual page number */
@@ -258,7 +265,7 @@ static inline int cpu_mmu_index (CPUSH4State *env, bool ifetch)
{
/* The instruction in a RTE delay slot is fetched in privileged
mode, but executed in user mode. */
- if (ifetch && (env->flags & DELAY_SLOT_RTE)) {
+ if (ifetch && (env->flags & TB_FLAG_DELAY_SLOT_RTE)) {
return 0;
} else {
return (env->sr & (1u << SR_MD)) == 0 ? 1 : 0;
@@ -366,11 +373,10 @@ static inline void cpu_get_tb_cpu_state(CPUSH4State *env, target_ulong *pc,
{
*pc = env->pc;
/* For a gUSA region, notice the end of the region. */
- *cs_base = env->flags & GUSA_MASK ? env->gregs[0] : 0;
- *flags = env->flags /* TB_FLAG_ENVFLAGS_MASK: bits 0-2, 4-12 */
- | (env->fpscr & (FPSCR_FR | FPSCR_SZ | FPSCR_PR)) /* Bits 19-21 */
- | (env->sr & ((1u << SR_MD) | (1u << SR_RB))) /* Bits 29-30 */
- | (env->sr & (1u << SR_FD)) /* Bit 15 */
+ *cs_base = env->flags & TB_FLAG_GUSA_MASK ? env->gregs[0] : 0;
+ *flags = env->flags
+ | (env->fpscr & TB_FLAG_FPSCR_MASK)
+ | (env->sr & TB_FLAG_SR_MASK)
| (env->movcal_backup ? TB_FLAG_PENDING_MOVCA : 0); /* Bit 3 */
#ifdef CONFIG_USER_ONLY
*flags |= TB_FLAG_UNALIGN * !env_cpu(env)->prctl_unalign_sigbus;
diff --git a/target/sh4/helper.c b/target/sh4/helper.c
index 6a620e3..e02e7af 100644
--- a/target/sh4/helper.c
+++ b/target/sh4/helper.c
@@ -147,11 +147,11 @@ void superh_cpu_do_interrupt(CPUState *cs)
env->sr |= (1u << SR_BL) | (1u << SR_MD) | (1u << SR_RB);
env->lock_addr = -1;
- if (env->flags & DELAY_SLOT_MASK) {
+ if (env->flags & TB_FLAG_DELAY_SLOT_MASK) {
/* Branch instruction should be executed again before delay slot. */
env->spc -= 2;
/* Clear flags for exception/interrupt routine. */
- env->flags &= ~DELAY_SLOT_MASK;
+ env->flags &= ~TB_FLAG_DELAY_SLOT_MASK;
}
if (do_exp) {
@@ -786,7 +786,7 @@ bool superh_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
CPUSH4State *env = &cpu->env;
/* Delay slots are indivisible, ignore interrupts */
- if (env->flags & DELAY_SLOT_MASK) {
+ if (env->flags & TB_FLAG_DELAY_SLOT_MASK) {
return false;
} else {
superh_cpu_do_interrupt(cs);
diff --git a/target/sh4/translate.c b/target/sh4/translate.c
index 0105657..26231b2 100644
--- a/target/sh4/translate.c
+++ b/target/sh4/translate.c
@@ -175,13 +175,13 @@ void superh_cpu_dump_state(CPUState *cs, FILE *f, int flags)
i, env->gregs[i], i + 1, env->gregs[i + 1],
i + 2, env->gregs[i + 2], i + 3, env->gregs[i + 3]);
}
- if (env->flags & DELAY_SLOT) {
+ if (env->flags & TB_FLAG_DELAY_SLOT) {
qemu_printf("in delay slot (delayed_pc=0x%08x)\n",
env->delayed_pc);
- } else if (env->flags & DELAY_SLOT_CONDITIONAL) {
+ } else if (env->flags & TB_FLAG_DELAY_SLOT_COND) {
qemu_printf("in conditional delay slot (delayed_pc=0x%08x)\n",
env->delayed_pc);
- } else if (env->flags & DELAY_SLOT_RTE) {
+ } else if (env->flags & TB_FLAG_DELAY_SLOT_RTE) {
qemu_fprintf(f, "in rte delay slot (delayed_pc=0x%08x)\n",
env->delayed_pc);
}
@@ -223,7 +223,7 @@ static inline void gen_save_cpu_state(DisasContext *ctx, bool save_pc)
static inline bool use_exit_tb(DisasContext *ctx)
{
- return (ctx->tbflags & GUSA_EXCLUSIVE) != 0;
+ return (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) != 0;
}
static bool use_goto_tb(DisasContext *ctx, target_ulong dest)
@@ -276,12 +276,12 @@ static void gen_conditional_jump(DisasContext *ctx, target_ulong dest,
TCGLabel *l1 = gen_new_label();
TCGCond cond_not_taken = jump_if_true ? TCG_COND_EQ : TCG_COND_NE;
- if (ctx->tbflags & GUSA_EXCLUSIVE) {
+ if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) {
/* When in an exclusive region, we must continue to the end.
Therefore, exit the region on a taken branch, but otherwise
fall through to the next instruction. */
tcg_gen_brcondi_i32(cond_not_taken, cpu_sr_t, 0, l1);
- tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~GUSA_MASK);
+ tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~TB_FLAG_GUSA_MASK);
/* Note that this won't actually use a goto_tb opcode because we
disallow it in use_goto_tb, but it handles exit + singlestep. */
gen_goto_tb(ctx, 0, dest);
@@ -307,14 +307,14 @@ static void gen_delayed_conditional_jump(DisasContext * ctx)
tcg_gen_mov_i32(ds, cpu_delayed_cond);
tcg_gen_discard_i32(cpu_delayed_cond);
- if (ctx->tbflags & GUSA_EXCLUSIVE) {
+ if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) {
/* When in an exclusive region, we must continue to the end.
Therefore, exit the region on a taken branch, but otherwise
fall through to the next instruction. */
tcg_gen_brcondi_i32(TCG_COND_EQ, ds, 0, l1);
/* Leave the gUSA region. */
- tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~GUSA_MASK);
+ tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~TB_FLAG_GUSA_MASK);
gen_jump(ctx);
gen_set_label(l1);
@@ -361,8 +361,8 @@ static inline void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
#define XHACK(x) ((((x) & 1 ) << 4) | ((x) & 0xe))
#define CHECK_NOT_DELAY_SLOT \
- if (ctx->envflags & DELAY_SLOT_MASK) { \
- goto do_illegal_slot; \
+ if (ctx->envflags & TB_FLAG_DELAY_SLOT_MASK) { \
+ goto do_illegal_slot; \
}
#define CHECK_PRIVILEGED \
@@ -436,7 +436,7 @@ static void _decode_opc(DisasContext * ctx)
case 0x000b: /* rts */
CHECK_NOT_DELAY_SLOT
tcg_gen_mov_i32(cpu_delayed_pc, cpu_pr);
- ctx->envflags |= DELAY_SLOT;
+ ctx->envflags |= TB_FLAG_DELAY_SLOT;
ctx->delayed_pc = (uint32_t) - 1;
return;
case 0x0028: /* clrmac */
@@ -458,7 +458,7 @@ static void _decode_opc(DisasContext * ctx)
CHECK_NOT_DELAY_SLOT
gen_write_sr(cpu_ssr);
tcg_gen_mov_i32(cpu_delayed_pc, cpu_spc);
- ctx->envflags |= DELAY_SLOT_RTE;
+ ctx->envflags |= TB_FLAG_DELAY_SLOT_RTE;
ctx->delayed_pc = (uint32_t) - 1;
ctx->base.is_jmp = DISAS_STOP;
return;
@@ -513,12 +513,15 @@ static void _decode_opc(DisasContext * ctx)
return;
case 0xe000: /* mov #imm,Rn */
#ifdef CONFIG_USER_ONLY
- /* Detect the start of a gUSA region. If so, update envflags
- and end the TB. This will allow us to see the end of the
- region (stored in R0) in the next TB. */
+ /*
+ * Detect the start of a gUSA region (mov #-n, r15).
+ * If so, update envflags and end the TB. This will allow us
+ * to see the end of the region (stored in R0) in the next TB.
+ */
if (B11_8 == 15 && B7_0s < 0 &&
(tb_cflags(ctx->base.tb) & CF_PARALLEL)) {
- ctx->envflags = deposit32(ctx->envflags, GUSA_SHIFT, 8, B7_0s);
+ ctx->envflags =
+ deposit32(ctx->envflags, TB_FLAG_GUSA_SHIFT, 8, B7_0s);
ctx->base.is_jmp = DISAS_STOP;
}
#endif
@@ -544,13 +547,13 @@ static void _decode_opc(DisasContext * ctx)
case 0xa000: /* bra disp */
CHECK_NOT_DELAY_SLOT
ctx->delayed_pc = ctx->base.pc_next + 4 + B11_0s * 2;
- ctx->envflags |= DELAY_SLOT;
+ ctx->envflags |= TB_FLAG_DELAY_SLOT;
return;
case 0xb000: /* bsr disp */
CHECK_NOT_DELAY_SLOT
tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4);
ctx->delayed_pc = ctx->base.pc_next + 4 + B11_0s * 2;
- ctx->envflags |= DELAY_SLOT;
+ ctx->envflags |= TB_FLAG_DELAY_SLOT;
return;
}
@@ -1194,7 +1197,7 @@ static void _decode_opc(DisasContext * ctx)
CHECK_NOT_DELAY_SLOT
tcg_gen_xori_i32(cpu_delayed_cond, cpu_sr_t, 1);
ctx->delayed_pc = ctx->base.pc_next + 4 + B7_0s * 2;
- ctx->envflags |= DELAY_SLOT_CONDITIONAL;
+ ctx->envflags |= TB_FLAG_DELAY_SLOT_COND;
return;
case 0x8900: /* bt label */
CHECK_NOT_DELAY_SLOT
@@ -1204,7 +1207,7 @@ static void _decode_opc(DisasContext * ctx)
CHECK_NOT_DELAY_SLOT
tcg_gen_mov_i32(cpu_delayed_cond, cpu_sr_t);
ctx->delayed_pc = ctx->base.pc_next + 4 + B7_0s * 2;
- ctx->envflags |= DELAY_SLOT_CONDITIONAL;
+ ctx->envflags |= TB_FLAG_DELAY_SLOT_COND;
return;
case 0x8800: /* cmp/eq #imm,R0 */
tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, REG(0), B7_0s);
@@ -1388,14 +1391,14 @@ static void _decode_opc(DisasContext * ctx)
case 0x0023: /* braf Rn */
CHECK_NOT_DELAY_SLOT
tcg_gen_addi_i32(cpu_delayed_pc, REG(B11_8), ctx->base.pc_next + 4);
- ctx->envflags |= DELAY_SLOT;
+ ctx->envflags |= TB_FLAG_DELAY_SLOT;
ctx->delayed_pc = (uint32_t) - 1;
return;
case 0x0003: /* bsrf Rn */
CHECK_NOT_DELAY_SLOT
tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4);
tcg_gen_add_i32(cpu_delayed_pc, REG(B11_8), cpu_pr);
- ctx->envflags |= DELAY_SLOT;
+ ctx->envflags |= TB_FLAG_DELAY_SLOT;
ctx->delayed_pc = (uint32_t) - 1;
return;
case 0x4015: /* cmp/pl Rn */
@@ -1411,14 +1414,14 @@ static void _decode_opc(DisasContext * ctx)
case 0x402b: /* jmp @Rn */
CHECK_NOT_DELAY_SLOT
tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8));
- ctx->envflags |= DELAY_SLOT;
+ ctx->envflags |= TB_FLAG_DELAY_SLOT;
ctx->delayed_pc = (uint32_t) - 1;
return;
case 0x400b: /* jsr @Rn */
CHECK_NOT_DELAY_SLOT
tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4);
tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8));
- ctx->envflags |= DELAY_SLOT;
+ ctx->envflags |= TB_FLAG_DELAY_SLOT;
ctx->delayed_pc = (uint32_t) - 1;
return;
case 0x400e: /* ldc Rm,SR */
@@ -1839,7 +1842,7 @@ static void _decode_opc(DisasContext * ctx)
fflush(stderr);
#endif
do_illegal:
- if (ctx->envflags & DELAY_SLOT_MASK) {
+ if (ctx->envflags & TB_FLAG_DELAY_SLOT_MASK) {
do_illegal_slot:
gen_save_cpu_state(ctx, true);
gen_helper_raise_slot_illegal_instruction(cpu_env);
@@ -1852,7 +1855,7 @@ static void _decode_opc(DisasContext * ctx)
do_fpu_disabled:
gen_save_cpu_state(ctx, true);
- if (ctx->envflags & DELAY_SLOT_MASK) {
+ if (ctx->envflags & TB_FLAG_DELAY_SLOT_MASK) {
gen_helper_raise_slot_fpu_disable(cpu_env);
} else {
gen_helper_raise_fpu_disable(cpu_env);
@@ -1867,23 +1870,23 @@ static void decode_opc(DisasContext * ctx)
_decode_opc(ctx);
- if (old_flags & DELAY_SLOT_MASK) {
+ if (old_flags & TB_FLAG_DELAY_SLOT_MASK) {
/* go out of the delay slot */
- ctx->envflags &= ~DELAY_SLOT_MASK;
+ ctx->envflags &= ~TB_FLAG_DELAY_SLOT_MASK;
/* When in an exclusive region, we must continue to the end
for conditional branches. */
- if (ctx->tbflags & GUSA_EXCLUSIVE
- && old_flags & DELAY_SLOT_CONDITIONAL) {
+ if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE
+ && old_flags & TB_FLAG_DELAY_SLOT_COND) {
gen_delayed_conditional_jump(ctx);
return;
}
/* Otherwise this is probably an invalid gUSA region.
Drop the GUSA bits so the next TB doesn't see them. */
- ctx->envflags &= ~GUSA_MASK;
+ ctx->envflags &= ~TB_FLAG_GUSA_MASK;
tcg_gen_movi_i32(cpu_flags, ctx->envflags);
- if (old_flags & DELAY_SLOT_CONDITIONAL) {
+ if (old_flags & TB_FLAG_DELAY_SLOT_COND) {
gen_delayed_conditional_jump(ctx);
} else {
gen_jump(ctx);
@@ -2223,7 +2226,7 @@ static void decode_gusa(DisasContext *ctx, CPUSH4State *env)
}
/* The entire region has been translated. */
- ctx->envflags &= ~GUSA_MASK;
+ ctx->envflags &= ~TB_FLAG_GUSA_MASK;
ctx->base.pc_next = pc_end;
ctx->base.num_insns += max_insns - 1;
return;
@@ -2234,7 +2237,7 @@ static void decode_gusa(DisasContext *ctx, CPUSH4State *env)
/* Restart with the EXCLUSIVE bit set, within a TB run via
cpu_exec_step_atomic holding the exclusive lock. */
- ctx->envflags |= GUSA_EXCLUSIVE;
+ ctx->envflags |= TB_FLAG_GUSA_EXCLUSIVE;
gen_save_cpu_state(ctx, false);
gen_helper_exclusive(cpu_env);
ctx->base.is_jmp = DISAS_NORETURN;
@@ -2267,17 +2270,19 @@ static void sh4_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
(tbflags & (1 << SR_RB))) * 0x10;
ctx->fbank = tbflags & FPSCR_FR ? 0x10 : 0;
- if (tbflags & GUSA_MASK) {
+#ifdef CONFIG_USER_ONLY
+ if (tbflags & TB_FLAG_GUSA_MASK) {
+ /* In gUSA exclusive region. */
uint32_t pc = ctx->base.pc_next;
uint32_t pc_end = ctx->base.tb->cs_base;
- int backup = sextract32(ctx->tbflags, GUSA_SHIFT, 8);
+ int backup = sextract32(ctx->tbflags, TB_FLAG_GUSA_SHIFT, 8);
int max_insns = (pc_end - pc) / 2;
if (pc != pc_end + backup || max_insns < 2) {
/* This is a malformed gUSA region. Don't do anything special,
since the interpreter is likely to get confused. */
- ctx->envflags &= ~GUSA_MASK;
- } else if (tbflags & GUSA_EXCLUSIVE) {
+ ctx->envflags &= ~TB_FLAG_GUSA_MASK;
+ } else if (tbflags & TB_FLAG_GUSA_EXCLUSIVE) {
/* Regardless of single-stepping or the end of the page,
we must complete execution of the gUSA region while
holding the exclusive lock. */
@@ -2285,6 +2290,7 @@ static void sh4_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
return;
}
}
+#endif
/* Since the ISA is fixed-width, we can bound by the number
of instructions remaining on the page. */
@@ -2309,8 +2315,8 @@ static void sh4_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
DisasContext *ctx = container_of(dcbase, DisasContext, base);
#ifdef CONFIG_USER_ONLY
- if (unlikely(ctx->envflags & GUSA_MASK)
- && !(ctx->envflags & GUSA_EXCLUSIVE)) {
+ if (unlikely(ctx->envflags & TB_FLAG_GUSA_MASK)
+ && !(ctx->envflags & TB_FLAG_GUSA_EXCLUSIVE)) {
/* We're in an gUSA region, and we have not already fallen
back on using an exclusive region. Attempt to parse the
region into a single supported atomic operation. Failure
@@ -2330,9 +2336,9 @@ static void sh4_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
{
DisasContext *ctx = container_of(dcbase, DisasContext, base);
- if (ctx->tbflags & GUSA_EXCLUSIVE) {
+ if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) {
/* Ending the region of exclusivity. Clear the bits. */
- ctx->envflags &= ~GUSA_MASK;
+ ctx->envflags &= ~TB_FLAG_GUSA_MASK;
}
switch (ctx->base.is_jmp) {
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
index 55268ed..1f9ef7a 100644
--- a/target/sparc/cpu.c
+++ b/target/sparc/cpu.c
@@ -693,12 +693,19 @@ static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
cpu->env.npc = value + 4;
}
+static vaddr sparc_cpu_get_pc(CPUState *cs)
+{
+ SPARCCPU *cpu = SPARC_CPU(cs);
+
+ return cpu->env.pc;
+}
+
static void sparc_cpu_synchronize_from_tb(CPUState *cs,
const TranslationBlock *tb)
{
SPARCCPU *cpu = SPARC_CPU(cs);
- cpu->env.pc = tb->pc;
+ cpu->env.pc = tb_pc(tb);
cpu->env.npc = tb->cs_base;
}
@@ -896,6 +903,7 @@ static void sparc_cpu_class_init(ObjectClass *oc, void *data)
cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
#endif
cc->set_pc = sparc_cpu_set_pc;
+ cc->get_pc = sparc_cpu_get_pc;
cc->gdb_read_register = sparc_cpu_gdb_read_register;
cc->gdb_write_register = sparc_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
diff --git a/target/tricore/cpu.c b/target/tricore/cpu.c
index b95682b..ab7a1e3 100644
--- a/target/tricore/cpu.c
+++ b/target/tricore/cpu.c
@@ -41,13 +41,21 @@ static void tricore_cpu_set_pc(CPUState *cs, vaddr value)
env->PC = value & ~(target_ulong)1;
}
+static vaddr tricore_cpu_get_pc(CPUState *cs)
+{
+ TriCoreCPU *cpu = TRICORE_CPU(cs);
+ CPUTriCoreState *env = &cpu->env;
+
+ return env->PC;
+}
+
static void tricore_cpu_synchronize_from_tb(CPUState *cs,
const TranslationBlock *tb)
{
TriCoreCPU *cpu = TRICORE_CPU(cs);
CPUTriCoreState *env = &cpu->env;
- env->PC = tb->pc;
+ env->PC = tb_pc(tb);
}
static void tricore_cpu_reset(DeviceState *dev)
@@ -176,6 +184,7 @@ static void tricore_cpu_class_init(ObjectClass *c, void *data)
cc->dump_state = tricore_cpu_dump_state;
cc->set_pc = tricore_cpu_set_pc;
+ cc->get_pc = tricore_cpu_get_pc;
cc->sysemu_ops = &tricore_sysemu_ops;
cc->tcg_ops = &tricore_tcg_ops;
}
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
index fd553fd..cbbe0e8 100644
--- a/target/xtensa/cpu.c
+++ b/target/xtensa/cpu.c
@@ -44,6 +44,13 @@ static void xtensa_cpu_set_pc(CPUState *cs, vaddr value)
cpu->env.pc = value;
}
+static vaddr xtensa_cpu_get_pc(CPUState *cs)
+{
+ XtensaCPU *cpu = XTENSA_CPU(cs);
+
+ return cpu->env.pc;
+}
+
static bool xtensa_cpu_has_work(CPUState *cs)
{
#ifndef CONFIG_USER_ONLY
@@ -233,6 +240,7 @@ static void xtensa_cpu_class_init(ObjectClass *oc, void *data)
cc->has_work = xtensa_cpu_has_work;
cc->dump_state = xtensa_cpu_dump_state;
cc->set_pc = xtensa_cpu_set_pc;
+ cc->get_pc = xtensa_cpu_get_pc;
cc->gdb_read_register = xtensa_cpu_gdb_read_register;
cc->gdb_write_register = xtensa_cpu_gdb_write_register;
cc->gdb_stop_before_watchpoint = true;