mirror of https://gitee.com/openkylin/qemu.git
Merge remote-tracking branch 'qemu-kvm/memory/urgent' into staging
* qemu-kvm/memory/urgent: (42 commits) memory: check for watchpoints when getting code ram_addr exec: fix write tlb entry misused as iotlb Sparc: avoid AREG0 wrappers for memory access helpers Sparc: avoid AREG0 for memory access helpers TCG: add 5 arg helpers to def-helper.h softmmu templates: optionally pass CPUState to memory access functions i386: Remove REGPARM sparc64: implement PCI and ISA irqs sparc: reset CPU state on reset apb: use normal PCI device header for PBM device w64: Fix data type of next_tb and tcg_qemu_tb_exec softfloat: fix for C99 vmstate: fix varrays with uint32_t indexes Fix large memory chunks allocation with tcg_malloc. hw/pxa2xx.c: Fix handling of pxa2xx_i2c variable offset within region hw/pxa2xx_lcd.c: drop target_phys_addr_t usage in device state hw/pxa2xx_dma.c: drop target_phys_addr_t usage in device state ARM: Remove unnecessary subpage workarounds malta: Fix display for LED array malta: Use symbolic hardware addresses ...
This commit is contained in:
commit
b8b3e75609
|
@ -80,7 +80,10 @@ libobj-y = exec.o translate-all.o cpu-exec.o translate.o
|
|||
libobj-y += tcg/tcg.o tcg/optimize.o
|
||||
libobj-$(CONFIG_TCG_INTERPRETER) += tci.o
|
||||
libobj-y += fpu/softfloat.o
|
||||
libobj-y += op_helper.o helper.o
|
||||
ifneq ($(TARGET_BASE_ARCH), sparc)
|
||||
libobj-y += op_helper.o
|
||||
endif
|
||||
libobj-y += helper.o
|
||||
ifeq ($(TARGET_BASE_ARCH), i386)
|
||||
libobj-y += cpuid.o
|
||||
endif
|
||||
|
@ -101,9 +104,12 @@ tci-dis.o: QEMU_CFLAGS += -I$(SRC_PATH)/tcg -I$(SRC_PATH)/tcg/tci
|
|||
|
||||
$(libobj-y): $(GENERATED_HEADERS)
|
||||
|
||||
# HELPER_CFLAGS is used for all the code compiled with static register
|
||||
# HELPER_CFLAGS is used for all the legacy code compiled with static register
|
||||
# variables
|
||||
op_helper.o ldst_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
|
||||
ifneq ($(TARGET_BASE_ARCH), sparc)
|
||||
op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
|
||||
endif
|
||||
user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
|
||||
|
||||
# Note: this is a workaround. The real fix is to avoid compiling
|
||||
# cpu_signal_handler() in user-exec.c.
|
||||
|
|
|
@ -3606,6 +3606,13 @@ case "$target_arch2" in
|
|||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$target_arch2" in
|
||||
sparc*)
|
||||
echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "TARGET_SHORT_ALIGNMENT=$target_short_alignment" >> $config_target_mak
|
||||
echo "TARGET_INT_ALIGNMENT=$target_int_alignment" >> $config_target_mak
|
||||
echo "TARGET_LONG_ALIGNMENT=$target_long_alignment" >> $config_target_mak
|
||||
|
|
|
@ -259,12 +259,21 @@ extern unsigned long reserved_va;
|
|||
#define stfl(p, v) stfl_raw(p, v)
|
||||
#define stfq(p, v) stfq_raw(p, v)
|
||||
|
||||
#ifndef CONFIG_TCG_PASS_AREG0
|
||||
#define ldub_code(p) ldub_raw(p)
|
||||
#define ldsb_code(p) ldsb_raw(p)
|
||||
#define lduw_code(p) lduw_raw(p)
|
||||
#define ldsw_code(p) ldsw_raw(p)
|
||||
#define ldl_code(p) ldl_raw(p)
|
||||
#define ldq_code(p) ldq_raw(p)
|
||||
#else
|
||||
#define cpu_ldub_code(env1, p) ldub_raw(p)
|
||||
#define cpu_ldsb_code(env1, p) ldsb_raw(p)
|
||||
#define cpu_lduw_code(env1, p) lduw_raw(p)
|
||||
#define cpu_ldsw_code(env1, p) ldsw_raw(p)
|
||||
#define cpu_ldl_code(env1, p) ldl_raw(p)
|
||||
#define cpu_ldq_code(env1, p) ldq_raw(p)
|
||||
#endif
|
||||
|
||||
#define ldub_kernel(p) ldub_raw(p)
|
||||
#define ldsb_kernel(p) ldsb_raw(p)
|
||||
|
|
|
@ -55,7 +55,7 @@ void cpu_resume_from_signal(CPUArchState *env, void *puc)
|
|||
static void cpu_exec_nocache(CPUArchState *env, int max_cycles,
|
||||
TranslationBlock *orig_tb)
|
||||
{
|
||||
unsigned long next_tb;
|
||||
tcg_target_ulong next_tb;
|
||||
TranslationBlock *tb;
|
||||
|
||||
/* Should never happen.
|
||||
|
@ -186,7 +186,7 @@ int cpu_exec(CPUArchState *env)
|
|||
int ret, interrupt_request;
|
||||
TranslationBlock *tb;
|
||||
uint8_t *tc_ptr;
|
||||
unsigned long next_tb;
|
||||
tcg_target_ulong next_tb;
|
||||
|
||||
if (env->halted) {
|
||||
if (!cpu_has_work(env)) {
|
||||
|
@ -565,7 +565,7 @@ int cpu_exec(CPUArchState *env)
|
|||
if ((next_tb & 3) == 2) {
|
||||
/* Instruction counter expired. */
|
||||
int insns_left;
|
||||
tb = (TranslationBlock *)(long)(next_tb & ~3);
|
||||
tb = (TranslationBlock *)(next_tb & ~3);
|
||||
/* Restore PC. */
|
||||
cpu_pc_from_tb(env, tb);
|
||||
insns_left = env->icount_decr.u32;
|
||||
|
|
26
def-helper.h
26
def-helper.h
|
@ -118,6 +118,8 @@
|
|||
DEF_HELPER_FLAGS_3(name, 0, ret, t1, t2, t3)
|
||||
#define DEF_HELPER_4(name, ret, t1, t2, t3, t4) \
|
||||
DEF_HELPER_FLAGS_4(name, 0, ret, t1, t2, t3, t4)
|
||||
#define DEF_HELPER_5(name, ret, t1, t2, t3, t4, t5) \
|
||||
DEF_HELPER_FLAGS_5(name, 0, ret, t1, t2, t3, t4, t5)
|
||||
|
||||
#endif /* DEF_HELPER_H */
|
||||
|
||||
|
@ -140,6 +142,10 @@ dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3));
|
|||
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
|
||||
dh_ctype(t4));
|
||||
|
||||
#define DEF_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5) \
|
||||
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
|
||||
dh_ctype(t4), dh_ctype(t5));
|
||||
|
||||
#undef GEN_HELPER
|
||||
#define GEN_HELPER -1
|
||||
|
||||
|
@ -203,6 +209,22 @@ static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) dh_arg_decl(t1, 1
|
|||
tcg_gen_helperN(HELPER(name), flags, sizemask, dh_retvar(ret), 4, args); \
|
||||
}
|
||||
|
||||
#define DEF_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5) \
|
||||
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
||||
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), \
|
||||
dh_arg_decl(t4, 4), dh_arg_decl(t5, 5)) \
|
||||
{ \
|
||||
TCGArg args[5]; \
|
||||
int sizemask = 0; \
|
||||
dh_sizemask(ret, 0); \
|
||||
dh_arg(t1, 1); \
|
||||
dh_arg(t2, 2); \
|
||||
dh_arg(t3, 3); \
|
||||
dh_arg(t4, 4); \
|
||||
dh_arg(t5, 5); \
|
||||
tcg_gen_helperN(HELPER(name), flags, sizemask, dh_retvar(ret), 5, args); \
|
||||
}
|
||||
|
||||
#undef GEN_HELPER
|
||||
#define GEN_HELPER -1
|
||||
|
||||
|
@ -224,6 +246,9 @@ DEF_HELPER_FLAGS_0(name, flags, ret)
|
|||
#define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \
|
||||
DEF_HELPER_FLAGS_0(name, flags, ret)
|
||||
|
||||
#define DEF_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5) \
|
||||
DEF_HELPER_FLAGS_0(name, flags, ret)
|
||||
|
||||
#undef GEN_HELPER
|
||||
#define GEN_HELPER -1
|
||||
|
||||
|
@ -235,6 +260,7 @@ DEF_HELPER_FLAGS_0(name, flags, ret)
|
|||
#undef DEF_HELPER_FLAGS_2
|
||||
#undef DEF_HELPER_FLAGS_3
|
||||
#undef DEF_HELPER_FLAGS_4
|
||||
#undef DEF_HELPER_FLAGS_5
|
||||
#undef GEN_HELPER
|
||||
|
||||
#endif
|
||||
|
|
|
@ -312,7 +312,9 @@ void tlb_fill(CPUArchState *env1, target_ulong addr, int is_write, int mmu_idx,
|
|||
|
||||
#define ACCESS_TYPE (NB_MMU_MODES + 1)
|
||||
#define MEMSUFFIX _code
|
||||
#ifndef CONFIG_TCG_PASS_AREG0
|
||||
#define env cpu_single_env
|
||||
#endif
|
||||
|
||||
#define DATA_SIZE 1
|
||||
#include "softmmu_header.h"
|
||||
|
|
18
exec.c
18
exec.c
|
@ -2031,14 +2031,19 @@ static void tlb_unprotect_code_phys(CPUArchState *env, ram_addr_t ram_addr,
|
|||
cpu_physical_memory_set_dirty_flags(ram_addr, CODE_DIRTY_FLAG);
|
||||
}
|
||||
|
||||
static bool tlb_is_dirty_ram(CPUTLBEntry *tlbe)
|
||||
{
|
||||
return (tlbe->addr_write & (TLB_INVALID_MASK|TLB_MMIO|TLB_NOTDIRTY)) == 0;
|
||||
}
|
||||
|
||||
static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
|
||||
unsigned long start, unsigned long length)
|
||||
{
|
||||
unsigned long addr;
|
||||
if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr) {
|
||||
if (tlb_is_dirty_ram(tlb_entry)) {
|
||||
addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
|
||||
if ((addr - start) < length) {
|
||||
tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | TLB_NOTDIRTY;
|
||||
tlb_entry->addr_write |= TLB_NOTDIRTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2091,7 +2096,7 @@ static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
|
|||
ram_addr_t ram_addr;
|
||||
void *p;
|
||||
|
||||
if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr) {
|
||||
if (tlb_is_dirty_ram(tlb_entry)) {
|
||||
p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK)
|
||||
+ tlb_entry->addend);
|
||||
ram_addr = qemu_ram_addr_from_host_nofail(p);
|
||||
|
@ -4595,12 +4600,17 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
|
|||
mmu_idx = cpu_mmu_index(env1);
|
||||
if (unlikely(env1->tlb_table[mmu_idx][page_index].addr_code !=
|
||||
(addr & TARGET_PAGE_MASK))) {
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
cpu_ldub_code(env1, addr);
|
||||
#else
|
||||
ldub_code(addr);
|
||||
#endif
|
||||
}
|
||||
pd = env1->iotlb[mmu_idx][page_index] & ~TARGET_PAGE_MASK;
|
||||
mr = iotlb_to_region(pd);
|
||||
if (mr != &io_mem_ram && mr != &io_mem_rom
|
||||
&& mr != &io_mem_notdirty && !mr->rom_device) {
|
||||
&& mr != &io_mem_notdirty && !mr->rom_device
|
||||
&& mr != &io_mem_watch) {
|
||||
#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SPARC)
|
||||
cpu_unassigned_access(env1, addr, 0, 1, 0, 4);
|
||||
#else
|
||||
|
|
|
@ -89,8 +89,8 @@ const float64 float64_default_nan = const_float64(LIT64( 0xFFF8000000000000 ));
|
|||
#define floatx80_default_nan_low LIT64( 0xC000000000000000 )
|
||||
#endif
|
||||
|
||||
const floatx80 floatx80_default_nan = make_floatx80(floatx80_default_nan_high,
|
||||
floatx80_default_nan_low);
|
||||
const floatx80 floatx80_default_nan
|
||||
= make_floatx80_init(floatx80_default_nan_high, floatx80_default_nan_low);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The pattern for a default generated quadruple-precision NaN. The `high' and
|
||||
|
@ -104,8 +104,8 @@ const floatx80 floatx80_default_nan = make_floatx80(floatx80_default_nan_high,
|
|||
#define float128_default_nan_low LIT64( 0x0000000000000000 )
|
||||
#endif
|
||||
|
||||
const float128 float128_default_nan = make_float128(float128_default_nan_high,
|
||||
float128_default_nan_low);
|
||||
const float128 float128_default_nan
|
||||
= make_float128_init(float128_default_nan_high, float128_default_nan_low);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Raises the exceptions specified by `flags'. Floating-point traps can be
|
||||
|
|
|
@ -129,6 +129,7 @@ typedef struct {
|
|||
uint16_t high;
|
||||
} floatx80;
|
||||
#define make_floatx80(exp, mant) ((floatx80) { mant, exp })
|
||||
#define make_floatx80_init(exp, mant) { .low = mant, .high = exp }
|
||||
typedef struct {
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
uint64_t high, low;
|
||||
|
@ -137,6 +138,7 @@ typedef struct {
|
|||
#endif
|
||||
} float128;
|
||||
#define make_float128(high_, low_) ((float128) { .high = high_, .low = low_ })
|
||||
#define make_float128_init(high_, low_) { .high = high_, .low = low_ }
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE floating-point underflow tininess-detection mode.
|
||||
|
|
49
hw/apb_pci.c
49
hw/apb_pci.c
|
@ -66,6 +66,8 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
|
|||
#define RESET_WCMASK 0x98000000
|
||||
#define RESET_WMASK 0x60000000
|
||||
|
||||
#define MAX_IVEC 0x30
|
||||
|
||||
typedef struct APBState {
|
||||
SysBusDevice busdev;
|
||||
PCIBus *bus;
|
||||
|
@ -77,7 +79,8 @@ typedef struct APBState {
|
|||
uint32_t pci_control[16];
|
||||
uint32_t pci_irq_map[8];
|
||||
uint32_t obio_irq_map[32];
|
||||
qemu_irq pci_irqs[32];
|
||||
qemu_irq *pbm_irqs;
|
||||
qemu_irq *ivec_irqs;
|
||||
uint32_t reset_control;
|
||||
unsigned int nr_resets;
|
||||
} APBState;
|
||||
|
@ -87,7 +90,7 @@ static void apb_config_writel (void *opaque, target_phys_addr_t addr,
|
|||
{
|
||||
APBState *s = opaque;
|
||||
|
||||
APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %x\n", __func__, addr, val);
|
||||
APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %" PRIx64 "\n", __func__, addr, val);
|
||||
|
||||
switch (addr & 0xffff) {
|
||||
case 0x30 ... 0x4f: /* DMA error registers */
|
||||
|
@ -104,6 +107,12 @@ static void apb_config_writel (void *opaque, target_phys_addr_t addr,
|
|||
s->pci_irq_map[(addr & 0x3f) >> 3] |= val & ~PBM_PCI_IMR_MASK;
|
||||
}
|
||||
break;
|
||||
case 0x1000 ... 0x1080: /* OBIO interrupt control */
|
||||
if (addr & 4) {
|
||||
s->obio_irq_map[(addr & 0xff) >> 3] &= PBM_PCI_IMR_MASK;
|
||||
s->obio_irq_map[(addr & 0xff) >> 3] |= val & ~PBM_PCI_IMR_MASK;
|
||||
}
|
||||
break;
|
||||
case 0x2000 ... 0x202f: /* PCI control */
|
||||
s->pci_control[(addr & 0x3f) >> 2] = val;
|
||||
break;
|
||||
|
@ -154,6 +163,13 @@ static uint64_t apb_config_readl (void *opaque,
|
|||
val = 0;
|
||||
}
|
||||
break;
|
||||
case 0x1000 ... 0x1080: /* OBIO interrupt control */
|
||||
if (addr & 4) {
|
||||
val = s->obio_irq_map[(addr & 0xff) >> 3];
|
||||
} else {
|
||||
val = 0;
|
||||
}
|
||||
break;
|
||||
case 0x2000 ... 0x202f: /* PCI control */
|
||||
val = s->pci_control[(addr & 0x3f) >> 2];
|
||||
break;
|
||||
|
@ -190,7 +206,7 @@ static void apb_pci_config_write(void *opaque, target_phys_addr_t addr,
|
|||
APBState *s = opaque;
|
||||
|
||||
val = qemu_bswap_len(val, size);
|
||||
APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %x\n", __func__, addr, val);
|
||||
APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %" PRIx64 "\n", __func__, addr, val);
|
||||
pci_data_write(s->bus, addr, val, size);
|
||||
}
|
||||
|
||||
|
@ -280,10 +296,19 @@ static void pci_apb_set_irq(void *opaque, int irq_num, int level)
|
|||
if (irq_num < 32) {
|
||||
if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
|
||||
APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
|
||||
qemu_set_irq(s->pci_irqs[irq_num], level);
|
||||
qemu_set_irq(s->ivec_irqs[irq_num], level);
|
||||
} else {
|
||||
APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num);
|
||||
qemu_irq_lower(s->pci_irqs[irq_num]);
|
||||
qemu_irq_lower(s->ivec_irqs[irq_num]);
|
||||
}
|
||||
} else {
|
||||
/* OBIO IRQ map onto the next 16 INO. */
|
||||
if (s->obio_irq_map[irq_num - 32] & PBM_PCI_IMR_ENABLED) {
|
||||
APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
|
||||
qemu_set_irq(s->ivec_irqs[irq_num], level);
|
||||
} else {
|
||||
APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num);
|
||||
qemu_irq_lower(s->ivec_irqs[irq_num]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -316,12 +341,12 @@ static int apb_pci_bridge_initfn(PCIDevice *dev)
|
|||
|
||||
PCIBus *pci_apb_init(target_phys_addr_t special_base,
|
||||
target_phys_addr_t mem_base,
|
||||
qemu_irq *pic, PCIBus **bus2, PCIBus **bus3)
|
||||
qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3,
|
||||
qemu_irq **pbm_irqs)
|
||||
{
|
||||
DeviceState *dev;
|
||||
SysBusDevice *s;
|
||||
APBState *d;
|
||||
unsigned int i;
|
||||
PCIDevice *pci_dev;
|
||||
PCIBridge *br;
|
||||
|
||||
|
@ -346,9 +371,8 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
|
|||
get_system_io(),
|
||||
0, 32);
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
sysbus_connect_irq(s, i, pic[i]);
|
||||
}
|
||||
*pbm_irqs = d->pbm_irqs;
|
||||
d->ivec_irqs = ivec_irqs;
|
||||
|
||||
pci_create_simple(d->bus, 0, "pbm-pci");
|
||||
|
||||
|
@ -402,9 +426,7 @@ static int pci_pbm_init_device(SysBusDevice *dev)
|
|||
for (i = 0; i < 8; i++) {
|
||||
s->pci_irq_map[i] = (0x1f << 6) | (i << 2);
|
||||
}
|
||||
for (i = 0; i < 32; i++) {
|
||||
sysbus_init_irq(dev, &s->pci_irqs[i]);
|
||||
}
|
||||
s->pbm_irqs = qemu_allocate_irqs(pci_apb_set_irq, s, MAX_IVEC);
|
||||
|
||||
/* apb_config */
|
||||
memory_region_init_io(&s->apb_config, &apb_config_ops, s, "apb-config",
|
||||
|
@ -444,7 +466,6 @@ static void pbm_pci_host_class_init(ObjectClass *klass, void *data)
|
|||
k->vendor_id = PCI_VENDOR_ID_SUN;
|
||||
k->device_id = PCI_DEVICE_ID_SUN_SABRE;
|
||||
k->class_id = PCI_CLASS_BRIDGE_HOST;
|
||||
k->is_bridge = 1;
|
||||
}
|
||||
|
||||
static TypeInfo pbm_pci_host_info = {
|
||||
|
|
|
@ -5,5 +5,6 @@
|
|||
|
||||
PCIBus *pci_apb_init(target_phys_addr_t special_base,
|
||||
target_phys_addr_t mem_base,
|
||||
qemu_irq *pic, PCIBus **bus2, PCIBus **bus3);
|
||||
qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3,
|
||||
qemu_irq **pbm_irqs);
|
||||
#endif
|
||||
|
|
|
@ -42,7 +42,6 @@ static uint64_t mpcore_scu_read(void *opaque, target_phys_addr_t offset,
|
|||
{
|
||||
mpcore_priv_state *s = (mpcore_priv_state *)opaque;
|
||||
int id;
|
||||
offset &= 0xff;
|
||||
/* SCU */
|
||||
switch (offset) {
|
||||
case 0x00: /* Control. */
|
||||
|
@ -63,7 +62,6 @@ static void mpcore_scu_write(void *opaque, target_phys_addr_t offset,
|
|||
uint64_t value, unsigned size)
|
||||
{
|
||||
mpcore_priv_state *s = (mpcore_priv_state *)opaque;
|
||||
offset &= 0xff;
|
||||
/* SCU */
|
||||
switch (offset) {
|
||||
case 0: /* Control register. */
|
||||
|
|
|
@ -658,14 +658,14 @@ static uint64_t gic_thiscpu_read(void *opaque, target_phys_addr_t addr,
|
|||
unsigned size)
|
||||
{
|
||||
gic_state *s = (gic_state *)opaque;
|
||||
return gic_cpu_read(s, gic_get_current_cpu(), addr & 0xff);
|
||||
return gic_cpu_read(s, gic_get_current_cpu(), addr);
|
||||
}
|
||||
|
||||
static void gic_thiscpu_write(void *opaque, target_phys_addr_t addr,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
gic_state *s = (gic_state *)opaque;
|
||||
gic_cpu_write(s, gic_get_current_cpu(), addr & 0xff, value);
|
||||
gic_cpu_write(s, gic_get_current_cpu(), addr, value);
|
||||
}
|
||||
|
||||
/* Wrappers to read/write the GIC CPU interface for a specific CPU.
|
||||
|
@ -677,7 +677,7 @@ static uint64_t gic_do_cpu_read(void *opaque, target_phys_addr_t addr,
|
|||
gic_state **backref = (gic_state **)opaque;
|
||||
gic_state *s = *backref;
|
||||
int id = (backref - s->backref);
|
||||
return gic_cpu_read(s, id, addr & 0xff);
|
||||
return gic_cpu_read(s, id, addr);
|
||||
}
|
||||
|
||||
static void gic_do_cpu_write(void *opaque, target_phys_addr_t addr,
|
||||
|
@ -686,7 +686,7 @@ static void gic_do_cpu_write(void *opaque, target_phys_addr_t addr,
|
|||
gic_state **backref = (gic_state **)opaque;
|
||||
gic_state *s = *backref;
|
||||
int id = (backref - s->backref);
|
||||
gic_cpu_write(s, id, addr & 0xff, value);
|
||||
gic_cpu_write(s, id, addr, value);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps gic_thiscpu_ops = {
|
||||
|
|
|
@ -97,7 +97,6 @@ static uint64_t timerblock_read(void *opaque, target_phys_addr_t addr,
|
|||
{
|
||||
timerblock *tb = (timerblock *)opaque;
|
||||
int64_t val;
|
||||
addr &= 0x1f;
|
||||
switch (addr) {
|
||||
case 0: /* Load */
|
||||
return tb->load;
|
||||
|
@ -126,7 +125,6 @@ static void timerblock_write(void *opaque, target_phys_addr_t addr,
|
|||
{
|
||||
timerblock *tb = (timerblock *)opaque;
|
||||
int64_t old;
|
||||
addr &= 0x1f;
|
||||
switch (addr) {
|
||||
case 0: /* Load */
|
||||
tb->load = value;
|
||||
|
|
|
@ -55,6 +55,13 @@
|
|||
#define ENVP_NB_ENTRIES 16
|
||||
#define ENVP_ENTRY_SIZE 256
|
||||
|
||||
/* Hardware addresses */
|
||||
#define FLASH_ADDRESS 0x1e000000ULL
|
||||
#define FPGA_ADDRESS 0x1f000000ULL
|
||||
#define RESET_ADDRESS 0x1fc00000ULL
|
||||
|
||||
#define FLASH_SIZE 0x400000
|
||||
|
||||
#define MAX_IDE_BUS 2
|
||||
|
||||
typedef struct {
|
||||
|
@ -331,9 +338,9 @@ static void malta_fpga_write(void *opaque, target_phys_addr_t addr,
|
|||
break;
|
||||
|
||||
/* LEDBAR Register */
|
||||
/* XXX: implement a 8-LED array */
|
||||
case 0x00408:
|
||||
s->leds = val & 0xff;
|
||||
malta_fpga_update_display(s);
|
||||
break;
|
||||
|
||||
/* ASCIIWORD Register */
|
||||
|
@ -777,7 +784,7 @@ void mips_malta_init (ram_addr_t ram_size,
|
|||
MemoryRegion *system_memory = get_system_memory();
|
||||
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
||||
MemoryRegion *bios, *bios_alias = g_new(MemoryRegion, 1);
|
||||
target_long bios_size;
|
||||
target_long bios_size = FLASH_SIZE;
|
||||
int64_t kernel_entry;
|
||||
PCIBus *pci_bus;
|
||||
ISABus *isa_bus;
|
||||
|
@ -791,7 +798,7 @@ void mips_malta_init (ram_addr_t ram_size,
|
|||
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
|
||||
DriveInfo *fd[MAX_FD];
|
||||
int fl_idx = 0;
|
||||
int fl_sectors = 0;
|
||||
int fl_sectors = bios_size >> 16;
|
||||
int be;
|
||||
|
||||
DeviceState *dev = qdev_create(NULL, "mips-malta");
|
||||
|
@ -847,19 +854,26 @@ void mips_malta_init (ram_addr_t ram_size,
|
|||
be = 0;
|
||||
#endif
|
||||
/* FPGA */
|
||||
malta_fpga_init(system_memory, 0x1f000000LL, env->irq[2], serial_hds[2]);
|
||||
malta_fpga_init(system_memory, FPGA_ADDRESS, env->irq[2], serial_hds[2]);
|
||||
|
||||
/* Load firmware in flash / BIOS unless we boot directly into a kernel. */
|
||||
/* Load firmware in flash / BIOS. */
|
||||
dinfo = drive_get(IF_PFLASH, 0, fl_idx);
|
||||
#ifdef DEBUG_BOARD_INIT
|
||||
if (dinfo) {
|
||||
printf("Register parallel flash %d size " TARGET_FMT_lx " at "
|
||||
"addr %08llx '%s' %x\n",
|
||||
fl_idx, bios_size, FLASH_ADDRESS,
|
||||
bdrv_get_device_name(dinfo->bdrv), fl_sectors);
|
||||
}
|
||||
#endif
|
||||
fl = pflash_cfi01_register(FLASH_ADDRESS, NULL, "mips_malta.bios",
|
||||
BIOS_SIZE, dinfo ? dinfo->bdrv : NULL,
|
||||
65536, fl_sectors,
|
||||
4, 0x0000, 0x0000, 0x0000, 0x0000, be);
|
||||
bios = pflash_cfi01_get_memory(fl);
|
||||
fl_idx++;
|
||||
if (kernel_filename) {
|
||||
/* Write a small bootloader to the flash location. */
|
||||
bios = g_new(MemoryRegion, 1);
|
||||
memory_region_init_ram(bios, "mips_malta.bios", BIOS_SIZE);
|
||||
vmstate_register_ram_global(bios);
|
||||
memory_region_set_readonly(bios, true);
|
||||
memory_region_init_alias(bios_alias, "bios.1fc", bios, 0, BIOS_SIZE);
|
||||
/* Map the bios at two physical locations, as on the real board. */
|
||||
memory_region_add_subregion(system_memory, 0x1e000000LL, bios);
|
||||
memory_region_add_subregion(system_memory, 0x1fc00000LL, bios_alias);
|
||||
loaderparams.ram_size = ram_size;
|
||||
loaderparams.kernel_filename = kernel_filename;
|
||||
loaderparams.kernel_cmdline = kernel_cmdline;
|
||||
|
@ -867,45 +881,15 @@ void mips_malta_init (ram_addr_t ram_size,
|
|||
kernel_entry = load_kernel();
|
||||
write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry);
|
||||
} else {
|
||||
dinfo = drive_get(IF_PFLASH, 0, fl_idx);
|
||||
if (dinfo) {
|
||||
/* Load firmware from flash. */
|
||||
bios_size = 0x400000;
|
||||
fl_sectors = bios_size >> 16;
|
||||
#ifdef DEBUG_BOARD_INIT
|
||||
printf("Register parallel flash %d size " TARGET_FMT_lx " at "
|
||||
"addr %08llx '%s' %x\n",
|
||||
fl_idx, bios_size, 0x1e000000LL,
|
||||
bdrv_get_device_name(dinfo->bdrv), fl_sectors);
|
||||
#endif
|
||||
fl = pflash_cfi01_register(0x1e000000LL,
|
||||
NULL, "mips_malta.bios", BIOS_SIZE,
|
||||
dinfo->bdrv, 65536, fl_sectors,
|
||||
4, 0x0000, 0x0000, 0x0000, 0x0000, be);
|
||||
bios = pflash_cfi01_get_memory(fl);
|
||||
/* Map the bios at two physical locations, as on the real board. */
|
||||
memory_region_init_alias(bios_alias, "bios.1fc",
|
||||
bios, 0, BIOS_SIZE);
|
||||
memory_region_add_subregion(system_memory, 0x1fc00000LL,
|
||||
bios_alias);
|
||||
fl_idx++;
|
||||
} else {
|
||||
bios = g_new(MemoryRegion, 1);
|
||||
memory_region_init_ram(bios, "mips_malta.bios", BIOS_SIZE);
|
||||
vmstate_register_ram_global(bios);
|
||||
memory_region_set_readonly(bios, true);
|
||||
memory_region_init_alias(bios_alias, "bios.1fc",
|
||||
bios, 0, BIOS_SIZE);
|
||||
/* Map the bios at two physical locations, as on the real board. */
|
||||
memory_region_add_subregion(system_memory, 0x1e000000LL, bios);
|
||||
memory_region_add_subregion(system_memory, 0x1fc00000LL,
|
||||
bios_alias);
|
||||
/* Load firmware from flash. */
|
||||
if (!dinfo) {
|
||||
/* Load a BIOS image. */
|
||||
if (bios_name == NULL)
|
||||
if (bios_name == NULL) {
|
||||
bios_name = BIOS_FILENAME;
|
||||
}
|
||||
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
|
||||
if (filename) {
|
||||
bios_size = load_image_targphys(filename, 0x1fc00000LL,
|
||||
bios_size = load_image_targphys(filename, FLASH_ADDRESS,
|
||||
BIOS_SIZE);
|
||||
g_free(filename);
|
||||
} else {
|
||||
|
@ -932,6 +916,10 @@ void mips_malta_init (ram_addr_t ram_size,
|
|||
#endif
|
||||
}
|
||||
|
||||
/* Map the BIOS at a 2nd physical location, as on the real board. */
|
||||
memory_region_init_alias(bios_alias, "bios.1fc", bios, 0, BIOS_SIZE);
|
||||
memory_region_add_subregion(system_memory, RESET_ADDRESS, bios_alias);
|
||||
|
||||
/* Board ID = 0x420 (Malta Board with CoreLV)
|
||||
XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
|
||||
map to the board ID. */
|
||||
|
|
12
hw/nseries.c
12
hw/nseries.c
|
@ -45,7 +45,6 @@ struct n800_s {
|
|||
uint32_t (*txrx)(void *opaque, uint32_t value, int len);
|
||||
uWireSlave *chip;
|
||||
} ts;
|
||||
i2c_bus *i2c;
|
||||
|
||||
int keymap[0x80];
|
||||
DeviceState *kbd;
|
||||
|
@ -194,12 +193,10 @@ static void n8x0_i2c_setup(struct n800_s *s)
|
|||
{
|
||||
DeviceState *dev;
|
||||
qemu_irq tmp_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_TMP105_GPIO);
|
||||
|
||||
/* Attach the CPU on one end of our I2C bus. */
|
||||
s->i2c = omap_i2c_bus(s->cpu->i2c[0]);
|
||||
i2c_bus *i2c = omap_i2c_bus(s->cpu->i2c[0]);
|
||||
|
||||
/* Attach a menelaus PM chip */
|
||||
dev = i2c_create_slave(s->i2c, "twl92230", N8X0_MENELAUS_ADDR);
|
||||
dev = i2c_create_slave(i2c, "twl92230", N8X0_MENELAUS_ADDR);
|
||||
qdev_connect_gpio_out(dev, 3,
|
||||
qdev_get_gpio_in(s->cpu->ih[0],
|
||||
OMAP_INT_24XX_SYS_NIRQ));
|
||||
|
@ -207,7 +204,7 @@ static void n8x0_i2c_setup(struct n800_s *s)
|
|||
qemu_system_powerdown = qdev_get_gpio_in(dev, 3);
|
||||
|
||||
/* Attach a TMP105 PM chip (A0 wired to ground) */
|
||||
dev = i2c_create_slave(s->i2c, "tmp105", N8X0_TMP105_ADDR);
|
||||
dev = i2c_create_slave(i2c, "tmp105", N8X0_TMP105_ADDR);
|
||||
qdev_connect_gpio_out(dev, 0, tmp_irq);
|
||||
}
|
||||
|
||||
|
@ -391,7 +388,8 @@ static void n810_kbd_setup(struct n800_s *s)
|
|||
|
||||
/* Attach the LM8322 keyboard to the I2C bus,
|
||||
* should happen in n8x0_i2c_setup and s->kbd be initialised here. */
|
||||
s->kbd = i2c_create_slave(s->i2c, "lm8323", N810_LM8323_ADDR);
|
||||
s->kbd = i2c_create_slave(omap_i2c_bus(s->cpu->i2c[0]),
|
||||
"lm8323", N810_LM8323_ADDR);
|
||||
qdev_connect_gpio_out(s->kbd, 0, kbd_irq);
|
||||
}
|
||||
|
||||
|
|
13
hw/omap.h
13
hw/omap.h
|
@ -764,16 +764,7 @@ void omap_mmc_handlers(struct omap_mmc_s *s, qemu_irq ro, qemu_irq cover);
|
|||
void omap_mmc_enable(struct omap_mmc_s *s, int enable);
|
||||
|
||||
/* omap_i2c.c */
|
||||
struct omap_i2c_s;
|
||||
struct omap_i2c_s *omap_i2c_init(MemoryRegion *sysmem,
|
||||
target_phys_addr_t base,
|
||||
qemu_irq irq,
|
||||
qemu_irq *dma,
|
||||
omap_clk clk);
|
||||
struct omap_i2c_s *omap2_i2c_init(struct omap_target_agent_s *ta,
|
||||
qemu_irq irq, qemu_irq *dma, omap_clk fclk, omap_clk iclk);
|
||||
void omap_i2c_reset(struct omap_i2c_s *s);
|
||||
i2c_bus *omap_i2c_bus(struct omap_i2c_s *s);
|
||||
i2c_bus *omap_i2c_bus(DeviceState *omap_i2c);
|
||||
|
||||
# define cpu_is_omap310(cpu) (cpu->mpu_model == omap310)
|
||||
# define cpu_is_omap1510(cpu) (cpu->mpu_model == omap1510)
|
||||
|
@ -867,7 +858,7 @@ struct omap_mpu_state_s {
|
|||
|
||||
struct omap_pwl_s *pwl;
|
||||
struct omap_pwt_s *pwt;
|
||||
struct omap_i2c_s *i2c[2];
|
||||
DeviceState *i2c[2];
|
||||
|
||||
struct omap_rtc_s *rtc;
|
||||
|
||||
|
|
13
hw/omap1.c
13
hw/omap1.c
|
@ -3694,7 +3694,6 @@ static void omap1_mpu_reset(void *opaque)
|
|||
omap_uwire_reset(mpu->microwire);
|
||||
omap_pwl_reset(mpu->pwl);
|
||||
omap_pwt_reset(mpu->pwt);
|
||||
omap_i2c_reset(mpu->i2c[0]);
|
||||
omap_rtc_reset(mpu->rtc);
|
||||
omap_mcbsp_reset(mpu->mcbsp1);
|
||||
omap_mcbsp_reset(mpu->mcbsp2);
|
||||
|
@ -3993,9 +3992,15 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
|
|||
s->pwt = omap_pwt_init(system_memory, 0xfffb6000,
|
||||
omap_findclk(s, "armxor_ck"));
|
||||
|
||||
s->i2c[0] = omap_i2c_init(system_memory, 0xfffb3800,
|
||||
qdev_get_gpio_in(s->ih[1], OMAP_INT_I2C),
|
||||
&s->drq[OMAP_DMA_I2C_RX], omap_findclk(s, "mpuper_ck"));
|
||||
s->i2c[0] = qdev_create(NULL, "omap_i2c");
|
||||
qdev_prop_set_uint8(s->i2c[0], "revision", 0x11);
|
||||
qdev_prop_set_ptr(s->i2c[0], "fclk", omap_findclk(s, "mpuper_ck"));
|
||||
qdev_init_nofail(s->i2c[0]);
|
||||
busdev = sysbus_from_qdev(s->i2c[0]);
|
||||
sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(s->ih[1], OMAP_INT_I2C));
|
||||
sysbus_connect_irq(busdev, 1, s->drq[OMAP_DMA_I2C_TX]);
|
||||
sysbus_connect_irq(busdev, 2, s->drq[OMAP_DMA_I2C_RX]);
|
||||
sysbus_mmio_map(busdev, 0, 0xfffb3800);
|
||||
|
||||
s->rtc = omap_rtc_init(system_memory, 0xfffb4800,
|
||||
qdev_get_gpio_in(s->ih[1], OMAP_INT_RTC_TIMER),
|
||||
|
|
35
hw/omap2.c
35
hw/omap2.c
|
@ -2222,8 +2222,6 @@ static void omap2_mpu_reset(void *opaque)
|
|||
omap_mmc_reset(mpu->mmc);
|
||||
omap_mcspi_reset(mpu->mcspi[0]);
|
||||
omap_mcspi_reset(mpu->mcspi[1]);
|
||||
omap_i2c_reset(mpu->i2c[0]);
|
||||
omap_i2c_reset(mpu->i2c[1]);
|
||||
cpu_state_reset(mpu->env);
|
||||
}
|
||||
|
||||
|
@ -2395,16 +2393,29 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
|
|||
omap_findclk(s, "clk32-kHz"),
|
||||
omap_findclk(s, "core_l4_iclk"));
|
||||
|
||||
s->i2c[0] = omap2_i2c_init(omap_l4tao(s->l4, 5),
|
||||
qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C1_IRQ),
|
||||
&s->drq[OMAP24XX_DMA_I2C1_TX],
|
||||
omap_findclk(s, "i2c1.fclk"),
|
||||
omap_findclk(s, "i2c1.iclk"));
|
||||
s->i2c[1] = omap2_i2c_init(omap_l4tao(s->l4, 6),
|
||||
qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C2_IRQ),
|
||||
&s->drq[OMAP24XX_DMA_I2C2_TX],
|
||||
omap_findclk(s, "i2c2.fclk"),
|
||||
omap_findclk(s, "i2c2.iclk"));
|
||||
s->i2c[0] = qdev_create(NULL, "omap_i2c");
|
||||
qdev_prop_set_uint8(s->i2c[0], "revision", 0x34);
|
||||
qdev_prop_set_ptr(s->i2c[0], "iclk", omap_findclk(s, "i2c1.iclk"));
|
||||
qdev_prop_set_ptr(s->i2c[0], "fclk", omap_findclk(s, "i2c1.fclk"));
|
||||
qdev_init_nofail(s->i2c[0]);
|
||||
busdev = sysbus_from_qdev(s->i2c[0]);
|
||||
sysbus_connect_irq(busdev, 0,
|
||||
qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C1_IRQ));
|
||||
sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_I2C1_TX]);
|
||||
sysbus_connect_irq(busdev, 2, s->drq[OMAP24XX_DMA_I2C1_RX]);
|
||||
sysbus_mmio_map(busdev, 0, omap_l4_region_base(omap_l4tao(s->l4, 5), 0));
|
||||
|
||||
s->i2c[1] = qdev_create(NULL, "omap_i2c");
|
||||
qdev_prop_set_uint8(s->i2c[1], "revision", 0x34);
|
||||
qdev_prop_set_ptr(s->i2c[1], "iclk", omap_findclk(s, "i2c2.iclk"));
|
||||
qdev_prop_set_ptr(s->i2c[1], "fclk", omap_findclk(s, "i2c2.fclk"));
|
||||
qdev_init_nofail(s->i2c[1]);
|
||||
busdev = sysbus_from_qdev(s->i2c[1]);
|
||||
sysbus_connect_irq(busdev, 0,
|
||||
qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C2_IRQ));
|
||||
sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_I2C2_TX]);
|
||||
sysbus_connect_irq(busdev, 2, s->drq[OMAP24XX_DMA_I2C2_RX]);
|
||||
sysbus_mmio_map(busdev, 0, omap_l4_region_base(omap_l4tao(s->l4, 6), 0));
|
||||
|
||||
s->gpio = qdev_create(NULL, "omap2-gpio");
|
||||
qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model);
|
||||
|
|
111
hw/omap_i2c.c
111
hw/omap_i2c.c
|
@ -19,14 +19,20 @@
|
|||
#include "hw.h"
|
||||
#include "i2c.h"
|
||||
#include "omap.h"
|
||||
#include "sysbus.h"
|
||||
|
||||
struct omap_i2c_s {
|
||||
|
||||
typedef struct OMAPI2CState {
|
||||
SysBusDevice busdev;
|
||||
MemoryRegion iomem;
|
||||
qemu_irq irq;
|
||||
qemu_irq drq[2];
|
||||
i2c_bus *bus;
|
||||
|
||||
uint8_t revision;
|
||||
void *iclk;
|
||||
void *fclk;
|
||||
|
||||
uint8_t mask;
|
||||
uint16_t stat;
|
||||
uint16_t dma;
|
||||
|
@ -40,12 +46,12 @@ struct omap_i2c_s {
|
|||
uint8_t divider;
|
||||
uint8_t times[2];
|
||||
uint16_t test;
|
||||
};
|
||||
} OMAPI2CState;
|
||||
|
||||
#define OMAP2_INTR_REV 0x34
|
||||
#define OMAP2_GC_REV 0x34
|
||||
|
||||
static void omap_i2c_interrupts_update(struct omap_i2c_s *s)
|
||||
static void omap_i2c_interrupts_update(OMAPI2CState *s)
|
||||
{
|
||||
qemu_set_irq(s->irq, s->stat & s->mask);
|
||||
if ((s->dma >> 15) & 1) /* RDMA_EN */
|
||||
|
@ -54,7 +60,7 @@ static void omap_i2c_interrupts_update(struct omap_i2c_s *s)
|
|||
qemu_set_irq(s->drq[1], (s->stat >> 4) & 1); /* XRDY */
|
||||
}
|
||||
|
||||
static void omap_i2c_fifo_run(struct omap_i2c_s *s)
|
||||
static void omap_i2c_fifo_run(OMAPI2CState *s)
|
||||
{
|
||||
int ack = 1;
|
||||
|
||||
|
@ -122,8 +128,10 @@ static void omap_i2c_fifo_run(struct omap_i2c_s *s)
|
|||
s->control &= ~(1 << 1); /* STP */
|
||||
}
|
||||
|
||||
void omap_i2c_reset(struct omap_i2c_s *s)
|
||||
static void omap_i2c_reset(DeviceState *dev)
|
||||
{
|
||||
OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState,
|
||||
sysbus_from_qdev(dev));
|
||||
s->mask = 0;
|
||||
s->stat = 0;
|
||||
s->dma = 0;
|
||||
|
@ -143,7 +151,7 @@ void omap_i2c_reset(struct omap_i2c_s *s)
|
|||
|
||||
static uint32_t omap_i2c_read(void *opaque, target_phys_addr_t addr)
|
||||
{
|
||||
struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
|
||||
OMAPI2CState *s = opaque;
|
||||
int offset = addr & OMAP_MPUI_REG_MASK;
|
||||
uint16_t ret;
|
||||
|
||||
|
@ -243,7 +251,7 @@ static uint32_t omap_i2c_read(void *opaque, target_phys_addr_t addr)
|
|||
static void omap_i2c_write(void *opaque, target_phys_addr_t addr,
|
||||
uint32_t value)
|
||||
{
|
||||
struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
|
||||
OMAPI2CState *s = opaque;
|
||||
int offset = addr & OMAP_MPUI_REG_MASK;
|
||||
int nack;
|
||||
|
||||
|
@ -309,14 +317,14 @@ static void omap_i2c_write(void *opaque, target_phys_addr_t addr,
|
|||
}
|
||||
|
||||
if (value & 2)
|
||||
omap_i2c_reset(s);
|
||||
omap_i2c_reset(&s->busdev.qdev);
|
||||
break;
|
||||
|
||||
case 0x24: /* I2C_CON */
|
||||
s->control = value & 0xcf87;
|
||||
if (~value & (1 << 15)) { /* I2C_EN */
|
||||
if (s->revision < OMAP2_INTR_REV)
|
||||
omap_i2c_reset(s);
|
||||
omap_i2c_reset(&s->busdev.qdev);
|
||||
break;
|
||||
}
|
||||
if ((value & (1 << 15)) && !(value & (1 << 10))) { /* MST */
|
||||
|
@ -385,7 +393,7 @@ static void omap_i2c_write(void *opaque, target_phys_addr_t addr,
|
|||
static void omap_i2c_writeb(void *opaque, target_phys_addr_t addr,
|
||||
uint32_t value)
|
||||
{
|
||||
struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
|
||||
OMAPI2CState *s = opaque;
|
||||
int offset = addr & OMAP_MPUI_REG_MASK;
|
||||
|
||||
switch (offset) {
|
||||
|
@ -426,50 +434,59 @@ static const MemoryRegionOps omap_i2c_ops = {
|
|||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
struct omap_i2c_s *omap_i2c_init(MemoryRegion *sysmem,
|
||||
target_phys_addr_t base,
|
||||
qemu_irq irq,
|
||||
qemu_irq *dma,
|
||||
omap_clk clk)
|
||||
static int omap_i2c_init(SysBusDevice *dev)
|
||||
{
|
||||
struct omap_i2c_s *s = (struct omap_i2c_s *)
|
||||
g_malloc0(sizeof(struct omap_i2c_s));
|
||||
OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState, dev);
|
||||
|
||||
/* TODO: set a value greater or equal to real hardware */
|
||||
s->revision = 0x11;
|
||||
s->irq = irq;
|
||||
s->drq[0] = dma[0];
|
||||
s->drq[1] = dma[1];
|
||||
s->bus = i2c_init_bus(NULL, "i2c");
|
||||
omap_i2c_reset(s);
|
||||
|
||||
memory_region_init_io(&s->iomem, &omap_i2c_ops, s, "omap.i2c", 0x800);
|
||||
memory_region_add_subregion(sysmem, base, &s->iomem);
|
||||
|
||||
return s;
|
||||
if (!s->fclk) {
|
||||
hw_error("omap_i2c: fclk not connected\n");
|
||||
}
|
||||
if (s->revision >= OMAP2_INTR_REV && !s->iclk) {
|
||||
/* Note that OMAP1 doesn't have a separate interface clock */
|
||||
hw_error("omap_i2c: iclk not connected\n");
|
||||
}
|
||||
sysbus_init_irq(dev, &s->irq);
|
||||
sysbus_init_irq(dev, &s->drq[0]);
|
||||
sysbus_init_irq(dev, &s->drq[1]);
|
||||
memory_region_init_io(&s->iomem, &omap_i2c_ops, s, "omap.i2c",
|
||||
(s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000);
|
||||
sysbus_init_mmio(dev, &s->iomem);
|
||||
s->bus = i2c_init_bus(&dev->qdev, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct omap_i2c_s *omap2_i2c_init(struct omap_target_agent_s *ta,
|
||||
qemu_irq irq, qemu_irq *dma, omap_clk fclk, omap_clk iclk)
|
||||
static Property omap_i2c_properties[] = {
|
||||
DEFINE_PROP_UINT8("revision", OMAPI2CState, revision, 0),
|
||||
DEFINE_PROP_PTR("iclk", OMAPI2CState, iclk),
|
||||
DEFINE_PROP_PTR("fclk", OMAPI2CState, fclk),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void omap_i2c_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
struct omap_i2c_s *s = (struct omap_i2c_s *)
|
||||
g_malloc0(sizeof(struct omap_i2c_s));
|
||||
|
||||
s->revision = 0x34;
|
||||
s->irq = irq;
|
||||
s->drq[0] = dma[0];
|
||||
s->drq[1] = dma[1];
|
||||
s->bus = i2c_init_bus(NULL, "i2c");
|
||||
omap_i2c_reset(s);
|
||||
|
||||
memory_region_init_io(&s->iomem, &omap_i2c_ops, s, "omap2.i2c",
|
||||
omap_l4_region_size(ta, 0));
|
||||
omap_l4_attach(ta, 0, &s->iomem);
|
||||
|
||||
return s;
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
|
||||
k->init = omap_i2c_init;
|
||||
dc->props = omap_i2c_properties;
|
||||
dc->reset = omap_i2c_reset;
|
||||
}
|
||||
|
||||
i2c_bus *omap_i2c_bus(struct omap_i2c_s *s)
|
||||
static TypeInfo omap_i2c_info = {
|
||||
.name = "omap_i2c",
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(OMAPI2CState),
|
||||
.class_init = omap_i2c_class_init,
|
||||
};
|
||||
|
||||
static void omap_i2c_register_types(void)
|
||||
{
|
||||
type_register_static(&omap_i2c_info);
|
||||
}
|
||||
|
||||
i2c_bus *omap_i2c_bus(DeviceState *omap_i2c)
|
||||
{
|
||||
OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState, sysbus_from_qdev(omap_i2c));
|
||||
return s->bus;
|
||||
}
|
||||
|
||||
type_init(omap_i2c_register_types)
|
||||
|
|
12
hw/openpic.c
12
hw/openpic.c
|
@ -713,7 +713,7 @@ static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val)
|
|||
DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
|
||||
if (addr & 0xF)
|
||||
return;
|
||||
addr -= 0x1100;
|
||||
addr -= 0x10;
|
||||
addr &= 0xFFFF;
|
||||
idx = (addr & 0xFFF0) >> 6;
|
||||
addr = addr & 0x30;
|
||||
|
@ -746,7 +746,7 @@ static uint32_t openpic_timer_read (void *opaque, uint32_t addr)
|
|||
retval = 0xFFFFFFFF;
|
||||
if (addr & 0xF)
|
||||
return retval;
|
||||
addr -= 0x1100;
|
||||
addr -= 0x10;
|
||||
addr &= 0xFFFF;
|
||||
idx = (addr & 0xFFF0) >> 6;
|
||||
addr = addr & 0x30;
|
||||
|
@ -1361,7 +1361,6 @@ static void mpic_src_ext_write (void *opaque, target_phys_addr_t addr,
|
|||
if (addr & 0xF)
|
||||
return;
|
||||
|
||||
addr -= MPIC_EXT_REG_START & (OPENPIC_PAGE_SIZE - 1);
|
||||
if (addr < MPIC_EXT_REG_SIZE) {
|
||||
idx += (addr & 0xFFF0) >> 5;
|
||||
if (addr & 0x10) {
|
||||
|
@ -1385,7 +1384,6 @@ static uint32_t mpic_src_ext_read (void *opaque, target_phys_addr_t addr)
|
|||
if (addr & 0xF)
|
||||
return retval;
|
||||
|
||||
addr -= MPIC_EXT_REG_START & (OPENPIC_PAGE_SIZE - 1);
|
||||
if (addr < MPIC_EXT_REG_SIZE) {
|
||||
idx += (addr & 0xFFF0) >> 5;
|
||||
if (addr & 0x10) {
|
||||
|
@ -1411,7 +1409,6 @@ static void mpic_src_int_write (void *opaque, target_phys_addr_t addr,
|
|||
if (addr & 0xF)
|
||||
return;
|
||||
|
||||
addr -= MPIC_INT_REG_START & (OPENPIC_PAGE_SIZE - 1);
|
||||
if (addr < MPIC_INT_REG_SIZE) {
|
||||
idx += (addr & 0xFFF0) >> 5;
|
||||
if (addr & 0x10) {
|
||||
|
@ -1435,7 +1432,6 @@ static uint32_t mpic_src_int_read (void *opaque, target_phys_addr_t addr)
|
|||
if (addr & 0xF)
|
||||
return retval;
|
||||
|
||||
addr -= MPIC_INT_REG_START & (OPENPIC_PAGE_SIZE - 1);
|
||||
if (addr < MPIC_INT_REG_SIZE) {
|
||||
idx += (addr & 0xFFF0) >> 5;
|
||||
if (addr & 0x10) {
|
||||
|
@ -1461,7 +1457,6 @@ static void mpic_src_msg_write (void *opaque, target_phys_addr_t addr,
|
|||
if (addr & 0xF)
|
||||
return;
|
||||
|
||||
addr -= MPIC_MSG_REG_START & (OPENPIC_PAGE_SIZE - 1);
|
||||
if (addr < MPIC_MSG_REG_SIZE) {
|
||||
idx += (addr & 0xFFF0) >> 5;
|
||||
if (addr & 0x10) {
|
||||
|
@ -1485,7 +1480,6 @@ static uint32_t mpic_src_msg_read (void *opaque, target_phys_addr_t addr)
|
|||
if (addr & 0xF)
|
||||
return retval;
|
||||
|
||||
addr -= MPIC_MSG_REG_START & (OPENPIC_PAGE_SIZE - 1);
|
||||
if (addr < MPIC_MSG_REG_SIZE) {
|
||||
idx += (addr & 0xFFF0) >> 5;
|
||||
if (addr & 0x10) {
|
||||
|
@ -1511,7 +1505,6 @@ static void mpic_src_msi_write (void *opaque, target_phys_addr_t addr,
|
|||
if (addr & 0xF)
|
||||
return;
|
||||
|
||||
addr -= MPIC_MSI_REG_START & (OPENPIC_PAGE_SIZE - 1);
|
||||
if (addr < MPIC_MSI_REG_SIZE) {
|
||||
idx += (addr & 0xFFF0) >> 5;
|
||||
if (addr & 0x10) {
|
||||
|
@ -1534,7 +1527,6 @@ static uint32_t mpic_src_msi_read (void *opaque, target_phys_addr_t addr)
|
|||
if (addr & 0xF)
|
||||
return retval;
|
||||
|
||||
addr -= MPIC_MSI_REG_START & (OPENPIC_PAGE_SIZE - 1);
|
||||
if (addr < MPIC_MSI_REG_SIZE) {
|
||||
idx += (addr & 0xFFF0) >> 5;
|
||||
if (addr & 0x10) {
|
||||
|
|
|
@ -2471,6 +2471,8 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
|
|||
ppc4xx_pob_init(env);
|
||||
/* OBP arbitrer */
|
||||
ppc4xx_opba_init(0xef600600);
|
||||
/* Initialize timers */
|
||||
ppc_booke_timers_init(env, sysclk, 0);
|
||||
/* Universal interrupt controller */
|
||||
irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
|
||||
irqs[PPCUIC_OUTPUT_INT] =
|
||||
|
|
|
@ -182,7 +182,7 @@ static uint64_t spin_read(void *opaque, target_phys_addr_t addr, unsigned len)
|
|||
}
|
||||
}
|
||||
|
||||
const MemoryRegionOps spin_rw_ops = {
|
||||
static const MemoryRegionOps spin_rw_ops = {
|
||||
.read = spin_read,
|
||||
.write = spin_write,
|
||||
.endianness = DEVICE_BIG_ENDIAN,
|
||||
|
|
|
@ -1507,8 +1507,7 @@ PXA2xxI2CState *pxa2xx_i2c_init(target_phys_addr_t base,
|
|||
|
||||
i2c_dev = sysbus_from_qdev(qdev_create(NULL, "pxa2xx_i2c"));
|
||||
qdev_prop_set_uint32(&i2c_dev->qdev, "size", region_size + 1);
|
||||
qdev_prop_set_uint32(&i2c_dev->qdev, "offset",
|
||||
base - (base & (~region_size) & TARGET_PAGE_MASK));
|
||||
qdev_prop_set_uint32(&i2c_dev->qdev, "offset", base & region_size);
|
||||
|
||||
qdev_init_nofail(&i2c_dev->qdev);
|
||||
|
||||
|
|
|
@ -18,9 +18,9 @@
|
|||
#define PXA2XX_DMA_NUM_REQUESTS 75
|
||||
|
||||
typedef struct {
|
||||
target_phys_addr_t descr;
|
||||
target_phys_addr_t src;
|
||||
target_phys_addr_t dest;
|
||||
uint32_t descr;
|
||||
uint32_t src;
|
||||
uint32_t dest;
|
||||
uint32_t cmd;
|
||||
uint32_t state;
|
||||
int request;
|
||||
|
@ -512,9 +512,9 @@ static VMStateDescription vmstate_pxa2xx_dma_chan = {
|
|||
.minimum_version_id = 1,
|
||||
.minimum_version_id_old = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINTTL(descr, PXA2xxDMAChannel),
|
||||
VMSTATE_UINTTL(src, PXA2xxDMAChannel),
|
||||
VMSTATE_UINTTL(dest, PXA2xxDMAChannel),
|
||||
VMSTATE_UINT32(descr, PXA2xxDMAChannel),
|
||||
VMSTATE_UINT32(src, PXA2xxDMAChannel),
|
||||
VMSTATE_UINT32(dest, PXA2xxDMAChannel),
|
||||
VMSTATE_UINT32(cmd, PXA2xxDMAChannel),
|
||||
VMSTATE_UINT32(state, PXA2xxDMAChannel),
|
||||
VMSTATE_INT32(request, PXA2xxDMAChannel),
|
||||
|
|
|
@ -19,15 +19,15 @@
|
|||
#include "framebuffer.h"
|
||||
|
||||
struct DMAChannel {
|
||||
target_phys_addr_t branch;
|
||||
uint32_t branch;
|
||||
uint8_t up;
|
||||
uint8_t palette[1024];
|
||||
uint8_t pbuffer[1024];
|
||||
void (*redraw)(PXA2xxLCDState *s, target_phys_addr_t addr,
|
||||
int *miny, int *maxy);
|
||||
|
||||
target_phys_addr_t descriptor;
|
||||
target_phys_addr_t source;
|
||||
uint32_t descriptor;
|
||||
uint32_t source;
|
||||
uint32_t id;
|
||||
uint32_t command;
|
||||
};
|
||||
|
@ -929,11 +929,11 @@ static const VMStateDescription vmstate_dma_channel = {
|
|||
.minimum_version_id = 0,
|
||||
.minimum_version_id_old = 0,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINTTL(branch, struct DMAChannel),
|
||||
VMSTATE_UINT32(branch, struct DMAChannel),
|
||||
VMSTATE_UINT8(up, struct DMAChannel),
|
||||
VMSTATE_BUFFER(pbuffer, struct DMAChannel),
|
||||
VMSTATE_UINTTL(descriptor, struct DMAChannel),
|
||||
VMSTATE_UINTTL(source, struct DMAChannel),
|
||||
VMSTATE_UINT32(descriptor, struct DMAChannel),
|
||||
VMSTATE_UINT32(source, struct DMAChannel),
|
||||
VMSTATE_UINT32(id, struct DMAChannel),
|
||||
VMSTATE_UINT32(command, struct DMAChannel),
|
||||
VMSTATE_END_OF_LIST()
|
||||
|
|
|
@ -83,7 +83,8 @@
|
|||
|
||||
sPAPREnvironment *spapr;
|
||||
|
||||
qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num)
|
||||
qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num,
|
||||
enum xics_irq_type type)
|
||||
{
|
||||
uint32_t irq;
|
||||
qemu_irq qirq;
|
||||
|
@ -95,7 +96,7 @@ qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num)
|
|||
irq = spapr->next_irq++;
|
||||
}
|
||||
|
||||
qirq = xics_find_qirq(spapr->icp, irq);
|
||||
qirq = xics_assign_irq(spapr->icp, irq, type);
|
||||
if (!qirq) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
13
hw/spapr.h
13
hw/spapr.h
|
@ -286,7 +286,18 @@ void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn);
|
|||
target_ulong spapr_hypercall(CPUPPCState *env, target_ulong opcode,
|
||||
target_ulong *args);
|
||||
|
||||
qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num);
|
||||
qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num,
|
||||
enum xics_irq_type type);
|
||||
|
||||
static inline qemu_irq spapr_allocate_msi(uint32_t hint, uint32_t *irq_num)
|
||||
{
|
||||
return spapr_allocate_irq(hint, irq_num, XICS_MSI);
|
||||
}
|
||||
|
||||
static inline qemu_irq spapr_allocate_lsi(uint32_t hint, uint32_t *irq_num)
|
||||
{
|
||||
return spapr_allocate_irq(hint, irq_num, XICS_LSI);
|
||||
}
|
||||
|
||||
static inline uint32_t rtas_ld(target_ulong phys, int n)
|
||||
{
|
||||
|
|
193
hw/spapr_pci.c
193
hw/spapr_pci.c
|
@ -32,13 +32,6 @@
|
|||
|
||||
#include "hw/pci_internals.h"
|
||||
|
||||
static const uint32_t bars[] = {
|
||||
PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1,
|
||||
PCI_BASE_ADDRESS_2, PCI_BASE_ADDRESS_3,
|
||||
PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5
|
||||
/*, PCI_ROM_ADDRESS*/
|
||||
};
|
||||
|
||||
static PCIDevice *find_dev(sPAPREnvironment *spapr,
|
||||
uint64_t buid, uint32_t config_addr)
|
||||
{
|
||||
|
@ -187,69 +180,6 @@ static void pci_spapr_set_irq(void *opaque, int irq_num, int level)
|
|||
qemu_set_irq(phb->lsi_table[irq_num].qirq, level);
|
||||
}
|
||||
|
||||
static int spapr_phb_init(SysBusDevice *s)
|
||||
{
|
||||
sPAPRPHBState *phb = FROM_SYSBUS(sPAPRPHBState, s);
|
||||
int i;
|
||||
|
||||
/* Initialize the LSI table */
|
||||
for (i = 0; i < SPAPR_PCI_NUM_LSI; i++) {
|
||||
qemu_irq qirq;
|
||||
uint32_t num;
|
||||
|
||||
qirq = spapr_allocate_irq(0, &num);
|
||||
if (!qirq) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
phb->lsi_table[i].dt_irq = num;
|
||||
phb->lsi_table[i].qirq = qirq;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spapr_main_pci_host_init(PCIDevice *d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void spapr_main_pci_host_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||
|
||||
k->init = spapr_main_pci_host_init;
|
||||
}
|
||||
|
||||
static TypeInfo spapr_main_pci_host_info = {
|
||||
.name = "spapr-pci-host-bridge-pci",
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(PCIDevice),
|
||||
.class_init = spapr_main_pci_host_class_init,
|
||||
};
|
||||
|
||||
static void spapr_phb_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
|
||||
|
||||
sdc->init = spapr_phb_init;
|
||||
}
|
||||
|
||||
static TypeInfo spapr_phb_info = {
|
||||
.name = "spapr-pci-host-bridge",
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(sPAPRPHBState),
|
||||
.class_init = spapr_phb_class_init,
|
||||
};
|
||||
|
||||
static void spapr_register_types(void)
|
||||
{
|
||||
type_register_static(&spapr_phb_info);
|
||||
type_register_static(&spapr_main_pci_host_info);
|
||||
}
|
||||
|
||||
type_init(spapr_register_types)
|
||||
|
||||
static uint64_t spapr_io_read(void *opaque, target_phys_addr_t addr,
|
||||
unsigned size)
|
||||
{
|
||||
|
@ -287,35 +217,29 @@ static const MemoryRegionOps spapr_io_ops = {
|
|||
.write = spapr_io_write
|
||||
};
|
||||
|
||||
void spapr_create_phb(sPAPREnvironment *spapr,
|
||||
const char *busname, uint64_t buid,
|
||||
uint64_t mem_win_addr, uint64_t mem_win_size,
|
||||
uint64_t io_win_addr)
|
||||
/*
|
||||
* PHB PCI device
|
||||
*/
|
||||
static int spapr_phb_init(SysBusDevice *s)
|
||||
{
|
||||
DeviceState *dev;
|
||||
SysBusDevice *s;
|
||||
sPAPRPHBState *phb;
|
||||
sPAPRPHBState *phb = FROM_SYSBUS(sPAPRPHBState, s);
|
||||
char *namebuf;
|
||||
int i;
|
||||
PCIBus *bus;
|
||||
char namebuf[strlen(busname)+11];
|
||||
|
||||
dev = qdev_create(NULL, "spapr-pci-host-bridge");
|
||||
qdev_init_nofail(dev);
|
||||
s = sysbus_from_qdev(dev);
|
||||
phb = FROM_SYSBUS(sPAPRPHBState, s);
|
||||
phb->dtbusname = g_strdup_printf("pci@%" PRIx64, phb->buid);
|
||||
namebuf = alloca(strlen(phb->dtbusname) + 32);
|
||||
|
||||
phb->mem_win_addr = mem_win_addr;
|
||||
|
||||
sprintf(namebuf, "%s-mem", busname);
|
||||
/* Initialize memory regions */
|
||||
sprintf(namebuf, "%s.mmio", phb->dtbusname);
|
||||
memory_region_init(&phb->memspace, namebuf, INT64_MAX);
|
||||
|
||||
sprintf(namebuf, "%s-memwindow", busname);
|
||||
sprintf(namebuf, "%s.mmio-alias", phb->dtbusname);
|
||||
memory_region_init_alias(&phb->memwindow, namebuf, &phb->memspace,
|
||||
SPAPR_PCI_MEM_WIN_BUS_OFFSET, mem_win_size);
|
||||
memory_region_add_subregion(get_system_memory(), mem_win_addr,
|
||||
SPAPR_PCI_MEM_WIN_BUS_OFFSET, phb->mem_win_size);
|
||||
memory_region_add_subregion(get_system_memory(), phb->mem_win_addr,
|
||||
&phb->memwindow);
|
||||
|
||||
phb->io_win_addr = io_win_addr;
|
||||
|
||||
/* On ppc, we only have MMIO no specific IO space from the CPU
|
||||
* perspective. In theory we ought to be able to embed the PCI IO
|
||||
* memory region direction in the system memory space. However,
|
||||
|
@ -324,33 +248,92 @@ void spapr_create_phb(sPAPREnvironment *spapr,
|
|||
* system io address space. This hack to bounce things via
|
||||
* system_io works around the problem until all the users of
|
||||
* old_portion are updated */
|
||||
sprintf(namebuf, "%s-io", busname);
|
||||
sprintf(namebuf, "%s.io", phb->dtbusname);
|
||||
memory_region_init(&phb->iospace, namebuf, SPAPR_PCI_IO_WIN_SIZE);
|
||||
/* FIXME: fix to support multiple PHBs */
|
||||
memory_region_add_subregion(get_system_io(), 0, &phb->iospace);
|
||||
|
||||
sprintf(namebuf, "%s-iowindow", busname);
|
||||
sprintf(namebuf, "%s.io-alias", phb->dtbusname);
|
||||
memory_region_init_io(&phb->iowindow, &spapr_io_ops, phb,
|
||||
namebuf, SPAPR_PCI_IO_WIN_SIZE);
|
||||
memory_region_add_subregion(get_system_memory(), io_win_addr,
|
||||
memory_region_add_subregion(get_system_memory(), phb->io_win_addr,
|
||||
&phb->iowindow);
|
||||
|
||||
phb->host_state.bus = bus = pci_register_bus(&phb->busdev.qdev, busname,
|
||||
pci_spapr_set_irq,
|
||||
pci_spapr_map_irq,
|
||||
phb,
|
||||
&phb->memspace, &phb->iospace,
|
||||
PCI_DEVFN(0, 0),
|
||||
SPAPR_PCI_NUM_LSI);
|
||||
bus = pci_register_bus(&phb->busdev.qdev,
|
||||
phb->busname ? phb->busname : phb->dtbusname,
|
||||
pci_spapr_set_irq, pci_spapr_map_irq, phb,
|
||||
&phb->memspace, &phb->iospace,
|
||||
PCI_DEVFN(0, 0), SPAPR_PCI_NUM_LSI);
|
||||
phb->host_state.bus = bus;
|
||||
|
||||
QLIST_INSERT_HEAD(&spapr->phbs, phb, list);
|
||||
|
||||
/* Initialize the LSI table */
|
||||
for (i = 0; i < SPAPR_PCI_NUM_LSI; i++) {
|
||||
qemu_irq qirq;
|
||||
uint32_t num;
|
||||
|
||||
qirq = spapr_allocate_lsi(0, &num);
|
||||
if (!qirq) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
phb->lsi_table[i].dt_irq = num;
|
||||
phb->lsi_table[i].qirq = qirq;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Property spapr_phb_properties[] = {
|
||||
DEFINE_PROP_HEX64("buid", sPAPRPHBState, buid, 0),
|
||||
DEFINE_PROP_STRING("busname", sPAPRPHBState, busname),
|
||||
DEFINE_PROP_HEX64("mem_win_addr", sPAPRPHBState, mem_win_addr, 0),
|
||||
DEFINE_PROP_HEX64("mem_win_size", sPAPRPHBState, mem_win_size, 0x20000000),
|
||||
DEFINE_PROP_HEX64("io_win_addr", sPAPRPHBState, io_win_addr, 0),
|
||||
DEFINE_PROP_HEX64("io_win_size", sPAPRPHBState, io_win_size, 0x10000),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void spapr_phb_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
sdc->init = spapr_phb_init;
|
||||
dc->props = spapr_phb_properties;
|
||||
|
||||
spapr_rtas_register("read-pci-config", rtas_read_pci_config);
|
||||
spapr_rtas_register("write-pci-config", rtas_write_pci_config);
|
||||
spapr_rtas_register("ibm,read-pci-config", rtas_ibm_read_pci_config);
|
||||
spapr_rtas_register("ibm,write-pci-config", rtas_ibm_write_pci_config);
|
||||
}
|
||||
|
||||
QLIST_INSERT_HEAD(&spapr->phbs, phb, list);
|
||||
static TypeInfo spapr_phb_info = {
|
||||
.name = "spapr-pci-host-bridge",
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(sPAPRPHBState),
|
||||
.class_init = spapr_phb_class_init,
|
||||
};
|
||||
|
||||
/* pci_bus_set_mem_base(bus, mem_va_start - SPAPR_PCI_MEM_BAR_START); */
|
||||
void spapr_create_phb(sPAPREnvironment *spapr,
|
||||
const char *busname, uint64_t buid,
|
||||
uint64_t mem_win_addr, uint64_t mem_win_size,
|
||||
uint64_t io_win_addr)
|
||||
{
|
||||
DeviceState *dev;
|
||||
|
||||
dev = qdev_create(NULL, spapr_phb_info.name);
|
||||
|
||||
if (busname) {
|
||||
qdev_prop_set_string(dev, "busname", g_strdup(busname));
|
||||
}
|
||||
qdev_prop_set_uint64(dev, "buid", buid);
|
||||
qdev_prop_set_uint64(dev, "mem_win_addr", mem_win_addr);
|
||||
qdev_prop_set_uint64(dev, "mem_win_size", mem_win_size);
|
||||
qdev_prop_set_uint64(dev, "io_win_addr", io_win_addr);
|
||||
|
||||
qdev_init_nofail(dev);
|
||||
}
|
||||
|
||||
/* Macros to operate with address in OF binding to PCI */
|
||||
|
@ -442,3 +425,9 @@ int spapr_populate_pci_devices(sPAPRPHBState *phb,
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void register_types(void)
|
||||
{
|
||||
type_register_static(&spapr_phb_info);
|
||||
}
|
||||
type_init(register_types)
|
||||
|
|
|
@ -33,9 +33,11 @@ typedef struct sPAPRPHBState {
|
|||
PCIHostState host_state;
|
||||
|
||||
uint64_t buid;
|
||||
char *busname;
|
||||
char *dtbusname;
|
||||
|
||||
MemoryRegion memspace, iospace;
|
||||
target_phys_addr_t mem_win_addr, io_win_addr;
|
||||
target_phys_addr_t mem_win_addr, mem_win_size, io_win_addr, io_win_size;
|
||||
MemoryRegion memwindow, iowindow;
|
||||
|
||||
struct {
|
||||
|
|
|
@ -670,7 +670,7 @@ static int spapr_vio_busdev_init(DeviceState *qdev)
|
|||
dev->qdev.id = id;
|
||||
}
|
||||
|
||||
dev->qirq = spapr_allocate_irq(dev->vio_irq_num, &dev->vio_irq_num);
|
||||
dev->qirq = spapr_allocate_msi(dev->vio_irq_num, &dev->vio_irq_num);
|
||||
if (!dev->qirq) {
|
||||
return -1;
|
||||
}
|
||||
|
|
57
hw/sun4u.c
57
hw/sun4u.c
|
@ -81,7 +81,7 @@
|
|||
#define FW_CFG_SPARC64_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01)
|
||||
#define FW_CFG_SPARC64_DEPTH (FW_CFG_ARCH_LOCAL + 0x02)
|
||||
|
||||
#define MAX_PILS 16
|
||||
#define IVEC_MAX 0x30
|
||||
|
||||
#define TICK_MAX 0x7fffffffffffffffULL
|
||||
|
||||
|
@ -304,18 +304,24 @@ static void cpu_kick_irq(CPUSPARCState *env)
|
|||
qemu_cpu_kick(env);
|
||||
}
|
||||
|
||||
static void cpu_set_irq(void *opaque, int irq, int level)
|
||||
static void cpu_set_ivec_irq(void *opaque, int irq, int level)
|
||||
{
|
||||
CPUSPARCState *env = opaque;
|
||||
|
||||
if (level) {
|
||||
CPUIRQ_DPRINTF("Raise CPU IRQ %d\n", irq);
|
||||
env->pil_in |= 1 << irq;
|
||||
cpu_kick_irq(env);
|
||||
} else {
|
||||
CPUIRQ_DPRINTF("Lower CPU IRQ %d\n", irq);
|
||||
env->pil_in &= ~(1 << irq);
|
||||
cpu_check_irqs(env);
|
||||
CPUIRQ_DPRINTF("Raise IVEC IRQ %d\n", irq);
|
||||
env->interrupt_index = TT_IVEC;
|
||||
env->pil_in |= 1 << 5;
|
||||
env->ivec_status |= 0x20;
|
||||
env->ivec_data[0] = (0x1f << 6) | irq;
|
||||
env->ivec_data[1] = 0;
|
||||
env->ivec_data[2] = 0;
|
||||
cpu_interrupt(env, CPU_INTERRUPT_HARD);
|
||||
} else {
|
||||
CPUIRQ_DPRINTF("Lower IVEC IRQ %d\n", irq);
|
||||
env->pil_in &= ~(1 << 5);
|
||||
env->ivec_status &= ~0x20;
|
||||
cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -521,13 +527,29 @@ void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit)
|
|||
}
|
||||
}
|
||||
|
||||
static void dummy_isa_irq_handler(void *opaque, int n, int level)
|
||||
static void isa_irq_handler(void *opaque, int n, int level)
|
||||
{
|
||||
static const int isa_irq_to_ivec[16] = {
|
||||
[1] = 0x29, /* keyboard */
|
||||
[4] = 0x2b, /* serial */
|
||||
[6] = 0x27, /* floppy */
|
||||
[7] = 0x22, /* parallel */
|
||||
[12] = 0x2a, /* mouse */
|
||||
};
|
||||
qemu_irq *irqs = opaque;
|
||||
int ivec;
|
||||
|
||||
assert(n < 16);
|
||||
ivec = isa_irq_to_ivec[n];
|
||||
EBUS_DPRINTF("Set ISA IRQ %d level %d -> ivec 0x%x\n", n, level, ivec);
|
||||
if (ivec) {
|
||||
qemu_set_irq(irqs[ivec], level);
|
||||
}
|
||||
}
|
||||
|
||||
/* EBUS (Eight bit bus) bridge */
|
||||
static ISABus *
|
||||
pci_ebus_init(PCIBus *bus, int devfn)
|
||||
pci_ebus_init(PCIBus *bus, int devfn, qemu_irq *irqs)
|
||||
{
|
||||
qemu_irq *isa_irq;
|
||||
PCIDevice *pci_dev;
|
||||
|
@ -536,7 +558,7 @@ pci_ebus_init(PCIBus *bus, int devfn)
|
|||
pci_dev = pci_create_simple(bus, devfn, "ebus");
|
||||
isa_bus = DO_UPCAST(ISABus, qbus,
|
||||
qdev_get_child_bus(&pci_dev->qdev, "isa.0"));
|
||||
isa_irq = qemu_allocate_irqs(dummy_isa_irq_handler, NULL, 16);
|
||||
isa_irq = qemu_allocate_irqs(isa_irq_handler, irqs, 16);
|
||||
isa_bus_irqs(isa_bus, isa_irq);
|
||||
return isa_bus;
|
||||
}
|
||||
|
@ -761,7 +783,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
|
|||
long initrd_size, kernel_size;
|
||||
PCIBus *pci_bus, *pci_bus2, *pci_bus3;
|
||||
ISABus *isa_bus;
|
||||
qemu_irq *irq;
|
||||
qemu_irq *ivec_irqs, *pbm_irqs;
|
||||
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
|
||||
DriveInfo *fd[MAX_FD];
|
||||
void *fw_cfg;
|
||||
|
@ -774,14 +796,13 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
|
|||
|
||||
prom_init(hwdef->prom_addr, bios_name);
|
||||
|
||||
|
||||
irq = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS);
|
||||
pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, irq, &pci_bus2,
|
||||
&pci_bus3);
|
||||
ivec_irqs = qemu_allocate_irqs(cpu_set_ivec_irq, env, IVEC_MAX);
|
||||
pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, ivec_irqs, &pci_bus2,
|
||||
&pci_bus3, &pbm_irqs);
|
||||
pci_vga_init(pci_bus);
|
||||
|
||||
// XXX Should be pci_bus3
|
||||
isa_bus = pci_ebus_init(pci_bus, -1);
|
||||
isa_bus = pci_ebus_init(pci_bus, -1, pbm_irqs);
|
||||
|
||||
i = 0;
|
||||
if (hwdef->console_serial_base) {
|
||||
|
|
145
hw/xics.c
145
hw/xics.c
|
@ -132,9 +132,9 @@ static void icp_eoi(struct icp_state *icp, int server, uint32_t xirr)
|
|||
{
|
||||
struct icp_server_state *ss = icp->ss + server;
|
||||
|
||||
ics_eoi(icp->ics, xirr & XISR_MASK);
|
||||
/* Send EOI -> ICS */
|
||||
ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
|
||||
ics_eoi(icp->ics, xirr & XISR_MASK);
|
||||
if (!XISR(ss)) {
|
||||
icp_resend(icp, server);
|
||||
}
|
||||
|
@ -165,8 +165,9 @@ struct ics_irq_state {
|
|||
int server;
|
||||
uint8_t priority;
|
||||
uint8_t saved_priority;
|
||||
/* int pending:1; */
|
||||
/* int presented:1; */
|
||||
enum xics_irq_type type;
|
||||
int asserted:1;
|
||||
int sent:1;
|
||||
int rejected:1;
|
||||
int masked_pending:1;
|
||||
};
|
||||
|
@ -185,9 +186,32 @@ static int ics_valid_irq(struct ics_state *ics, uint32_t nr)
|
|||
&& (nr < (ics->offset + ics->nr_irqs));
|
||||
}
|
||||
|
||||
static void ics_set_irq_msi(void *opaque, int srcno, int val)
|
||||
static void resend_msi(struct ics_state *ics, int srcno)
|
||||
{
|
||||
struct ics_irq_state *irq = ics->irqs + srcno;
|
||||
|
||||
/* FIXME: filter by server#? */
|
||||
if (irq->rejected) {
|
||||
irq->rejected = 0;
|
||||
if (irq->priority != 0xff) {
|
||||
icp_irq(ics->icp, irq->server, srcno + ics->offset,
|
||||
irq->priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void resend_lsi(struct ics_state *ics, int srcno)
|
||||
{
|
||||
struct ics_irq_state *irq = ics->irqs + srcno;
|
||||
|
||||
if ((irq->priority != 0xff) && irq->asserted && !irq->sent) {
|
||||
irq->sent = 1;
|
||||
icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
|
||||
}
|
||||
}
|
||||
|
||||
static void set_irq_msi(struct ics_state *ics, int srcno, int val)
|
||||
{
|
||||
struct ics_state *ics = (struct ics_state *)opaque;
|
||||
struct ics_irq_state *irq = ics->irqs + srcno;
|
||||
|
||||
if (val) {
|
||||
|
@ -200,14 +224,68 @@ static void ics_set_irq_msi(void *opaque, int srcno, int val)
|
|||
}
|
||||
}
|
||||
|
||||
static void ics_reject_msi(struct ics_state *ics, int nr)
|
||||
static void set_irq_lsi(struct ics_state *ics, int srcno, int val)
|
||||
{
|
||||
struct ics_irq_state *irq = ics->irqs + srcno;
|
||||
|
||||
irq->asserted = val;
|
||||
resend_lsi(ics, srcno);
|
||||
}
|
||||
|
||||
static void ics_set_irq(void *opaque, int srcno, int val)
|
||||
{
|
||||
struct ics_state *ics = (struct ics_state *)opaque;
|
||||
struct ics_irq_state *irq = ics->irqs + srcno;
|
||||
|
||||
if (irq->type == XICS_LSI) {
|
||||
set_irq_lsi(ics, srcno, val);
|
||||
} else {
|
||||
set_irq_msi(ics, srcno, val);
|
||||
}
|
||||
}
|
||||
|
||||
static void write_xive_msi(struct ics_state *ics, int srcno)
|
||||
{
|
||||
struct ics_irq_state *irq = ics->irqs + srcno;
|
||||
|
||||
if (!irq->masked_pending || (irq->priority == 0xff)) {
|
||||
return;
|
||||
}
|
||||
|
||||
irq->masked_pending = 0;
|
||||
icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
|
||||
}
|
||||
|
||||
static void write_xive_lsi(struct ics_state *ics, int srcno)
|
||||
{
|
||||
resend_lsi(ics, srcno);
|
||||
}
|
||||
|
||||
static void ics_write_xive(struct ics_state *ics, int nr, int server,
|
||||
uint8_t priority)
|
||||
{
|
||||
int srcno = nr - ics->offset;
|
||||
struct ics_irq_state *irq = ics->irqs + srcno;
|
||||
|
||||
irq->server = server;
|
||||
irq->priority = priority;
|
||||
|
||||
if (irq->type == XICS_LSI) {
|
||||
write_xive_lsi(ics, srcno);
|
||||
} else {
|
||||
write_xive_msi(ics, srcno);
|
||||
}
|
||||
}
|
||||
|
||||
static void ics_reject(struct ics_state *ics, int nr)
|
||||
{
|
||||
struct ics_irq_state *irq = ics->irqs + nr - ics->offset;
|
||||
|
||||
irq->rejected = 1;
|
||||
irq->rejected = 1; /* Irrelevant but harmless for LSI */
|
||||
irq->sent = 0; /* Irrelevant but harmless for MSI */
|
||||
}
|
||||
|
||||
static void ics_resend_msi(struct ics_state *ics)
|
||||
static void ics_resend(struct ics_state *ics)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -215,56 +293,39 @@ static void ics_resend_msi(struct ics_state *ics)
|
|||
struct ics_irq_state *irq = ics->irqs + i;
|
||||
|
||||
/* FIXME: filter by server#? */
|
||||
if (irq->rejected) {
|
||||
irq->rejected = 0;
|
||||
if (irq->priority != 0xff) {
|
||||
icp_irq(ics->icp, irq->server, i + ics->offset, irq->priority);
|
||||
}
|
||||
if (irq->type == XICS_LSI) {
|
||||
resend_lsi(ics, i);
|
||||
} else {
|
||||
resend_msi(ics, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ics_write_xive_msi(struct ics_state *ics, int nr, int server,
|
||||
uint8_t priority)
|
||||
{
|
||||
struct ics_irq_state *irq = ics->irqs + nr - ics->offset;
|
||||
|
||||
irq->server = server;
|
||||
irq->priority = priority;
|
||||
|
||||
if (!irq->masked_pending || (priority == 0xff)) {
|
||||
return;
|
||||
}
|
||||
|
||||
irq->masked_pending = 0;
|
||||
icp_irq(ics->icp, server, nr, priority);
|
||||
}
|
||||
|
||||
static void ics_reject(struct ics_state *ics, int nr)
|
||||
{
|
||||
ics_reject_msi(ics, nr);
|
||||
}
|
||||
|
||||
static void ics_resend(struct ics_state *ics)
|
||||
{
|
||||
ics_resend_msi(ics);
|
||||
}
|
||||
|
||||
static void ics_eoi(struct ics_state *ics, int nr)
|
||||
{
|
||||
int srcno = nr - ics->offset;
|
||||
struct ics_irq_state *irq = ics->irqs + srcno;
|
||||
|
||||
if (irq->type == XICS_LSI) {
|
||||
irq->sent = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Exported functions
|
||||
*/
|
||||
|
||||
qemu_irq xics_find_qirq(struct icp_state *icp, int irq)
|
||||
qemu_irq xics_assign_irq(struct icp_state *icp, int irq,
|
||||
enum xics_irq_type type)
|
||||
{
|
||||
if ((irq < icp->ics->offset)
|
||||
|| (irq >= (icp->ics->offset + icp->ics->nr_irqs))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
assert((type == XICS_MSI) || (type == XICS_LSI));
|
||||
|
||||
icp->ics->irqs[irq - icp->ics->offset].type = type;
|
||||
return icp->ics->qirqs[irq - icp->ics->offset];
|
||||
}
|
||||
|
||||
|
@ -332,7 +393,7 @@ static void rtas_set_xive(sPAPREnvironment *spapr, uint32_t token,
|
|||
return;
|
||||
}
|
||||
|
||||
ics_write_xive_msi(ics, nr, server, priority);
|
||||
ics_write_xive(ics, nr, server, priority);
|
||||
|
||||
rtas_st(rets, 0, 0); /* Success */
|
||||
}
|
||||
|
@ -477,7 +538,7 @@ struct icp_state *xics_system_init(int nr_irqs)
|
|||
ics->irqs[i].saved_priority = 0xff;
|
||||
}
|
||||
|
||||
ics->qirqs = qemu_allocate_irqs(ics_set_irq_msi, ics, nr_irqs);
|
||||
ics->qirqs = qemu_allocate_irqs(ics_set_irq, ics, nr_irqs);
|
||||
|
||||
spapr_register_hypercall(H_CPPR, h_cppr);
|
||||
spapr_register_hypercall(H_IPI, h_ipi);
|
||||
|
|
|
@ -31,7 +31,13 @@
|
|||
|
||||
struct icp_state;
|
||||
|
||||
qemu_irq xics_find_qirq(struct icp_state *icp, int irq);
|
||||
enum xics_irq_type {
|
||||
XICS_MSI, /* Message-signalled (edge) interrupt */
|
||||
XICS_LSI, /* Level-signalled interrupt */
|
||||
};
|
||||
|
||||
qemu_irq xics_assign_irq(struct icp_state *icp, int irq,
|
||||
enum xics_irq_type type);
|
||||
|
||||
struct icp_state *xics_system_init(int nr_irqs);
|
||||
|
||||
|
|
|
@ -79,7 +79,10 @@ struct KVMState
|
|||
int pit_state2;
|
||||
int xsave, xcrs;
|
||||
int many_ioeventfds;
|
||||
int irqchip_inject_ioctl;
|
||||
/* The man page (and posix) say ioctl numbers are signed int, but
|
||||
* they're not. Linux, glibc and *BSD all treat ioctl numbers as
|
||||
* unsigned, and treating them as signed here can break things */
|
||||
unsigned irqchip_inject_ioctl;
|
||||
#ifdef KVM_CAP_IRQ_ROUTING
|
||||
struct kvm_irq_routing *irq_routes;
|
||||
int nr_allocated_irq_routes;
|
||||
|
|
|
@ -4118,7 +4118,7 @@ static target_ulong get_sigframe(struct target_sigaction *ka,
|
|||
oldsp = env->gpr[1];
|
||||
|
||||
if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
|
||||
(sas_ss_flags(oldsp))) {
|
||||
(sas_ss_flags(oldsp) == 0)) {
|
||||
oldsp = (target_sigaltstack_used.ss_sp
|
||||
+ target_sigaltstack_used.ss_size);
|
||||
}
|
||||
|
|
6
osdep.h
6
osdep.h
|
@ -70,12 +70,6 @@
|
|||
#define inline always_inline
|
||||
#endif
|
||||
|
||||
#ifdef __i386__
|
||||
#define REGPARM __attribute((regparm(3)))
|
||||
#else
|
||||
#define REGPARM
|
||||
#endif
|
||||
|
||||
#define qemu_printf printf
|
||||
|
||||
int qemu_daemon(int nochdir, int noclose);
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
- SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
|
||||
implementation for certain IBM POWER hardware. The sources are at
|
||||
https://github.com/dgibson/SLOF, and the image currently in qemu is
|
||||
built from git tag qemu-slof-20120111.1.
|
||||
built from git tag qemu-slof-20120217.
|
||||
|
||||
- sgabios (the Serial Graphics Adapter option ROM) provides a means for
|
||||
legacy x86 software to communicate with an attached serial console as
|
||||
|
|
BIN
pc-bios/slof.bin
BIN
pc-bios/slof.bin
Binary file not shown.
|
@ -1 +1 @@
|
|||
Subproject commit ab062ff3b37c39649f2b0d94ed607adc6f6b3c7d
|
||||
Subproject commit d153364253548d6cd91403711f84996e6a7dab31
|
2
savevm.c
2
savevm.c
|
@ -1486,6 +1486,8 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
|
|||
n_elems = field->num;
|
||||
} else if (field->flags & VMS_VARRAY_INT32) {
|
||||
n_elems = *(int32_t *)(opaque+field->num_offset);
|
||||
} else if (field->flags & VMS_VARRAY_UINT32) {
|
||||
n_elems = *(uint32_t *)(opaque+field->num_offset);
|
||||
} else if (field->flags & VMS_VARRAY_UINT16) {
|
||||
n_elems = *(uint16_t *)(opaque+field->num_offset);
|
||||
} else if (field->flags & VMS_VARRAY_UINT8) {
|
||||
|
|
|
@ -9,22 +9,50 @@
|
|||
#ifndef SOFTMMU_DEFS_H
|
||||
#define SOFTMMU_DEFS_H
|
||||
|
||||
uint8_t REGPARM __ldb_mmu(target_ulong addr, int mmu_idx);
|
||||
void REGPARM __stb_mmu(target_ulong addr, uint8_t val, int mmu_idx);
|
||||
uint16_t REGPARM __ldw_mmu(target_ulong addr, int mmu_idx);
|
||||
void REGPARM __stw_mmu(target_ulong addr, uint16_t val, int mmu_idx);
|
||||
uint32_t REGPARM __ldl_mmu(target_ulong addr, int mmu_idx);
|
||||
void REGPARM __stl_mmu(target_ulong addr, uint32_t val, int mmu_idx);
|
||||
uint64_t REGPARM __ldq_mmu(target_ulong addr, int mmu_idx);
|
||||
void REGPARM __stq_mmu(target_ulong addr, uint64_t val, int mmu_idx);
|
||||
#ifndef CONFIG_TCG_PASS_AREG0
|
||||
uint8_t __ldb_mmu(target_ulong addr, int mmu_idx);
|
||||
void __stb_mmu(target_ulong addr, uint8_t val, int mmu_idx);
|
||||
uint16_t __ldw_mmu(target_ulong addr, int mmu_idx);
|
||||
void __stw_mmu(target_ulong addr, uint16_t val, int mmu_idx);
|
||||
uint32_t __ldl_mmu(target_ulong addr, int mmu_idx);
|
||||
void __stl_mmu(target_ulong addr, uint32_t val, int mmu_idx);
|
||||
uint64_t __ldq_mmu(target_ulong addr, int mmu_idx);
|
||||
void __stq_mmu(target_ulong addr, uint64_t val, int mmu_idx);
|
||||
|
||||
uint8_t REGPARM __ldb_cmmu(target_ulong addr, int mmu_idx);
|
||||
void REGPARM __stb_cmmu(target_ulong addr, uint8_t val, int mmu_idx);
|
||||
uint16_t REGPARM __ldw_cmmu(target_ulong addr, int mmu_idx);
|
||||
void REGPARM __stw_cmmu(target_ulong addr, uint16_t val, int mmu_idx);
|
||||
uint32_t REGPARM __ldl_cmmu(target_ulong addr, int mmu_idx);
|
||||
void REGPARM __stl_cmmu(target_ulong addr, uint32_t val, int mmu_idx);
|
||||
uint64_t REGPARM __ldq_cmmu(target_ulong addr, int mmu_idx);
|
||||
void REGPARM __stq_cmmu(target_ulong addr, uint64_t val, int mmu_idx);
|
||||
uint8_t __ldb_cmmu(target_ulong addr, int mmu_idx);
|
||||
void __stb_cmmu(target_ulong addr, uint8_t val, int mmu_idx);
|
||||
uint16_t __ldw_cmmu(target_ulong addr, int mmu_idx);
|
||||
void __stw_cmmu(target_ulong addr, uint16_t val, int mmu_idx);
|
||||
uint32_t __ldl_cmmu(target_ulong addr, int mmu_idx);
|
||||
void __stl_cmmu(target_ulong addr, uint32_t val, int mmu_idx);
|
||||
uint64_t __ldq_cmmu(target_ulong addr, int mmu_idx);
|
||||
void __stq_cmmu(target_ulong addr, uint64_t val, int mmu_idx);
|
||||
#else
|
||||
uint8_t helper_ldb_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
|
||||
void helper_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
|
||||
int mmu_idx);
|
||||
uint16_t helper_ldw_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
|
||||
void helper_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
|
||||
int mmu_idx);
|
||||
uint32_t helper_ldl_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
|
||||
void helper_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
|
||||
int mmu_idx);
|
||||
uint64_t helper_ldq_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
|
||||
void helper_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
int mmu_idx);
|
||||
|
||||
uint8_t helper_ldb_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
|
||||
void helper_stb_cmmu(CPUArchState *env, target_ulong addr, uint8_t val,
|
||||
int mmu_idx);
|
||||
uint16_t helper_ldw_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
|
||||
void helper_stw_cmmu(CPUArchState *env, target_ulong addr, uint16_t val,
|
||||
int mmu_idx);
|
||||
uint32_t helper_ldl_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
|
||||
void helper_stl_cmmu(CPUArchState *env, target_ulong addr, uint32_t val,
|
||||
int mmu_idx);
|
||||
uint64_t helper_ldq_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
|
||||
void helper_stq_cmmu(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
int mmu_idx);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -78,9 +78,23 @@
|
|||
#define ADDR_READ addr_read
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_TCG_PASS_AREG0
|
||||
#define ENV_PARAM
|
||||
#define ENV_VAR
|
||||
#define CPU_PREFIX
|
||||
#define HELPER_PREFIX __
|
||||
#else
|
||||
#define ENV_PARAM CPUArchState *env,
|
||||
#define ENV_VAR env,
|
||||
#define CPU_PREFIX cpu_
|
||||
#define HELPER_PREFIX helper_
|
||||
#endif
|
||||
|
||||
/* generic load/store macros */
|
||||
|
||||
static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
|
||||
static inline RES_TYPE
|
||||
glue(glue(glue(CPU_PREFIX, ld), USUFFIX), MEMSUFFIX)(ENV_PARAM
|
||||
target_ulong ptr)
|
||||
{
|
||||
int page_index;
|
||||
RES_TYPE res;
|
||||
|
@ -93,7 +107,9 @@ static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
|
|||
mmu_idx = CPU_MMU_INDEX;
|
||||
if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
|
||||
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
|
||||
res = glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, mmu_idx);
|
||||
res = glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_VAR
|
||||
addr,
|
||||
mmu_idx);
|
||||
} else {
|
||||
physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
|
||||
res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr);
|
||||
|
@ -102,7 +118,9 @@ static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
|
|||
}
|
||||
|
||||
#if DATA_SIZE <= 2
|
||||
static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
|
||||
static inline int
|
||||
glue(glue(glue(CPU_PREFIX, lds), SUFFIX), MEMSUFFIX)(ENV_PARAM
|
||||
target_ulong ptr)
|
||||
{
|
||||
int res, page_index;
|
||||
target_ulong addr;
|
||||
|
@ -114,7 +132,8 @@ static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
|
|||
mmu_idx = CPU_MMU_INDEX;
|
||||
if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
|
||||
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
|
||||
res = (DATA_STYPE)glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, mmu_idx);
|
||||
res = (DATA_STYPE)glue(glue(glue(HELPER_PREFIX, ld), SUFFIX),
|
||||
MMUSUFFIX)(ENV_VAR addr, mmu_idx);
|
||||
} else {
|
||||
physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
|
||||
res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)physaddr);
|
||||
|
@ -127,7 +146,9 @@ static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
|
|||
|
||||
/* generic store macro */
|
||||
|
||||
static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v)
|
||||
static inline void
|
||||
glue(glue(glue(CPU_PREFIX, st), SUFFIX), MEMSUFFIX)(ENV_PARAM target_ulong ptr,
|
||||
RES_TYPE v)
|
||||
{
|
||||
int page_index;
|
||||
target_ulong addr;
|
||||
|
@ -139,7 +160,8 @@ static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE
|
|||
mmu_idx = CPU_MMU_INDEX;
|
||||
if (unlikely(env->tlb_table[mmu_idx][page_index].addr_write !=
|
||||
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
|
||||
glue(glue(__st, SUFFIX), MMUSUFFIX)(addr, v, mmu_idx);
|
||||
glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_VAR addr, v,
|
||||
mmu_idx);
|
||||
} else {
|
||||
physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
|
||||
glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, v);
|
||||
|
@ -151,46 +173,52 @@ static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE
|
|||
#if ACCESS_TYPE != (NB_MMU_MODES + 1)
|
||||
|
||||
#if DATA_SIZE == 8
|
||||
static inline float64 glue(ldfq, MEMSUFFIX)(target_ulong ptr)
|
||||
static inline float64 glue(glue(CPU_PREFIX, ldfq), MEMSUFFIX)(ENV_PARAM
|
||||
target_ulong ptr)
|
||||
{
|
||||
union {
|
||||
float64 d;
|
||||
uint64_t i;
|
||||
} u;
|
||||
u.i = glue(ldq, MEMSUFFIX)(ptr);
|
||||
u.i = glue(glue(CPU_PREFIX, ldq), MEMSUFFIX)(ENV_VAR ptr);
|
||||
return u.d;
|
||||
}
|
||||
|
||||
static inline void glue(stfq, MEMSUFFIX)(target_ulong ptr, float64 v)
|
||||
static inline void glue(glue(CPU_PREFIX, stfq), MEMSUFFIX)(ENV_PARAM
|
||||
target_ulong ptr,
|
||||
float64 v)
|
||||
{
|
||||
union {
|
||||
float64 d;
|
||||
uint64_t i;
|
||||
} u;
|
||||
u.d = v;
|
||||
glue(stq, MEMSUFFIX)(ptr, u.i);
|
||||
glue(glue(CPU_PREFIX, stq), MEMSUFFIX)(ENV_VAR ptr, u.i);
|
||||
}
|
||||
#endif /* DATA_SIZE == 8 */
|
||||
|
||||
#if DATA_SIZE == 4
|
||||
static inline float32 glue(ldfl, MEMSUFFIX)(target_ulong ptr)
|
||||
static inline float32 glue(glue(CPU_PREFIX, ldfl), MEMSUFFIX)(ENV_PARAM
|
||||
target_ulong ptr)
|
||||
{
|
||||
union {
|
||||
float32 f;
|
||||
uint32_t i;
|
||||
} u;
|
||||
u.i = glue(ldl, MEMSUFFIX)(ptr);
|
||||
u.i = glue(glue(CPU_PREFIX, ldl), MEMSUFFIX)(ENV_VAR ptr);
|
||||
return u.f;
|
||||
}
|
||||
|
||||
static inline void glue(stfl, MEMSUFFIX)(target_ulong ptr, float32 v)
|
||||
static inline void glue(glue(CPU_PREFIX, stfl), MEMSUFFIX)(ENV_PARAM
|
||||
target_ulong ptr,
|
||||
float32 v)
|
||||
{
|
||||
union {
|
||||
float32 f;
|
||||
uint32_t i;
|
||||
} u;
|
||||
u.f = v;
|
||||
glue(stl, MEMSUFFIX)(ptr, u.i);
|
||||
glue(glue(CPU_PREFIX, stl), MEMSUFFIX)(ENV_VAR ptr, u.i);
|
||||
}
|
||||
#endif /* DATA_SIZE == 4 */
|
||||
|
||||
|
@ -205,3 +233,7 @@ static inline void glue(stfl, MEMSUFFIX)(target_ulong ptr, float32 v)
|
|||
#undef CPU_MMU_INDEX
|
||||
#undef MMUSUFFIX
|
||||
#undef ADDR_READ
|
||||
#undef ENV_PARAM
|
||||
#undef ENV_VAR
|
||||
#undef CPU_PREFIX
|
||||
#undef HELPER_PREFIX
|
||||
|
|
|
@ -54,10 +54,24 @@
|
|||
#define ADDR_READ addr_read
|
||||
#endif
|
||||
|
||||
static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
|
||||
#ifndef CONFIG_TCG_PASS_AREG0
|
||||
#define ENV_PARAM
|
||||
#define ENV_VAR
|
||||
#define CPU_PREFIX
|
||||
#define HELPER_PREFIX __
|
||||
#else
|
||||
#define ENV_PARAM CPUArchState *env,
|
||||
#define ENV_VAR env,
|
||||
#define CPU_PREFIX cpu_
|
||||
#define HELPER_PREFIX helper_
|
||||
#endif
|
||||
|
||||
static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_PARAM
|
||||
target_ulong addr,
|
||||
int mmu_idx,
|
||||
void *retaddr);
|
||||
static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr,
|
||||
static inline DATA_TYPE glue(io_read, SUFFIX)(ENV_PARAM
|
||||
target_phys_addr_t physaddr,
|
||||
target_ulong addr,
|
||||
void *retaddr)
|
||||
{
|
||||
|
@ -89,8 +103,10 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr,
|
|||
}
|
||||
|
||||
/* handle all cases except unaligned access which span two pages */
|
||||
DATA_TYPE REGPARM glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
|
||||
int mmu_idx)
|
||||
DATA_TYPE
|
||||
glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_PARAM
|
||||
target_ulong addr,
|
||||
int mmu_idx)
|
||||
{
|
||||
DATA_TYPE res;
|
||||
int index;
|
||||
|
@ -111,22 +127,22 @@ DATA_TYPE REGPARM glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
|
|||
goto do_unaligned_access;
|
||||
retaddr = GETPC();
|
||||
ioaddr = env->iotlb[mmu_idx][index];
|
||||
res = glue(io_read, SUFFIX)(ioaddr, addr, retaddr);
|
||||
res = glue(io_read, SUFFIX)(ENV_VAR ioaddr, addr, retaddr);
|
||||
} else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
|
||||
/* slow unaligned access (it spans two pages or IO) */
|
||||
do_unaligned_access:
|
||||
retaddr = GETPC();
|
||||
#ifdef ALIGNED_ONLY
|
||||
do_unaligned_access(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
|
||||
do_unaligned_access(ENV_VAR addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
|
||||
#endif
|
||||
res = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr,
|
||||
res = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_VAR addr,
|
||||
mmu_idx, retaddr);
|
||||
} else {
|
||||
/* unaligned/aligned access in the same page */
|
||||
#ifdef ALIGNED_ONLY
|
||||
if ((addr & (DATA_SIZE - 1)) != 0) {
|
||||
retaddr = GETPC();
|
||||
do_unaligned_access(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
|
||||
do_unaligned_access(ENV_VAR addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
|
||||
}
|
||||
#endif
|
||||
addend = env->tlb_table[mmu_idx][index].addend;
|
||||
|
@ -137,7 +153,7 @@ DATA_TYPE REGPARM glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
|
|||
retaddr = GETPC();
|
||||
#ifdef ALIGNED_ONLY
|
||||
if ((addr & (DATA_SIZE - 1)) != 0)
|
||||
do_unaligned_access(addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
|
||||
do_unaligned_access(ENV_VAR addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
|
||||
#endif
|
||||
tlb_fill(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
|
||||
goto redo;
|
||||
|
@ -146,9 +162,11 @@ DATA_TYPE REGPARM glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
|
|||
}
|
||||
|
||||
/* handle all unaligned cases */
|
||||
static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
|
||||
int mmu_idx,
|
||||
void *retaddr)
|
||||
static DATA_TYPE
|
||||
glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_PARAM
|
||||
target_ulong addr,
|
||||
int mmu_idx,
|
||||
void *retaddr)
|
||||
{
|
||||
DATA_TYPE res, res1, res2;
|
||||
int index, shift;
|
||||
|
@ -165,15 +183,15 @@ static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
|
|||
if ((addr & (DATA_SIZE - 1)) != 0)
|
||||
goto do_unaligned_access;
|
||||
ioaddr = env->iotlb[mmu_idx][index];
|
||||
res = glue(io_read, SUFFIX)(ioaddr, addr, retaddr);
|
||||
res = glue(io_read, SUFFIX)(ENV_VAR ioaddr, addr, retaddr);
|
||||
} else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
|
||||
do_unaligned_access:
|
||||
/* slow unaligned access (it spans two pages) */
|
||||
addr1 = addr & ~(DATA_SIZE - 1);
|
||||
addr2 = addr1 + DATA_SIZE;
|
||||
res1 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr1,
|
||||
res1 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_VAR addr1,
|
||||
mmu_idx, retaddr);
|
||||
res2 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr2,
|
||||
res2 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_VAR addr2,
|
||||
mmu_idx, retaddr);
|
||||
shift = (addr & (DATA_SIZE - 1)) * 8;
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
|
@ -197,12 +215,14 @@ static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
|
|||
|
||||
#ifndef SOFTMMU_CODE_ACCESS
|
||||
|
||||
static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
|
||||
static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_PARAM
|
||||
target_ulong addr,
|
||||
DATA_TYPE val,
|
||||
int mmu_idx,
|
||||
void *retaddr);
|
||||
|
||||
static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr,
|
||||
static inline void glue(io_write, SUFFIX)(ENV_PARAM
|
||||
target_phys_addr_t physaddr,
|
||||
DATA_TYPE val,
|
||||
target_ulong addr,
|
||||
void *retaddr)
|
||||
|
@ -232,9 +252,10 @@ static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr,
|
|||
#endif /* SHIFT > 2 */
|
||||
}
|
||||
|
||||
void REGPARM glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr,
|
||||
DATA_TYPE val,
|
||||
int mmu_idx)
|
||||
void glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_PARAM
|
||||
target_ulong addr,
|
||||
DATA_TYPE val,
|
||||
int mmu_idx)
|
||||
{
|
||||
target_phys_addr_t ioaddr;
|
||||
unsigned long addend;
|
||||
|
@ -252,21 +273,21 @@ void REGPARM glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr,
|
|||
goto do_unaligned_access;
|
||||
retaddr = GETPC();
|
||||
ioaddr = env->iotlb[mmu_idx][index];
|
||||
glue(io_write, SUFFIX)(ioaddr, val, addr, retaddr);
|
||||
glue(io_write, SUFFIX)(ENV_VAR ioaddr, val, addr, retaddr);
|
||||
} else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
|
||||
do_unaligned_access:
|
||||
retaddr = GETPC();
|
||||
#ifdef ALIGNED_ONLY
|
||||
do_unaligned_access(addr, 1, mmu_idx, retaddr);
|
||||
do_unaligned_access(ENV_VAR addr, 1, mmu_idx, retaddr);
|
||||
#endif
|
||||
glue(glue(slow_st, SUFFIX), MMUSUFFIX)(addr, val,
|
||||
glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_VAR addr, val,
|
||||
mmu_idx, retaddr);
|
||||
} else {
|
||||
/* aligned/unaligned access in the same page */
|
||||
#ifdef ALIGNED_ONLY
|
||||
if ((addr & (DATA_SIZE - 1)) != 0) {
|
||||
retaddr = GETPC();
|
||||
do_unaligned_access(addr, 1, mmu_idx, retaddr);
|
||||
do_unaligned_access(ENV_VAR addr, 1, mmu_idx, retaddr);
|
||||
}
|
||||
#endif
|
||||
addend = env->tlb_table[mmu_idx][index].addend;
|
||||
|
@ -277,7 +298,7 @@ void REGPARM glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr,
|
|||
retaddr = GETPC();
|
||||
#ifdef ALIGNED_ONLY
|
||||
if ((addr & (DATA_SIZE - 1)) != 0)
|
||||
do_unaligned_access(addr, 1, mmu_idx, retaddr);
|
||||
do_unaligned_access(ENV_VAR addr, 1, mmu_idx, retaddr);
|
||||
#endif
|
||||
tlb_fill(env, addr, 1, mmu_idx, retaddr);
|
||||
goto redo;
|
||||
|
@ -285,7 +306,8 @@ void REGPARM glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr,
|
|||
}
|
||||
|
||||
/* handles all unaligned cases */
|
||||
static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
|
||||
static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_PARAM
|
||||
target_ulong addr,
|
||||
DATA_TYPE val,
|
||||
int mmu_idx,
|
||||
void *retaddr)
|
||||
|
@ -304,7 +326,7 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
|
|||
if ((addr & (DATA_SIZE - 1)) != 0)
|
||||
goto do_unaligned_access;
|
||||
ioaddr = env->iotlb[mmu_idx][index];
|
||||
glue(io_write, SUFFIX)(ioaddr, val, addr, retaddr);
|
||||
glue(io_write, SUFFIX)(ENV_VAR ioaddr, val, addr, retaddr);
|
||||
} else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) {
|
||||
do_unaligned_access:
|
||||
/* XXX: not efficient, but simple */
|
||||
|
@ -312,10 +334,12 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
|
|||
* previous page from the TLB cache. */
|
||||
for(i = DATA_SIZE - 1; i >= 0; i--) {
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
glue(slow_stb, MMUSUFFIX)(addr + i, val >> (((DATA_SIZE - 1) * 8) - (i * 8)),
|
||||
glue(slow_stb, MMUSUFFIX)(ENV_VAR addr + i,
|
||||
val >> (((DATA_SIZE - 1) * 8) - (i * 8)),
|
||||
mmu_idx, retaddr);
|
||||
#else
|
||||
glue(slow_stb, MMUSUFFIX)(addr + i, val >> (i * 8),
|
||||
glue(slow_stb, MMUSUFFIX)(ENV_VAR addr + i,
|
||||
val >> (i * 8),
|
||||
mmu_idx, retaddr);
|
||||
#endif
|
||||
}
|
||||
|
@ -340,3 +364,7 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr,
|
|||
#undef USUFFIX
|
||||
#undef DATA_SIZE
|
||||
#undef ADDR_READ
|
||||
#undef ENV_PARAM
|
||||
#undef ENV_VAR
|
||||
#undef CPU_PREFIX
|
||||
#undef HELPER_PREFIX
|
||||
|
|
|
@ -877,7 +877,8 @@ static void do_interrupt_v7m(CPUARMState *env)
|
|||
v7m_push(env, env->regs[1]);
|
||||
v7m_push(env, env->regs[0]);
|
||||
switch_v7m_sp(env, 0);
|
||||
env->uncached_cpsr &= ~CPSR_IT;
|
||||
/* Clear IT bits */
|
||||
env->condexec_bits = 0;
|
||||
env->regs[14] = lr;
|
||||
addr = ldl_phys(env->v7m.vecbase + env->v7m.exception * 4);
|
||||
env->regs[15] = addr & 0xfffffffe;
|
||||
|
@ -2025,7 +2026,7 @@ uint32_t HELPER(get_cp15)(CPUARMState *env, uint32_t insn)
|
|||
return env->cp15.c5_data;
|
||||
case 1:
|
||||
if (arm_feature(env, ARM_FEATURE_MPU))
|
||||
return simple_mpu_ap_bits(env->cp15.c5_data);
|
||||
return simple_mpu_ap_bits(env->cp15.c5_insn);
|
||||
return env->cp15.c5_insn;
|
||||
case 2:
|
||||
if (!arm_feature(env, ARM_FEATURE_MPU))
|
||||
|
|
|
@ -9704,32 +9704,49 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
|
|||
store_reg(s, rd, tmp);
|
||||
break;
|
||||
|
||||
case 6: /* cps */
|
||||
ARCH(6);
|
||||
if (IS_USER(s))
|
||||
case 6:
|
||||
switch ((insn >> 5) & 7) {
|
||||
case 2:
|
||||
/* setend */
|
||||
ARCH(6);
|
||||
if (insn & (1 << 3)) {
|
||||
/* BE8 mode not implemented. */
|
||||
goto illegal_op;
|
||||
}
|
||||
break;
|
||||
if (IS_M(env)) {
|
||||
tmp = tcg_const_i32((insn & (1 << 4)) != 0);
|
||||
/* FAULTMASK */
|
||||
if (insn & 1) {
|
||||
addr = tcg_const_i32(19);
|
||||
gen_helper_v7m_msr(cpu_env, addr, tmp);
|
||||
tcg_temp_free_i32(addr);
|
||||
case 3:
|
||||
/* cps */
|
||||
ARCH(6);
|
||||
if (IS_USER(s)) {
|
||||
break;
|
||||
}
|
||||
/* PRIMASK */
|
||||
if (insn & 2) {
|
||||
addr = tcg_const_i32(16);
|
||||
gen_helper_v7m_msr(cpu_env, addr, tmp);
|
||||
tcg_temp_free_i32(addr);
|
||||
if (IS_M(env)) {
|
||||
tmp = tcg_const_i32((insn & (1 << 4)) != 0);
|
||||
/* FAULTMASK */
|
||||
if (insn & 1) {
|
||||
addr = tcg_const_i32(19);
|
||||
gen_helper_v7m_msr(cpu_env, addr, tmp);
|
||||
tcg_temp_free_i32(addr);
|
||||
}
|
||||
/* PRIMASK */
|
||||
if (insn & 2) {
|
||||
addr = tcg_const_i32(16);
|
||||
gen_helper_v7m_msr(cpu_env, addr, tmp);
|
||||
tcg_temp_free_i32(addr);
|
||||
}
|
||||
tcg_temp_free_i32(tmp);
|
||||
gen_lookup_tb(s);
|
||||
} else {
|
||||
if (insn & (1 << 4)) {
|
||||
shift = CPSR_A | CPSR_I | CPSR_F;
|
||||
} else {
|
||||
shift = 0;
|
||||
}
|
||||
gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
|
||||
}
|
||||
tcg_temp_free_i32(tmp);
|
||||
gen_lookup_tb(s);
|
||||
} else {
|
||||
if (insn & (1 << 4))
|
||||
shift = CPSR_A | CPSR_I | CPSR_F;
|
||||
else
|
||||
shift = 0;
|
||||
gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
|
||||
break;
|
||||
default:
|
||||
goto undef;
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -1918,8 +1918,10 @@ enum {
|
|||
PPC2_DFP = 0x0000000000000004ULL,
|
||||
/* Embedded.Processor Control */
|
||||
PPC2_PRCNTL = 0x0000000000000008ULL,
|
||||
/* Byte-reversed, indexed, double-word load and store */
|
||||
PPC2_DBRX = 0x0000000000000010ULL,
|
||||
|
||||
#define PPC_TCG_INSNS2 (PPC2_BOOKE206 | PPC2_PRCNTL)
|
||||
#define PPC_TCG_INSNS2 (PPC2_BOOKE206 | PPC2_PRCNTL | PPC2_DBRX)
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
@ -591,12 +591,6 @@ static inline int _find_pte(CPUPPCState *env, mmu_ctx_t *ctx, int is_64b, int h,
|
|||
pte1 = ldq_phys(env->htab_base + pteg_off + (i * 16) + 8);
|
||||
}
|
||||
|
||||
/* We have a TLB that saves 4K pages, so let's
|
||||
* split a huge page to 4k chunks */
|
||||
if (target_page_bits != TARGET_PAGE_BITS)
|
||||
pte1 |= (ctx->eaddr & (( 1 << target_page_bits ) - 1))
|
||||
& TARGET_PAGE_MASK;
|
||||
|
||||
r = pte64_check(ctx, pte0, pte1, h, rw, type);
|
||||
LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
|
||||
TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
|
||||
|
@ -672,6 +666,12 @@ static inline int _find_pte(CPUPPCState *env, mmu_ctx_t *ctx, int is_64b, int h,
|
|||
}
|
||||
}
|
||||
|
||||
/* We have a TLB that saves 4K pages, so let's
|
||||
* split a huge page to 4k chunks */
|
||||
if (target_page_bits != TARGET_PAGE_BITS) {
|
||||
ctx->raddr |= (ctx->eaddr & ((1 << target_page_bits) - 1))
|
||||
& TARGET_PAGE_MASK;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -843,12 +843,18 @@ void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd)
|
|||
int fd;
|
||||
void *table;
|
||||
|
||||
/* Must set fd to -1 so we don't try to munmap when called for
|
||||
* destroying the table, which the upper layers -will- do
|
||||
*/
|
||||
*pfd = -1;
|
||||
if (!cap_spapr_tce) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_SPAPR_TCE, &args);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "KVM: Failed to create TCE table for liobn 0x%x\n",
|
||||
liobn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -857,6 +863,8 @@ void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd)
|
|||
|
||||
table = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (table == MAP_FAILED) {
|
||||
fprintf(stderr, "KVM: Failed to map TCE table for liobn 0x%x\n",
|
||||
liobn);
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -876,8 +884,8 @@ int kvmppc_remove_spapr_tce(void *table, int fd, uint32_t window_size)
|
|||
len = (window_size / SPAPR_VIO_TCE_PAGE_SIZE)*sizeof(VIOsPAPR_RTCE);
|
||||
if ((munmap(table, len) < 0) ||
|
||||
(close(fd) < 0)) {
|
||||
fprintf(stderr, "KVM: Unexpected error removing KVM SPAPR TCE "
|
||||
"table: %s", strerror(errno));
|
||||
fprintf(stderr, "KVM: Unexpected error removing TCE table: %s",
|
||||
strerror(errno));
|
||||
/* Leak the table */
|
||||
}
|
||||
|
||||
|
|
|
@ -2650,7 +2650,7 @@ static void glue(gen_, name##ux)(DisasContext *ctx)
|
|||
tcg_temp_free(EA); \
|
||||
}
|
||||
|
||||
#define GEN_LDX(name, ldop, opc2, opc3, type) \
|
||||
#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2) \
|
||||
static void glue(gen_, name##x)(DisasContext *ctx) \
|
||||
{ \
|
||||
TCGv EA; \
|
||||
|
@ -2660,6 +2660,8 @@ static void glue(gen_, name##x)(DisasContext *ctx) \
|
|||
gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \
|
||||
tcg_temp_free(EA); \
|
||||
}
|
||||
#define GEN_LDX(name, ldop, opc2, opc3, type) \
|
||||
GEN_LDX_E(name, ldop, opc2, opc3, type, PPC_NONE)
|
||||
|
||||
#define GEN_LDS(name, ldop, op, type) \
|
||||
GEN_LD(name, ldop, op | 0x20, type); \
|
||||
|
@ -2793,8 +2795,8 @@ static void glue(gen_, name##ux)(DisasContext *ctx)
|
|||
tcg_temp_free(EA); \
|
||||
}
|
||||
|
||||
#define GEN_STX(name, stop, opc2, opc3, type) \
|
||||
static void glue(gen_, name##x)(DisasContext *ctx) \
|
||||
#define GEN_STX_E(name, stop, opc2, opc3, type, type2) \
|
||||
static void glue(gen_, name##x)(DisasContext *ctx) \
|
||||
{ \
|
||||
TCGv EA; \
|
||||
gen_set_access_type(ctx, ACCESS_INT); \
|
||||
|
@ -2803,6 +2805,8 @@ static void glue(gen_, name##x)(DisasContext *ctx)
|
|||
gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \
|
||||
tcg_temp_free(EA); \
|
||||
}
|
||||
#define GEN_STX(name, stop, opc2, opc3, type) \
|
||||
GEN_STX_E(name, stop, opc2, opc3, type, PPC_NONE)
|
||||
|
||||
#define GEN_STS(name, stop, op, type) \
|
||||
GEN_ST(name, stop, op | 0x20, type); \
|
||||
|
@ -2891,6 +2895,18 @@ static inline void gen_qemu_ld32ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
|
|||
}
|
||||
GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
|
||||
|
||||
#if defined(TARGET_PPC64)
|
||||
/* ldbrx */
|
||||
static inline void gen_qemu_ld64ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
|
||||
{
|
||||
tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
|
||||
if (likely(!ctx->le_mode)) {
|
||||
tcg_gen_bswap64_tl(arg1, arg1);
|
||||
}
|
||||
}
|
||||
GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX);
|
||||
#endif /* TARGET_PPC64 */
|
||||
|
||||
/* sthbrx */
|
||||
static inline void gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2)
|
||||
{
|
||||
|
@ -2921,6 +2937,22 @@ static inline void gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
|
|||
}
|
||||
GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
|
||||
|
||||
#if defined(TARGET_PPC64)
|
||||
/* stdbrx */
|
||||
static inline void gen_qemu_st64r(DisasContext *ctx, TCGv arg1, TCGv arg2)
|
||||
{
|
||||
if (likely(!ctx->le_mode)) {
|
||||
TCGv t0 = tcg_temp_new();
|
||||
tcg_gen_bswap64_tl(t0, arg1);
|
||||
tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
|
||||
tcg_temp_free(t0);
|
||||
} else {
|
||||
tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx);
|
||||
}
|
||||
}
|
||||
GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX);
|
||||
#endif /* TARGET_PPC64 */
|
||||
|
||||
/*** Integer load and store multiple ***/
|
||||
|
||||
/* lmw */
|
||||
|
@ -8818,7 +8850,7 @@ GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT),
|
|||
#undef GEN_LD
|
||||
#undef GEN_LDU
|
||||
#undef GEN_LDUX
|
||||
#undef GEN_LDX
|
||||
#undef GEN_LDX_E
|
||||
#undef GEN_LDS
|
||||
#define GEN_LD(name, ldop, opc, type) \
|
||||
GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
|
||||
|
@ -8826,8 +8858,8 @@ GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
|
|||
GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
|
||||
#define GEN_LDUX(name, ldop, opc2, opc3, type) \
|
||||
GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type),
|
||||
#define GEN_LDX(name, ldop, opc2, opc3, type) \
|
||||
GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
|
||||
#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2) \
|
||||
GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
|
||||
#define GEN_LDS(name, ldop, op, type) \
|
||||
GEN_LD(name, ldop, op | 0x20, type) \
|
||||
GEN_LDU(name, ldop, op | 0x21, type) \
|
||||
|
@ -8843,6 +8875,7 @@ GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B)
|
|||
GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B)
|
||||
GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B)
|
||||
GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B)
|
||||
GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX)
|
||||
#endif
|
||||
GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER)
|
||||
GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER)
|
||||
|
@ -8850,7 +8883,7 @@ GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER)
|
|||
#undef GEN_ST
|
||||
#undef GEN_STU
|
||||
#undef GEN_STUX
|
||||
#undef GEN_STX
|
||||
#undef GEN_STX_E
|
||||
#undef GEN_STS
|
||||
#define GEN_ST(name, stop, opc, type) \
|
||||
GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
|
||||
|
@ -8858,8 +8891,8 @@ GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
|
|||
GEN_HANDLER(stop##u, opc, 0xFF, 0xFF, 0x00000000, type),
|
||||
#define GEN_STUX(name, stop, opc2, opc3, type) \
|
||||
GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type),
|
||||
#define GEN_STX(name, stop, opc2, opc3, type) \
|
||||
GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
|
||||
#define GEN_STX_E(name, stop, opc2, opc3, type, type2) \
|
||||
GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
|
||||
#define GEN_STS(name, stop, op, type) \
|
||||
GEN_ST(name, stop, op | 0x20, type) \
|
||||
GEN_STU(name, stop, op | 0x21, type) \
|
||||
|
@ -8872,6 +8905,7 @@ GEN_STS(stw, st32, 0x04, PPC_INTEGER)
|
|||
#if defined(TARGET_PPC64)
|
||||
GEN_STUX(std, st64, 0x15, 0x05, PPC_64B)
|
||||
GEN_STX(std, st64, 0x15, 0x04, PPC_64B)
|
||||
GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX)
|
||||
#endif
|
||||
GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER)
|
||||
GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER)
|
||||
|
@ -9285,6 +9319,8 @@ void cpu_dump_state (CPUPPCState *env, FILE *f, fprintf_function cpu_fprintf,
|
|||
|
||||
int i;
|
||||
|
||||
cpu_synchronize_state(env);
|
||||
|
||||
cpu_fprintf(f, "NIP " TARGET_FMT_lx " LR " TARGET_FMT_lx " CTR "
|
||||
TARGET_FMT_lx " XER " TARGET_FMT_lx "\n",
|
||||
env->nip, env->lr, env->ctr, env->xer);
|
||||
|
|
|
@ -6571,7 +6571,7 @@ static void init_proc_970MP (CPUPPCState *env)
|
|||
PPC_64B | PPC_ALTIVEC | \
|
||||
PPC_SEGMENT_64B | PPC_SLBI | \
|
||||
PPC_POPCNTB | PPC_POPCNTWD)
|
||||
#define POWERPC_INSNS2_POWER7 (PPC2_VSX | PPC2_DFP)
|
||||
#define POWERPC_INSNS2_POWER7 (PPC2_VSX | PPC2_DFP | PPC2_DBRX)
|
||||
#define POWERPC_MSRM_POWER7 (0x800000000204FF36ULL)
|
||||
#define POWERPC_MMU_POWER7 (POWERPC_MMU_2_06)
|
||||
#define POWERPC_EXCP_POWER7 (POWERPC_EXCP_POWER7)
|
||||
|
@ -6588,6 +6588,11 @@ static void init_proc_POWER7 (CPUPPCState *env)
|
|||
gen_spr_7xx(env);
|
||||
/* Time base */
|
||||
gen_tbl(env);
|
||||
/* Processor identification */
|
||||
spr_register(env, SPR_PIR, "PIR",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
&spr_read_generic, &spr_write_pir,
|
||||
0x00000000);
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
/* PURR & SPURR: Hack - treat these as aliases for the TB for now */
|
||||
spr_register(env, SPR_PURR, "PURR",
|
||||
|
@ -6713,7 +6718,7 @@ static void init_proc_620 (CPUPPCState *env)
|
|||
#if defined (TARGET_PPC64) && 0 // XXX: TODO
|
||||
#define CPU_POWERPC_DEFAULT CPU_POWERPC_PPC64
|
||||
#define POWERPC_INSNS_DEFAULT POWERPC_INSNS_PPC64
|
||||
#define POWERPC_INSNS2_DEFAULT POWERPC_INSNS_PPC64
|
||||
#define POWERPC_INSNS2_DEFAULT POWERPC_INSNS2_PPC64
|
||||
#define POWERPC_MSRM_DEFAULT POWERPC_MSRM_PPC64
|
||||
#define POWERPC_MMU_DEFAULT POWERPC_MMU_PPC64
|
||||
#define POWERPC_EXCP_DEFAULT POWERPC_EXCP_PPC64
|
||||
|
@ -6725,7 +6730,7 @@ static void init_proc_620 (CPUPPCState *env)
|
|||
#else
|
||||
#define CPU_POWERPC_DEFAULT CPU_POWERPC_PPC32
|
||||
#define POWERPC_INSNS_DEFAULT POWERPC_INSNS_PPC32
|
||||
#define POWERPC_INSNS2_DEFAULT POWERPC_INSNS_PPC32
|
||||
#define POWERPC_INSNS2_DEFAULT POWERPC_INSNS2_PPC32
|
||||
#define POWERPC_MSRM_DEFAULT POWERPC_MSRM_PPC32
|
||||
#define POWERPC_MMU_DEFAULT POWERPC_MMU_PPC32
|
||||
#define POWERPC_EXCP_DEFAULT POWERPC_EXCP_PPC32
|
||||
|
|
|
@ -415,14 +415,15 @@ struct CPUSPARCState {
|
|||
#if !defined(TARGET_SPARC64)
|
||||
int psref; /* enable fpu */
|
||||
#endif
|
||||
target_ulong version;
|
||||
int interrupt_index;
|
||||
uint32_t nwindows;
|
||||
/* NOTE: we allow 8 more registers to handle wrapping */
|
||||
target_ulong regbase[MAX_NWINDOWS * 16 + 8];
|
||||
|
||||
CPU_COMMON
|
||||
|
||||
target_ulong version;
|
||||
uint32_t nwindows;
|
||||
|
||||
/* MMU regs */
|
||||
#if defined(TARGET_SPARC64)
|
||||
uint64_t lsu;
|
||||
|
@ -492,6 +493,9 @@ struct CPUSPARCState {
|
|||
/* UA 2005 hyperprivileged registers */
|
||||
uint64_t hpstate, htstate[MAXTL_MAX], hintp, htba, hver, hstick_cmpr, ssr;
|
||||
CPUTimer *hstick; // UA 2005
|
||||
/* Interrupt vector registers */
|
||||
uint64_t ivec_status;
|
||||
uint64_t ivec_data[3];
|
||||
uint32_t softint;
|
||||
#define SOFTINT_TIMER 1
|
||||
#define SOFTINT_STIMER (1 << 16)
|
||||
|
@ -582,7 +586,6 @@ void cpu_unassigned_access(CPUSPARCState *env1, target_phys_addr_t addr,
|
|||
#if defined(TARGET_SPARC64)
|
||||
target_phys_addr_t cpu_get_phys_page_nofault(CPUSPARCState *env, target_ulong addr,
|
||||
int mmu_idx);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);
|
||||
|
@ -696,6 +699,8 @@ uint64_t cpu_tick_get_count(CPUTimer *timer);
|
|||
void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit);
|
||||
trap_state* cpu_tsptr(CPUSPARCState* env);
|
||||
#endif
|
||||
void do_unaligned_access(CPUSPARCState *env, target_ulong addr, int is_write,
|
||||
int is_user, void *retaddr);
|
||||
|
||||
#define TB_FLAG_FPU_ENABLED (1 << 4)
|
||||
#define TB_FLAG_AM_ENABLED (1 << 5)
|
||||
|
|
|
@ -30,6 +30,7 @@ void cpu_state_reset(CPUSPARCState *env)
|
|||
log_cpu_state(env, 0);
|
||||
}
|
||||
|
||||
memset(env, 0, offsetof(CPUSPARCState, breakpoints));
|
||||
tlb_flush(env, 1);
|
||||
env->cwp = 0;
|
||||
#ifndef TARGET_SPARC64
|
||||
|
|
|
@ -18,11 +18,11 @@ DEF_HELPER_1(rdcwp, tl, env)
|
|||
DEF_HELPER_2(wrcwp, void, env, tl)
|
||||
DEF_HELPER_FLAGS_2(array8, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
|
||||
DEF_HELPER_1(popc, tl, tl)
|
||||
DEF_HELPER_3(ldda_asi, void, tl, int, int)
|
||||
DEF_HELPER_4(ldf_asi, void, tl, int, int, int)
|
||||
DEF_HELPER_4(stf_asi, void, tl, int, int, int)
|
||||
DEF_HELPER_4(cas_asi, tl, tl, tl, tl, i32)
|
||||
DEF_HELPER_4(casx_asi, tl, tl, tl, tl, i32)
|
||||
DEF_HELPER_4(ldda_asi, void, env, tl, int, int)
|
||||
DEF_HELPER_5(ldf_asi, void, env, tl, int, int, int)
|
||||
DEF_HELPER_5(stf_asi, void, env, tl, int, int, int)
|
||||
DEF_HELPER_5(cas_asi, tl, env, tl, tl, tl, i32)
|
||||
DEF_HELPER_5(casx_asi, tl, env, tl, tl, tl, i32)
|
||||
DEF_HELPER_2(set_softint, void, env, i64)
|
||||
DEF_HELPER_2(clear_softint, void, env, i64)
|
||||
DEF_HELPER_2(write_softint, void, env, i64)
|
||||
|
@ -30,7 +30,7 @@ DEF_HELPER_2(tick_set_count, void, ptr, i64)
|
|||
DEF_HELPER_1(tick_get_count, i64, ptr)
|
||||
DEF_HELPER_2(tick_set_limit, void, ptr, i64)
|
||||
#endif
|
||||
DEF_HELPER_2(check_align, void, tl, i32)
|
||||
DEF_HELPER_3(check_align, void, env, tl, i32)
|
||||
DEF_HELPER_1(debug, void, env)
|
||||
DEF_HELPER_1(save, void, env)
|
||||
DEF_HELPER_1(restore, void, env)
|
||||
|
@ -38,11 +38,11 @@ DEF_HELPER_3(udiv, tl, env, tl, tl)
|
|||
DEF_HELPER_3(udiv_cc, tl, env, tl, tl)
|
||||
DEF_HELPER_3(sdiv, tl, env, tl, tl)
|
||||
DEF_HELPER_3(sdiv_cc, tl, env, tl, tl)
|
||||
DEF_HELPER_2(ldqf, void, tl, int)
|
||||
DEF_HELPER_2(stqf, void, tl, int)
|
||||
DEF_HELPER_3(ldqf, void, env, tl, int)
|
||||
DEF_HELPER_3(stqf, void, env, tl, int)
|
||||
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
|
||||
DEF_HELPER_4(ld_asi, i64, tl, int, int, int)
|
||||
DEF_HELPER_4(st_asi, void, tl, i64, int, int)
|
||||
DEF_HELPER_5(ld_asi, i64, env, tl, int, int, int)
|
||||
DEF_HELPER_5(st_asi, void, env, tl, i64, int, int)
|
||||
#endif
|
||||
DEF_HELPER_2(ldfsr, void, env, i32)
|
||||
DEF_HELPER_FLAGS_1(fabss, TCG_CALL_CONST | TCG_CALL_PURE, f32, f32)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,74 +0,0 @@
|
|||
#include "cpu.h"
|
||||
#include "dyngen-exec.h"
|
||||
#include "helper.h"
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
|
||||
void *retaddr);
|
||||
|
||||
#define MMUSUFFIX _mmu
|
||||
#define ALIGNED_ONLY
|
||||
|
||||
#define SHIFT 0
|
||||
#include "softmmu_template.h"
|
||||
|
||||
#define SHIFT 1
|
||||
#include "softmmu_template.h"
|
||||
|
||||
#define SHIFT 2
|
||||
#include "softmmu_template.h"
|
||||
|
||||
#define SHIFT 3
|
||||
#include "softmmu_template.h"
|
||||
|
||||
/* XXX: make it generic ? */
|
||||
static void cpu_restore_state2(void *retaddr)
|
||||
{
|
||||
TranslationBlock *tb;
|
||||
unsigned long pc;
|
||||
|
||||
if (retaddr) {
|
||||
/* now we have a real cpu fault */
|
||||
pc = (unsigned long)retaddr;
|
||||
tb = tb_find_pc(pc);
|
||||
if (tb) {
|
||||
/* the PC is inside the translated code. It means that we have
|
||||
a virtual CPU fault */
|
||||
cpu_restore_state(tb, env, pc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
|
||||
void *retaddr)
|
||||
{
|
||||
#ifdef DEBUG_UNALIGNED
|
||||
printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
|
||||
"\n", addr, env->pc);
|
||||
#endif
|
||||
cpu_restore_state2(retaddr);
|
||||
helper_raise_exception(env, TT_UNALIGNED);
|
||||
}
|
||||
|
||||
/* try to fill the TLB and return an exception if error. If retaddr is
|
||||
NULL, it means that the function was called in C code (i.e. not
|
||||
from generated code or from helper.c) */
|
||||
/* XXX: fix it to restore all registers */
|
||||
void tlb_fill(CPUSPARCState *env1, target_ulong addr, int is_write, int mmu_idx,
|
||||
void *retaddr)
|
||||
{
|
||||
int ret;
|
||||
CPUSPARCState *saved_env;
|
||||
|
||||
saved_env = env;
|
||||
env = env1;
|
||||
|
||||
ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx);
|
||||
if (ret) {
|
||||
cpu_restore_state2(retaddr);
|
||||
cpu_loop_exit(env);
|
||||
}
|
||||
env = saved_env;
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_USER_ONLY */
|
|
@ -1955,7 +1955,7 @@ static inline void gen_ld_asi(TCGv dst, TCGv addr, int insn, int size,
|
|||
r_asi = gen_get_asi(insn, addr);
|
||||
r_size = tcg_const_i32(size);
|
||||
r_sign = tcg_const_i32(sign);
|
||||
gen_helper_ld_asi(dst, addr, r_asi, r_size, r_sign);
|
||||
gen_helper_ld_asi(dst, cpu_env, addr, r_asi, r_size, r_sign);
|
||||
tcg_temp_free_i32(r_sign);
|
||||
tcg_temp_free_i32(r_size);
|
||||
tcg_temp_free_i32(r_asi);
|
||||
|
@ -1967,7 +1967,7 @@ static inline void gen_st_asi(TCGv src, TCGv addr, int insn, int size)
|
|||
|
||||
r_asi = gen_get_asi(insn, addr);
|
||||
r_size = tcg_const_i32(size);
|
||||
gen_helper_st_asi(addr, src, r_asi, r_size);
|
||||
gen_helper_st_asi(cpu_env, addr, src, r_asi, r_size);
|
||||
tcg_temp_free_i32(r_size);
|
||||
tcg_temp_free_i32(r_asi);
|
||||
}
|
||||
|
@ -1979,7 +1979,7 @@ static inline void gen_ldf_asi(TCGv addr, int insn, int size, int rd)
|
|||
r_asi = gen_get_asi(insn, addr);
|
||||
r_size = tcg_const_i32(size);
|
||||
r_rd = tcg_const_i32(rd);
|
||||
gen_helper_ldf_asi(addr, r_asi, r_size, r_rd);
|
||||
gen_helper_ldf_asi(cpu_env, addr, r_asi, r_size, r_rd);
|
||||
tcg_temp_free_i32(r_rd);
|
||||
tcg_temp_free_i32(r_size);
|
||||
tcg_temp_free_i32(r_asi);
|
||||
|
@ -1992,7 +1992,7 @@ static inline void gen_stf_asi(TCGv addr, int insn, int size, int rd)
|
|||
r_asi = gen_get_asi(insn, addr);
|
||||
r_size = tcg_const_i32(size);
|
||||
r_rd = tcg_const_i32(rd);
|
||||
gen_helper_stf_asi(addr, r_asi, r_size, r_rd);
|
||||
gen_helper_stf_asi(cpu_env, addr, r_asi, r_size, r_rd);
|
||||
tcg_temp_free_i32(r_rd);
|
||||
tcg_temp_free_i32(r_size);
|
||||
tcg_temp_free_i32(r_asi);
|
||||
|
@ -2005,9 +2005,9 @@ static inline void gen_swap_asi(TCGv dst, TCGv addr, int insn)
|
|||
r_asi = gen_get_asi(insn, addr);
|
||||
r_size = tcg_const_i32(4);
|
||||
r_sign = tcg_const_i32(0);
|
||||
gen_helper_ld_asi(cpu_tmp64, addr, r_asi, r_size, r_sign);
|
||||
gen_helper_ld_asi(cpu_tmp64, cpu_env, addr, r_asi, r_size, r_sign);
|
||||
tcg_temp_free_i32(r_sign);
|
||||
gen_helper_st_asi(addr, dst, r_asi, r_size);
|
||||
gen_helper_st_asi(cpu_env, addr, dst, r_asi, r_size);
|
||||
tcg_temp_free_i32(r_size);
|
||||
tcg_temp_free_i32(r_asi);
|
||||
tcg_gen_trunc_i64_tl(dst, cpu_tmp64);
|
||||
|
@ -2019,7 +2019,7 @@ static inline void gen_ldda_asi(TCGv hi, TCGv addr, int insn, int rd)
|
|||
|
||||
r_asi = gen_get_asi(insn, addr);
|
||||
r_rd = tcg_const_i32(rd);
|
||||
gen_helper_ldda_asi(addr, r_asi, r_rd);
|
||||
gen_helper_ldda_asi(cpu_env, addr, r_asi, r_rd);
|
||||
tcg_temp_free_i32(r_rd);
|
||||
tcg_temp_free_i32(r_asi);
|
||||
}
|
||||
|
@ -2032,7 +2032,7 @@ static inline void gen_stda_asi(TCGv hi, TCGv addr, int insn, int rd)
|
|||
tcg_gen_concat_tl_i64(cpu_tmp64, cpu_tmp0, hi);
|
||||
r_asi = gen_get_asi(insn, addr);
|
||||
r_size = tcg_const_i32(8);
|
||||
gen_helper_st_asi(addr, cpu_tmp64, r_asi, r_size);
|
||||
gen_helper_st_asi(cpu_env, addr, cpu_tmp64, r_asi, r_size);
|
||||
tcg_temp_free_i32(r_size);
|
||||
tcg_temp_free_i32(r_asi);
|
||||
}
|
||||
|
@ -2046,7 +2046,7 @@ static inline void gen_cas_asi(TCGv dst, TCGv addr, TCGv val2, int insn,
|
|||
r_val1 = tcg_temp_new();
|
||||
gen_movl_reg_TN(rd, r_val1);
|
||||
r_asi = gen_get_asi(insn, addr);
|
||||
gen_helper_cas_asi(dst, addr, r_val1, val2, r_asi);
|
||||
gen_helper_cas_asi(dst, cpu_env, addr, r_val1, val2, r_asi);
|
||||
tcg_temp_free_i32(r_asi);
|
||||
tcg_temp_free(r_val1);
|
||||
}
|
||||
|
@ -2058,7 +2058,7 @@ static inline void gen_casx_asi(TCGv dst, TCGv addr, TCGv val2, int insn,
|
|||
|
||||
gen_movl_reg_TN(rd, cpu_tmp64);
|
||||
r_asi = gen_get_asi(insn, addr);
|
||||
gen_helper_casx_asi(dst, addr, cpu_tmp64, val2, r_asi);
|
||||
gen_helper_casx_asi(dst, cpu_env, addr, cpu_tmp64, val2, r_asi);
|
||||
tcg_temp_free_i32(r_asi);
|
||||
}
|
||||
|
||||
|
@ -2072,7 +2072,7 @@ static inline void gen_ld_asi(TCGv dst, TCGv addr, int insn, int size,
|
|||
r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
|
||||
r_size = tcg_const_i32(size);
|
||||
r_sign = tcg_const_i32(sign);
|
||||
gen_helper_ld_asi(cpu_tmp64, addr, r_asi, r_size, r_sign);
|
||||
gen_helper_ld_asi(cpu_tmp64, cpu_env, addr, r_asi, r_size, r_sign);
|
||||
tcg_temp_free(r_sign);
|
||||
tcg_temp_free(r_size);
|
||||
tcg_temp_free(r_asi);
|
||||
|
@ -2086,7 +2086,7 @@ static inline void gen_st_asi(TCGv src, TCGv addr, int insn, int size)
|
|||
tcg_gen_extu_tl_i64(cpu_tmp64, src);
|
||||
r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
|
||||
r_size = tcg_const_i32(size);
|
||||
gen_helper_st_asi(addr, cpu_tmp64, r_asi, r_size);
|
||||
gen_helper_st_asi(cpu_env, addr, cpu_tmp64, r_asi, r_size);
|
||||
tcg_temp_free(r_size);
|
||||
tcg_temp_free(r_asi);
|
||||
}
|
||||
|
@ -2099,11 +2099,11 @@ static inline void gen_swap_asi(TCGv dst, TCGv addr, int insn)
|
|||
r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
|
||||
r_size = tcg_const_i32(4);
|
||||
r_sign = tcg_const_i32(0);
|
||||
gen_helper_ld_asi(cpu_tmp64, addr, r_asi, r_size, r_sign);
|
||||
gen_helper_ld_asi(cpu_tmp64, cpu_env, addr, r_asi, r_size, r_sign);
|
||||
tcg_temp_free(r_sign);
|
||||
r_val = tcg_temp_new_i64();
|
||||
tcg_gen_extu_tl_i64(r_val, dst);
|
||||
gen_helper_st_asi(addr, r_val, r_asi, r_size);
|
||||
gen_helper_st_asi(cpu_env, addr, r_val, r_asi, r_size);
|
||||
tcg_temp_free_i64(r_val);
|
||||
tcg_temp_free(r_size);
|
||||
tcg_temp_free(r_asi);
|
||||
|
@ -2117,7 +2117,7 @@ static inline void gen_ldda_asi(TCGv hi, TCGv addr, int insn, int rd)
|
|||
r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
|
||||
r_size = tcg_const_i32(8);
|
||||
r_sign = tcg_const_i32(0);
|
||||
gen_helper_ld_asi(cpu_tmp64, addr, r_asi, r_size, r_sign);
|
||||
gen_helper_ld_asi(cpu_tmp64, cpu_env, addr, r_asi, r_size, r_sign);
|
||||
tcg_temp_free(r_sign);
|
||||
tcg_temp_free(r_size);
|
||||
tcg_temp_free(r_asi);
|
||||
|
@ -2136,7 +2136,7 @@ static inline void gen_stda_asi(TCGv hi, TCGv addr, int insn, int rd)
|
|||
tcg_gen_concat_tl_i64(cpu_tmp64, cpu_tmp0, hi);
|
||||
r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
|
||||
r_size = tcg_const_i32(8);
|
||||
gen_helper_st_asi(addr, cpu_tmp64, r_asi, r_size);
|
||||
gen_helper_st_asi(cpu_env, addr, cpu_tmp64, r_asi, r_size);
|
||||
tcg_temp_free(r_size);
|
||||
tcg_temp_free(r_asi);
|
||||
}
|
||||
|
@ -2153,7 +2153,7 @@ static inline void gen_ldstub_asi(TCGv dst, TCGv addr, int insn)
|
|||
r_val = tcg_const_i64(0xffULL);
|
||||
r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
|
||||
r_size = tcg_const_i32(1);
|
||||
gen_helper_st_asi(addr, r_val, r_asi, r_size);
|
||||
gen_helper_st_asi(cpu_env, addr, r_val, r_asi, r_size);
|
||||
tcg_temp_free_i32(r_size);
|
||||
tcg_temp_free_i32(r_asi);
|
||||
tcg_temp_free_i64(r_val);
|
||||
|
@ -2373,9 +2373,9 @@ static void gen_faligndata(TCGv dst, TCGv gsr, TCGv s1, TCGv s2)
|
|||
goto nfpu_insn;
|
||||
|
||||
/* before an instruction, dc->pc must be static */
|
||||
static void disas_sparc_insn(DisasContext * dc)
|
||||
static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
|
||||
{
|
||||
unsigned int insn, opc, rs1, rs2, rd;
|
||||
unsigned int opc, rs1, rs2, rd;
|
||||
TCGv cpu_src1, cpu_src2, cpu_tmp1, cpu_tmp2;
|
||||
TCGv_i32 cpu_src1_32, cpu_src2_32, cpu_dst_32;
|
||||
TCGv_i64 cpu_src1_64, cpu_src2_64, cpu_dst_64;
|
||||
|
@ -2383,7 +2383,7 @@ static void disas_sparc_insn(DisasContext * dc)
|
|||
|
||||
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
|
||||
tcg_gen_debug_insn_start(dc->pc);
|
||||
insn = ldl_code(dc->pc);
|
||||
|
||||
opc = GET_FIELD(insn, 0, 1);
|
||||
|
||||
rd = GET_FIELD(insn, 2, 6);
|
||||
|
@ -4547,7 +4547,7 @@ static void disas_sparc_insn(DisasContext * dc)
|
|||
gen_helper_restore(cpu_env);
|
||||
gen_mov_pc_npc(dc, cpu_cond);
|
||||
r_const = tcg_const_i32(3);
|
||||
gen_helper_check_align(cpu_dst, r_const);
|
||||
gen_helper_check_align(cpu_env, cpu_dst, r_const);
|
||||
tcg_temp_free_i32(r_const);
|
||||
tcg_gen_mov_tl(cpu_npc, cpu_dst);
|
||||
dc->npc = DYNAMIC_PC;
|
||||
|
@ -4577,7 +4577,7 @@ static void disas_sparc_insn(DisasContext * dc)
|
|||
tcg_temp_free(r_pc);
|
||||
gen_mov_pc_npc(dc, cpu_cond);
|
||||
r_const = tcg_const_i32(3);
|
||||
gen_helper_check_align(cpu_dst, r_const);
|
||||
gen_helper_check_align(cpu_env, cpu_dst, r_const);
|
||||
tcg_temp_free_i32(r_const);
|
||||
tcg_gen_mov_tl(cpu_npc, cpu_dst);
|
||||
dc->npc = DYNAMIC_PC;
|
||||
|
@ -4592,7 +4592,7 @@ static void disas_sparc_insn(DisasContext * dc)
|
|||
goto priv_insn;
|
||||
gen_mov_pc_npc(dc, cpu_cond);
|
||||
r_const = tcg_const_i32(3);
|
||||
gen_helper_check_align(cpu_dst, r_const);
|
||||
gen_helper_check_align(cpu_env, cpu_dst, r_const);
|
||||
tcg_temp_free_i32(r_const);
|
||||
tcg_gen_mov_tl(cpu_npc, cpu_dst);
|
||||
dc->npc = DYNAMIC_PC;
|
||||
|
@ -4696,7 +4696,8 @@ static void disas_sparc_insn(DisasContext * dc)
|
|||
|
||||
save_state(dc, cpu_cond);
|
||||
r_const = tcg_const_i32(7);
|
||||
gen_helper_check_align(cpu_addr, r_const); // XXX remove
|
||||
/* XXX remove alignment check */
|
||||
gen_helper_check_align(cpu_env, cpu_addr, r_const);
|
||||
tcg_temp_free_i32(r_const);
|
||||
gen_address_mask(dc, cpu_addr);
|
||||
tcg_gen_qemu_ld64(cpu_tmp64, cpu_addr, dc->mem_idx);
|
||||
|
@ -4921,7 +4922,7 @@ static void disas_sparc_insn(DisasContext * dc)
|
|||
CHECK_FPU_FEATURE(dc, FLOAT128);
|
||||
r_const = tcg_const_i32(dc->mem_idx);
|
||||
gen_address_mask(dc, cpu_addr);
|
||||
gen_helper_ldqf(cpu_addr, r_const);
|
||||
gen_helper_ldqf(cpu_env, cpu_addr, r_const);
|
||||
tcg_temp_free_i32(r_const);
|
||||
gen_op_store_QT0_fpr(QFPREG(rd));
|
||||
gen_update_fprs_dirty(QFPREG(rd));
|
||||
|
@ -4961,7 +4962,8 @@ static void disas_sparc_insn(DisasContext * dc)
|
|||
save_state(dc, cpu_cond);
|
||||
gen_address_mask(dc, cpu_addr);
|
||||
r_const = tcg_const_i32(7);
|
||||
gen_helper_check_align(cpu_addr, r_const); // XXX remove
|
||||
/* XXX remove alignment check */
|
||||
gen_helper_check_align(cpu_env, cpu_addr, r_const);
|
||||
tcg_temp_free_i32(r_const);
|
||||
gen_movl_reg_TN(rd + 1, cpu_tmp0);
|
||||
tcg_gen_concat_tl_i64(cpu_tmp64, cpu_tmp0, cpu_val);
|
||||
|
@ -5065,7 +5067,7 @@ static void disas_sparc_insn(DisasContext * dc)
|
|||
gen_op_load_fpr_QT0(QFPREG(rd));
|
||||
r_const = tcg_const_i32(dc->mem_idx);
|
||||
gen_address_mask(dc, cpu_addr);
|
||||
gen_helper_stqf(cpu_addr, r_const);
|
||||
gen_helper_stqf(cpu_env, cpu_addr, r_const);
|
||||
tcg_temp_free_i32(r_const);
|
||||
}
|
||||
break;
|
||||
|
@ -5108,7 +5110,7 @@ static void disas_sparc_insn(DisasContext * dc)
|
|||
goto jmp_insn;
|
||||
}
|
||||
r_const = tcg_const_i32(7);
|
||||
gen_helper_check_align(cpu_addr, r_const);
|
||||
gen_helper_check_align(cpu_env, cpu_addr, r_const);
|
||||
tcg_temp_free_i32(r_const);
|
||||
gen_stf_asi(cpu_addr, insn, 16, QFPREG(rd));
|
||||
}
|
||||
|
@ -5238,6 +5240,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
|
|||
int j, lj = -1;
|
||||
int num_insns;
|
||||
int max_insns;
|
||||
unsigned int insn;
|
||||
|
||||
memset(dc, 0, sizeof(DisasContext));
|
||||
dc->tb = tb;
|
||||
|
@ -5297,7 +5300,8 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
|
|||
if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
|
||||
gen_io_start();
|
||||
last_pc = dc->pc;
|
||||
disas_sparc_insn(dc);
|
||||
insn = cpu_ldl_code(env, dc->pc);
|
||||
disas_sparc_insn(dc, insn);
|
||||
num_insns++;
|
||||
|
||||
if (dc->is_br)
|
||||
|
|
|
@ -929,6 +929,27 @@ static inline void tcg_out_goto_label(TCGContext *s, int cond, int label_index)
|
|||
|
||||
#include "../../softmmu_defs.h"
|
||||
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
|
||||
int mmu_idx) */
|
||||
static const void * const qemu_ld_helpers[4] = {
|
||||
helper_ldb_mmu,
|
||||
helper_ldw_mmu,
|
||||
helper_ldl_mmu,
|
||||
helper_ldq_mmu,
|
||||
};
|
||||
|
||||
/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
|
||||
uintxx_t val, int mmu_idx) */
|
||||
static const void * const qemu_st_helpers[4] = {
|
||||
helper_stb_mmu,
|
||||
helper_stw_mmu,
|
||||
helper_stl_mmu,
|
||||
helper_stq_mmu,
|
||||
};
|
||||
#else
|
||||
/* legacy helper signature: __ld_mmu(target_ulong addr, int
|
||||
mmu_idx) */
|
||||
static void *qemu_ld_helpers[4] = {
|
||||
__ldb_mmu,
|
||||
__ldw_mmu,
|
||||
|
@ -936,6 +957,8 @@ static void *qemu_ld_helpers[4] = {
|
|||
__ldq_mmu,
|
||||
};
|
||||
|
||||
/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val,
|
||||
int mmu_idx) */
|
||||
static void *qemu_st_helpers[4] = {
|
||||
__stb_mmu,
|
||||
__stw_mmu,
|
||||
|
@ -943,6 +966,7 @@ static void *qemu_st_helpers[4] = {
|
|||
__stq_mmu,
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define TLB_SHIFT (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
|
||||
|
||||
|
@ -1075,6 +1099,19 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
|
|||
TCG_REG_R1, 0, addr_reg2, SHIFT_IMM_LSL(0));
|
||||
tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
|
||||
# endif
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* XXX/FIXME: suboptimal and incorrect for 64 bit */
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
|
||||
tcg_target_call_iarg_regs[2], 0,
|
||||
tcg_target_call_iarg_regs[1], SHIFT_IMM_LSL(0));
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
|
||||
tcg_target_call_iarg_regs[1], 0,
|
||||
tcg_target_call_iarg_regs[0], SHIFT_IMM_LSL(0));
|
||||
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
|
||||
tcg_target_call_iarg_regs[0], 0, TCG_AREG0,
|
||||
SHIFT_IMM_LSL(0));
|
||||
#endif
|
||||
tcg_out_call(s, (tcg_target_long) qemu_ld_helpers[s_bits]);
|
||||
|
||||
switch (opc) {
|
||||
|
@ -1341,6 +1378,22 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
|
|||
}
|
||||
# endif
|
||||
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* XXX/FIXME: suboptimal and incorrect for 64 bit */
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
|
||||
tcg_target_call_iarg_regs[3], 0,
|
||||
tcg_target_call_iarg_regs[2], SHIFT_IMM_LSL(0));
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
|
||||
tcg_target_call_iarg_regs[2], 0,
|
||||
tcg_target_call_iarg_regs[1], SHIFT_IMM_LSL(0));
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
|
||||
tcg_target_call_iarg_regs[1], 0,
|
||||
tcg_target_call_iarg_regs[0], SHIFT_IMM_LSL(0));
|
||||
|
||||
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
|
||||
tcg_target_call_iarg_regs[0], 0, TCG_AREG0,
|
||||
SHIFT_IMM_LSL(0));
|
||||
#endif
|
||||
tcg_out_call(s, (tcg_target_long) qemu_st_helpers[s_bits]);
|
||||
if (opc == 3)
|
||||
tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R13, TCG_REG_R13, 0x10);
|
||||
|
|
|
@ -882,6 +882,27 @@ static void tcg_out_setcond2(TCGContext *s, int cond, TCGArg ret,
|
|||
#if defined(CONFIG_SOFTMMU)
|
||||
#include "../../softmmu_defs.h"
|
||||
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
|
||||
int mmu_idx) */
|
||||
static const void * const qemu_ld_helpers[4] = {
|
||||
helper_ldb_mmu,
|
||||
helper_ldw_mmu,
|
||||
helper_ldl_mmu,
|
||||
helper_ldq_mmu,
|
||||
};
|
||||
|
||||
/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
|
||||
uintxx_t val, int mmu_idx) */
|
||||
static const void * const qemu_st_helpers[4] = {
|
||||
helper_stb_mmu,
|
||||
helper_stw_mmu,
|
||||
helper_stl_mmu,
|
||||
helper_stq_mmu,
|
||||
};
|
||||
#else
|
||||
/* legacy helper signature: __ld_mmu(target_ulong addr, int
|
||||
mmu_idx) */
|
||||
static void *qemu_ld_helpers[4] = {
|
||||
__ldb_mmu,
|
||||
__ldw_mmu,
|
||||
|
@ -889,12 +910,15 @@ static void *qemu_ld_helpers[4] = {
|
|||
__ldq_mmu,
|
||||
};
|
||||
|
||||
/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val,
|
||||
int mmu_idx) */
|
||||
static void *qemu_st_helpers[4] = {
|
||||
__stb_mmu,
|
||||
__stw_mmu,
|
||||
__stl_mmu,
|
||||
__stq_mmu,
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Load and compare a TLB entry, and branch if TLB miss. OFFSET is set to
|
||||
the offset of the first ADDR_READ or ADDR_WRITE member of the appropriate
|
||||
|
@ -1061,6 +1085,15 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
|
|||
}
|
||||
tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index);
|
||||
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* XXX/FIXME: suboptimal */
|
||||
tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2],
|
||||
tcg_target_call_iarg_regs[1]);
|
||||
tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
|
||||
tcg_target_call_iarg_regs[0]);
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
|
||||
TCG_AREG0);
|
||||
#endif
|
||||
tcg_out_call(s, qemu_ld_helpers[opc & 3]);
|
||||
|
||||
switch (opc) {
|
||||
|
@ -1212,6 +1245,17 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
|
|||
tcg_abort();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* XXX/FIXME: suboptimal */
|
||||
tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
|
||||
tcg_target_call_iarg_regs[2]);
|
||||
tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
|
||||
tcg_target_call_iarg_regs[1]);
|
||||
tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
|
||||
tcg_target_call_iarg_regs[0]);
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
|
||||
TCG_AREG0);
|
||||
#endif
|
||||
tcg_out_call(s, qemu_st_helpers[opc]);
|
||||
|
||||
/* label2: */
|
||||
|
|
|
@ -116,17 +116,7 @@ static inline int tcg_target_get_call_iarg_regs_count(int flags)
|
|||
return 6;
|
||||
}
|
||||
|
||||
flags &= TCG_CALL_TYPE_MASK;
|
||||
switch(flags) {
|
||||
case TCG_CALL_TYPE_STD:
|
||||
return 0;
|
||||
case TCG_CALL_TYPE_REGPARM_1:
|
||||
case TCG_CALL_TYPE_REGPARM_2:
|
||||
case TCG_CALL_TYPE_REGPARM:
|
||||
return flags - TCG_CALL_TYPE_REGPARM_1 + 1;
|
||||
default:
|
||||
tcg_abort();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* parse target specific constraints */
|
||||
|
@ -188,6 +178,9 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
|
|||
tcg_regset_set32(ct->u.regs, 0, 0xffff);
|
||||
tcg_regset_reset_reg(ct->u.regs, TCG_REG_RSI);
|
||||
tcg_regset_reset_reg(ct->u.regs, TCG_REG_RDI);
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
tcg_regset_reset_reg(ct->u.regs, TCG_REG_RDX);
|
||||
#endif
|
||||
} else {
|
||||
tcg_regset_set32(ct->u.regs, 0, 0xff);
|
||||
tcg_regset_reset_reg(ct->u.regs, TCG_REG_EAX);
|
||||
|
@ -967,6 +960,27 @@ static void tcg_out_jmp(TCGContext *s, tcg_target_long dest)
|
|||
|
||||
#include "../../softmmu_defs.h"
|
||||
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
|
||||
int mmu_idx) */
|
||||
static const void *qemu_ld_helpers[4] = {
|
||||
helper_ldb_mmu,
|
||||
helper_ldw_mmu,
|
||||
helper_ldl_mmu,
|
||||
helper_ldq_mmu,
|
||||
};
|
||||
|
||||
/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
|
||||
uintxx_t val, int mmu_idx) */
|
||||
static const void *qemu_st_helpers[4] = {
|
||||
helper_stb_mmu,
|
||||
helper_stw_mmu,
|
||||
helper_stl_mmu,
|
||||
helper_stq_mmu,
|
||||
};
|
||||
#else
|
||||
/* legacy helper signature: __ld_mmu(target_ulong addr, int
|
||||
mmu_idx) */
|
||||
static void *qemu_ld_helpers[4] = {
|
||||
__ldb_mmu,
|
||||
__ldw_mmu,
|
||||
|
@ -974,12 +988,15 @@ static void *qemu_ld_helpers[4] = {
|
|||
__ldq_mmu,
|
||||
};
|
||||
|
||||
/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val,
|
||||
int mmu_idx) */
|
||||
static void *qemu_st_helpers[4] = {
|
||||
__stb_mmu,
|
||||
__stw_mmu,
|
||||
__stl_mmu,
|
||||
__stq_mmu,
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Perform the TLB load and compare.
|
||||
|
||||
|
@ -1148,7 +1165,12 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
|
|||
int data_reg, data_reg2 = 0;
|
||||
int addrlo_idx;
|
||||
#if defined(CONFIG_SOFTMMU)
|
||||
int mem_index, s_bits, arg_idx;
|
||||
int mem_index, s_bits;
|
||||
#if TCG_TARGET_REG_BITS == 64
|
||||
int arg_idx;
|
||||
#else
|
||||
int stack_adjust;
|
||||
#endif
|
||||
uint8_t *label_ptr[3];
|
||||
#endif
|
||||
|
||||
|
@ -1184,16 +1206,48 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
|
|||
}
|
||||
|
||||
/* XXX: move that code at the end of the TB */
|
||||
#if TCG_TARGET_REG_BITS == 32
|
||||
tcg_out_pushi(s, mem_index);
|
||||
stack_adjust = 4;
|
||||
if (TARGET_LONG_BITS == 64) {
|
||||
tcg_out_push(s, args[addrlo_idx + 1]);
|
||||
stack_adjust += 4;
|
||||
}
|
||||
tcg_out_push(s, args[addrlo_idx]);
|
||||
stack_adjust += 4;
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
tcg_out_push(s, TCG_AREG0);
|
||||
stack_adjust += 4;
|
||||
#endif
|
||||
#else
|
||||
/* The first argument is already loaded with addrlo. */
|
||||
arg_idx = 1;
|
||||
if (TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 64) {
|
||||
tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx++],
|
||||
args[addrlo_idx + 1]);
|
||||
}
|
||||
tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx],
|
||||
mem_index);
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* XXX/FIXME: suboptimal */
|
||||
tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[3],
|
||||
tcg_target_call_iarg_regs[2]);
|
||||
tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
|
||||
tcg_target_call_iarg_regs[1]);
|
||||
tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[1],
|
||||
tcg_target_call_iarg_regs[0]);
|
||||
tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0],
|
||||
TCG_AREG0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
tcg_out_calli(s, (tcg_target_long)qemu_ld_helpers[s_bits]);
|
||||
|
||||
#if TCG_TARGET_REG_BITS == 32
|
||||
if (stack_adjust == (TCG_TARGET_REG_BITS / 8)) {
|
||||
/* Pop and discard. This is 2 bytes smaller than the add. */
|
||||
tcg_out_pop(s, TCG_REG_ECX);
|
||||
} else if (stack_adjust != 0) {
|
||||
tcg_out_addi(s, TCG_REG_CALL_STACK, stack_adjust);
|
||||
}
|
||||
#endif
|
||||
|
||||
switch(opc) {
|
||||
case 0 | 4:
|
||||
tcg_out_ext8s(s, data_reg, TCG_REG_EAX, P_REXW);
|
||||
|
@ -1359,45 +1413,42 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
|
|||
}
|
||||
|
||||
/* XXX: move that code at the end of the TB */
|
||||
if (TCG_TARGET_REG_BITS == 64) {
|
||||
tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32),
|
||||
TCG_REG_RSI, data_reg);
|
||||
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RDX, mem_index);
|
||||
stack_adjust = 0;
|
||||
} else if (TARGET_LONG_BITS == 32) {
|
||||
tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_EDX, data_reg);
|
||||
if (opc == 3) {
|
||||
tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_ECX, data_reg2);
|
||||
tcg_out_pushi(s, mem_index);
|
||||
stack_adjust = 4;
|
||||
} else {
|
||||
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
|
||||
stack_adjust = 0;
|
||||
}
|
||||
} else {
|
||||
if (opc == 3) {
|
||||
tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_EDX, args[addrlo_idx + 1]);
|
||||
tcg_out_pushi(s, mem_index);
|
||||
tcg_out_push(s, data_reg2);
|
||||
tcg_out_push(s, data_reg);
|
||||
stack_adjust = 12;
|
||||
} else {
|
||||
tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_EDX, args[addrlo_idx + 1]);
|
||||
switch(opc) {
|
||||
case 0:
|
||||
tcg_out_ext8u(s, TCG_REG_ECX, data_reg);
|
||||
break;
|
||||
case 1:
|
||||
tcg_out_ext16u(s, TCG_REG_ECX, data_reg);
|
||||
break;
|
||||
case 2:
|
||||
tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_ECX, data_reg);
|
||||
break;
|
||||
}
|
||||
tcg_out_pushi(s, mem_index);
|
||||
stack_adjust = 4;
|
||||
}
|
||||
#if TCG_TARGET_REG_BITS == 32
|
||||
tcg_out_pushi(s, mem_index);
|
||||
stack_adjust = 4;
|
||||
if (opc == 3) {
|
||||
tcg_out_push(s, data_reg2);
|
||||
stack_adjust += 4;
|
||||
}
|
||||
tcg_out_push(s, data_reg);
|
||||
stack_adjust += 4;
|
||||
if (TARGET_LONG_BITS == 64) {
|
||||
tcg_out_push(s, args[addrlo_idx + 1]);
|
||||
stack_adjust += 4;
|
||||
}
|
||||
tcg_out_push(s, args[addrlo_idx]);
|
||||
stack_adjust += 4;
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
tcg_out_push(s, TCG_AREG0);
|
||||
stack_adjust += 4;
|
||||
#endif
|
||||
#else
|
||||
tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32),
|
||||
TCG_REG_RSI, data_reg);
|
||||
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RDX, mem_index);
|
||||
stack_adjust = 0;
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* XXX/FIXME: suboptimal */
|
||||
tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[3],
|
||||
tcg_target_call_iarg_regs[2]);
|
||||
tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
|
||||
tcg_target_call_iarg_regs[1]);
|
||||
tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[1],
|
||||
tcg_target_call_iarg_regs[0]);
|
||||
tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0],
|
||||
TCG_AREG0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
tcg_out_calli(s, (tcg_target_long)qemu_st_helpers[s_bits]);
|
||||
|
||||
|
@ -1962,9 +2013,15 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
|||
tcg_out_push(s, tcg_target_callee_save_regs[i]);
|
||||
}
|
||||
|
||||
tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
|
||||
|
||||
#if TCG_TARGET_REG_BITS == 32
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_ESP,
|
||||
(ARRAY_SIZE(tcg_target_callee_save_regs) + 1) * 4);
|
||||
tcg_out_ld(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[1], TCG_REG_ESP,
|
||||
(ARRAY_SIZE(tcg_target_callee_save_regs) + 2) * 4);
|
||||
#else
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
|
||||
#endif
|
||||
tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
|
||||
|
||||
/* jmp *tb. */
|
||||
tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, tcg_target_call_iarg_regs[1]);
|
||||
|
|
|
@ -1452,12 +1452,25 @@ static inline void tcg_out_qemu_tlb(TCGContext *s, TCGArg addr_reg,
|
|||
TCG_REG_P7, TCG_REG_R3, TCG_REG_R57));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
|
||||
int mmu_idx) */
|
||||
static const void * const qemu_ld_helpers[4] = {
|
||||
helper_ldb_mmu,
|
||||
helper_ldw_mmu,
|
||||
helper_ldl_mmu,
|
||||
helper_ldq_mmu,
|
||||
};
|
||||
#else
|
||||
/* legacy helper signature: __ld_mmu(target_ulong addr, int
|
||||
mmu_idx) */
|
||||
static void *qemu_ld_helpers[4] = {
|
||||
__ldb_mmu,
|
||||
__ldw_mmu,
|
||||
__ldl_mmu,
|
||||
__ldq_mmu,
|
||||
};
|
||||
#endif
|
||||
|
||||
static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
|
||||
{
|
||||
|
@ -1517,6 +1530,15 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
|
|||
tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2),
|
||||
tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
|
||||
}
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* XXX/FIXME: suboptimal */
|
||||
tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2],
|
||||
tcg_target_call_iarg_regs[1]);
|
||||
tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
|
||||
tcg_target_call_iarg_regs[0]);
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
|
||||
TCG_AREG0);
|
||||
#endif
|
||||
if (!bswap || s_bits == 0) {
|
||||
tcg_out_bundle(s, miB,
|
||||
tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
|
||||
|
@ -1547,12 +1569,25 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
|
||||
uintxx_t val, int mmu_idx) */
|
||||
static const void * const qemu_st_helpers[4] = {
|
||||
helper_stb_mmu,
|
||||
helper_stw_mmu,
|
||||
helper_stl_mmu,
|
||||
helper_stq_mmu,
|
||||
};
|
||||
#else
|
||||
/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val,
|
||||
int mmu_idx) */
|
||||
static void *qemu_st_helpers[4] = {
|
||||
__stb_mmu,
|
||||
__stw_mmu,
|
||||
__stl_mmu,
|
||||
__stq_mmu,
|
||||
};
|
||||
#endif
|
||||
|
||||
static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
|
||||
{
|
||||
|
@ -1622,6 +1657,17 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
|
|||
data_reg = TCG_REG_R2;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* XXX/FIXME: suboptimal */
|
||||
tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
|
||||
tcg_target_call_iarg_regs[2]);
|
||||
tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
|
||||
tcg_target_call_iarg_regs[1]);
|
||||
tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
|
||||
tcg_target_call_iarg_regs[0]);
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
|
||||
TCG_AREG0);
|
||||
#endif
|
||||
tcg_out_bundle(s, miB,
|
||||
tcg_opc_m4 (TCG_REG_P6, opc_st_m4[opc],
|
||||
data_reg, TCG_REG_R3),
|
||||
|
|
|
@ -750,6 +750,27 @@ static void tcg_out_setcond2(TCGContext *s, TCGCond cond, int ret,
|
|||
|
||||
#include "../../softmmu_defs.h"
|
||||
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
|
||||
int mmu_idx) */
|
||||
static const void * const qemu_ld_helpers[4] = {
|
||||
helper_ldb_mmu,
|
||||
helper_ldw_mmu,
|
||||
helper_ldl_mmu,
|
||||
helper_ldq_mmu,
|
||||
};
|
||||
|
||||
/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
|
||||
uintxx_t val, int mmu_idx) */
|
||||
static const void * const qemu_st_helpers[4] = {
|
||||
helper_stb_mmu,
|
||||
helper_stw_mmu,
|
||||
helper_stl_mmu,
|
||||
helper_stq_mmu,
|
||||
};
|
||||
#else
|
||||
/* legacy helper signature: __ld_mmu(target_ulong addr, int
|
||||
mmu_idx) */
|
||||
static void *qemu_ld_helpers[4] = {
|
||||
__ldb_mmu,
|
||||
__ldw_mmu,
|
||||
|
@ -757,6 +778,8 @@ static void *qemu_ld_helpers[4] = {
|
|||
__ldq_mmu,
|
||||
};
|
||||
|
||||
/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val,
|
||||
int mmu_idx) */
|
||||
static void *qemu_st_helpers[4] = {
|
||||
__stb_mmu,
|
||||
__stw_mmu,
|
||||
|
@ -764,6 +787,7 @@ static void *qemu_st_helpers[4] = {
|
|||
__stq_mmu,
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
|
||||
int opc)
|
||||
|
@ -858,6 +882,15 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
|
|||
# endif
|
||||
tcg_out_movi(s, TCG_TYPE_I32, sp_args++, mem_index);
|
||||
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_ld_helpers[s_bits]);
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* XXX/FIXME: suboptimal and incorrect for 64 on 32 bit */
|
||||
tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2],
|
||||
tcg_target_call_iarg_regs[1]);
|
||||
tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
|
||||
tcg_target_call_iarg_regs[0]);
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
|
||||
TCG_AREG0);
|
||||
#endif
|
||||
tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
|
||||
tcg_out_nop(s);
|
||||
|
||||
|
@ -1069,6 +1102,17 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
|
|||
}
|
||||
|
||||
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_st_helpers[s_bits]);
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* XXX/FIXME: suboptimal and incorrect for 64 on 32 bit */
|
||||
tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
|
||||
tcg_target_call_iarg_regs[2]);
|
||||
tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
|
||||
tcg_target_call_iarg_regs[1]);
|
||||
tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
|
||||
tcg_target_call_iarg_regs[0]);
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
|
||||
TCG_AREG0);
|
||||
#endif
|
||||
tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
|
||||
tcg_out_nop(s);
|
||||
|
||||
|
|
|
@ -508,6 +508,27 @@ static void tcg_out_call (TCGContext *s, tcg_target_long arg, int const_arg)
|
|||
|
||||
#include "../../softmmu_defs.h"
|
||||
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
|
||||
int mmu_idx) */
|
||||
static const void * const qemu_ld_helpers[4] = {
|
||||
helper_ldb_mmu,
|
||||
helper_ldw_mmu,
|
||||
helper_ldl_mmu,
|
||||
helper_ldq_mmu,
|
||||
};
|
||||
|
||||
/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
|
||||
uintxx_t val, int mmu_idx) */
|
||||
static const void * const qemu_st_helpers[4] = {
|
||||
helper_stb_mmu,
|
||||
helper_stw_mmu,
|
||||
helper_stl_mmu,
|
||||
helper_stq_mmu,
|
||||
};
|
||||
#else
|
||||
/* legacy helper signature: __ld_mmu(target_ulong addr, int
|
||||
mmu_idx) */
|
||||
static void *qemu_ld_helpers[4] = {
|
||||
__ldb_mmu,
|
||||
__ldw_mmu,
|
||||
|
@ -515,6 +536,8 @@ static void *qemu_ld_helpers[4] = {
|
|||
__ldq_mmu,
|
||||
};
|
||||
|
||||
/* legacy helper signature: __ld_mmu(target_ulong addr, int
|
||||
mmu_idx) */
|
||||
static void *qemu_st_helpers[4] = {
|
||||
__stb_mmu,
|
||||
__stw_mmu,
|
||||
|
@ -522,6 +545,7 @@ static void *qemu_st_helpers[4] = {
|
|||
__stq_mmu,
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
|
||||
{
|
||||
|
@ -598,6 +622,16 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
|
|||
tcg_out_movi (s, TCG_TYPE_I32, 5, mem_index);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* XXX/FIXME: suboptimal */
|
||||
tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2],
|
||||
tcg_target_call_iarg_regs[1]);
|
||||
tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
|
||||
tcg_target_call_iarg_regs[0]);
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
|
||||
TCG_AREG0);
|
||||
#endif
|
||||
|
||||
tcg_out_call (s, (tcg_target_long) qemu_ld_helpers[s_bits], 1);
|
||||
switch (opc) {
|
||||
case 0|4:
|
||||
|
@ -829,6 +863,17 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
|
|||
ir++;
|
||||
|
||||
tcg_out_movi (s, TCG_TYPE_I32, ir, mem_index);
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* XXX/FIXME: suboptimal */
|
||||
tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
|
||||
tcg_target_call_iarg_regs[2]);
|
||||
tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
|
||||
tcg_target_call_iarg_regs[1]);
|
||||
tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
|
||||
tcg_target_call_iarg_regs[0]);
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
|
||||
TCG_AREG0);
|
||||
#endif
|
||||
tcg_out_call (s, (tcg_target_long) qemu_st_helpers[opc], 1);
|
||||
label2_ptr = s->code_ptr;
|
||||
tcg_out32 (s, B);
|
||||
|
|
|
@ -98,5 +98,5 @@ typedef enum {
|
|||
#define TCG_TARGET_HAS_GUEST_BASE
|
||||
|
||||
#define tcg_qemu_tb_exec(env, tb_ptr) \
|
||||
((long REGPARM __attribute__ ((longcall)) \
|
||||
((long __attribute__ ((longcall)) \
|
||||
(*)(void *, void *))code_gen_prologue)(env, tb_ptr)
|
||||
|
|
|
@ -552,6 +552,27 @@ static void tcg_out_ldsta (TCGContext *s, int ret, int addr,
|
|||
|
||||
#include "../../softmmu_defs.h"
|
||||
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
|
||||
int mmu_idx) */
|
||||
static const void * const qemu_ld_helpers[4] = {
|
||||
helper_ldb_mmu,
|
||||
helper_ldw_mmu,
|
||||
helper_ldl_mmu,
|
||||
helper_ldq_mmu,
|
||||
};
|
||||
|
||||
/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
|
||||
uintxx_t val, int mmu_idx) */
|
||||
static const void * const qemu_st_helpers[4] = {
|
||||
helper_stb_mmu,
|
||||
helper_stw_mmu,
|
||||
helper_stl_mmu,
|
||||
helper_stq_mmu,
|
||||
};
|
||||
#else
|
||||
/* legacy helper signature: __ld_mmu(target_ulong addr, int
|
||||
mmu_idx) */
|
||||
static void *qemu_ld_helpers[4] = {
|
||||
__ldb_mmu,
|
||||
__ldw_mmu,
|
||||
|
@ -559,12 +580,15 @@ static void *qemu_ld_helpers[4] = {
|
|||
__ldq_mmu,
|
||||
};
|
||||
|
||||
/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val,
|
||||
int mmu_idx) */
|
||||
static void *qemu_st_helpers[4] = {
|
||||
__stb_mmu,
|
||||
__stw_mmu,
|
||||
__stl_mmu,
|
||||
__stq_mmu,
|
||||
};
|
||||
#endif
|
||||
|
||||
static void tcg_out_tlb_read (TCGContext *s, int r0, int r1, int r2,
|
||||
int addr_reg, int s_bits, int offset)
|
||||
|
@ -648,6 +672,15 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
|
|||
tcg_out_mov (s, TCG_TYPE_I64, 3, addr_reg);
|
||||
tcg_out_movi (s, TCG_TYPE_I64, 4, mem_index);
|
||||
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* XXX/FIXME: suboptimal */
|
||||
tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2],
|
||||
tcg_target_call_iarg_regs[1]);
|
||||
tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
|
||||
tcg_target_call_iarg_regs[0]);
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
|
||||
TCG_AREG0);
|
||||
#endif
|
||||
tcg_out_call (s, (tcg_target_long) qemu_ld_helpers[s_bits], 1);
|
||||
|
||||
switch (opc) {
|
||||
|
@ -796,6 +829,17 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
|
|||
tcg_out_rld (s, RLDICL, 4, data_reg, 0, 64 - (1 << (3 + opc)));
|
||||
tcg_out_movi (s, TCG_TYPE_I64, 5, mem_index);
|
||||
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* XXX/FIXME: suboptimal */
|
||||
tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
|
||||
tcg_target_call_iarg_regs[2]);
|
||||
tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
|
||||
tcg_target_call_iarg_regs[1]);
|
||||
tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
|
||||
tcg_target_call_iarg_regs[0]);
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
|
||||
TCG_AREG0);
|
||||
#endif
|
||||
tcg_out_call (s, (tcg_target_long) qemu_st_helpers[opc], 1);
|
||||
|
||||
label2_ptr = s->code_ptr;
|
||||
|
|
|
@ -301,6 +301,27 @@ static const uint8_t tcg_cond_to_ltr_cond[10] = {
|
|||
|
||||
#include "../../softmmu_defs.h"
|
||||
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
|
||||
int mmu_idx) */
|
||||
static const void * const qemu_ld_helpers[4] = {
|
||||
helper_ldb_mmu,
|
||||
helper_ldw_mmu,
|
||||
helper_ldl_mmu,
|
||||
helper_ldq_mmu,
|
||||
};
|
||||
|
||||
/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
|
||||
uintxx_t val, int mmu_idx) */
|
||||
static const void * const qemu_st_helpers[4] = {
|
||||
helper_stb_mmu,
|
||||
helper_stw_mmu,
|
||||
helper_stl_mmu,
|
||||
helper_stq_mmu,
|
||||
};
|
||||
#else
|
||||
/* legacy helper signature: __ld_mmu(target_ulong addr, int
|
||||
mmu_idx) */
|
||||
static void *qemu_ld_helpers[4] = {
|
||||
__ldb_mmu,
|
||||
__ldw_mmu,
|
||||
|
@ -308,6 +329,8 @@ static void *qemu_ld_helpers[4] = {
|
|||
__ldq_mmu,
|
||||
};
|
||||
|
||||
/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val,
|
||||
int mmu_idx) */
|
||||
static void *qemu_st_helpers[4] = {
|
||||
__stb_mmu,
|
||||
__stw_mmu,
|
||||
|
@ -315,6 +338,7 @@ static void *qemu_st_helpers[4] = {
|
|||
__stq_mmu,
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static uint8_t *tb_ret_addr;
|
||||
|
||||
|
@ -1483,9 +1507,29 @@ static void tcg_prepare_qemu_ldst(TCGContext* s, TCGReg data_reg,
|
|||
tcg_abort();
|
||||
}
|
||||
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R4, mem_index);
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* XXX/FIXME: suboptimal */
|
||||
tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2],
|
||||
tcg_target_call_iarg_regs[1]);
|
||||
tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
|
||||
tcg_target_call_iarg_regs[0]);
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
|
||||
TCG_AREG0);
|
||||
#endif
|
||||
tgen_calli(s, (tcg_target_ulong)qemu_st_helpers[s_bits]);
|
||||
} else {
|
||||
tcg_out_movi(s, TCG_TYPE_I32, arg1, mem_index);
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* XXX/FIXME: suboptimal */
|
||||
tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
|
||||
tcg_target_call_iarg_regs[2]);
|
||||
tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
|
||||
tcg_target_call_iarg_regs[1]);
|
||||
tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
|
||||
tcg_target_call_iarg_regs[0]);
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
|
||||
TCG_AREG0);
|
||||
#endif
|
||||
tgen_calli(s, (tcg_target_ulong)qemu_ld_helpers[s_bits]);
|
||||
|
||||
/* sign extension */
|
||||
|
|
|
@ -59,6 +59,12 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
|
|||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
#define ARG_OFFSET 1
|
||||
#else
|
||||
#define ARG_OFFSET 0
|
||||
#endif
|
||||
|
||||
static const int tcg_target_reg_alloc_order[] = {
|
||||
TCG_REG_L0,
|
||||
TCG_REG_L1,
|
||||
|
@ -86,9 +92,9 @@ static const int tcg_target_call_iarg_regs[6] = {
|
|||
|
||||
static const int tcg_target_call_oarg_regs[] = {
|
||||
TCG_REG_O0,
|
||||
#if TCG_TARGET_REG_BITS == 32
|
||||
TCG_REG_O1
|
||||
#endif
|
||||
TCG_REG_O1,
|
||||
TCG_REG_O2,
|
||||
TCG_REG_O3,
|
||||
};
|
||||
|
||||
static inline int check_fit_tl(tcg_target_long val, unsigned int bits)
|
||||
|
@ -155,6 +161,9 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
|
|||
tcg_regset_reset_reg(ct->u.regs, TCG_REG_O0);
|
||||
tcg_regset_reset_reg(ct->u.regs, TCG_REG_O1);
|
||||
tcg_regset_reset_reg(ct->u.regs, TCG_REG_O2);
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
tcg_regset_reset_reg(ct->u.regs, TCG_REG_O3);
|
||||
#endif
|
||||
break;
|
||||
case 'I':
|
||||
ct->ct |= TCG_CT_CONST_S11;
|
||||
|
@ -706,6 +715,27 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
|||
|
||||
#include "../../softmmu_defs.h"
|
||||
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
|
||||
int mmu_idx) */
|
||||
static const void * const qemu_ld_helpers[4] = {
|
||||
helper_ldb_mmu,
|
||||
helper_ldw_mmu,
|
||||
helper_ldl_mmu,
|
||||
helper_ldq_mmu,
|
||||
};
|
||||
|
||||
/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
|
||||
uintxx_t val, int mmu_idx) */
|
||||
static const void * const qemu_st_helpers[4] = {
|
||||
helper_stb_mmu,
|
||||
helper_stw_mmu,
|
||||
helper_stl_mmu,
|
||||
helper_stq_mmu,
|
||||
};
|
||||
#else
|
||||
/* legacy helper signature: __ld_mmu(target_ulong addr, int
|
||||
mmu_idx) */
|
||||
static const void * const qemu_ld_helpers[4] = {
|
||||
__ldb_mmu,
|
||||
__ldw_mmu,
|
||||
|
@ -713,6 +743,8 @@ static const void * const qemu_ld_helpers[4] = {
|
|||
__ldq_mmu,
|
||||
};
|
||||
|
||||
/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val,
|
||||
int mmu_idx) */
|
||||
static const void * const qemu_st_helpers[4] = {
|
||||
__stb_mmu,
|
||||
__stw_mmu,
|
||||
|
@ -720,6 +752,7 @@ static const void * const qemu_st_helpers[4] = {
|
|||
__stq_mmu,
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if TARGET_LONG_BITS == 32
|
||||
#define TARGET_LD_OP LDUW
|
||||
|
@ -801,6 +834,17 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
|
|||
|
||||
/* mov */
|
||||
tcg_out_movi(s, TCG_TYPE_I32, arg1, mem_index);
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
/* XXX/FIXME: suboptimal */
|
||||
tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
|
||||
tcg_target_call_iarg_regs[2]);
|
||||
tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
|
||||
tcg_target_call_iarg_regs[1]);
|
||||
tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
|
||||
tcg_target_call_iarg_regs[0]);
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
|
||||
TCG_AREG0);
|
||||
#endif
|
||||
|
||||
/* XXX: move that code at the end of the TB */
|
||||
/* qemu_ld_helper[s_bits](arg0, arg1) */
|
||||
|
|
28
tcg/tcg.c
28
tcg/tcg.c
|
@ -173,11 +173,9 @@ void *tcg_malloc_internal(TCGContext *s, int size)
|
|||
/* big malloc: insert a new pool (XXX: could optimize) */
|
||||
p = g_malloc(sizeof(TCGPool) + size);
|
||||
p->size = size;
|
||||
if (s->pool_current)
|
||||
s->pool_current->next = p;
|
||||
else
|
||||
s->pool_first = p;
|
||||
p->next = s->pool_current;
|
||||
p->next = s->pool_first_large;
|
||||
s->pool_first_large = p;
|
||||
return p->data;
|
||||
} else {
|
||||
p = s->pool_current;
|
||||
if (!p) {
|
||||
|
@ -208,6 +206,12 @@ void *tcg_malloc_internal(TCGContext *s, int size)
|
|||
|
||||
void tcg_pool_reset(TCGContext *s)
|
||||
{
|
||||
TCGPool *p, *t;
|
||||
for (p = s->pool_first_large; p; p = t) {
|
||||
t = p->next;
|
||||
g_free(p);
|
||||
}
|
||||
s->pool_first_large = NULL;
|
||||
s->pool_cur = s->pool_end = NULL;
|
||||
s->pool_current = NULL;
|
||||
}
|
||||
|
@ -590,9 +594,6 @@ void tcg_register_helper(void *func, const char *name)
|
|||
void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
|
||||
int sizemask, TCGArg ret, int nargs, TCGArg *args)
|
||||
{
|
||||
#if defined(TCG_TARGET_I386) && TCG_TARGET_REG_BITS < 64
|
||||
int call_type;
|
||||
#endif
|
||||
int i;
|
||||
int real_args;
|
||||
int nb_rets;
|
||||
|
@ -617,9 +618,6 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
|
|||
|
||||
*gen_opc_ptr++ = INDEX_op_call;
|
||||
nparam = gen_opparam_ptr++;
|
||||
#if defined(TCG_TARGET_I386) && TCG_TARGET_REG_BITS < 64
|
||||
call_type = (flags & TCG_CALL_TYPE_MASK);
|
||||
#endif
|
||||
if (ret != TCG_CALL_DUMMY_ARG) {
|
||||
#if TCG_TARGET_REG_BITS < 64
|
||||
if (sizemask & 1) {
|
||||
|
@ -645,14 +643,6 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
|
|||
#if TCG_TARGET_REG_BITS < 64
|
||||
int is_64bit = sizemask & (1 << (i+1)*2);
|
||||
if (is_64bit) {
|
||||
#ifdef TCG_TARGET_I386
|
||||
/* REGPARM case: if the third parameter is 64 bit, it is
|
||||
allocated on the stack */
|
||||
if (i == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
|
||||
call_type = TCG_CALL_TYPE_REGPARM_2;
|
||||
flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
|
||||
}
|
||||
#endif
|
||||
#ifdef TCG_TARGET_CALL_ALIGN_ARGS
|
||||
/* some targets want aligned 64 bit args */
|
||||
if (real_args & 1) {
|
||||
|
|
|
@ -252,11 +252,6 @@ typedef int TCGv_i64;
|
|||
#define TCGV_UNUSED_I64(x) x = MAKE_TCGV_I64(-1)
|
||||
|
||||
/* call flags */
|
||||
#define TCG_CALL_TYPE_MASK 0x000f
|
||||
#define TCG_CALL_TYPE_STD 0x0000 /* standard C call */
|
||||
#define TCG_CALL_TYPE_REGPARM_1 0x0001 /* i386 style regparm call (1 reg) */
|
||||
#define TCG_CALL_TYPE_REGPARM_2 0x0002 /* i386 style regparm call (2 regs) */
|
||||
#define TCG_CALL_TYPE_REGPARM 0x0003 /* i386 style regparm call (3 regs) */
|
||||
/* A pure function only reads its arguments and TCG global variables
|
||||
and cannot raise exceptions. Hence a call to a pure function can be
|
||||
safely suppressed if the return value is not used. */
|
||||
|
@ -337,7 +332,7 @@ typedef struct TCGContext TCGContext;
|
|||
|
||||
struct TCGContext {
|
||||
uint8_t *pool_cur, *pool_end;
|
||||
TCGPool *pool_first, *pool_current;
|
||||
TCGPool *pool_first, *pool_current, *pool_first_large;
|
||||
TCGLabel *labels;
|
||||
int nb_labels;
|
||||
TCGTemp *temps; /* globals first, temps after */
|
||||
|
@ -589,5 +584,5 @@ extern uint8_t code_gen_prologue[];
|
|||
/* TCG targets may use a different definition of tcg_qemu_tb_exec. */
|
||||
#if !defined(tcg_qemu_tb_exec)
|
||||
# define tcg_qemu_tb_exec(env, tb_ptr) \
|
||||
((long REGPARM (*)(void *, void *))code_gen_prologue)(env, tb_ptr)
|
||||
((tcg_target_ulong (*)(void *, void *))code_gen_prologue)(env, tb_ptr)
|
||||
#endif
|
||||
|
|
|
@ -798,6 +798,9 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
|
|||
case INDEX_op_qemu_st8:
|
||||
case INDEX_op_qemu_st16:
|
||||
case INDEX_op_qemu_st32:
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
tcg_out_r(s, TCG_AREG0);
|
||||
#endif
|
||||
tcg_out_r(s, *args++);
|
||||
tcg_out_r(s, *args++);
|
||||
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
|
||||
|
@ -808,6 +811,9 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
|
|||
#endif
|
||||
break;
|
||||
case INDEX_op_qemu_st64:
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
tcg_out_r(s, TCG_AREG0);
|
||||
#endif
|
||||
tcg_out_r(s, *args++);
|
||||
#if TCG_TARGET_REG_BITS == 32
|
||||
tcg_out_r(s, *args++);
|
||||
|
|
|
@ -154,7 +154,7 @@ typedef enum {
|
|||
|
||||
void tci_disas(uint8_t opc);
|
||||
|
||||
unsigned long tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr);
|
||||
tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr);
|
||||
#define tcg_qemu_tb_exec tcg_qemu_tb_exec
|
||||
|
||||
static inline void flush_icache_range(tcg_target_ulong start,
|
||||
|
|
4
tci.c
4
tci.c
|
@ -429,9 +429,9 @@ static bool tci_compare64(uint64_t u0, uint64_t u1, TCGCond condition)
|
|||
}
|
||||
|
||||
/* Interpret pseudo code in tb. */
|
||||
unsigned long tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr)
|
||||
tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *cpustate, uint8_t *tb_ptr)
|
||||
{
|
||||
unsigned long next_tb = 0;
|
||||
tcg_target_ulong next_tb = 0;
|
||||
|
||||
env = cpustate;
|
||||
tci_reg[TCG_AREG0] = (tcg_target_ulong)env;
|
||||
|
|
Loading…
Reference in New Issue