F: include/exec/tb-hash.h
F: include/sysemu/cpus.h
F: include/sysemu/tcg.h
+F: include/hw/core/tcg-cpu-ops.h
FPU emulation
#include "qemu-common.h"
#include "qemu/qemu-print.h"
#include "cpu.h"
+#include "hw/core/tcg-cpu-ops.h"
#include "trace.h"
#include "disas/disas.h"
#include "exec/exec-all.h"
TARGET_FMT_lx "] %s\n",
last_tb->tc.ptr, last_tb->pc,
lookup_symbol(last_tb->pc));
- if (cc->tcg_ops.synchronize_from_tb) {
- cc->tcg_ops.synchronize_from_tb(cpu, last_tb);
+ if (cc->tcg_ops->synchronize_from_tb) {
+ cc->tcg_ops->synchronize_from_tb(cpu, last_tb);
} else {
assert(cc->set_pc);
cc->set_pc(cpu, last_tb->pc);
{
CPUClass *cc = CPU_GET_CLASS(cpu);
- if (cc->tcg_ops.cpu_exec_enter) {
- cc->tcg_ops.cpu_exec_enter(cpu);
+ if (cc->tcg_ops->cpu_exec_enter) {
+ cc->tcg_ops->cpu_exec_enter(cpu);
}
}
{
CPUClass *cc = CPU_GET_CLASS(cpu);
- if (cc->tcg_ops.cpu_exec_exit) {
- cc->tcg_ops.cpu_exec_exit(cpu);
+ if (cc->tcg_ops->cpu_exec_exit) {
+ cc->tcg_ops->cpu_exec_exit(cpu);
}
}
}
}
- if (cc->tcg_ops.debug_excp_handler) {
- cc->tcg_ops.debug_excp_handler(cpu);
+ if (cc->tcg_ops->debug_excp_handler) {
+ cc->tcg_ops->debug_excp_handler(cpu);
}
}
loop */
#if defined(TARGET_I386)
CPUClass *cc = CPU_GET_CLASS(cpu);
- cc->tcg_ops.do_interrupt(cpu);
+ cc->tcg_ops->do_interrupt(cpu);
#endif
*ret = cpu->exception_index;
cpu->exception_index = -1;
if (replay_exception()) {
CPUClass *cc = CPU_GET_CLASS(cpu);
qemu_mutex_lock_iothread();
- cc->tcg_ops.do_interrupt(cpu);
+ cc->tcg_ops->do_interrupt(cpu);
qemu_mutex_unlock_iothread();
cpu->exception_index = -1;
True when it is, and we should restart on a new TB,
and via longjmp via cpu_loop_exit. */
else {
- if (cc->tcg_ops.cpu_exec_interrupt &&
- cc->tcg_ops.cpu_exec_interrupt(cpu, interrupt_request)) {
+ if (cc->tcg_ops->cpu_exec_interrupt &&
+ cc->tcg_ops->cpu_exec_interrupt(cpu, interrupt_request)) {
if (need_replay_interrupt(interrupt_request)) {
replay_interrupt();
}
CPUClass *cc = CPU_GET_CLASS(cpu);
if (!tcg_target_initialized) {
- cc->tcg_ops.initialize();
+ cc->tcg_ops->initialize();
tcg_target_initialized = true;
}
tlb_init(cpu);
#include "qemu/osdep.h"
#include "qemu/main-loop.h"
#include "cpu.h"
+#include "hw/core/tcg-cpu-ops.h"
#include "exec/exec-all.h"
#include "exec/memory.h"
#include "exec/address-spaces.h"
* This is not a probe, so only valid return is success; failure
* should result in exception + longjmp to the cpu loop.
*/
- ok = cc->tcg_ops.tlb_fill(cpu, addr, size,
- access_type, mmu_idx, false, retaddr);
+ ok = cc->tcg_ops->tlb_fill(cpu, addr, size,
+ access_type, mmu_idx, false, retaddr);
assert(ok);
}
+static inline void cpu_unaligned_access(CPUState *cpu, vaddr addr,
+ MMUAccessType access_type,
+ int mmu_idx, uintptr_t retaddr)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ cc->tcg_ops->do_unaligned_access(cpu, addr, access_type, mmu_idx, retaddr);
+}
+
+static inline void cpu_transaction_failed(CPUState *cpu, hwaddr physaddr,
+ vaddr addr, unsigned size,
+ MMUAccessType access_type,
+ int mmu_idx, MemTxAttrs attrs,
+ MemTxResult response,
+ uintptr_t retaddr)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ if (!cpu->ignore_memory_transaction_failures &&
+ cc->tcg_ops->do_transaction_failed) {
+ cc->tcg_ops->do_transaction_failed(cpu, physaddr, addr, size,
+ access_type, mmu_idx, attrs,
+ response, retaddr);
+ }
+}
+
static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
int mmu_idx, target_ulong addr, uintptr_t retaddr,
MMUAccessType access_type, MemOp op)
CPUState *cs = env_cpu(env);
CPUClass *cc = CPU_GET_CLASS(cs);
- if (!cc->tcg_ops.tlb_fill(cs, addr, fault_size, access_type,
- mmu_idx, nonfault, retaddr)) {
+ if (!cc->tcg_ops->tlb_fill(cs, addr, fault_size, access_type,
+ mmu_idx, nonfault, retaddr)) {
/* Non-faulting page table read failed. */
*phost = NULL;
return TLB_INVALID_MASK;
*/
#include "qemu/osdep.h"
#include "cpu.h"
+#include "hw/core/tcg-cpu-ops.h"
#include "disas/disas.h"
#include "exec/exec-all.h"
#include "tcg/tcg.h"
clear_helper_retaddr();
cc = CPU_GET_CLASS(cpu);
- cc->tcg_ops.tlb_fill(cpu, address, 0, access_type,
- MMU_USER_IDX, false, pc);
+ cc->tcg_ops->tlb_fill(cpu, address, 0, access_type,
+ MMU_USER_IDX, false, pc);
g_assert_not_reached();
}
} else {
CPUState *cpu = env_cpu(env);
CPUClass *cc = CPU_GET_CLASS(cpu);
- cc->tcg_ops.tlb_fill(cpu, addr, fault_size, access_type,
- MMU_USER_IDX, false, ra);
+ cc->tcg_ops->tlb_fill(cpu, addr, fault_size, access_type,
+ MMU_USER_IDX, false, ra);
g_assert_not_reached();
}
}
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "qemu/help_option.h"
+#ifdef CONFIG_TCG
+#include "hw/core/tcg-cpu-ops.h"
+#endif /* CONFIG_TCG */
enum jazz_model_e {
JAZZ_MAGNUM,
*/
cc = CPU_GET_CLASS(cpu);
#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY)
- real_do_transaction_failed = cc->tcg_ops.do_transaction_failed;
- cc->tcg_ops.do_transaction_failed = mips_jazz_do_transaction_failed;
+ real_do_transaction_failed = cc->tcg_ops->do_transaction_failed;
+ cc->tcg_ops->do_transaction_failed = mips_jazz_do_transaction_failed;
#endif /* CONFIG_TCG && !CONFIG_USER_ONLY */
/* allocate RAM */
struct TranslationBlock;
-/**
- * struct TcgCpuOperations: TCG operations specific to a CPU class
- */
-typedef struct TcgCpuOperations {
- /**
- * @initialize: Initalize TCG state
- *
- * Called when the first CPU is realized.
- */
- void (*initialize)(void);
- /**
- * @synchronize_from_tb: Synchronize state from a TCG #TranslationBlock
- *
- * This is called when we abandon execution of a TB before starting it,
- * and must set all parts of the CPU state which the previous TB in the
- * chain may not have updated.
- * By default, when this is NULL, a call is made to @set_pc(tb->pc).
- *
- * If more state needs to be restored, the target must implement a
- * function to restore all the state, and register it here.
- */
- void (*synchronize_from_tb)(CPUState *cpu,
- const struct TranslationBlock *tb);
- /** @cpu_exec_enter: Callback for cpu_exec preparation */
- void (*cpu_exec_enter)(CPUState *cpu);
- /** @cpu_exec_exit: Callback for cpu_exec cleanup */
- void (*cpu_exec_exit)(CPUState *cpu);
- /** @cpu_exec_interrupt: Callback for processing interrupts in cpu_exec */
- bool (*cpu_exec_interrupt)(CPUState *cpu, int interrupt_request);
- /** @do_interrupt: Callback for interrupt handling. */
- void (*do_interrupt)(CPUState *cpu);
- /**
- * @tlb_fill: Handle a softmmu tlb miss or user-only address fault
- *
- * For system mode, if the access is valid, call tlb_set_page
- * and return true; if the access is invalid, and probe is
- * true, return false; otherwise raise an exception and do
- * not return. For user-only mode, always raise an exception
- * and do not return.
- */
- bool (*tlb_fill)(CPUState *cpu, vaddr address, int size,
- MMUAccessType access_type, int mmu_idx,
- bool probe, uintptr_t retaddr);
- /** @debug_excp_handler: Callback for handling debug exceptions */
- void (*debug_excp_handler)(CPUState *cpu);
-
- /**
- * @do_transaction_failed: Callback for handling failed memory transactions
- * (ie bus faults or external aborts; not MMU faults)
- */
- void (*do_transaction_failed)(CPUState *cpu, hwaddr physaddr, vaddr addr,
- unsigned size, MMUAccessType access_type,
- int mmu_idx, MemTxAttrs attrs,
- MemTxResult response, uintptr_t retaddr);
- /**
- * @do_unaligned_access: Callback for unaligned access handling
- */
- void (*do_unaligned_access)(CPUState *cpu, vaddr addr,
- MMUAccessType access_type,
- int mmu_idx, uintptr_t retaddr);
- /**
- * @adjust_watchpoint_address: hack for cpu_check_watchpoint used by ARM
- */
- vaddr (*adjust_watchpoint_address)(CPUState *cpu, vaddr addr, int len);
-
- /**
- * @debug_check_watchpoint: return true if the architectural
- * watchpoint whose address has matched should really fire, used by ARM
- */
- bool (*debug_check_watchpoint)(CPUState *cpu, CPUWatchpoint *wp);
-
-} TcgCpuOperations;
+/* see tcg-cpu-ops.h */
+struct TCGCPUOps;
/**
* CPUClass:
int gdb_num_core_regs;
bool gdb_stop_before_watchpoint;
- TcgCpuOperations tcg_ops;
+ /* when TCG is not available, this pointer is NULL */
+ struct TCGCPUOps *tcg_ops;
};
/*
void cpu_interrupt(CPUState *cpu, int mask);
-static inline void cpu_unaligned_access(CPUState *cpu, vaddr addr,
- MMUAccessType access_type,
- int mmu_idx, uintptr_t retaddr)
-{
- CPUClass *cc = CPU_GET_CLASS(cpu);
-
- cc->tcg_ops.do_unaligned_access(cpu, addr, access_type, mmu_idx, retaddr);
-}
-
-static inline void cpu_transaction_failed(CPUState *cpu, hwaddr physaddr,
- vaddr addr, unsigned size,
- MMUAccessType access_type,
- int mmu_idx, MemTxAttrs attrs,
- MemTxResult response,
- uintptr_t retaddr)
-{
- CPUClass *cc = CPU_GET_CLASS(cpu);
-
- if (!cpu->ignore_memory_transaction_failures &&
- cc->tcg_ops.do_transaction_failed) {
- cc->tcg_ops.do_transaction_failed(cpu, physaddr, addr, size,
- access_type, mmu_idx, attrs,
- response, retaddr);
- }
-}
-
/**
* cpu_set_pc:
* @cpu: The CPU to set the program counter for.
--- /dev/null
+/*
+ * TCG CPU-specific operations
+ *
+ * Copyright 2021 SUSE LLC
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef TCG_CPU_OPS_H
+#define TCG_CPU_OPS_H
+
+#include "hw/core/cpu.h"
+
+struct TCGCPUOps {
+ /**
+ * @initialize: Initalize TCG state
+ *
+ * Called when the first CPU is realized.
+ */
+ void (*initialize)(void);
+ /**
+ * @synchronize_from_tb: Synchronize state from a TCG #TranslationBlock
+ *
+ * This is called when we abandon execution of a TB before starting it,
+ * and must set all parts of the CPU state which the previous TB in the
+ * chain may not have updated.
+ * By default, when this is NULL, a call is made to @set_pc(tb->pc).
+ *
+ * If more state needs to be restored, the target must implement a
+ * function to restore all the state, and register it here.
+ */
+ void (*synchronize_from_tb)(CPUState *cpu,
+ const struct TranslationBlock *tb);
+ /** @cpu_exec_enter: Callback for cpu_exec preparation */
+ void (*cpu_exec_enter)(CPUState *cpu);
+ /** @cpu_exec_exit: Callback for cpu_exec cleanup */
+ void (*cpu_exec_exit)(CPUState *cpu);
+ /** @cpu_exec_interrupt: Callback for processing interrupts in cpu_exec */
+ bool (*cpu_exec_interrupt)(CPUState *cpu, int interrupt_request);
+ /**
+ * @do_interrupt: Callback for interrupt handling.
+ *
+ * note that this is in general SOFTMMU only, but it actually isn't
+ * because of an x86 hack (accel/tcg/cpu-exec.c), so we cannot put it
+ * in the SOFTMMU section in general.
+ */
+ void (*do_interrupt)(CPUState *cpu);
+ /**
+ * @tlb_fill: Handle a softmmu tlb miss or user-only address fault
+ *
+ * For system mode, if the access is valid, call tlb_set_page
+ * and return true; if the access is invalid, and probe is
+ * true, return false; otherwise raise an exception and do
+ * not return. For user-only mode, always raise an exception
+ * and do not return.
+ */
+ bool (*tlb_fill)(CPUState *cpu, vaddr address, int size,
+ MMUAccessType access_type, int mmu_idx,
+ bool probe, uintptr_t retaddr);
+ /** @debug_excp_handler: Callback for handling debug exceptions */
+ void (*debug_excp_handler)(CPUState *cpu);
+
+#ifdef NEED_CPU_H
+#ifdef CONFIG_SOFTMMU
+ /**
+ * @do_transaction_failed: Callback for handling failed memory transactions
+ * (ie bus faults or external aborts; not MMU faults)
+ */
+ void (*do_transaction_failed)(CPUState *cpu, hwaddr physaddr, vaddr addr,
+ unsigned size, MMUAccessType access_type,
+ int mmu_idx, MemTxAttrs attrs,
+ MemTxResult response, uintptr_t retaddr);
+ /**
+ * @do_unaligned_access: Callback for unaligned access handling
+ */
+ void (*do_unaligned_access)(CPUState *cpu, vaddr addr,
+ MMUAccessType access_type,
+ int mmu_idx, uintptr_t retaddr);
+
+ /**
+ * @adjust_watchpoint_address: hack for cpu_check_watchpoint used by ARM
+ */
+ vaddr (*adjust_watchpoint_address)(CPUState *cpu, vaddr addr, int len);
+
+ /**
+ * @debug_check_watchpoint: return true if the architectural
+ * watchpoint whose address has matched should really fire, used by ARM
+ */
+ bool (*debug_check_watchpoint)(CPUState *cpu, CPUWatchpoint *wp);
+
+#endif /* CONFIG_SOFTMMU */
+#endif /* NEED_CPU_H */
+
+};
+
+#endif /* TCG_CPU_OPS_H */
#include "qemu/cutils.h"
#include "qemu/cacheflush.h"
#include "cpu.h"
+
+#ifdef CONFIG_TCG
+#include "hw/core/tcg-cpu-ops.h"
+#endif /* CONFIG_TCG */
+
#include "exec/exec-all.h"
#include "exec/target_page.h"
#include "hw/qdev-core.h"
return;
}
- if (cc->tcg_ops.adjust_watchpoint_address) {
+ if (cc->tcg_ops->adjust_watchpoint_address) {
/* this is currently used only by ARM BE32 */
- addr = cc->tcg_ops.adjust_watchpoint_address(cpu, addr, len);
+ addr = cc->tcg_ops->adjust_watchpoint_address(cpu, addr, len);
}
QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) {
if (watchpoint_address_matches(wp, addr, len)
wp->hitaddr = MAX(addr, wp->vaddr);
wp->hitattrs = attrs;
if (!cpu->watchpoint_hit) {
- if (wp->flags & BP_CPU && cc->tcg_ops.debug_check_watchpoint &&
- !cc->tcg_ops.debug_check_watchpoint(cpu, wp)) {
+ if (wp->flags & BP_CPU && cc->tcg_ops->debug_check_watchpoint &&
+ !cc->tcg_ops->debug_check_watchpoint(cpu, wp)) {
wp->flags &= ~BP_WATCHPOINT_HIT;
continue;
}
#endif
}
+#include "hw/core/tcg-cpu-ops.h"
+
+static struct TCGCPUOps alpha_tcg_ops = {
+ .initialize = alpha_translate_init,
+ .cpu_exec_interrupt = alpha_cpu_exec_interrupt,
+ .tlb_fill = alpha_cpu_tlb_fill,
+
+#ifndef CONFIG_USER_ONLY
+ .do_interrupt = alpha_cpu_do_interrupt,
+ .do_transaction_failed = alpha_cpu_do_transaction_failed,
+ .do_unaligned_access = alpha_cpu_do_unaligned_access,
+#endif /* !CONFIG_USER_ONLY */
+};
+
static void alpha_cpu_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
cc->class_by_name = alpha_cpu_class_by_name;
cc->has_work = alpha_cpu_has_work;
- cc->tcg_ops.do_interrupt = alpha_cpu_do_interrupt;
- cc->tcg_ops.cpu_exec_interrupt = alpha_cpu_exec_interrupt;
cc->dump_state = alpha_cpu_dump_state;
cc->set_pc = alpha_cpu_set_pc;
cc->gdb_read_register = alpha_cpu_gdb_read_register;
cc->gdb_write_register = alpha_cpu_gdb_write_register;
- cc->tcg_ops.tlb_fill = alpha_cpu_tlb_fill;
#ifndef CONFIG_USER_ONLY
- cc->tcg_ops.do_transaction_failed = alpha_cpu_do_transaction_failed;
- cc->tcg_ops.do_unaligned_access = alpha_cpu_do_unaligned_access;
cc->get_phys_page_debug = alpha_cpu_get_phys_page_debug;
dc->vmsd = &vmstate_alpha_cpu;
#endif
cc->disas_set_info = alpha_cpu_disas_set_info;
- cc->tcg_ops.initialize = alpha_translate_init;
+ cc->tcg_ops = &alpha_tcg_ops;
cc->gdb_num_core_regs = 67;
}
#include "qapi/error.h"
#include "qapi/visitor.h"
#include "cpu.h"
+#ifdef CONFIG_TCG
+#include "hw/core/tcg-cpu-ops.h"
+#endif /* CONFIG_TCG */
#include "internals.h"
#include "exec/exec-all.h"
#include "hw/qdev-properties.h"
}
#ifdef CONFIG_TCG
-static void arm_cpu_synchronize_from_tb(CPUState *cs,
- const TranslationBlock *tb)
+void arm_cpu_synchronize_from_tb(CPUState *cs,
+ const TranslationBlock *tb)
{
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
found:
cs->exception_index = excp_idx;
env->exception.target_el = target_el;
- cc->tcg_ops.do_interrupt(cs);
+ cc->tcg_ops->do_interrupt(cs);
return true;
}
return g_strdup("arm");
}
+#ifdef CONFIG_TCG
+static struct TCGCPUOps arm_tcg_ops = {
+ .initialize = arm_translate_init,
+ .synchronize_from_tb = arm_cpu_synchronize_from_tb,
+ .cpu_exec_interrupt = arm_cpu_exec_interrupt,
+ .tlb_fill = arm_cpu_tlb_fill,
+ .debug_excp_handler = arm_debug_excp_handler,
+
+#if !defined(CONFIG_USER_ONLY)
+ .do_interrupt = arm_cpu_do_interrupt,
+ .do_transaction_failed = arm_cpu_do_transaction_failed,
+ .do_unaligned_access = arm_cpu_do_unaligned_access,
+ .adjust_watchpoint_address = arm_adjust_watchpoint_address,
+ .debug_check_watchpoint = arm_debug_check_watchpoint,
+#endif /* !CONFIG_USER_ONLY */
+};
+#endif /* CONFIG_TCG */
+
static void arm_cpu_class_init(ObjectClass *oc, void *data)
{
ARMCPUClass *acc = ARM_CPU_CLASS(oc);
cc->gdb_get_dynamic_xml = arm_gdb_get_dynamic_xml;
cc->gdb_stop_before_watchpoint = true;
cc->disas_set_info = arm_disas_set_info;
+
#ifdef CONFIG_TCG
- cc->tcg_ops.initialize = arm_translate_init;
- cc->tcg_ops.cpu_exec_interrupt = arm_cpu_exec_interrupt;
- cc->tcg_ops.synchronize_from_tb = arm_cpu_synchronize_from_tb;
- cc->tcg_ops.tlb_fill = arm_cpu_tlb_fill;
- cc->tcg_ops.debug_excp_handler = arm_debug_excp_handler;
-#if !defined(CONFIG_USER_ONLY)
- cc->tcg_ops.do_interrupt = arm_cpu_do_interrupt;
- cc->tcg_ops.do_transaction_failed = arm_cpu_do_transaction_failed;
- cc->tcg_ops.do_unaligned_access = arm_cpu_do_unaligned_access;
- cc->tcg_ops.adjust_watchpoint_address = arm_adjust_watchpoint_address;
- cc->tcg_ops.debug_check_watchpoint = arm_debug_check_watchpoint;
-#endif /* CONFIG_TCG && !CONFIG_USER_ONLY */
+ cc->tcg_ops = &arm_tcg_ops;
#endif /* CONFIG_TCG */
}
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "cpu.h"
+#ifdef CONFIG_TCG
+#include "hw/core/tcg-cpu-ops.h"
+#endif /* CONFIG_TCG */
#include "qemu/module.h"
#if !defined(CONFIG_USER_ONLY)
#include "hw/loader.h"
{
CPUClass *cc = CPU_CLASS(oc);
-#ifdef CONFIG_TCG
- cc->tcg_ops.cpu_exec_interrupt = arm_cpu_exec_interrupt;
-#endif /* CONFIG_TCG */
-
cc->gdb_read_register = aarch64_cpu_gdb_read_register;
cc->gdb_write_register = aarch64_cpu_gdb_write_register;
cc->gdb_num_core_regs = 34;
#include "qemu/osdep.h"
#include "cpu.h"
+#ifdef CONFIG_TCG
+#include "hw/core/tcg-cpu-ops.h"
+#endif /* CONFIG_TCG */
#include "internals.h"
/* CPU models. These are not needed for the AArch64 linux-user build. */
if (interrupt_request & CPU_INTERRUPT_HARD
&& (armv7m_nvic_can_take_pending_exception(env->nvic))) {
cs->exception_index = EXCP_IRQ;
- cc->tcg_ops.do_interrupt(cs);
+ cc->tcg_ops->do_interrupt(cs);
ret = true;
}
return ret;
cpu->reset_sctlr = 0x00000078;
}
+#ifdef CONFIG_TCG
+static struct TCGCPUOps arm_v7m_tcg_ops = {
+ .initialize = arm_translate_init,
+ .synchronize_from_tb = arm_cpu_synchronize_from_tb,
+ .cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt,
+ .tlb_fill = arm_cpu_tlb_fill,
+ .debug_excp_handler = arm_debug_excp_handler,
+
+#if !defined(CONFIG_USER_ONLY)
+ .do_interrupt = arm_v7m_cpu_do_interrupt,
+ .do_transaction_failed = arm_cpu_do_transaction_failed,
+ .do_unaligned_access = arm_cpu_do_unaligned_access,
+ .adjust_watchpoint_address = arm_adjust_watchpoint_address,
+ .debug_check_watchpoint = arm_debug_check_watchpoint,
+#endif /* !CONFIG_USER_ONLY */
+};
+#endif /* CONFIG_TCG */
+
static void arm_v7m_class_init(ObjectClass *oc, void *data)
{
ARMCPUClass *acc = ARM_CPU_CLASS(oc);
acc->info = data;
#ifdef CONFIG_TCG
- cc->tcg_ops.cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt;
-#ifndef CONFIG_USER_ONLY
- cc->tcg_ops.do_interrupt = arm_v7m_cpu_do_interrupt;
-#endif
+ cc->tcg_ops = &arm_v7m_tcg_ops;
#endif /* CONFIG_TCG */
cc->gdb_core_xml_file = "arm-m-profile.xml";
void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu);
void arm_translate_init(void);
+#ifdef CONFIG_TCG
+void arm_cpu_synchronize_from_tb(CPUState *cs,
+ const struct TranslationBlock *tb);
+#endif /* CONFIG_TCG */
+
+
enum arm_fprounding {
FPROUNDING_TIEEVEN,
FPROUNDING_POSINF,
qemu_fprintf(f, "\n");
}
+#include "hw/core/tcg-cpu-ops.h"
+
+static struct TCGCPUOps avr_tcg_ops = {
+ .initialize = avr_cpu_tcg_init,
+ .synchronize_from_tb = avr_cpu_synchronize_from_tb,
+ .cpu_exec_interrupt = avr_cpu_exec_interrupt,
+ .tlb_fill = avr_cpu_tlb_fill,
+
+#ifndef CONFIG_USER_ONLY
+ .do_interrupt = avr_cpu_do_interrupt,
+#endif /* !CONFIG_USER_ONLY */
+};
+
static void avr_cpu_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
cc->class_by_name = avr_cpu_class_by_name;
cc->has_work = avr_cpu_has_work;
- cc->tcg_ops.do_interrupt = avr_cpu_do_interrupt;
- cc->tcg_ops.cpu_exec_interrupt = avr_cpu_exec_interrupt;
cc->dump_state = avr_cpu_dump_state;
cc->set_pc = avr_cpu_set_pc;
cc->memory_rw_debug = avr_cpu_memory_rw_debug;
cc->get_phys_page_debug = avr_cpu_get_phys_page_debug;
- cc->tcg_ops.tlb_fill = avr_cpu_tlb_fill;
cc->vmsd = &vms_avr_cpu;
cc->disas_set_info = avr_cpu_disas_set_info;
- cc->tcg_ops.initialize = avr_cpu_tcg_init;
- cc->tcg_ops.synchronize_from_tb = avr_cpu_synchronize_from_tb;
cc->gdb_read_register = avr_cpu_gdb_read_register;
cc->gdb_write_register = avr_cpu_gdb_write_register;
cc->gdb_num_core_regs = 35;
cc->gdb_core_xml_file = "avr-cpu.xml";
+ cc->tcg_ops = &avr_tcg_ops;
}
/*
#include "qemu/osdep.h"
#include "cpu.h"
+#include "hw/core/tcg-cpu-ops.h"
#include "exec/exec-all.h"
#include "exec/address-spaces.h"
#include "exec/helper-proto.h"
if (interrupt_request & CPU_INTERRUPT_RESET) {
if (cpu_interrupts_enabled(env)) {
cs->exception_index = EXCP_RESET;
- cc->tcg_ops.do_interrupt(cs);
+ cc->tcg_ops->do_interrupt(cs);
cs->interrupt_request &= ~CPU_INTERRUPT_RESET;
if (cpu_interrupts_enabled(env) && env->intsrc != 0) {
int index = ctz32(env->intsrc);
cs->exception_index = EXCP_INT(index);
- cc->tcg_ops.do_interrupt(cs);
+ cc->tcg_ops->do_interrupt(cs);
env->intsrc &= env->intsrc - 1; /* clear the interrupt */
cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
#endif
}
+#include "hw/core/tcg-cpu-ops.h"
+
+static struct TCGCPUOps crisv10_tcg_ops = {
+ .initialize = cris_initialize_crisv10_tcg,
+ .cpu_exec_interrupt = cris_cpu_exec_interrupt,
+ .tlb_fill = cris_cpu_tlb_fill,
+
+#ifndef CONFIG_USER_ONLY
+ .do_interrupt = crisv10_cpu_do_interrupt,
+#endif /* !CONFIG_USER_ONLY */
+};
+
+static struct TCGCPUOps crisv32_tcg_ops = {
+ .initialize = cris_initialize_tcg,
+ .cpu_exec_interrupt = cris_cpu_exec_interrupt,
+ .tlb_fill = cris_cpu_tlb_fill,
+
+#ifndef CONFIG_USER_ONLY
+ .do_interrupt = cris_cpu_do_interrupt,
+#endif /* !CONFIG_USER_ONLY */
+};
+
static void crisv8_cpu_class_init(ObjectClass *oc, void *data)
{
CPUClass *cc = CPU_CLASS(oc);
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
ccc->vr = 8;
- cc->tcg_ops.do_interrupt = crisv10_cpu_do_interrupt;
cc->gdb_read_register = crisv10_cpu_gdb_read_register;
- cc->tcg_ops.initialize = cris_initialize_crisv10_tcg;
+ cc->tcg_ops = &crisv10_tcg_ops;
}
static void crisv9_cpu_class_init(ObjectClass *oc, void *data)
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
ccc->vr = 9;
- cc->tcg_ops.do_interrupt = crisv10_cpu_do_interrupt;
cc->gdb_read_register = crisv10_cpu_gdb_read_register;
- cc->tcg_ops.initialize = cris_initialize_crisv10_tcg;
+ cc->tcg_ops = &crisv10_tcg_ops;
}
static void crisv10_cpu_class_init(ObjectClass *oc, void *data)
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
ccc->vr = 10;
- cc->tcg_ops.do_interrupt = crisv10_cpu_do_interrupt;
cc->gdb_read_register = crisv10_cpu_gdb_read_register;
- cc->tcg_ops.initialize = cris_initialize_crisv10_tcg;
+ cc->tcg_ops = &crisv10_tcg_ops;
}
static void crisv11_cpu_class_init(ObjectClass *oc, void *data)
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
ccc->vr = 11;
- cc->tcg_ops.do_interrupt = crisv10_cpu_do_interrupt;
cc->gdb_read_register = crisv10_cpu_gdb_read_register;
- cc->tcg_ops.initialize = cris_initialize_crisv10_tcg;
+ cc->tcg_ops = &crisv10_tcg_ops;
}
static void crisv17_cpu_class_init(ObjectClass *oc, void *data)
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
ccc->vr = 17;
- cc->tcg_ops.do_interrupt = crisv10_cpu_do_interrupt;
cc->gdb_read_register = crisv10_cpu_gdb_read_register;
- cc->tcg_ops.initialize = cris_initialize_crisv10_tcg;
+ cc->tcg_ops = &crisv10_tcg_ops;
}
static void crisv32_cpu_class_init(ObjectClass *oc, void *data)
{
+ CPUClass *cc = CPU_CLASS(oc);
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
ccc->vr = 32;
+ cc->tcg_ops = &crisv32_tcg_ops;
}
static void cris_cpu_class_init(ObjectClass *oc, void *data)
cc->class_by_name = cris_cpu_class_by_name;
cc->has_work = cris_cpu_has_work;
- cc->tcg_ops.do_interrupt = cris_cpu_do_interrupt;
- cc->tcg_ops.cpu_exec_interrupt = cris_cpu_exec_interrupt;
cc->dump_state = cris_cpu_dump_state;
cc->set_pc = cris_cpu_set_pc;
cc->gdb_read_register = cris_cpu_gdb_read_register;
cc->gdb_write_register = cris_cpu_gdb_write_register;
- cc->tcg_ops.tlb_fill = cris_cpu_tlb_fill;
#ifndef CONFIG_USER_ONLY
cc->get_phys_page_debug = cris_cpu_get_phys_page_debug;
dc->vmsd = &vmstate_cris_cpu;
cc->gdb_stop_before_watchpoint = true;
cc->disas_set_info = cris_disas_set_info;
- cc->tcg_ops.initialize = cris_initialize_tcg;
}
#define DEFINE_CRIS_CPU_TYPE(cpu_model, initfn) \
#include "qemu/osdep.h"
#include "cpu.h"
+#include "hw/core/tcg-cpu-ops.h"
#include "mmu.h"
#include "qemu/host-utils.h"
#include "exec/exec-all.h"
&& (env->pregs[PR_CCS] & I_FLAG)
&& !env->locked_irq) {
cs->exception_index = EXCP_IRQ;
- cc->tcg_ops.do_interrupt(cs);
+ cc->tcg_ops->do_interrupt(cs);
ret = true;
}
if (interrupt_request & CPU_INTERRUPT_NMI) {
}
if ((env->pregs[PR_CCS] & m_flag_archval)) {
cs->exception_index = EXCP_NMI;
- cc->tcg_ops.do_interrupt(cs);
+ cc->tcg_ops->do_interrupt(cs);
ret = true;
}
}
return object_class_by_name(TYPE_HPPA_CPU);
}
+#include "hw/core/tcg-cpu-ops.h"
+
+static struct TCGCPUOps hppa_tcg_ops = {
+ .initialize = hppa_translate_init,
+ .synchronize_from_tb = hppa_cpu_synchronize_from_tb,
+ .cpu_exec_interrupt = hppa_cpu_exec_interrupt,
+ .tlb_fill = hppa_cpu_tlb_fill,
+
+#ifndef CONFIG_USER_ONLY
+ .do_interrupt = hppa_cpu_do_interrupt,
+ .do_unaligned_access = hppa_cpu_do_unaligned_access,
+#endif /* !CONFIG_USER_ONLY */
+};
+
static void hppa_cpu_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
cc->class_by_name = hppa_cpu_class_by_name;
cc->has_work = hppa_cpu_has_work;
- cc->tcg_ops.do_interrupt = hppa_cpu_do_interrupt;
- cc->tcg_ops.cpu_exec_interrupt = hppa_cpu_exec_interrupt;
cc->dump_state = hppa_cpu_dump_state;
cc->set_pc = hppa_cpu_set_pc;
- cc->tcg_ops.synchronize_from_tb = hppa_cpu_synchronize_from_tb;
cc->gdb_read_register = hppa_cpu_gdb_read_register;
cc->gdb_write_register = hppa_cpu_gdb_write_register;
- cc->tcg_ops.tlb_fill = hppa_cpu_tlb_fill;
#ifndef CONFIG_USER_ONLY
cc->get_phys_page_debug = hppa_cpu_get_phys_page_debug;
- cc->tcg_ops.do_unaligned_access = hppa_cpu_do_unaligned_access;
dc->vmsd = &vmstate_hppa_cpu;
#endif
cc->disas_set_info = hppa_cpu_disas_set_info;
- cc->tcg_ops.initialize = hppa_translate_init;
-
cc->gdb_num_core_regs = 128;
+ cc->tcg_ops = &hppa_tcg_ops;
}
static const TypeInfo hppa_cpu_type_info = {
cpu->env.eip = tb->pc - tb->cs_base;
}
+#include "hw/core/tcg-cpu-ops.h"
+
+static struct TCGCPUOps x86_tcg_ops = {
+ .initialize = tcg_x86_init,
+ .synchronize_from_tb = x86_cpu_synchronize_from_tb,
+ .cpu_exec_enter = x86_cpu_exec_enter,
+ .cpu_exec_exit = x86_cpu_exec_exit,
+ .cpu_exec_interrupt = x86_cpu_exec_interrupt,
+ .do_interrupt = x86_cpu_do_interrupt,
+ .tlb_fill = x86_cpu_tlb_fill,
+#ifndef CONFIG_USER_ONLY
+ .debug_excp_handler = breakpoint_handler,
+#endif /* !CONFIG_USER_ONLY */
+};
+
void tcg_cpu_common_class_init(CPUClass *cc)
{
- cc->tcg_ops.do_interrupt = x86_cpu_do_interrupt;
- cc->tcg_ops.cpu_exec_interrupt = x86_cpu_exec_interrupt;
- cc->tcg_ops.synchronize_from_tb = x86_cpu_synchronize_from_tb;
- cc->tcg_ops.cpu_exec_enter = x86_cpu_exec_enter;
- cc->tcg_ops.cpu_exec_exit = x86_cpu_exec_exit;
- cc->tcg_ops.initialize = tcg_x86_init;
- cc->tcg_ops.tlb_fill = x86_cpu_tlb_fill;
-#ifndef CONFIG_USER_ONLY
- cc->tcg_ops.debug_excp_handler = breakpoint_handler;
-#endif
+ cc->tcg_ops = &x86_tcg_ops;
}
return oc;
}
+#include "hw/core/tcg-cpu-ops.h"
+
+static struct TCGCPUOps lm32_tcg_ops = {
+ .initialize = lm32_translate_init,
+ .cpu_exec_interrupt = lm32_cpu_exec_interrupt,
+ .tlb_fill = lm32_cpu_tlb_fill,
+ .debug_excp_handler = lm32_debug_excp_handler,
+
+#ifndef CONFIG_USER_ONLY
+ .do_interrupt = lm32_cpu_do_interrupt,
+#endif /* !CONFIG_USER_ONLY */
+};
+
static void lm32_cpu_class_init(ObjectClass *oc, void *data)
{
LM32CPUClass *lcc = LM32_CPU_CLASS(oc);
cc->class_by_name = lm32_cpu_class_by_name;
cc->has_work = lm32_cpu_has_work;
- cc->tcg_ops.do_interrupt = lm32_cpu_do_interrupt;
- cc->tcg_ops.cpu_exec_interrupt = lm32_cpu_exec_interrupt;
cc->dump_state = lm32_cpu_dump_state;
cc->set_pc = lm32_cpu_set_pc;
cc->gdb_read_register = lm32_cpu_gdb_read_register;
cc->gdb_write_register = lm32_cpu_gdb_write_register;
- cc->tcg_ops.tlb_fill = lm32_cpu_tlb_fill;
#ifndef CONFIG_USER_ONLY
cc->get_phys_page_debug = lm32_cpu_get_phys_page_debug;
cc->vmsd = &vmstate_lm32_cpu;
#endif
cc->gdb_num_core_regs = 32 + 7;
cc->gdb_stop_before_watchpoint = true;
- cc->tcg_ops.debug_excp_handler = lm32_debug_excp_handler;
cc->disas_set_info = lm32_cpu_disas_set_info;
- cc->tcg_ops.initialize = lm32_translate_init;
+ cc->tcg_ops = &lm32_tcg_ops;
}
#define DEFINE_LM32_CPU_TYPE(cpu_model, initfn) \
};
#endif
+#include "hw/core/tcg-cpu-ops.h"
+
+static struct TCGCPUOps m68k_tcg_ops = {
+ .initialize = m68k_tcg_init,
+ .cpu_exec_interrupt = m68k_cpu_exec_interrupt,
+ .tlb_fill = m68k_cpu_tlb_fill,
+
+#ifndef CONFIG_USER_ONLY
+ .do_interrupt = m68k_cpu_do_interrupt,
+ .do_transaction_failed = m68k_cpu_transaction_failed,
+#endif /* !CONFIG_USER_ONLY */
+};
+
static void m68k_cpu_class_init(ObjectClass *c, void *data)
{
M68kCPUClass *mcc = M68K_CPU_CLASS(c);
cc->class_by_name = m68k_cpu_class_by_name;
cc->has_work = m68k_cpu_has_work;
- cc->tcg_ops.do_interrupt = m68k_cpu_do_interrupt;
- cc->tcg_ops.cpu_exec_interrupt = m68k_cpu_exec_interrupt;
cc->dump_state = m68k_cpu_dump_state;
cc->set_pc = m68k_cpu_set_pc;
cc->gdb_read_register = m68k_cpu_gdb_read_register;
cc->gdb_write_register = m68k_cpu_gdb_write_register;
- cc->tcg_ops.tlb_fill = m68k_cpu_tlb_fill;
#if defined(CONFIG_SOFTMMU)
- cc->tcg_ops.do_transaction_failed = m68k_cpu_transaction_failed;
cc->get_phys_page_debug = m68k_cpu_get_phys_page_debug;
dc->vmsd = &vmstate_m68k_cpu;
#endif
cc->disas_set_info = m68k_cpu_disas_set_info;
- cc->tcg_ops.initialize = m68k_tcg_init;
cc->gdb_num_core_regs = 18;
+ cc->tcg_ops = &m68k_tcg_ops;
}
static void m68k_cpu_class_init_cf_core(ObjectClass *c, void *data)
return object_class_by_name(TYPE_MICROBLAZE_CPU);
}
+#include "hw/core/tcg-cpu-ops.h"
+
+static struct TCGCPUOps mb_tcg_ops = {
+ .initialize = mb_tcg_init,
+ .synchronize_from_tb = mb_cpu_synchronize_from_tb,
+ .cpu_exec_interrupt = mb_cpu_exec_interrupt,
+ .tlb_fill = mb_cpu_tlb_fill,
+
+#ifndef CONFIG_USER_ONLY
+ .do_interrupt = mb_cpu_do_interrupt,
+ .do_transaction_failed = mb_cpu_transaction_failed,
+ .do_unaligned_access = mb_cpu_do_unaligned_access,
+#endif /* !CONFIG_USER_ONLY */
+};
+
static void mb_cpu_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
cc->class_by_name = mb_cpu_class_by_name;
cc->has_work = mb_cpu_has_work;
- cc->tcg_ops.do_interrupt = mb_cpu_do_interrupt;
- cc->tcg_ops.cpu_exec_interrupt = mb_cpu_exec_interrupt;
+
cc->dump_state = mb_cpu_dump_state;
cc->set_pc = mb_cpu_set_pc;
- cc->tcg_ops.synchronize_from_tb = mb_cpu_synchronize_from_tb;
cc->gdb_read_register = mb_cpu_gdb_read_register;
cc->gdb_write_register = mb_cpu_gdb_write_register;
- cc->tcg_ops.tlb_fill = mb_cpu_tlb_fill;
+
#ifndef CONFIG_USER_ONLY
- cc->tcg_ops.do_transaction_failed = mb_cpu_transaction_failed;
- cc->tcg_ops.do_unaligned_access = mb_cpu_do_unaligned_access;
cc->get_phys_page_attrs_debug = mb_cpu_get_phys_page_attrs_debug;
dc->vmsd = &vmstate_mb_cpu;
#endif
cc->gdb_num_core_regs = 32 + 27;
cc->disas_set_info = mb_disas_set_info;
- cc->tcg_ops.initialize = mb_tcg_init;
+ cc->tcg_ops = &mb_tcg_ops;
}
static const TypeInfo mb_cpu_type_info = {
DEFINE_PROP_END_OF_LIST()
};
+#ifdef CONFIG_TCG
+#include "hw/core/tcg-cpu-ops.h"
+/*
+ * NB: cannot be const, as some elements are changed for specific
+ * mips hardware (see hw/mips/jazz.c).
+ */
+static struct TCGCPUOps mips_tcg_ops = {
+ .initialize = mips_tcg_init,
+ .synchronize_from_tb = mips_cpu_synchronize_from_tb,
+ .cpu_exec_interrupt = mips_cpu_exec_interrupt,
+ .tlb_fill = mips_cpu_tlb_fill,
+
+#if !defined(CONFIG_USER_ONLY)
+ .do_interrupt = mips_cpu_do_interrupt,
+ .do_transaction_failed = mips_cpu_do_transaction_failed,
+ .do_unaligned_access = mips_cpu_do_unaligned_access,
+#endif /* !CONFIG_USER_ONLY */
+};
+#endif /* CONFIG_TCG */
+
static void mips_cpu_class_init(ObjectClass *c, void *data)
{
MIPSCPUClass *mcc = MIPS_CPU_CLASS(c);
cc->vmsd = &vmstate_mips_cpu;
#endif
cc->disas_set_info = mips_cpu_disas_set_info;
-#ifdef CONFIG_TCG
- cc->tcg_ops.initialize = mips_tcg_init;
- cc->tcg_ops.do_interrupt = mips_cpu_do_interrupt;
- cc->tcg_ops.cpu_exec_interrupt = mips_cpu_exec_interrupt;
- cc->tcg_ops.synchronize_from_tb = mips_cpu_synchronize_from_tb;
- cc->tcg_ops.tlb_fill = mips_cpu_tlb_fill;
-#ifndef CONFIG_USER_ONLY
- cc->tcg_ops.do_transaction_failed = mips_cpu_do_transaction_failed;
- cc->tcg_ops.do_unaligned_access = mips_cpu_do_unaligned_access;
-
-#endif /* CONFIG_USER_ONLY */
-#endif /* CONFIG_TCG */
-
cc->gdb_num_core_regs = 73;
cc->gdb_stop_before_watchpoint = true;
+#ifdef CONFIG_TCG
+ cc->tcg_ops = &mips_tcg_ops;
+#endif /* CONFIG_TCG */
}
static const TypeInfo mips_cpu_type_info = {
return oc;
}
+#include "hw/core/tcg-cpu-ops.h"
+
+static struct TCGCPUOps moxie_tcg_ops = {
+ .initialize = moxie_translate_init,
+ .tlb_fill = moxie_cpu_tlb_fill,
+
+#ifndef CONFIG_USER_ONLY
+ .do_interrupt = moxie_cpu_do_interrupt,
+#endif /* !CONFIG_USER_ONLY */
+};
+
static void moxie_cpu_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
cc->class_by_name = moxie_cpu_class_by_name;
cc->has_work = moxie_cpu_has_work;
- cc->tcg_ops.do_interrupt = moxie_cpu_do_interrupt;
cc->dump_state = moxie_cpu_dump_state;
cc->set_pc = moxie_cpu_set_pc;
- cc->tcg_ops.tlb_fill = moxie_cpu_tlb_fill;
#ifndef CONFIG_USER_ONLY
cc->get_phys_page_debug = moxie_cpu_get_phys_page_debug;
cc->vmsd = &vmstate_moxie_cpu;
#endif
cc->disas_set_info = moxie_cpu_disas_set_info;
- cc->tcg_ops.initialize = moxie_translate_init;
+ cc->tcg_ops = &moxie_tcg_ops;
}
static void moxielite_initfn(Object *obj)
DEFINE_PROP_END_OF_LIST(),
};
+#include "hw/core/tcg-cpu-ops.h"
+
+static struct TCGCPUOps nios2_tcg_ops = {
+ .initialize = nios2_tcg_init,
+ .cpu_exec_interrupt = nios2_cpu_exec_interrupt,
+ .tlb_fill = nios2_cpu_tlb_fill,
+
+#ifndef CONFIG_USER_ONLY
+ .do_interrupt = nios2_cpu_do_interrupt,
+ .do_unaligned_access = nios2_cpu_do_unaligned_access,
+#endif /* !CONFIG_USER_ONLY */
+};
static void nios2_cpu_class_init(ObjectClass *oc, void *data)
{
cc->class_by_name = nios2_cpu_class_by_name;
cc->has_work = nios2_cpu_has_work;
- cc->tcg_ops.do_interrupt = nios2_cpu_do_interrupt;
- cc->tcg_ops.cpu_exec_interrupt = nios2_cpu_exec_interrupt;
cc->dump_state = nios2_cpu_dump_state;
cc->set_pc = nios2_cpu_set_pc;
cc->disas_set_info = nios2_cpu_disas_set_info;
- cc->tcg_ops.tlb_fill = nios2_cpu_tlb_fill;
#ifndef CONFIG_USER_ONLY
- cc->tcg_ops.do_unaligned_access = nios2_cpu_do_unaligned_access;
cc->get_phys_page_debug = nios2_cpu_get_phys_page_debug;
#endif
cc->gdb_read_register = nios2_cpu_gdb_read_register;
cc->gdb_write_register = nios2_cpu_gdb_write_register;
cc->gdb_num_core_regs = 49;
- cc->tcg_ops.initialize = nios2_tcg_init;
+ cc->tcg_ops = &nios2_tcg_ops;
}
static const TypeInfo nios2_cpu_type_info = {
| (IMMUCFGR_NTS & (ctz32(TLB_SIZE) << 2));
}
+#include "hw/core/tcg-cpu-ops.h"
+
+static struct TCGCPUOps openrisc_tcg_ops = {
+ .initialize = openrisc_translate_init,
+ .cpu_exec_interrupt = openrisc_cpu_exec_interrupt,
+ .tlb_fill = openrisc_cpu_tlb_fill,
+
+#ifndef CONFIG_USER_ONLY
+ .do_interrupt = openrisc_cpu_do_interrupt,
+#endif /* !CONFIG_USER_ONLY */
+};
+
static void openrisc_cpu_class_init(ObjectClass *oc, void *data)
{
OpenRISCCPUClass *occ = OPENRISC_CPU_CLASS(oc);
cc->class_by_name = openrisc_cpu_class_by_name;
cc->has_work = openrisc_cpu_has_work;
- cc->tcg_ops.do_interrupt = openrisc_cpu_do_interrupt;
- cc->tcg_ops.cpu_exec_interrupt = openrisc_cpu_exec_interrupt;
cc->dump_state = openrisc_cpu_dump_state;
cc->set_pc = openrisc_cpu_set_pc;
cc->gdb_read_register = openrisc_cpu_gdb_read_register;
cc->gdb_write_register = openrisc_cpu_gdb_write_register;
- cc->tcg_ops.tlb_fill = openrisc_cpu_tlb_fill;
#ifndef CONFIG_USER_ONLY
cc->get_phys_page_debug = openrisc_cpu_get_phys_page_debug;
dc->vmsd = &vmstate_openrisc_cpu;
#endif
cc->gdb_num_core_regs = 32 + 3;
- cc->tcg_ops.initialize = openrisc_translate_init;
cc->disas_set_info = openrisc_disas_set_info;
+ cc->tcg_ops = &openrisc_tcg_ops;
}
/* Sort alphabetically by type name, except for "any". */
DEFINE_PROP_END_OF_LIST(),
};
+#ifdef CONFIG_TCG
+#include "hw/core/tcg-cpu-ops.h"
+
+static struct TCGCPUOps ppc_tcg_ops = {
+ .initialize = ppc_translate_init,
+ .cpu_exec_interrupt = ppc_cpu_exec_interrupt,
+ .tlb_fill = ppc_cpu_tlb_fill,
+
+#ifndef CONFIG_USER_ONLY
+ .do_interrupt = ppc_cpu_do_interrupt,
+ .cpu_exec_enter = ppc_cpu_exec_enter,
+ .cpu_exec_exit = ppc_cpu_exec_exit,
+ .do_unaligned_access = ppc_cpu_do_unaligned_access,
+#endif /* !CONFIG_USER_ONLY */
+};
+#endif /* CONFIG_TCG */
+
static void ppc_cpu_class_init(ObjectClass *oc, void *data)
{
PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
#ifndef CONFIG_USER_ONLY
cc->virtio_is_big_endian = ppc_cpu_is_big_endian;
#endif
-#ifdef CONFIG_TCG
- cc->tcg_ops.initialize = ppc_translate_init;
- cc->tcg_ops.cpu_exec_interrupt = ppc_cpu_exec_interrupt;
- cc->tcg_ops.do_interrupt = ppc_cpu_do_interrupt;
- cc->tcg_ops.tlb_fill = ppc_cpu_tlb_fill;
-#ifndef CONFIG_USER_ONLY
- cc->tcg_ops.cpu_exec_enter = ppc_cpu_exec_enter;
- cc->tcg_ops.cpu_exec_exit = ppc_cpu_exec_exit;
- cc->tcg_ops.do_unaligned_access = ppc_cpu_do_unaligned_access;
-#endif /* !CONFIG_USER_ONLY */
-#endif /* CONFIG_TCG */
-
cc->disas_set_info = ppc_disas_set_info;
dc->fw_name = "PowerPC,UNKNOWN";
+
+#ifdef CONFIG_TCG
+ cc->tcg_ops = &ppc_tcg_ops;
+#endif /* CONFIG_TCG */
}
static const TypeInfo ppc_cpu_type_info = {
return NULL;
}
+#include "hw/core/tcg-cpu-ops.h"
+
+static struct TCGCPUOps riscv_tcg_ops = {
+ .initialize = riscv_translate_init,
+ .synchronize_from_tb = riscv_cpu_synchronize_from_tb,
+ .cpu_exec_interrupt = riscv_cpu_exec_interrupt,
+ .tlb_fill = riscv_cpu_tlb_fill,
+
+#ifndef CONFIG_USER_ONLY
+ .do_interrupt = riscv_cpu_do_interrupt,
+ .do_transaction_failed = riscv_cpu_do_transaction_failed,
+ .do_unaligned_access = riscv_cpu_do_unaligned_access,
+#endif /* !CONFIG_USER_ONLY */
+};
+
static void riscv_cpu_class_init(ObjectClass *c, void *data)
{
RISCVCPUClass *mcc = RISCV_CPU_CLASS(c);
cc->class_by_name = riscv_cpu_class_by_name;
cc->has_work = riscv_cpu_has_work;
- cc->tcg_ops.do_interrupt = riscv_cpu_do_interrupt;
- cc->tcg_ops.cpu_exec_interrupt = riscv_cpu_exec_interrupt;
cc->dump_state = riscv_cpu_dump_state;
cc->set_pc = riscv_cpu_set_pc;
- cc->tcg_ops.synchronize_from_tb = riscv_cpu_synchronize_from_tb;
cc->gdb_read_register = riscv_cpu_gdb_read_register;
cc->gdb_write_register = riscv_cpu_gdb_write_register;
cc->gdb_num_core_regs = 33;
cc->gdb_stop_before_watchpoint = true;
cc->disas_set_info = riscv_cpu_disas_set_info;
#ifndef CONFIG_USER_ONLY
- cc->tcg_ops.do_transaction_failed = riscv_cpu_do_transaction_failed;
- cc->tcg_ops.do_unaligned_access = riscv_cpu_do_unaligned_access;
cc->get_phys_page_debug = riscv_cpu_get_phys_page_debug;
/* For now, mark unmigratable: */
cc->vmsd = &vmstate_riscv_cpu;
#endif
cc->gdb_arch_name = riscv_gdb_arch_name;
cc->gdb_get_dynamic_xml = riscv_gdb_get_dynamic_xml;
- cc->tcg_ops.initialize = riscv_translate_init;
- cc->tcg_ops.tlb_fill = riscv_cpu_tlb_fill;
+ cc->tcg_ops = &riscv_tcg_ops;
device_class_set_props(dc, riscv_cpu_properties);
}
qdev_init_gpio_in(DEVICE(cpu), rx_cpu_set_irq, 2);
}
+#include "hw/core/tcg-cpu-ops.h"
+
+static struct TCGCPUOps rx_tcg_ops = {
+ .initialize = rx_translate_init,
+ .synchronize_from_tb = rx_cpu_synchronize_from_tb,
+ .cpu_exec_interrupt = rx_cpu_exec_interrupt,
+ .tlb_fill = rx_cpu_tlb_fill,
+
+#ifndef CONFIG_USER_ONLY
+ .do_interrupt = rx_cpu_do_interrupt,
+#endif /* !CONFIG_USER_ONLY */
+};
+
static void rx_cpu_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
cc->class_by_name = rx_cpu_class_by_name;
cc->has_work = rx_cpu_has_work;
- cc->tcg_ops.do_interrupt = rx_cpu_do_interrupt;
- cc->tcg_ops.cpu_exec_interrupt = rx_cpu_exec_interrupt;
cc->dump_state = rx_cpu_dump_state;
cc->set_pc = rx_cpu_set_pc;
- cc->tcg_ops.synchronize_from_tb = rx_cpu_synchronize_from_tb;
+
cc->gdb_read_register = rx_cpu_gdb_read_register;
cc->gdb_write_register = rx_cpu_gdb_write_register;
cc->get_phys_page_debug = rx_cpu_get_phys_page_debug;
cc->disas_set_info = rx_cpu_disas_set_info;
- cc->tcg_ops.initialize = rx_translate_init;
- cc->tcg_ops.tlb_fill = rx_cpu_tlb_fill;
cc->gdb_num_core_regs = 26;
cc->gdb_core_xml_file = "rx-core.xml";
+ cc->tcg_ops = &rx_tcg_ops;
}
static const TypeInfo rx_cpu_info = {
return s390_cpu_reset(s, S390_CPU_RESET_CLEAR);
}
+#ifdef CONFIG_TCG
+#include "hw/core/tcg-cpu-ops.h"
+
+static struct TCGCPUOps s390_tcg_ops = {
+ .initialize = s390x_translate_init,
+ .tlb_fill = s390_cpu_tlb_fill,
+
+#if !defined(CONFIG_USER_ONLY)
+ .cpu_exec_interrupt = s390_cpu_exec_interrupt,
+ .do_interrupt = s390_cpu_do_interrupt,
+ .debug_excp_handler = s390x_cpu_debug_excp_handler,
+ .do_unaligned_access = s390x_cpu_do_unaligned_access,
+#endif /* !CONFIG_USER_ONLY */
+};
+#endif /* CONFIG_TCG */
+
static void s390_cpu_class_init(ObjectClass *oc, void *data)
{
S390CPUClass *scc = S390_CPU_CLASS(oc);
scc->reset = s390_cpu_reset;
cc->class_by_name = s390_cpu_class_by_name,
cc->has_work = s390_cpu_has_work;
-#ifdef CONFIG_TCG
- cc->tcg_ops.do_interrupt = s390_cpu_do_interrupt;
-#endif
cc->dump_state = s390_cpu_dump_state;
cc->set_pc = s390_cpu_set_pc;
cc->gdb_read_register = s390_cpu_gdb_read_register;
cc->vmsd = &vmstate_s390_cpu;
cc->get_crash_info = s390_cpu_get_crash_info;
cc->write_elf64_note = s390_cpu_write_elf64_note;
-#ifdef CONFIG_TCG
- cc->tcg_ops.cpu_exec_interrupt = s390_cpu_exec_interrupt;
- cc->tcg_ops.debug_excp_handler = s390x_cpu_debug_excp_handler;
- cc->tcg_ops.do_unaligned_access = s390x_cpu_do_unaligned_access;
-#endif
#endif
cc->disas_set_info = s390_cpu_disas_set_info;
-#ifdef CONFIG_TCG
- cc->tcg_ops.initialize = s390x_translate_init;
- cc->tcg_ops.tlb_fill = s390_cpu_tlb_fill;
-#endif
-
cc->gdb_num_core_regs = S390_NUM_CORE_REGS;
cc->gdb_core_xml_file = "s390x-core64.xml";
cc->gdb_arch_name = s390_gdb_arch_name;
s390_cpu_model_class_register_props(oc);
+
+#ifdef CONFIG_TCG
+ cc->tcg_ops = &s390_tcg_ops;
+#endif /* CONFIG_TCG */
}
static const TypeInfo s390_cpu_type_info = {
.unmigratable = 1,
};
+#include "hw/core/tcg-cpu-ops.h"
+
+static struct TCGCPUOps superh_tcg_ops = {
+ .initialize = sh4_translate_init,
+ .synchronize_from_tb = superh_cpu_synchronize_from_tb,
+ .cpu_exec_interrupt = superh_cpu_exec_interrupt,
+ .tlb_fill = superh_cpu_tlb_fill,
+
+#ifndef CONFIG_USER_ONLY
+ .do_interrupt = superh_cpu_do_interrupt,
+ .do_unaligned_access = superh_cpu_do_unaligned_access,
+#endif /* !CONFIG_USER_ONLY */
+};
+
static void superh_cpu_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
cc->class_by_name = superh_cpu_class_by_name;
cc->has_work = superh_cpu_has_work;
- cc->tcg_ops.do_interrupt = superh_cpu_do_interrupt;
- cc->tcg_ops.cpu_exec_interrupt = superh_cpu_exec_interrupt;
cc->dump_state = superh_cpu_dump_state;
cc->set_pc = superh_cpu_set_pc;
- cc->tcg_ops.synchronize_from_tb = superh_cpu_synchronize_from_tb;
cc->gdb_read_register = superh_cpu_gdb_read_register;
cc->gdb_write_register = superh_cpu_gdb_write_register;
- cc->tcg_ops.tlb_fill = superh_cpu_tlb_fill;
#ifndef CONFIG_USER_ONLY
- cc->tcg_ops.do_unaligned_access = superh_cpu_do_unaligned_access;
cc->get_phys_page_debug = superh_cpu_get_phys_page_debug;
#endif
cc->disas_set_info = superh_cpu_disas_set_info;
- cc->tcg_ops.initialize = sh4_translate_init;
cc->gdb_num_core_regs = 59;
dc->vmsd = &vmstate_sh_cpu;
+ cc->tcg_ops = &superh_tcg_ops;
}
#define DEFINE_SUPERH_CPU_TYPE(type_name, cinit, initfn) \
DEFINE_PROP_END_OF_LIST()
};
+#ifdef CONFIG_TCG
+#include "hw/core/tcg-cpu-ops.h"
+
+static struct TCGCPUOps sparc_tcg_ops = {
+ .initialize = sparc_tcg_init,
+ .synchronize_from_tb = sparc_cpu_synchronize_from_tb,
+ .cpu_exec_interrupt = sparc_cpu_exec_interrupt,
+ .tlb_fill = sparc_cpu_tlb_fill,
+
+#ifndef CONFIG_USER_ONLY
+ .do_interrupt = sparc_cpu_do_interrupt,
+ .do_transaction_failed = sparc_cpu_do_transaction_failed,
+ .do_unaligned_access = sparc_cpu_do_unaligned_access,
+#endif /* !CONFIG_USER_ONLY */
+};
+#endif /* CONFIG_TCG */
+
static void sparc_cpu_class_init(ObjectClass *oc, void *data)
{
SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
cc->class_by_name = sparc_cpu_class_by_name;
cc->parse_features = sparc_cpu_parse_features;
cc->has_work = sparc_cpu_has_work;
- cc->tcg_ops.do_interrupt = sparc_cpu_do_interrupt;
- cc->tcg_ops.cpu_exec_interrupt = sparc_cpu_exec_interrupt;
cc->dump_state = sparc_cpu_dump_state;
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
#endif
cc->set_pc = sparc_cpu_set_pc;
- cc->tcg_ops.synchronize_from_tb = sparc_cpu_synchronize_from_tb;
cc->gdb_read_register = sparc_cpu_gdb_read_register;
cc->gdb_write_register = sparc_cpu_gdb_write_register;
- cc->tcg_ops.tlb_fill = sparc_cpu_tlb_fill;
#ifndef CONFIG_USER_ONLY
- cc->tcg_ops.do_transaction_failed = sparc_cpu_do_transaction_failed;
- cc->tcg_ops.do_unaligned_access = sparc_cpu_do_unaligned_access;
cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
cc->vmsd = &vmstate_sparc_cpu;
#endif
cc->disas_set_info = cpu_sparc_disas_set_info;
- cc->tcg_ops.initialize = sparc_tcg_init;
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
cc->gdb_num_core_regs = 86;
#else
cc->gdb_num_core_regs = 72;
#endif
+ cc->tcg_ops = &sparc_tcg_ops;
}
static const TypeInfo sparc_cpu_type_info = {
return false;
}
+#include "hw/core/tcg-cpu-ops.h"
+
+static struct TCGCPUOps tilegx_tcg_ops = {
+ .initialize = tilegx_tcg_init,
+ .cpu_exec_interrupt = tilegx_cpu_exec_interrupt,
+ .tlb_fill = tilegx_cpu_tlb_fill,
+
+#ifndef CONFIG_USER_ONLY
+ .do_interrupt = tilegx_cpu_do_interrupt,
+#endif /* !CONFIG_USER_ONLY */
+};
+
static void tilegx_cpu_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
cc->class_by_name = tilegx_cpu_class_by_name;
cc->has_work = tilegx_cpu_has_work;
- cc->tcg_ops.do_interrupt = tilegx_cpu_do_interrupt;
- cc->tcg_ops.cpu_exec_interrupt = tilegx_cpu_exec_interrupt;
cc->dump_state = tilegx_cpu_dump_state;
cc->set_pc = tilegx_cpu_set_pc;
- cc->tcg_ops.tlb_fill = tilegx_cpu_tlb_fill;
cc->gdb_num_core_regs = 0;
- cc->tcg_ops.initialize = tilegx_tcg_init;
+ cc->tcg_ops = &tilegx_tcg_ops;
}
static const TypeInfo tilegx_cpu_type_info = {
set_feature(&cpu->env, TRICORE_FEATURE_161);
}
+#include "hw/core/tcg-cpu-ops.h"
+
+static struct TCGCPUOps tricore_tcg_ops = {
+ .initialize = tricore_tcg_init,
+ .synchronize_from_tb = tricore_cpu_synchronize_from_tb,
+ .tlb_fill = tricore_cpu_tlb_fill,
+};
+
static void tricore_cpu_class_init(ObjectClass *c, void *data)
{
TriCoreCPUClass *mcc = TRICORE_CPU_CLASS(c);
cc->dump_state = tricore_cpu_dump_state;
cc->set_pc = tricore_cpu_set_pc;
- cc->tcg_ops.synchronize_from_tb = tricore_cpu_synchronize_from_tb;
cc->get_phys_page_debug = tricore_cpu_get_phys_page_debug;
- cc->tcg_ops.initialize = tricore_tcg_init;
- cc->tcg_ops.tlb_fill = tricore_cpu_tlb_fill;
+ cc->tcg_ops = &tricore_tcg_ops;
}
#define DEFINE_TRICORE_CPU_TYPE(cpu_model, initfn) \
.unmigratable = 1,
};
+#include "hw/core/tcg-cpu-ops.h"
+
+static struct TCGCPUOps uc32_tcg_ops = {
+ .initialize = uc32_translate_init,
+ .cpu_exec_interrupt = uc32_cpu_exec_interrupt,
+ .tlb_fill = uc32_cpu_tlb_fill,
+
+#ifndef CONFIG_USER_ONLY
+ .do_interrupt = uc32_cpu_do_interrupt,
+#endif /* !CONFIG_USER_ONLY */
+};
+
static void uc32_cpu_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
cc->class_by_name = uc32_cpu_class_by_name;
cc->has_work = uc32_cpu_has_work;
- cc->tcg_ops.do_interrupt = uc32_cpu_do_interrupt;
- cc->tcg_ops.cpu_exec_interrupt = uc32_cpu_exec_interrupt;
cc->dump_state = uc32_cpu_dump_state;
cc->set_pc = uc32_cpu_set_pc;
- cc->tcg_ops.tlb_fill = uc32_cpu_tlb_fill;
cc->get_phys_page_debug = uc32_cpu_get_phys_page_debug;
- cc->tcg_ops.initialize = uc32_translate_init;
dc->vmsd = &vmstate_uc32_cpu;
+ cc->tcg_ops = &uc32_tcg_ops;
}
#define DEFINE_UNICORE32_CPU_TYPE(cpu_model, initfn) \
.unmigratable = 1,
};
+#include "hw/core/tcg-cpu-ops.h"
+
+static struct TCGCPUOps xtensa_tcg_ops = {
+ .initialize = xtensa_translate_init,
+ .cpu_exec_interrupt = xtensa_cpu_exec_interrupt,
+ .tlb_fill = xtensa_cpu_tlb_fill,
+ .debug_excp_handler = xtensa_breakpoint_handler,
+
+#ifndef CONFIG_USER_ONLY
+ .do_interrupt = xtensa_cpu_do_interrupt,
+ .do_transaction_failed = xtensa_cpu_do_transaction_failed,
+ .do_unaligned_access = xtensa_cpu_do_unaligned_access,
+#endif /* !CONFIG_USER_ONLY */
+};
+
static void xtensa_cpu_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
cc->class_by_name = xtensa_cpu_class_by_name;
cc->has_work = xtensa_cpu_has_work;
- cc->tcg_ops.do_interrupt = xtensa_cpu_do_interrupt;
- cc->tcg_ops.cpu_exec_interrupt = xtensa_cpu_exec_interrupt;
cc->dump_state = xtensa_cpu_dump_state;
cc->set_pc = xtensa_cpu_set_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;
- cc->tcg_ops.tlb_fill = xtensa_cpu_tlb_fill;
#ifndef CONFIG_USER_ONLY
- cc->tcg_ops.do_unaligned_access = xtensa_cpu_do_unaligned_access;
cc->get_phys_page_debug = xtensa_cpu_get_phys_page_debug;
- cc->tcg_ops.do_transaction_failed = xtensa_cpu_do_transaction_failed;
#endif
- cc->tcg_ops.debug_excp_handler = xtensa_breakpoint_handler;
cc->disas_set_info = xtensa_cpu_disas_set_info;
- cc->tcg_ops.initialize = xtensa_translate_init;
dc->vmsd = &vmstate_xtensa_cpu;
+ cc->tcg_ops = &xtensa_tcg_ops;
}
static const TypeInfo xtensa_cpu_type_info = {