mirror of https://github.com/xqemu/xqemu.git
sparc merge (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1098 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
023fcb9507
commit
8d5f07fa3b
11
Makefile
11
Makefile
|
@ -1,4 +1,4 @@
|
||||||
include config-host.mak
|
-include config-host.mak
|
||||||
|
|
||||||
CFLAGS=-Wall -O2 -g -fno-strict-aliasing
|
CFLAGS=-Wall -O2 -g -fno-strict-aliasing
|
||||||
ifdef CONFIG_DARWIN
|
ifdef CONFIG_DARWIN
|
||||||
|
@ -14,8 +14,9 @@ TOOLS=qemu-img
|
||||||
ifdef CONFIG_STATIC
|
ifdef CONFIG_STATIC
|
||||||
LDFLAGS+=-static
|
LDFLAGS+=-static
|
||||||
endif
|
endif
|
||||||
|
DOCS=qemu-doc.html qemu-tech.html qemu.1
|
||||||
|
|
||||||
all: dyngen$(EXESUF) $(TOOLS) qemu-doc.html qemu-tech.html qemu.1
|
all: dyngen$(EXESUF) $(TOOLS) $(DOCS)
|
||||||
for d in $(TARGET_DIRS); do \
|
for d in $(TARGET_DIRS); do \
|
||||||
$(MAKE) -C $$d $@ || exit 1 ; \
|
$(MAKE) -C $$d $@ || exit 1 ; \
|
||||||
done
|
done
|
||||||
|
@ -29,14 +30,14 @@ dyngen$(EXESUF): dyngen.c
|
||||||
clean:
|
clean:
|
||||||
# avoid old build problems by removing potentially incorrect old files
|
# avoid old build problems by removing potentially incorrect old files
|
||||||
rm -f config.mak config.h op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
|
rm -f config.mak config.h op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
|
||||||
rm -f *.o *.a $(TOOLS) dyngen$(EXESUF) TAGS qemu.pod
|
rm -f *.o *.a $(TOOLS) dyngen$(EXESUF) TAGS qemu.pod *~ */*~
|
||||||
$(MAKE) -C tests clean
|
$(MAKE) -C tests clean
|
||||||
for d in $(TARGET_DIRS); do \
|
for d in $(TARGET_DIRS); do \
|
||||||
$(MAKE) -C $$d $@ || exit 1 ; \
|
$(MAKE) -C $$d $@ || exit 1 ; \
|
||||||
done
|
done
|
||||||
|
|
||||||
distclean: clean
|
distclean: clean
|
||||||
rm -f config-host.mak config-host.h
|
rm -f config-host.mak config-host.h $(DOCS)
|
||||||
for d in $(TARGET_DIRS); do \
|
for d in $(TARGET_DIRS); do \
|
||||||
rm -rf $$d || exit 1 ; \
|
rm -rf $$d || exit 1 ; \
|
||||||
done
|
done
|
||||||
|
@ -50,6 +51,7 @@ endif
|
||||||
install -m 644 pc-bios/bios.bin pc-bios/vgabios.bin \
|
install -m 644 pc-bios/bios.bin pc-bios/vgabios.bin \
|
||||||
pc-bios/vgabios-cirrus.bin \
|
pc-bios/vgabios-cirrus.bin \
|
||||||
pc-bios/ppc_rom.bin \
|
pc-bios/ppc_rom.bin \
|
||||||
|
pc-bios/proll.bin \
|
||||||
pc-bios/linux_boot.bin "$(datadir)"
|
pc-bios/linux_boot.bin "$(datadir)"
|
||||||
mkdir -p "$(docdir)"
|
mkdir -p "$(docdir)"
|
||||||
install -m 644 qemu-doc.html qemu-tech.html "$(docdir)"
|
install -m 644 qemu-doc.html qemu-tech.html "$(docdir)"
|
||||||
|
@ -99,6 +101,7 @@ tarbin:
|
||||||
$(datadir)/vgabios.bin \
|
$(datadir)/vgabios.bin \
|
||||||
$(datadir)/vgabios-cirrus.bin \
|
$(datadir)/vgabios-cirrus.bin \
|
||||||
$(datadir)/ppc_rom.bin \
|
$(datadir)/ppc_rom.bin \
|
||||||
|
$(datadir)/proll.bin \
|
||||||
$(datadir)/linux_boot.bin \
|
$(datadir)/linux_boot.bin \
|
||||||
$(docdir)/qemu-doc.html \
|
$(docdir)/qemu-doc.html \
|
||||||
$(docdir)/qemu-tech.html \
|
$(docdir)/qemu-tech.html \
|
||||||
|
|
|
@ -279,7 +279,7 @@ VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
|
||||||
VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o
|
VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o
|
||||||
endif
|
endif
|
||||||
ifeq ($(TARGET_ARCH), sparc)
|
ifeq ($(TARGET_ARCH), sparc)
|
||||||
VL_OBJS+= sun4m.o tcx.o lance.o iommu.o sched.o m48t08.o magic-load.o
|
VL_OBJS+= sun4m.o tcx.o lance.o iommu.o sched.o m48t08.o magic-load.o timer.o
|
||||||
endif
|
endif
|
||||||
ifdef CONFIG_GDBSTUB
|
ifdef CONFIG_GDBSTUB
|
||||||
VL_OBJS+=gdbstub.o
|
VL_OBJS+=gdbstub.o
|
||||||
|
|
|
@ -387,6 +387,9 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
|
||||||
env->eip = addr;
|
env->eip = addr;
|
||||||
#elif defined (TARGET_PPC)
|
#elif defined (TARGET_PPC)
|
||||||
env->nip = addr;
|
env->nip = addr;
|
||||||
|
#elif defined (TARGET_SPARC)
|
||||||
|
env->pc = addr;
|
||||||
|
env->npc = addr + 4;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
vm_start();
|
vm_start();
|
||||||
|
@ -398,6 +401,9 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
|
||||||
env->eip = addr;
|
env->eip = addr;
|
||||||
#elif defined (TARGET_PPC)
|
#elif defined (TARGET_PPC)
|
||||||
env->nip = addr;
|
env->nip = addr;
|
||||||
|
#elif defined (TARGET_SPARC)
|
||||||
|
env->pc = addr;
|
||||||
|
env->npc = addr + 4;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
cpu_single_step(env, 1);
|
cpu_single_step(env, 1);
|
||||||
|
|
83
hw/iommu.c
83
hw/iommu.c
|
@ -107,29 +107,24 @@ struct iommu_regs {
|
||||||
#define IOPTE_VALID 0x00000002 /* IOPTE is valid */
|
#define IOPTE_VALID 0x00000002 /* IOPTE is valid */
|
||||||
#define IOPTE_WAZ 0x00000001 /* Write as zeros */
|
#define IOPTE_WAZ 0x00000001 /* Write as zeros */
|
||||||
|
|
||||||
#define PHYS_JJ_IOMMU 0x10000000 /* First page of sun4m IOMMU */
|
|
||||||
#define PAGE_SHIFT 12
|
#define PAGE_SHIFT 12
|
||||||
#define PAGE_SIZE (1 << PAGE_SHIFT)
|
#define PAGE_SIZE (1 << PAGE_SHIFT)
|
||||||
#define PAGE_MASK (PAGE_SIZE - 1)
|
#define PAGE_MASK (PAGE_SIZE - 1)
|
||||||
|
|
||||||
typedef struct IOMMUState {
|
typedef struct IOMMUState {
|
||||||
|
uint32_t addr;
|
||||||
uint32_t regs[sizeof(struct iommu_regs)];
|
uint32_t regs[sizeof(struct iommu_regs)];
|
||||||
|
uint32_t iostart;
|
||||||
} IOMMUState;
|
} IOMMUState;
|
||||||
|
|
||||||
static IOMMUState *ps;
|
static IOMMUState *ps;
|
||||||
|
|
||||||
static int iommu_io_memory;
|
|
||||||
|
|
||||||
static void iommu_reset(IOMMUState *s)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t iommu_mem_readw(void *opaque, target_phys_addr_t addr)
|
static uint32_t iommu_mem_readw(void *opaque, target_phys_addr_t addr)
|
||||||
{
|
{
|
||||||
IOMMUState *s = opaque;
|
IOMMUState *s = opaque;
|
||||||
uint32_t saddr;
|
uint32_t saddr;
|
||||||
|
|
||||||
saddr = (addr - PHYS_JJ_IOMMU) >> 2;
|
saddr = (addr - s->addr) >> 2;
|
||||||
switch (saddr) {
|
switch (saddr) {
|
||||||
default:
|
default:
|
||||||
return s->regs[saddr];
|
return s->regs[saddr];
|
||||||
|
@ -143,8 +138,37 @@ static void iommu_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val
|
||||||
IOMMUState *s = opaque;
|
IOMMUState *s = opaque;
|
||||||
uint32_t saddr;
|
uint32_t saddr;
|
||||||
|
|
||||||
saddr = (addr - PHYS_JJ_IOMMU) >> 2;
|
saddr = (addr - s->addr) >> 2;
|
||||||
switch (saddr) {
|
switch (saddr) {
|
||||||
|
case 0:
|
||||||
|
switch (val & IOMMU_CTRL_RNGE) {
|
||||||
|
case IOMMU_RNGE_16MB:
|
||||||
|
s->iostart = 0xff000000;
|
||||||
|
break;
|
||||||
|
case IOMMU_RNGE_32MB:
|
||||||
|
s->iostart = 0xfe000000;
|
||||||
|
break;
|
||||||
|
case IOMMU_RNGE_64MB:
|
||||||
|
s->iostart = 0xfc000000;
|
||||||
|
break;
|
||||||
|
case IOMMU_RNGE_128MB:
|
||||||
|
s->iostart = 0xf8000000;
|
||||||
|
break;
|
||||||
|
case IOMMU_RNGE_256MB:
|
||||||
|
s->iostart = 0xf0000000;
|
||||||
|
break;
|
||||||
|
case IOMMU_RNGE_512MB:
|
||||||
|
s->iostart = 0xe0000000;
|
||||||
|
break;
|
||||||
|
case IOMMU_RNGE_1GB:
|
||||||
|
s->iostart = 0xc0000000;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case IOMMU_RNGE_2GB:
|
||||||
|
s->iostart = 0x80000000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Fall through */
|
||||||
default:
|
default:
|
||||||
s->regs[saddr] = val;
|
s->regs[saddr] = val;
|
||||||
break;
|
break;
|
||||||
|
@ -165,57 +189,30 @@ static CPUWriteMemoryFunc *iommu_mem_write[3] = {
|
||||||
|
|
||||||
uint32_t iommu_translate(uint32_t addr)
|
uint32_t iommu_translate(uint32_t addr)
|
||||||
{
|
{
|
||||||
uint32_t *iopte = (void *)(ps->regs[1] << 4), pa, iostart;
|
uint32_t *iopte = (void *)(ps->regs[1] << 4), pa;
|
||||||
|
|
||||||
switch (ps->regs[0] & IOMMU_CTRL_RNGE) {
|
iopte += ((addr - ps->iostart) >> PAGE_SHIFT);
|
||||||
case IOMMU_RNGE_16MB:
|
|
||||||
iostart = 0xff000000;
|
|
||||||
break;
|
|
||||||
case IOMMU_RNGE_32MB:
|
|
||||||
iostart = 0xfe000000;
|
|
||||||
break;
|
|
||||||
case IOMMU_RNGE_64MB:
|
|
||||||
iostart = 0xfc000000;
|
|
||||||
break;
|
|
||||||
case IOMMU_RNGE_128MB:
|
|
||||||
iostart = 0xf8000000;
|
|
||||||
break;
|
|
||||||
case IOMMU_RNGE_256MB:
|
|
||||||
iostart = 0xf0000000;
|
|
||||||
break;
|
|
||||||
case IOMMU_RNGE_512MB:
|
|
||||||
iostart = 0xe0000000;
|
|
||||||
break;
|
|
||||||
case IOMMU_RNGE_1GB:
|
|
||||||
iostart = 0xc0000000;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
case IOMMU_RNGE_2GB:
|
|
||||||
iostart = 0x80000000;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
iopte += ((addr - iostart) >> PAGE_SHIFT);
|
|
||||||
cpu_physical_memory_rw((uint32_t)iopte, (void *) &pa, 4, 0);
|
cpu_physical_memory_rw((uint32_t)iopte, (void *) &pa, 4, 0);
|
||||||
bswap32s(&pa);
|
bswap32s(&pa);
|
||||||
pa = (pa & IOPTE_PAGE) << 4; /* Loose higher bits of 36 */
|
pa = (pa & IOPTE_PAGE) << 4; /* Loose higher bits of 36 */
|
||||||
//return pa + PAGE_SIZE;
|
|
||||||
return pa + (addr & PAGE_MASK);
|
return pa + (addr & PAGE_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
void iommu_init()
|
void iommu_init(uint32_t addr)
|
||||||
{
|
{
|
||||||
IOMMUState *s;
|
IOMMUState *s;
|
||||||
|
int iommu_io_memory;
|
||||||
|
|
||||||
s = qemu_mallocz(sizeof(IOMMUState));
|
s = qemu_mallocz(sizeof(IOMMUState));
|
||||||
if (!s)
|
if (!s)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
s->addr = addr;
|
||||||
|
|
||||||
iommu_io_memory = cpu_register_io_memory(0, iommu_mem_read, iommu_mem_write, s);
|
iommu_io_memory = cpu_register_io_memory(0, iommu_mem_read, iommu_mem_write, s);
|
||||||
cpu_register_physical_memory(PHYS_JJ_IOMMU, sizeof(struct iommu_regs),
|
cpu_register_physical_memory(addr, sizeof(struct iommu_regs),
|
||||||
iommu_io_memory);
|
iommu_io_memory);
|
||||||
|
|
||||||
iommu_reset(s);
|
|
||||||
ps = s;
|
ps = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
42
hw/lance.c
42
hw/lance.c
|
@ -24,11 +24,7 @@
|
||||||
#include "vl.h"
|
#include "vl.h"
|
||||||
|
|
||||||
/* debug LANCE card */
|
/* debug LANCE card */
|
||||||
#define DEBUG_LANCE
|
//#define DEBUG_LANCE
|
||||||
|
|
||||||
#define PHYS_JJ_IOMMU 0x10000000 /* First page of sun4m IOMMU */
|
|
||||||
#define PHYS_JJ_LEDMA 0x78400010 /* ledma, off by 10 from unused SCSI */
|
|
||||||
#define PHYS_JJ_LE 0x78C00000 /* LANCE, typical sun4m */
|
|
||||||
|
|
||||||
#ifndef LANCE_LOG_TX_BUFFERS
|
#ifndef LANCE_LOG_TX_BUFFERS
|
||||||
#define LANCE_LOG_TX_BUFFERS 4
|
#define LANCE_LOG_TX_BUFFERS 4
|
||||||
|
@ -162,10 +158,12 @@ struct sparc_dma_registers {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct LEDMAState {
|
typedef struct LEDMAState {
|
||||||
|
uint32_t addr;
|
||||||
uint32_t regs[LEDMA_REGS];
|
uint32_t regs[LEDMA_REGS];
|
||||||
} LEDMAState;
|
} LEDMAState;
|
||||||
|
|
||||||
typedef struct LANCEState {
|
typedef struct LANCEState {
|
||||||
|
uint32_t paddr;
|
||||||
NetDriverState *nd;
|
NetDriverState *nd;
|
||||||
uint32_t leptr;
|
uint32_t leptr;
|
||||||
uint16_t addr;
|
uint16_t addr;
|
||||||
|
@ -175,8 +173,6 @@ typedef struct LANCEState {
|
||||||
LEDMAState *ledma;
|
LEDMAState *ledma;
|
||||||
} LANCEState;
|
} LANCEState;
|
||||||
|
|
||||||
static int lance_io_memory;
|
|
||||||
|
|
||||||
static unsigned int rxptr, txptr;
|
static unsigned int rxptr, txptr;
|
||||||
|
|
||||||
static void lance_send(void *opaque);
|
static void lance_send(void *opaque);
|
||||||
|
@ -194,7 +190,7 @@ static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr)
|
||||||
LANCEState *s = opaque;
|
LANCEState *s = opaque;
|
||||||
uint32_t saddr;
|
uint32_t saddr;
|
||||||
|
|
||||||
saddr = addr - PHYS_JJ_LE;
|
saddr = addr - s->paddr;
|
||||||
switch (saddr >> 1) {
|
switch (saddr >> 1) {
|
||||||
case LE_RDP:
|
case LE_RDP:
|
||||||
return s->regs[s->addr];
|
return s->regs[s->addr];
|
||||||
|
@ -210,9 +206,9 @@ static void lance_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val
|
||||||
{
|
{
|
||||||
LANCEState *s = opaque;
|
LANCEState *s = opaque;
|
||||||
uint32_t saddr;
|
uint32_t saddr;
|
||||||
uint16_t clear, reg;
|
uint16_t reg;
|
||||||
|
|
||||||
saddr = addr - PHYS_JJ_LE;
|
saddr = addr - s->paddr;
|
||||||
switch (saddr >> 1) {
|
switch (saddr >> 1) {
|
||||||
case LE_RDP:
|
case LE_RDP:
|
||||||
switch(s->addr) {
|
switch(s->addr) {
|
||||||
|
@ -406,14 +402,12 @@ static void lance_send(void *opaque)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ledma_io_memory;
|
|
||||||
|
|
||||||
static uint32_t ledma_mem_readl(void *opaque, target_phys_addr_t addr)
|
static uint32_t ledma_mem_readl(void *opaque, target_phys_addr_t addr)
|
||||||
{
|
{
|
||||||
LEDMAState *s = opaque;
|
LEDMAState *s = opaque;
|
||||||
uint32_t saddr;
|
uint32_t saddr;
|
||||||
|
|
||||||
saddr = (addr - PHYS_JJ_LEDMA) >> 2;
|
saddr = (addr - s->addr) >> 2;
|
||||||
if (saddr < LEDMA_REGS)
|
if (saddr < LEDMA_REGS)
|
||||||
return s->regs[saddr];
|
return s->regs[saddr];
|
||||||
else
|
else
|
||||||
|
@ -425,7 +419,7 @@ static void ledma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val
|
||||||
LEDMAState *s = opaque;
|
LEDMAState *s = opaque;
|
||||||
uint32_t saddr;
|
uint32_t saddr;
|
||||||
|
|
||||||
saddr = (addr - PHYS_JJ_LEDMA) >> 2;
|
saddr = (addr - s->addr) >> 2;
|
||||||
if (saddr < LEDMA_REGS)
|
if (saddr < LEDMA_REGS)
|
||||||
s->regs[saddr] = val;
|
s->regs[saddr] = val;
|
||||||
}
|
}
|
||||||
|
@ -442,29 +436,31 @@ static CPUWriteMemoryFunc *ledma_mem_write[3] = {
|
||||||
ledma_mem_writel,
|
ledma_mem_writel,
|
||||||
};
|
};
|
||||||
|
|
||||||
void lance_init(NetDriverState *nd, int irq)
|
void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr)
|
||||||
{
|
{
|
||||||
LANCEState *s;
|
LANCEState *s;
|
||||||
LEDMAState *led;
|
LEDMAState *led;
|
||||||
|
int lance_io_memory, ledma_io_memory;
|
||||||
|
|
||||||
s = qemu_mallocz(sizeof(LANCEState));
|
s = qemu_mallocz(sizeof(LANCEState));
|
||||||
if (!s)
|
if (!s)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
s->paddr = leaddr;
|
||||||
|
s->nd = nd;
|
||||||
|
s->irq = irq;
|
||||||
|
|
||||||
lance_io_memory = cpu_register_io_memory(0, lance_mem_read, lance_mem_write, s);
|
lance_io_memory = cpu_register_io_memory(0, lance_mem_read, lance_mem_write, s);
|
||||||
cpu_register_physical_memory(PHYS_JJ_LE, 8,
|
cpu_register_physical_memory(leaddr, 8, lance_io_memory);
|
||||||
lance_io_memory);
|
|
||||||
led = qemu_mallocz(sizeof(LEDMAState));
|
led = qemu_mallocz(sizeof(LEDMAState));
|
||||||
if (!led)
|
if (!led)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, led);
|
|
||||||
cpu_register_physical_memory(PHYS_JJ_LEDMA, 16,
|
|
||||||
ledma_io_memory);
|
|
||||||
|
|
||||||
s->nd = nd;
|
|
||||||
s->ledma = led;
|
s->ledma = led;
|
||||||
s->irq = irq;
|
led->addr = ledaddr;
|
||||||
|
ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, led);
|
||||||
|
cpu_register_physical_memory(ledaddr, 16, ledma_io_memory);
|
||||||
|
|
||||||
lance_reset(s);
|
lance_reset(s);
|
||||||
qemu_add_read_packet(nd, lance_can_receive, lance_receive, s);
|
qemu_add_read_packet(nd, lance_can_receive, lance_receive, s);
|
||||||
|
|
|
@ -341,7 +341,7 @@ static CPUReadMemoryFunc *nvram_read[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Initialisation routine */
|
/* Initialisation routine */
|
||||||
m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size)
|
m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size, uint8_t *macaddr)
|
||||||
{
|
{
|
||||||
m48t08_t *s;
|
m48t08_t *s;
|
||||||
int i;
|
int i;
|
||||||
|
@ -367,7 +367,7 @@ m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size)
|
||||||
i = 0x1fd8;
|
i = 0x1fd8;
|
||||||
s->buffer[i++] = 0x01;
|
s->buffer[i++] = 0x01;
|
||||||
s->buffer[i++] = 0x80; /* Sun4m OBP */
|
s->buffer[i++] = 0x80; /* Sun4m OBP */
|
||||||
/* XXX: Ethernet address, etc */
|
memcpy(&s->buffer[i], macaddr, 6);
|
||||||
|
|
||||||
/* Calculate checksum */
|
/* Calculate checksum */
|
||||||
for (i = 0x1fd8; i < 0x1fe7; i++) {
|
for (i = 0x1fd8; i < 0x1fe7; i++) {
|
||||||
|
|
|
@ -7,6 +7,6 @@ void m48t08_write (m48t08_t *NVRAM, uint32_t val);
|
||||||
uint32_t m48t08_read (m48t08_t *NVRAM);
|
uint32_t m48t08_read (m48t08_t *NVRAM);
|
||||||
void m48t08_set_addr (m48t08_t *NVRAM, uint32_t addr);
|
void m48t08_set_addr (m48t08_t *NVRAM, uint32_t addr);
|
||||||
void m48t08_toggle_lock (m48t08_t *NVRAM, int lock);
|
void m48t08_toggle_lock (m48t08_t *NVRAM, int lock);
|
||||||
m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size);
|
m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size, uint8_t *macaddr);
|
||||||
|
|
||||||
#endif /* !defined (__M48T08_H__) */
|
#endif /* !defined (__M48T08_H__) */
|
||||||
|
|
421
hw/magic-load.c
421
hw/magic-load.c
|
@ -1,41 +1,12 @@
|
||||||
/* This is the Linux kernel elf-loading code, ported into user space */
|
|
||||||
#include "vl.h"
|
#include "vl.h"
|
||||||
#include "disas.h"
|
#include "disas.h"
|
||||||
|
|
||||||
/* XXX: this code is not used as it is under the GPL license. Please
|
|
||||||
remove or recode it */
|
|
||||||
//#define USE_ELF_LOADER
|
|
||||||
|
|
||||||
#ifdef USE_ELF_LOADER
|
|
||||||
/* should probably go in elf.h */
|
|
||||||
#ifndef ELIBBAD
|
|
||||||
#define ELIBBAD 80
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define ELF_START_MMAP 0x80000000
|
|
||||||
|
|
||||||
#define elf_check_arch(x) ( (x) == EM_SPARC )
|
|
||||||
|
|
||||||
#define ELF_CLASS ELFCLASS32
|
#define ELF_CLASS ELFCLASS32
|
||||||
#define ELF_DATA ELFDATA2MSB
|
#define ELF_DATA ELFDATA2MSB
|
||||||
#define ELF_ARCH EM_SPARC
|
#define ELF_ARCH EM_SPARC
|
||||||
|
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
|
|
||||||
/*
|
|
||||||
* This structure is used to hold the arguments that are
|
|
||||||
* used when loading binaries.
|
|
||||||
*/
|
|
||||||
struct linux_binprm {
|
|
||||||
char buf[128];
|
|
||||||
int fd;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
|
|
||||||
#define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
|
|
||||||
#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
|
|
||||||
|
|
||||||
#ifdef BSWAP_NEEDED
|
#ifdef BSWAP_NEEDED
|
||||||
static void bswap_ehdr(Elf32_Ehdr *ehdr)
|
static void bswap_ehdr(Elf32_Ehdr *ehdr)
|
||||||
{
|
{
|
||||||
|
@ -87,186 +58,192 @@ static void bswap_sym(Elf32_Sym *sym)
|
||||||
bswap32s(&sym->st_size);
|
bswap32s(&sym->st_size);
|
||||||
bswap16s(&sym->st_shndx);
|
bswap16s(&sym->st_shndx);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
#define bswap_ehdr(e) do { } while (0)
|
||||||
|
#define bswap_phdr(e) do { } while (0)
|
||||||
|
#define bswap_shdr(e) do { } while (0)
|
||||||
|
#define bswap_sym(e) do { } while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int prepare_binprm(struct linux_binprm *bprm)
|
static int find_phdr(struct elfhdr *ehdr, int fd, struct elf_phdr *phdr, uint32_t type)
|
||||||
{
|
{
|
||||||
int retval;
|
int i, retval;
|
||||||
|
|
||||||
memset(bprm->buf, 0, sizeof(bprm->buf));
|
retval = lseek(fd, ehdr->e_phoff, SEEK_SET);
|
||||||
retval = lseek(bprm->fd, 0L, SEEK_SET);
|
|
||||||
if(retval >= 0) {
|
|
||||||
retval = read(bprm->fd, bprm->buf, 128);
|
|
||||||
}
|
|
||||||
if(retval < 0) {
|
|
||||||
perror("prepare_binprm");
|
|
||||||
exit(-1);
|
|
||||||
/* return(-errno); */
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return(retval);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Best attempt to load symbols from this ELF object. */
|
|
||||||
static void load_symbols(struct elfhdr *hdr, int fd)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
struct elf_shdr sechdr, symtab, strtab;
|
|
||||||
char *strings;
|
|
||||||
|
|
||||||
lseek(fd, hdr->e_shoff, SEEK_SET);
|
|
||||||
for (i = 0; i < hdr->e_shnum; i++) {
|
|
||||||
if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr))
|
|
||||||
return;
|
|
||||||
#ifdef BSWAP_NEEDED
|
|
||||||
bswap_shdr(&sechdr);
|
|
||||||
#endif
|
|
||||||
if (sechdr.sh_type == SHT_SYMTAB) {
|
|
||||||
symtab = sechdr;
|
|
||||||
lseek(fd, hdr->e_shoff
|
|
||||||
+ sizeof(sechdr) * sechdr.sh_link, SEEK_SET);
|
|
||||||
if (read(fd, &strtab, sizeof(strtab))
|
|
||||||
!= sizeof(strtab))
|
|
||||||
return;
|
|
||||||
#ifdef BSWAP_NEEDED
|
|
||||||
bswap_shdr(&strtab);
|
|
||||||
#endif
|
|
||||||
goto found;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return; /* Shouldn't happen... */
|
|
||||||
|
|
||||||
found:
|
|
||||||
/* Now know where the strtab and symtab are. Snarf them. */
|
|
||||||
disas_symtab = qemu_malloc(symtab.sh_size);
|
|
||||||
disas_strtab = strings = qemu_malloc(strtab.sh_size);
|
|
||||||
if (!disas_symtab || !disas_strtab)
|
|
||||||
return;
|
|
||||||
|
|
||||||
lseek(fd, symtab.sh_offset, SEEK_SET);
|
|
||||||
if (read(fd, disas_symtab, symtab.sh_size) != symtab.sh_size)
|
|
||||||
return;
|
|
||||||
|
|
||||||
#ifdef BSWAP_NEEDED
|
|
||||||
for (i = 0; i < symtab.sh_size / sizeof(struct elf_sym); i++)
|
|
||||||
bswap_sym(disas_symtab + sizeof(struct elf_sym)*i);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
lseek(fd, strtab.sh_offset, SEEK_SET);
|
|
||||||
if (read(fd, strings, strtab.sh_size) != strtab.sh_size)
|
|
||||||
return;
|
|
||||||
disas_num_syms = symtab.sh_size / sizeof(struct elf_sym);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int load_elf_binary(struct linux_binprm * bprm, uint8_t *addr)
|
|
||||||
{
|
|
||||||
struct elfhdr elf_ex;
|
|
||||||
unsigned long startaddr = addr;
|
|
||||||
int i;
|
|
||||||
struct elf_phdr * elf_ppnt;
|
|
||||||
struct elf_phdr *elf_phdata;
|
|
||||||
int retval;
|
|
||||||
|
|
||||||
elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */
|
|
||||||
#ifdef BSWAP_NEEDED
|
|
||||||
bswap_ehdr(&elf_ex);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (elf_ex.e_ident[0] != 0x7f ||
|
|
||||||
strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) {
|
|
||||||
return -ENOEXEC;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* First of all, some simple consistency checks */
|
|
||||||
if (! elf_check_arch(elf_ex.e_machine)) {
|
|
||||||
return -ENOEXEC;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now read in all of the header information */
|
|
||||||
elf_phdata = (struct elf_phdr *)qemu_malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
|
|
||||||
if (elf_phdata == NULL) {
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
|
|
||||||
if(retval > 0) {
|
|
||||||
retval = read(bprm->fd, (char *) elf_phdata,
|
|
||||||
elf_ex.e_phentsize * elf_ex.e_phnum);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (retval < 0) {
|
|
||||||
perror("load_elf_binary");
|
|
||||||
exit(-1);
|
|
||||||
qemu_free (elf_phdata);
|
|
||||||
return -errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef BSWAP_NEEDED
|
|
||||||
elf_ppnt = elf_phdata;
|
|
||||||
for (i=0; i<elf_ex.e_phnum; i++, elf_ppnt++) {
|
|
||||||
bswap_phdr(elf_ppnt);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
elf_ppnt = elf_phdata;
|
|
||||||
|
|
||||||
/* Now we do a little grungy work by mmaping the ELF image into
|
|
||||||
* the correct location in memory. At this point, we assume that
|
|
||||||
* the image should be loaded at fixed address, not at a variable
|
|
||||||
* address.
|
|
||||||
*/
|
|
||||||
|
|
||||||
for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
|
|
||||||
unsigned long error, offset, len;
|
|
||||||
|
|
||||||
if (elf_ppnt->p_type != PT_LOAD)
|
|
||||||
continue;
|
|
||||||
#if 0
|
|
||||||
error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr),
|
|
||||||
elf_prot,
|
|
||||||
(MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
|
|
||||||
bprm->fd,
|
|
||||||
(elf_ppnt->p_offset -
|
|
||||||
TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
|
|
||||||
#endif
|
|
||||||
//offset = elf_ppnt->p_offset - TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr);
|
|
||||||
offset = 0x4000;
|
|
||||||
lseek(bprm->fd, offset, SEEK_SET);
|
|
||||||
len = elf_ppnt->p_filesz + TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr);
|
|
||||||
error = read(bprm->fd, addr, len);
|
|
||||||
|
|
||||||
if (error == -1) {
|
|
||||||
perror("mmap");
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
addr += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
qemu_free(elf_phdata);
|
|
||||||
|
|
||||||
load_symbols(&elf_ex, bprm->fd);
|
|
||||||
|
|
||||||
return addr-startaddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
int elf_exec(const char * filename, uint8_t *addr)
|
|
||||||
{
|
|
||||||
struct linux_binprm bprm;
|
|
||||||
int retval;
|
|
||||||
|
|
||||||
retval = open(filename, O_RDONLY);
|
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
return retval;
|
return -1;
|
||||||
bprm.fd = retval;
|
|
||||||
|
|
||||||
retval = prepare_binprm(&bprm);
|
for (i = 0; i < ehdr->e_phnum; i++) {
|
||||||
|
retval = read(fd, phdr, sizeof(*phdr));
|
||||||
|
if (retval < 0)
|
||||||
|
return -1;
|
||||||
|
bswap_phdr(phdr);
|
||||||
|
if (phdr->p_type == type)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if(retval>=0) {
|
static void *find_shdr(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, uint32_t type)
|
||||||
retval = load_elf_binary(&bprm, addr);
|
{
|
||||||
|
int i, retval;
|
||||||
|
|
||||||
|
retval = lseek(fd, ehdr->e_shoff, SEEK_SET);
|
||||||
|
if (retval < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < ehdr->e_shnum; i++) {
|
||||||
|
retval = read(fd, shdr, sizeof(*shdr));
|
||||||
|
if (retval < 0)
|
||||||
|
return NULL;
|
||||||
|
bswap_shdr(shdr);
|
||||||
|
if (shdr->sh_type == type)
|
||||||
|
return qemu_malloc(shdr->sh_size);
|
||||||
}
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int find_strtab(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = lseek(fd, ehdr->e_shoff + sizeof(struct elf_shdr) * symtab->sh_link, SEEK_SET);
|
||||||
|
if (retval < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
retval = read(fd, shdr, sizeof(*shdr));
|
||||||
|
if (retval < 0)
|
||||||
|
return -1;
|
||||||
|
bswap_shdr(shdr);
|
||||||
|
if (shdr->sh_type == SHT_STRTAB)
|
||||||
|
return qemu_malloc(shdr->sh_size);;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read_program(int fd, struct elf_phdr *phdr, void *dst)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
retval = lseek(fd, 0x4000, SEEK_SET);
|
||||||
|
if (retval < 0)
|
||||||
|
return -1;
|
||||||
|
return read(fd, dst, phdr->p_filesz);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read_section(int fd, struct elf_shdr *s, void *dst)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = lseek(fd, s->sh_offset, SEEK_SET);
|
||||||
|
if (retval < 0)
|
||||||
|
return -1;
|
||||||
|
retval = read(fd, dst, s->sh_size);
|
||||||
|
if (retval < 0)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *process_section(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, uint32_t type)
|
||||||
|
{
|
||||||
|
void *dst;
|
||||||
|
|
||||||
|
dst = find_shdr(ehdr, fd, shdr, type);
|
||||||
|
if (!dst)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (read_section(fd, shdr, dst))
|
||||||
|
goto error;
|
||||||
|
return dst;
|
||||||
|
error:
|
||||||
|
qemu_free(dst);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *process_strtab(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
|
||||||
|
{
|
||||||
|
void *dst;
|
||||||
|
|
||||||
|
dst = find_strtab(ehdr, fd, shdr, symtab);
|
||||||
|
if (!dst)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (read_section(fd, shdr, dst))
|
||||||
|
goto error;
|
||||||
|
return dst;
|
||||||
|
error:
|
||||||
|
qemu_free(dst);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void load_symbols(struct elfhdr *ehdr, int fd)
|
||||||
|
{
|
||||||
|
struct elf_shdr symtab, strtab;
|
||||||
|
struct elf_sym *syms;
|
||||||
|
int nsyms, i;
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
/* Symbol table */
|
||||||
|
syms = process_section(ehdr, fd, &symtab, SHT_SYMTAB);
|
||||||
|
if (!syms)
|
||||||
|
return;
|
||||||
|
|
||||||
|
nsyms = symtab.sh_size / sizeof(struct elf_sym);
|
||||||
|
for (i = 0; i < nsyms; i++)
|
||||||
|
bswap_sym(&syms[i]);
|
||||||
|
|
||||||
|
/* String table */
|
||||||
|
str = process_strtab(ehdr, fd, &strtab, &symtab);
|
||||||
|
if (!str)
|
||||||
|
goto error_freesyms;
|
||||||
|
|
||||||
|
/* Commit */
|
||||||
|
if (disas_symtab)
|
||||||
|
qemu_free(disas_symtab); /* XXX Merge with old symbols? */
|
||||||
|
if (disas_strtab)
|
||||||
|
qemu_free(disas_strtab);
|
||||||
|
disas_symtab = syms;
|
||||||
|
disas_num_syms = nsyms;
|
||||||
|
disas_strtab = str;
|
||||||
|
return;
|
||||||
|
error_freesyms:
|
||||||
|
qemu_free(syms);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int load_elf(const char * filename, uint8_t *addr)
|
||||||
|
{
|
||||||
|
struct elfhdr ehdr;
|
||||||
|
struct elf_phdr phdr;
|
||||||
|
int retval, fd;
|
||||||
|
|
||||||
|
fd = open(filename, O_RDONLY | O_BINARY);
|
||||||
|
if (fd < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
retval = read(fd, &ehdr, sizeof(ehdr));
|
||||||
|
if (retval < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
bswap_ehdr(&ehdr);
|
||||||
|
|
||||||
|
if (ehdr.e_ident[0] != 0x7f || ehdr.e_ident[1] != 'E'
|
||||||
|
|| ehdr.e_ident[2] != 'L' || ehdr.e_ident[3] != 'F'
|
||||||
|
|| ehdr.e_machine != EM_SPARC)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (find_phdr(&ehdr, fd, &phdr, PT_LOAD))
|
||||||
|
goto error;
|
||||||
|
retval = read_program(fd, &phdr, addr);
|
||||||
|
if (retval < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
load_symbols(&ehdr, fd);
|
||||||
|
|
||||||
|
close(fd);
|
||||||
return retval;
|
return retval;
|
||||||
|
error:
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
int load_kernel(const char *filename, uint8_t *addr)
|
int load_kernel(const char *filename, uint8_t *addr)
|
||||||
{
|
{
|
||||||
|
@ -286,28 +263,31 @@ int load_kernel(const char *filename, uint8_t *addr)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char saved_kfn[1024];
|
typedef struct MAGICState {
|
||||||
static uint32_t saved_addr;
|
uint32_t addr;
|
||||||
static int magic_state;
|
uint32_t saved_addr;
|
||||||
|
int magic_state;
|
||||||
|
char saved_kfn[1024];
|
||||||
|
} MAGICState;
|
||||||
|
|
||||||
static uint32_t magic_mem_readl(void *opaque, target_phys_addr_t addr)
|
static uint32_t magic_mem_readl(void *opaque, target_phys_addr_t addr)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
MAGICState *s = opaque;
|
||||||
|
|
||||||
if (magic_state == 0) {
|
if (s->magic_state == 0) {
|
||||||
#ifdef USE_ELF_LOADER
|
ret = load_elf(s->saved_kfn, (uint8_t *)s->saved_addr);
|
||||||
ret = elf_exec(saved_kfn, saved_addr);
|
if (ret < 0)
|
||||||
#else
|
ret = load_kernel(s->saved_kfn, (uint8_t *)s->saved_addr);
|
||||||
ret = load_kernel(saved_kfn, (uint8_t *)saved_addr);
|
|
||||||
#endif
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "qemu: could not load kernel '%s'\n",
|
fprintf(stderr, "qemu: could not load kernel '%s'\n",
|
||||||
saved_kfn);
|
s->saved_kfn);
|
||||||
}
|
}
|
||||||
magic_state = 1; /* No more magic */
|
s->magic_state = 1; /* No more magic */
|
||||||
tb_flush();
|
tb_flush();
|
||||||
|
return bswap32(ret);
|
||||||
}
|
}
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void magic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
|
static void magic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
|
||||||
|
@ -327,15 +307,20 @@ static CPUWriteMemoryFunc *magic_mem_write[3] = {
|
||||||
magic_mem_writel,
|
magic_mem_writel,
|
||||||
};
|
};
|
||||||
|
|
||||||
void magic_init(const char *kfn, int kloadaddr)
|
void magic_init(const char *kfn, int kloadaddr, uint32_t addr)
|
||||||
{
|
{
|
||||||
int magic_io_memory;
|
int magic_io_memory;
|
||||||
|
MAGICState *s;
|
||||||
|
|
||||||
strcpy(saved_kfn, kfn);
|
s = qemu_mallocz(sizeof(MAGICState));
|
||||||
saved_addr = kloadaddr;
|
if (!s)
|
||||||
magic_state = 0;
|
return;
|
||||||
magic_io_memory = cpu_register_io_memory(0, magic_mem_read, magic_mem_write, 0);
|
|
||||||
cpu_register_physical_memory(0x20000000, 4,
|
strcpy(s->saved_kfn, kfn);
|
||||||
magic_io_memory);
|
s->saved_addr = kloadaddr;
|
||||||
|
s->magic_state = 0;
|
||||||
|
s->addr = addr;
|
||||||
|
magic_io_memory = cpu_register_io_memory(0, magic_mem_read, magic_mem_write, s);
|
||||||
|
cpu_register_physical_memory(addr, 4, magic_io_memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
148
hw/sched.c
148
hw/sched.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* QEMU interrupt controller & timer emulation
|
* QEMU interrupt controller emulation
|
||||||
*
|
*
|
||||||
* Copyright (c) 2003-2004 Fabrice Bellard
|
* Copyright (c) 2003-2004 Fabrice Bellard
|
||||||
*
|
*
|
||||||
|
@ -22,11 +22,7 @@
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#include "vl.h"
|
#include "vl.h"
|
||||||
|
//#define DEBUG_IRQ_COUNT
|
||||||
#define PHYS_JJ_CLOCK 0x71D00000
|
|
||||||
#define PHYS_JJ_CLOCK1 0x71D10000
|
|
||||||
#define PHYS_JJ_INTR0 0x71E00000 /* CPU0 interrupt control registers */
|
|
||||||
#define PHYS_JJ_INTR_G 0x71E10000 /* Master interrupt control registers */
|
|
||||||
|
|
||||||
/* These registers are used for sending/receiving irqs from/to
|
/* These registers are used for sending/receiving irqs from/to
|
||||||
* different cpu's.
|
* different cpu's.
|
||||||
|
@ -63,18 +59,6 @@ struct sun4m_intreg_master {
|
||||||
/* This register is both READ and WRITE. */
|
/* This register is both READ and WRITE. */
|
||||||
unsigned int undirected_target; /* Which cpu gets undirected irqs. */
|
unsigned int undirected_target; /* Which cpu gets undirected irqs. */
|
||||||
};
|
};
|
||||||
/*
|
|
||||||
* Registers of hardware timer in sun4m.
|
|
||||||
*/
|
|
||||||
struct sun4m_timer_percpu {
|
|
||||||
volatile unsigned int l14_timer_limit; /* Initial value is 0x009c4000 */
|
|
||||||
volatile unsigned int l14_cur_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sun4m_timer_global {
|
|
||||||
volatile unsigned int l10_timer_limit;
|
|
||||||
volatile unsigned int l10_cur_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define SUN4M_INT_ENABLE 0x80000000
|
#define SUN4M_INT_ENABLE 0x80000000
|
||||||
#define SUN4M_INT_E14 0x00000080
|
#define SUN4M_INT_E14 0x00000080
|
||||||
|
@ -101,29 +85,25 @@ struct sun4m_timer_global {
|
||||||
#define SUN4M_INT_VME(x) (1 << (x))
|
#define SUN4M_INT_VME(x) (1 << (x))
|
||||||
|
|
||||||
typedef struct SCHEDState {
|
typedef struct SCHEDState {
|
||||||
|
uint32_t addr, addrg;
|
||||||
uint32_t intreg_pending;
|
uint32_t intreg_pending;
|
||||||
uint32_t intreg_enabled;
|
uint32_t intreg_enabled;
|
||||||
uint32_t intregm_pending;
|
uint32_t intregm_pending;
|
||||||
uint32_t intregm_enabled;
|
uint32_t intregm_enabled;
|
||||||
uint32_t timer_regs[2];
|
|
||||||
uint32_t timerm_regs[2];
|
|
||||||
} SCHEDState;
|
} SCHEDState;
|
||||||
|
|
||||||
static SCHEDState *ps;
|
static SCHEDState *ps;
|
||||||
|
|
||||||
static int intreg_io_memory, intregm_io_memory,
|
#ifdef DEBUG_IRQ_COUNT
|
||||||
timer_io_memory, timerm_io_memory;
|
static uint64_t irq_count[32];
|
||||||
|
#endif
|
||||||
static void sched_reset(SCHEDState *s)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t intreg_mem_readl(void *opaque, target_phys_addr_t addr)
|
static uint32_t intreg_mem_readl(void *opaque, target_phys_addr_t addr)
|
||||||
{
|
{
|
||||||
SCHEDState *s = opaque;
|
SCHEDState *s = opaque;
|
||||||
uint32_t saddr;
|
uint32_t saddr;
|
||||||
|
|
||||||
saddr = (addr - PHYS_JJ_INTR0) >> 2;
|
saddr = (addr - s->addr) >> 2;
|
||||||
switch (saddr) {
|
switch (saddr) {
|
||||||
case 0:
|
case 0:
|
||||||
return s->intreg_pending;
|
return s->intreg_pending;
|
||||||
|
@ -139,7 +119,7 @@ static void intreg_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t va
|
||||||
SCHEDState *s = opaque;
|
SCHEDState *s = opaque;
|
||||||
uint32_t saddr;
|
uint32_t saddr;
|
||||||
|
|
||||||
saddr = (addr - PHYS_JJ_INTR0) >> 2;
|
saddr = (addr - s->addr) >> 2;
|
||||||
switch (saddr) {
|
switch (saddr) {
|
||||||
case 0:
|
case 0:
|
||||||
s->intreg_pending = val;
|
s->intreg_pending = val;
|
||||||
|
@ -172,7 +152,7 @@ static uint32_t intregm_mem_readl(void *opaque, target_phys_addr_t addr)
|
||||||
SCHEDState *s = opaque;
|
SCHEDState *s = opaque;
|
||||||
uint32_t saddr;
|
uint32_t saddr;
|
||||||
|
|
||||||
saddr = (addr - PHYS_JJ_INTR_G) >> 2;
|
saddr = (addr - s->addrg) >> 2;
|
||||||
switch (saddr) {
|
switch (saddr) {
|
||||||
case 0:
|
case 0:
|
||||||
return s->intregm_pending;
|
return s->intregm_pending;
|
||||||
|
@ -191,7 +171,7 @@ static void intregm_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t v
|
||||||
SCHEDState *s = opaque;
|
SCHEDState *s = opaque;
|
||||||
uint32_t saddr;
|
uint32_t saddr;
|
||||||
|
|
||||||
saddr = (addr - PHYS_JJ_INTR_G) >> 2;
|
saddr = (addr - s->addrg) >> 2;
|
||||||
switch (saddr) {
|
switch (saddr) {
|
||||||
case 0:
|
case 0:
|
||||||
s->intregm_pending = val;
|
s->intregm_pending = val;
|
||||||
|
@ -222,87 +202,29 @@ static CPUWriteMemoryFunc *intregm_mem_write[3] = {
|
||||||
intregm_mem_writel,
|
intregm_mem_writel,
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint32_t timer_mem_readl(void *opaque, target_phys_addr_t addr)
|
void pic_info(void)
|
||||||
{
|
{
|
||||||
SCHEDState *s = opaque;
|
term_printf("per-cpu: pending 0x%08x, enabled 0x%08x\n", ps->intreg_pending, ps->intreg_enabled);
|
||||||
uint32_t saddr;
|
term_printf("master: pending 0x%08x, enabled 0x%08x\n", ps->intregm_pending, ps->intregm_enabled);
|
||||||
|
|
||||||
saddr = (addr - PHYS_JJ_CLOCK) >> 2;
|
|
||||||
switch (saddr) {
|
|
||||||
default:
|
|
||||||
return s->timer_regs[saddr];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void timer_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
|
void irq_info(void)
|
||||||
{
|
{
|
||||||
SCHEDState *s = opaque;
|
#ifndef DEBUG_IRQ_COUNT
|
||||||
uint32_t saddr;
|
term_printf("irq statistic code not compiled.\n");
|
||||||
|
#else
|
||||||
|
int i;
|
||||||
|
int64_t count;
|
||||||
|
|
||||||
saddr = (addr - PHYS_JJ_CLOCK) >> 2;
|
term_printf("IRQ statistics:\n");
|
||||||
switch (saddr) {
|
for (i = 0; i < 32; i++) {
|
||||||
default:
|
count = irq_count[i];
|
||||||
s->timer_regs[saddr] = val;
|
if (count > 0)
|
||||||
break;
|
term_printf("%2d: %lld\n", i, count);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static CPUReadMemoryFunc *timer_mem_read[3] = {
|
|
||||||
timer_mem_readl,
|
|
||||||
timer_mem_readl,
|
|
||||||
timer_mem_readl,
|
|
||||||
};
|
|
||||||
|
|
||||||
static CPUWriteMemoryFunc *timer_mem_write[3] = {
|
|
||||||
timer_mem_writel,
|
|
||||||
timer_mem_writel,
|
|
||||||
timer_mem_writel,
|
|
||||||
};
|
|
||||||
|
|
||||||
static uint32_t timerm_mem_readl(void *opaque, target_phys_addr_t addr)
|
|
||||||
{
|
|
||||||
SCHEDState *s = opaque;
|
|
||||||
uint32_t saddr;
|
|
||||||
|
|
||||||
saddr = (addr - PHYS_JJ_CLOCK1) >> 2;
|
|
||||||
switch (saddr) {
|
|
||||||
default:
|
|
||||||
return s->timerm_regs[saddr];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void timerm_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
|
|
||||||
{
|
|
||||||
SCHEDState *s = opaque;
|
|
||||||
uint32_t saddr;
|
|
||||||
|
|
||||||
saddr = (addr - PHYS_JJ_CLOCK1) >> 2;
|
|
||||||
switch (saddr) {
|
|
||||||
default:
|
|
||||||
s->timerm_regs[saddr] = val;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static CPUReadMemoryFunc *timerm_mem_read[3] = {
|
|
||||||
timerm_mem_readl,
|
|
||||||
timerm_mem_readl,
|
|
||||||
timerm_mem_readl,
|
|
||||||
};
|
|
||||||
|
|
||||||
static CPUWriteMemoryFunc *timerm_mem_write[3] = {
|
|
||||||
timerm_mem_writel,
|
|
||||||
timerm_mem_writel,
|
|
||||||
timerm_mem_writel,
|
|
||||||
};
|
|
||||||
|
|
||||||
void pic_info() {}
|
|
||||||
void irq_info() {}
|
|
||||||
|
|
||||||
static const unsigned int intr_to_mask[16] = {
|
static const unsigned int intr_to_mask[16] = {
|
||||||
0, 0, 0, 0, 0, 0, SUN4M_INT_ETHERNET, 0,
|
0, 0, 0, 0, 0, 0, SUN4M_INT_ETHERNET, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
@ -318,29 +240,29 @@ void pic_set_irq(int irq, int level)
|
||||||
cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
|
cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG_IRQ_COUNT
|
||||||
|
if (level == 1)
|
||||||
|
irq_count[irq]++;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void sched_init()
|
void sched_init(uint32_t addr, uint32_t addrg)
|
||||||
{
|
{
|
||||||
|
int intreg_io_memory, intregm_io_memory;
|
||||||
SCHEDState *s;
|
SCHEDState *s;
|
||||||
|
|
||||||
s = qemu_mallocz(sizeof(SCHEDState));
|
s = qemu_mallocz(sizeof(SCHEDState));
|
||||||
if (!s)
|
if (!s)
|
||||||
return;
|
return;
|
||||||
|
s->addr = addr;
|
||||||
|
s->addrg = addrg;
|
||||||
|
|
||||||
intreg_io_memory = cpu_register_io_memory(0, intreg_mem_read, intreg_mem_write, s);
|
intreg_io_memory = cpu_register_io_memory(0, intreg_mem_read, intreg_mem_write, s);
|
||||||
cpu_register_physical_memory(PHYS_JJ_INTR0, 3, intreg_io_memory);
|
cpu_register_physical_memory(addr, 3, intreg_io_memory);
|
||||||
|
|
||||||
intregm_io_memory = cpu_register_io_memory(0, intregm_mem_read, intregm_mem_write, s);
|
intregm_io_memory = cpu_register_io_memory(0, intregm_mem_read, intregm_mem_write, s);
|
||||||
cpu_register_physical_memory(PHYS_JJ_INTR_G, 5, intregm_io_memory);
|
cpu_register_physical_memory(addrg, 5, intregm_io_memory);
|
||||||
|
|
||||||
timer_io_memory = cpu_register_io_memory(0, timer_mem_read, timer_mem_write, s);
|
|
||||||
cpu_register_physical_memory(PHYS_JJ_CLOCK, 2, timer_io_memory);
|
|
||||||
|
|
||||||
timerm_io_memory = cpu_register_io_memory(0, timerm_mem_read, timerm_mem_write, s);
|
|
||||||
cpu_register_physical_memory(PHYS_JJ_CLOCK1, 2, timerm_io_memory);
|
|
||||||
|
|
||||||
sched_reset(s);
|
|
||||||
ps = s;
|
ps = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
75
hw/sun4m.c
75
hw/sun4m.c
|
@ -28,12 +28,26 @@
|
||||||
#define MMU_CONTEXT_TBL 0x00003000
|
#define MMU_CONTEXT_TBL 0x00003000
|
||||||
#define MMU_L1PTP (MMU_CONTEXT_TBL + 0x0400)
|
#define MMU_L1PTP (MMU_CONTEXT_TBL + 0x0400)
|
||||||
#define MMU_L2PTP (MMU_CONTEXT_TBL + 0x0800)
|
#define MMU_L2PTP (MMU_CONTEXT_TBL + 0x0800)
|
||||||
#define ROMVEC_DATA (MMU_CONTEXT_TBL + 0x1800)
|
|
||||||
#define PROM_ADDR 0xffd04000
|
#define PROM_ADDR 0xffd04000
|
||||||
#define PROM_FILENAME "proll.bin"
|
#define PROM_FILENAMEB "proll.bin"
|
||||||
|
#define PROM_FILENAMEE "proll.elf"
|
||||||
|
#define PROLL_MAGIC_ADDR 0x20000000
|
||||||
#define PHYS_JJ_EEPROM 0x71200000 /* [2000] MK48T08 */
|
#define PHYS_JJ_EEPROM 0x71200000 /* [2000] MK48T08 */
|
||||||
#define PHYS_JJ_IDPROM_OFF 0x1FD8
|
#define PHYS_JJ_IDPROM_OFF 0x1FD8
|
||||||
#define PHYS_JJ_EEPROM_SIZE 0x2000
|
#define PHYS_JJ_EEPROM_SIZE 0x2000
|
||||||
|
#define PHYS_JJ_IOMMU 0x10000000 /* First page of sun4m IOMMU */
|
||||||
|
#define PHYS_JJ_TCX_FB 0x50800000 /* Start address, frame buffer body */
|
||||||
|
#define PHYS_JJ_TCX_0E 0x5E000000 /* Top address, one byte used. */
|
||||||
|
#define PHYS_JJ_IOMMU 0x10000000 /* First page of sun4m IOMMU */
|
||||||
|
#define PHYS_JJ_LEDMA 0x78400010 /* ledma, off by 10 from unused SCSI */
|
||||||
|
#define PHYS_JJ_LE 0x78C00000 /* LANCE, typical sun4m */
|
||||||
|
#define PHYS_JJ_LE_IRQ 6
|
||||||
|
#define PHYS_JJ_CLOCK 0x71D00000
|
||||||
|
#define PHYS_JJ_CLOCK_IRQ 10
|
||||||
|
#define PHYS_JJ_CLOCK1 0x71D10000
|
||||||
|
#define PHYS_JJ_CLOCK1_IRQ 14
|
||||||
|
#define PHYS_JJ_INTR0 0x71E00000 /* CPU0 interrupt control registers */
|
||||||
|
#define PHYS_JJ_INTR_G 0x71E10000 /* Master interrupt control registers */
|
||||||
|
|
||||||
/* TSC handling */
|
/* TSC handling */
|
||||||
|
|
||||||
|
@ -44,8 +58,6 @@ uint64_t cpu_get_tsc()
|
||||||
|
|
||||||
void DMA_run() {}
|
void DMA_run() {}
|
||||||
void SB16_run() {}
|
void SB16_run() {}
|
||||||
void vga_invalidate_display() {}
|
|
||||||
void vga_screen_dump(const char *filename) {}
|
|
||||||
int serial_can_receive(SerialState *s) { return 0; }
|
int serial_can_receive(SerialState *s) { return 0; }
|
||||||
void serial_receive_byte(SerialState *s, int ch) {}
|
void serial_receive_byte(SerialState *s, int ch) {}
|
||||||
void serial_receive_break(SerialState *s) {}
|
void serial_receive_break(SerialState *s) {}
|
||||||
|
@ -59,7 +71,7 @@ void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
|
||||||
const char *initrd_filename)
|
const char *initrd_filename)
|
||||||
{
|
{
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
int ret, linux_boot, bios_size;
|
int ret, linux_boot;
|
||||||
unsigned long bios_offset;
|
unsigned long bios_offset;
|
||||||
|
|
||||||
linux_boot = (kernel_filename != NULL);
|
linux_boot = (kernel_filename != NULL);
|
||||||
|
@ -68,30 +80,19 @@ void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
|
||||||
cpu_register_physical_memory(0, ram_size, 0);
|
cpu_register_physical_memory(0, ram_size, 0);
|
||||||
bios_offset = ram_size;
|
bios_offset = ram_size;
|
||||||
|
|
||||||
iommu_init();
|
iommu_init(PHYS_JJ_IOMMU);
|
||||||
sched_init();
|
sched_init(PHYS_JJ_INTR0, PHYS_JJ_INTR_G);
|
||||||
tcx_init(ds);
|
tcx_init(ds, PHYS_JJ_TCX_FB);
|
||||||
lance_init(&nd_table[0], 6);
|
lance_init(&nd_table[0], PHYS_JJ_LE_IRQ, PHYS_JJ_LE, PHYS_JJ_LEDMA);
|
||||||
nvram = m48t08_init(PHYS_JJ_EEPROM, PHYS_JJ_EEPROM_SIZE);
|
nvram = m48t08_init(PHYS_JJ_EEPROM, PHYS_JJ_EEPROM_SIZE, &nd_table[0].macaddr);
|
||||||
|
timer_init(PHYS_JJ_CLOCK, PHYS_JJ_CLOCK_IRQ);
|
||||||
magic_init(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
|
timer_init(PHYS_JJ_CLOCK1, PHYS_JJ_CLOCK1_IRQ);
|
||||||
|
magic_init(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR, PROLL_MAGIC_ADDR);
|
||||||
#if 0
|
|
||||||
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAME);
|
|
||||||
bios_size = get_image_size(buf);
|
|
||||||
ret = load_image(buf, phys_ram_base + bios_offset);
|
|
||||||
if (ret != bios_size) {
|
|
||||||
fprintf(stderr, "qemu: could not load prom '%s'\n", buf);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
cpu_register_physical_memory(PROM_ADDR,
|
|
||||||
bios_size, bios_offset | IO_MEM_ROM);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* We load Proll as the kernel and start it. It will issue a magic
|
/* We load Proll as the kernel and start it. It will issue a magic
|
||||||
IO to load the real kernel */
|
IO to load the real kernel */
|
||||||
if (linux_boot) {
|
if (linux_boot) {
|
||||||
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAME);
|
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEB);
|
||||||
ret = load_kernel(buf,
|
ret = load_kernel(buf,
|
||||||
phys_ram_base + KERNEL_LOAD_ADDR);
|
phys_ram_base + KERNEL_LOAD_ADDR);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
@ -103,28 +104,10 @@ void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
|
||||||
/* Setup a MMU entry for entire address space */
|
/* Setup a MMU entry for entire address space */
|
||||||
stl_raw(phys_ram_base + MMU_CONTEXT_TBL, (MMU_L1PTP >> 4) | 1);
|
stl_raw(phys_ram_base + MMU_CONTEXT_TBL, (MMU_L1PTP >> 4) | 1);
|
||||||
stl_raw(phys_ram_base + MMU_L1PTP, (MMU_L2PTP >> 4) | 1);
|
stl_raw(phys_ram_base + MMU_L1PTP, (MMU_L2PTP >> 4) | 1);
|
||||||
#if 0
|
stl_raw(phys_ram_base + MMU_L1PTP + (0x01 << 2), (MMU_L2PTP >> 4) | 1); // 01.. == 00..
|
||||||
stl_raw(phys_ram_base + MMU_L1PTP + (0x50 << 2), (MMU_L2PTP >> 4) | 1); // frame buffer at 50..
|
|
||||||
#endif
|
|
||||||
stl_raw(phys_ram_base + MMU_L1PTP + (0xff << 2), (MMU_L2PTP >> 4) | 1); // ff.. == 00..
|
stl_raw(phys_ram_base + MMU_L1PTP + (0xff << 2), (MMU_L2PTP >> 4) | 1); // ff.. == 00..
|
||||||
|
stl_raw(phys_ram_base + MMU_L1PTP + (0xf0 << 2), (MMU_L2PTP >> 4) | 1); // f0.. == 00..
|
||||||
/* 3 = U:RWX S:RWX */
|
/* 3 = U:RWX S:RWX */
|
||||||
stl_raw(phys_ram_base + MMU_L2PTP, (3 << PTE_ACCESS_SHIFT) | 2);
|
stl_raw(phys_ram_base + MMU_L2PTP, (3 << PTE_ACCESS_SHIFT) | 2);
|
||||||
#if 0
|
stl_raw(phys_ram_base + MMU_L2PTP, ((0x01 << PTE_PPN_SHIFT) >> 4 ) | (3 << PTE_ACCESS_SHIFT) | 2);
|
||||||
stl_raw(phys_ram_base + MMU_L2PTP + 0x84, (PHYS_JJ_TCX_FB >> 4) \
|
|
||||||
| (3 << PTE_ACCESS_SHIFT) | 2); // frame buf
|
|
||||||
stl_raw(phys_ram_base + MMU_L2PTP + 0x88, (PHYS_JJ_TCX_FB >> 4) \
|
|
||||||
| (3 << PTE_ACCESS_SHIFT) | 2); // frame buf
|
|
||||||
stl_raw(phys_ram_base + MMU_L2PTP + 0x140, (PHYS_JJ_TCX_FB >> 4) \
|
|
||||||
| (3 << PTE_ACCESS_SHIFT) | 2); // frame buf
|
|
||||||
// "Empirical constant"
|
|
||||||
stl_raw(phys_ram_base + ROMVEC_DATA, 0x10010407);
|
|
||||||
|
|
||||||
// Version: V3 prom
|
|
||||||
stl_raw(phys_ram_base + ROMVEC_DATA + 4, 3);
|
|
||||||
|
|
||||||
stl_raw(phys_ram_base + ROMVEC_DATA + 0x1c, ROMVEC_DATA+0x400);
|
|
||||||
stl_raw(phys_ram_base + ROMVEC_DATA + 0x400, ROMVEC_DATA+0x404);
|
|
||||||
stl_raw(phys_ram_base + ROMVEC_DATA + 0x404, 0x81c3e008); // retl
|
|
||||||
stl_raw(phys_ram_base + ROMVEC_DATA + 0x408, 0x01000000); // nop
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
81
hw/tcx.c
81
hw/tcx.c
|
@ -23,9 +23,6 @@
|
||||||
*/
|
*/
|
||||||
#include "vl.h"
|
#include "vl.h"
|
||||||
|
|
||||||
#define PHYS_JJ_TCX_FB 0x50800000 /* Start address, frame buffer body */
|
|
||||||
#define PHYS_JJ_TCX_0E 0x5E000000 /* Top address, one byte used. */
|
|
||||||
|
|
||||||
#define MAXX 1024
|
#define MAXX 1024
|
||||||
#define MAXY 768
|
#define MAXY 768
|
||||||
#define XSZ (8*80)
|
#define XSZ (8*80)
|
||||||
|
@ -33,38 +30,32 @@
|
||||||
#define XOFF (MAXX-XSZ)
|
#define XOFF (MAXX-XSZ)
|
||||||
#define YOFF (MAXY-YSZ)
|
#define YOFF (MAXY-YSZ)
|
||||||
|
|
||||||
#define DEBUG_VGA_MEM
|
|
||||||
|
|
||||||
typedef struct TCXState {
|
typedef struct TCXState {
|
||||||
uint8_t *vram_ptr;
|
uint32_t addr;
|
||||||
unsigned long vram_offset;
|
|
||||||
unsigned int vram_size;
|
|
||||||
DisplayState *ds;
|
DisplayState *ds;
|
||||||
|
uint8_t *vram;
|
||||||
} TCXState;
|
} TCXState;
|
||||||
|
|
||||||
static TCXState *ts;
|
static TCXState *ts;
|
||||||
|
|
||||||
static int tcx_io_memory;
|
|
||||||
|
|
||||||
void vga_update_display()
|
void vga_update_display()
|
||||||
{
|
{
|
||||||
dpy_update(ts->ds, 0, 0, XSZ, YSZ);
|
dpy_update(ts->ds, 0, 0, XSZ, YSZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vga_invalidate_display() {}
|
||||||
|
|
||||||
static uint32_t tcx_mem_readb(void *opaque, target_phys_addr_t addr)
|
static uint32_t tcx_mem_readb(void *opaque, target_phys_addr_t addr)
|
||||||
{
|
{
|
||||||
TCXState *s = opaque;
|
TCXState *s = opaque;
|
||||||
uint32_t saddr;
|
uint32_t saddr;
|
||||||
unsigned int x, y;
|
unsigned int x, y;
|
||||||
char *sptr;
|
|
||||||
|
|
||||||
saddr = addr - PHYS_JJ_TCX_FB - YOFF*MAXX - XOFF;
|
saddr = addr - s->addr - YOFF*MAXX - XOFF;
|
||||||
y = saddr / MAXX;
|
y = saddr / MAXX;
|
||||||
x = saddr - y * MAXX;
|
x = saddr - y * MAXX;
|
||||||
if (x < MAXX && y < MAXY) {
|
if (x < XSZ && y < YSZ) {
|
||||||
sptr = s->ds->data;
|
return s->vram[y * XSZ + x];
|
||||||
if (sptr)
|
|
||||||
return sptr[y * s->ds->linesize + x*4];
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -99,7 +90,6 @@ static uint32_t tcx_mem_readl(void *opaque, target_phys_addr_t addr)
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* called for accesses between 0xa0000 and 0xc0000 */
|
|
||||||
static void tcx_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
|
static void tcx_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
|
||||||
{
|
{
|
||||||
TCXState *s = opaque;
|
TCXState *s = opaque;
|
||||||
|
@ -107,17 +97,24 @@ static void tcx_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
|
||||||
unsigned int x, y;
|
unsigned int x, y;
|
||||||
char *sptr;
|
char *sptr;
|
||||||
|
|
||||||
saddr = addr - PHYS_JJ_TCX_FB - YOFF*MAXX - XOFF;
|
saddr = addr - s->addr - YOFF*MAXX - XOFF;
|
||||||
y = saddr / MAXX;
|
y = saddr / MAXX;
|
||||||
x = saddr - y * MAXX;
|
x = saddr - y * MAXX;
|
||||||
if (x < MAXX && y < MAXY) {
|
if (x < XSZ && y < YSZ) {
|
||||||
sptr = s->ds->data;
|
sptr = s->ds->data;
|
||||||
if (sptr) {
|
if (sptr) {
|
||||||
sptr[y * s->ds->linesize + x*4] = val;
|
if (s->ds->depth == 24 || s->ds->depth == 32) {
|
||||||
sptr[y * s->ds->linesize + x*4+1] = val;
|
/* XXX need to do CLUT translation */
|
||||||
sptr[y * s->ds->linesize + x*4+2] = val;
|
sptr[y * s->ds->linesize + x*4] = val & 0xff;
|
||||||
cpu_physical_memory_set_dirty(addr);
|
sptr[y * s->ds->linesize + x*4+1] = val & 0xff;
|
||||||
|
sptr[y * s->ds->linesize + x*4+2] = val & 0xff;
|
||||||
}
|
}
|
||||||
|
else if (s->ds->depth == 8) {
|
||||||
|
sptr[y * s->ds->linesize + x] = val & 0xff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cpu_physical_memory_set_dirty(addr);
|
||||||
|
s->vram[y * XSZ + x] = val & 0xff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,18 +156,52 @@ static CPUWriteMemoryFunc *tcx_mem_write[3] = {
|
||||||
tcx_mem_writel,
|
tcx_mem_writel,
|
||||||
};
|
};
|
||||||
|
|
||||||
void tcx_init(DisplayState *ds)
|
void tcx_init(DisplayState *ds, uint32_t addr)
|
||||||
{
|
{
|
||||||
TCXState *s;
|
TCXState *s;
|
||||||
|
int tcx_io_memory;
|
||||||
|
|
||||||
s = qemu_mallocz(sizeof(TCXState));
|
s = qemu_mallocz(sizeof(TCXState));
|
||||||
if (!s)
|
if (!s)
|
||||||
return;
|
return;
|
||||||
s->ds = ds;
|
s->ds = ds;
|
||||||
|
s->addr = addr;
|
||||||
ts = s;
|
ts = s;
|
||||||
tcx_io_memory = cpu_register_io_memory(0, tcx_mem_read, tcx_mem_write, s);
|
tcx_io_memory = cpu_register_io_memory(0, tcx_mem_read, tcx_mem_write, s);
|
||||||
cpu_register_physical_memory(PHYS_JJ_TCX_FB, 0x100000,
|
cpu_register_physical_memory(addr, 0x100000,
|
||||||
tcx_io_memory);
|
tcx_io_memory);
|
||||||
|
s->vram = qemu_mallocz(XSZ*YSZ);
|
||||||
dpy_resize(s->ds, XSZ, YSZ);
|
dpy_resize(s->ds, XSZ, YSZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vga_screen_dump(const char *filename)
|
||||||
|
{
|
||||||
|
TCXState *s = ts;
|
||||||
|
FILE *f;
|
||||||
|
uint8_t *d, *d1;
|
||||||
|
unsigned int v;
|
||||||
|
int y, x;
|
||||||
|
|
||||||
|
f = fopen(filename, "wb");
|
||||||
|
if (!f)
|
||||||
|
return -1;
|
||||||
|
fprintf(f, "P6\n%d %d\n%d\n",
|
||||||
|
XSZ, YSZ, 255);
|
||||||
|
d1 = s->vram;
|
||||||
|
for(y = 0; y < YSZ; y++) {
|
||||||
|
d = d1;
|
||||||
|
for(x = 0; x < XSZ; x++) {
|
||||||
|
v = *d;
|
||||||
|
fputc((v) & 0xff, f);
|
||||||
|
fputc((v) & 0xff, f);
|
||||||
|
fputc((v) & 0xff, f);
|
||||||
|
d++;
|
||||||
|
}
|
||||||
|
d1 += XSZ;
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -952,11 +952,7 @@ static int monitor_get_tbl (struct MonitorDef *md, int val)
|
||||||
#if defined(TARGET_SPARC)
|
#if defined(TARGET_SPARC)
|
||||||
static int monitor_get_psr (struct MonitorDef *md, int val)
|
static int monitor_get_psr (struct MonitorDef *md, int val)
|
||||||
{
|
{
|
||||||
return (0<<28) | (4<<24) | cpu_single_env->psr \
|
return GET_PSR(cpu_single_env);
|
||||||
| (cpu_single_env->psrs? PSR_S : 0) \
|
|
||||||
| (cpu_single_env->psrs? PSR_PS : 0) \
|
|
||||||
| (cpu_single_env->psret? PSR_ET : 0) \
|
|
||||||
| cpu_single_env->cwp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int monitor_get_reg(struct MonitorDef *md, int val)
|
static int monitor_get_reg(struct MonitorDef *md, int val)
|
||||||
|
|
|
@ -6,3 +6,8 @@
|
||||||
|
|
||||||
- The PowerPC Open Hack'Ware Open Firmware Compatible BIOS is
|
- The PowerPC Open Hack'Ware Open Firmware Compatible BIOS is
|
||||||
available at http://site.voila.fr/jmayer/OpenHackWare/index.htm.
|
available at http://site.voila.fr/jmayer/OpenHackWare/index.htm.
|
||||||
|
|
||||||
|
- Proll is a GPL'd boot PROM for Sparc JavaStations
|
||||||
|
(http://people.redhat.com/zaitcev/linux/).
|
||||||
|
Applying proll.patch allows circumventing some bugs and enables
|
||||||
|
faster kernel load through a hack.
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,50 @@
|
||||||
|
diff -ru proll_18.orig/mrcoffee/main.c proll_18/mrcoffee/main.c
|
||||||
|
--- proll_18.orig/mrcoffee/main.c 2002-09-13 16:16:59.000000000 +0200
|
||||||
|
+++ proll_18/mrcoffee/main.c 2004-09-26 11:52:23.000000000 +0200
|
||||||
|
@@ -101,6 +101,7 @@
|
||||||
|
le_probe();
|
||||||
|
init_net();
|
||||||
|
|
||||||
|
+#ifdef ORIG
|
||||||
|
#if 0 /* RARP */
|
||||||
|
if (rarp() != 0) fatal();
|
||||||
|
/* printrarp(); */
|
||||||
|
@@ -117,13 +118,20 @@
|
||||||
|
xtoa(myipaddr, fname, 8);
|
||||||
|
if (load(boot_rec.bp_siaddr, fname) != 0) fatal();
|
||||||
|
#endif
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
romvec = init_openprom(bb.nbanks, bb.bankv, hiphybas);
|
||||||
|
|
||||||
|
printk("Memory used: virt 0x%x:0x%x[%dK] iomap 0x%x:0x%x\n",
|
||||||
|
PROLBASE, (int)cmem.curp, ((unsigned) cmem.curp - PROLBASE)/1024,
|
||||||
|
(int)cio.start, (int)cio.curp);
|
||||||
|
+#ifdef ORIG
|
||||||
|
set_timeout(5); while (!chk_timeout()) { } /* P3: let me read */
|
||||||
|
+#else
|
||||||
|
+ printk("loading kernel:");
|
||||||
|
+ i = ld_bypass(0x20000000);
|
||||||
|
+ printk(" done, size %d\n", i);
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
{
|
||||||
|
void (*entry)(void *, int) = (void (*)(void*, int)) LOADBASE;
|
||||||
|
diff -ru proll_18.orig/mrcoffee/openprom.c proll_18/mrcoffee/openprom.c
|
||||||
|
--- proll_18.orig/mrcoffee/openprom.c 2002-09-13 16:17:03.000000000 +0200
|
||||||
|
+++ proll_18/mrcoffee/openprom.c 2004-09-21 21:27:16.000000000 +0200
|
||||||
|
@@ -144,10 +144,14 @@
|
||||||
|
};
|
||||||
|
|
||||||
|
static int cpu_nctx = NCTX_SWIFT;
|
||||||
|
+static int cpu_cache_line_size = 0x20;
|
||||||
|
+static int cpu_cache_nlines = 0x200;
|
||||||
|
static struct property propv_cpu[] = {
|
||||||
|
{"name", "STP1012PGA", sizeof("STP1012PGA") },
|
||||||
|
{"device_type", "cpu", 4 },
|
||||||
|
{"mmu-nctx", (char*)&cpu_nctx, sizeof(int)},
|
||||||
|
+ {"cache-line-size", (char*)&cpu_cache_line_size, sizeof(int)},
|
||||||
|
+ {"cache-nlines", (char*)&cpu_cache_nlines, sizeof(int)},
|
||||||
|
{NULL, NULL, -1}
|
||||||
|
};
|
||||||
|
|
|
@ -76,6 +76,7 @@
|
||||||
#define PTE_ENTRYTYPE_MASK 3
|
#define PTE_ENTRYTYPE_MASK 3
|
||||||
#define PTE_ACCESS_MASK 0x1c
|
#define PTE_ACCESS_MASK 0x1c
|
||||||
#define PTE_ACCESS_SHIFT 2
|
#define PTE_ACCESS_SHIFT 2
|
||||||
|
#define PTE_PPN_SHIFT 7
|
||||||
#define PTE_ADDR_MASK 0xffffff00
|
#define PTE_ADDR_MASK 0xffffff00
|
||||||
|
|
||||||
#define PG_ACCESSED_BIT 5
|
#define PG_ACCESSED_BIT 5
|
||||||
|
|
|
@ -23,13 +23,16 @@ void helper_flush(target_ulong addr);
|
||||||
void helper_ld_asi(int asi, int size, int sign);
|
void helper_ld_asi(int asi, int size, int sign);
|
||||||
void helper_st_asi(int asi, int size, int sign);
|
void helper_st_asi(int asi, int size, int sign);
|
||||||
void helper_rett(void);
|
void helper_rett(void);
|
||||||
void helper_stfsr(void);
|
void helper_ldfsr(void);
|
||||||
void set_cwp(int new_cwp);
|
void set_cwp(int new_cwp);
|
||||||
void do_fabss(void);
|
void do_fabss(void);
|
||||||
void do_fsqrts(void);
|
void do_fsqrts(void);
|
||||||
void do_fsqrtd(void);
|
void do_fsqrtd(void);
|
||||||
void do_fcmps(void);
|
void do_fcmps(void);
|
||||||
void do_fcmpd(void);
|
void do_fcmpd(void);
|
||||||
|
void do_ldd_kernel(uint32_t addr);
|
||||||
|
void do_ldd_user(uint32_t addr);
|
||||||
|
void do_ldd_raw(uint32_t addr);
|
||||||
void do_interrupt(int intno, int is_int, int error_code,
|
void do_interrupt(int intno, int is_int, int error_code,
|
||||||
unsigned int next_eip, int is_hw);
|
unsigned int next_eip, int is_hw);
|
||||||
void raise_exception_err(int exception_index, int error_code);
|
void raise_exception_err(int exception_index, int error_code);
|
||||||
|
|
|
@ -21,19 +21,10 @@
|
||||||
|
|
||||||
#define DEBUG_PCALL
|
#define DEBUG_PCALL
|
||||||
|
|
||||||
#if 0
|
|
||||||
#define raise_exception_err(a, b)\
|
|
||||||
do {\
|
|
||||||
fprintf(logfile, "raise_exception line=%d\n", __LINE__);\
|
|
||||||
(raise_exception_err)(a, b);\
|
|
||||||
} while (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Sparc MMU emulation */
|
/* Sparc MMU emulation */
|
||||||
int cpu_sparc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
|
int cpu_sparc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
|
||||||
int is_user, int is_softmmu);
|
int is_user, int is_softmmu);
|
||||||
|
|
||||||
|
|
||||||
/* thread support */
|
/* thread support */
|
||||||
|
|
||||||
spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
|
spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
|
||||||
|
@ -48,15 +39,6 @@ void cpu_unlock(void)
|
||||||
spin_unlock(&global_cpu_lock);
|
spin_unlock(&global_cpu_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
void cpu_loop_exit(void)
|
|
||||||
{
|
|
||||||
/* NOTE: the register at this point must be saved by hand because
|
|
||||||
longjmp restore them */
|
|
||||||
longjmp(env->jmp_env, 1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(CONFIG_USER_ONLY)
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
|
|
||||||
#define MMUSUFFIX _mmu
|
#define MMUSUFFIX _mmu
|
||||||
|
@ -258,7 +240,7 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
|
||||||
env->mmuregs[3] |= (access_index << 5) | (error_code << 2) | 2;
|
env->mmuregs[3] |= (access_index << 5) | (error_code << 2) | 2;
|
||||||
env->mmuregs[4] = address; /* Fault address register */
|
env->mmuregs[4] = address; /* Fault address register */
|
||||||
|
|
||||||
if (env->mmuregs[0] & MMU_NF) // No fault
|
if (env->mmuregs[0] & MMU_NF || env->psret == 0) // No fault
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
env->exception_index = exception;
|
env->exception_index = exception;
|
||||||
|
@ -306,7 +288,7 @@ void do_interrupt(int intno, int is_int, int error_code,
|
||||||
fprintf(logfile, "%6d: v=%02x e=%04x i=%d pc=%08x npc=%08x SP=%08x\n",
|
fprintf(logfile, "%6d: v=%02x e=%04x i=%d pc=%08x npc=%08x SP=%08x\n",
|
||||||
count, intno, error_code, is_int,
|
count, intno, error_code, is_int,
|
||||||
env->pc,
|
env->pc,
|
||||||
env->npc, env->gregs[7]);
|
env->npc, env->regwptr[6]);
|
||||||
#if 0
|
#if 0
|
||||||
cpu_sparc_dump_state(env, logfile, 0);
|
cpu_sparc_dump_state(env, logfile, 0);
|
||||||
{
|
{
|
||||||
|
|
|
@ -474,92 +474,6 @@ void OPPROTO op_sra(void)
|
||||||
T0 = ((int32_t) T0) >> T1;
|
T0 = ((int32_t) T0) >> T1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
void OPPROTO op_st(void)
|
|
||||||
{
|
|
||||||
stl((void *) T0, T1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_stb(void)
|
|
||||||
{
|
|
||||||
stb((void *) T0, T1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_sth(void)
|
|
||||||
{
|
|
||||||
stw((void *) T0, T1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_std(void)
|
|
||||||
{
|
|
||||||
stl((void *) T0, T1);
|
|
||||||
stl((void *) (T0 + 4), T2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_ld(void)
|
|
||||||
{
|
|
||||||
T1 = ldl((void *) T0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_ldub(void)
|
|
||||||
{
|
|
||||||
T1 = ldub((void *) T0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_lduh(void)
|
|
||||||
{
|
|
||||||
T1 = lduw((void *) T0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_ldsb(void)
|
|
||||||
{
|
|
||||||
T1 = ldsb((void *) T0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_ldsh(void)
|
|
||||||
{
|
|
||||||
T1 = ldsw((void *) T0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_ldstub(void)
|
|
||||||
{
|
|
||||||
T1 = ldub((void *) T0);
|
|
||||||
stb((void *) T0, 0xff); /* XXX: Should be Atomically */
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_swap(void)
|
|
||||||
{
|
|
||||||
unsigned int tmp = ldl((void *) T0);
|
|
||||||
stl((void *) T0, T1); /* XXX: Should be Atomically */
|
|
||||||
T1 = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_ldd(void)
|
|
||||||
{
|
|
||||||
T1 = ldl((void *) T0);
|
|
||||||
T0 = ldl((void *) (T0 + 4));
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_stf(void)
|
|
||||||
{
|
|
||||||
stfl((void *) T0, FT0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_stdf(void)
|
|
||||||
{
|
|
||||||
stfq((void *) T0, DT0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_ldf(void)
|
|
||||||
{
|
|
||||||
FT0 = ldfl((void *) T0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_lddf(void)
|
|
||||||
{
|
|
||||||
DT0 = ldfq((void *) T0);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
/* Load and store */
|
/* Load and store */
|
||||||
#define MEMSUFFIX _raw
|
#define MEMSUFFIX _raw
|
||||||
#include "op_mem.h"
|
#include "op_mem.h"
|
||||||
|
@ -570,19 +484,16 @@ void OPPROTO op_lddf(void)
|
||||||
#define MEMSUFFIX _kernel
|
#define MEMSUFFIX _kernel
|
||||||
#include "op_mem.h"
|
#include "op_mem.h"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
void OPPROTO op_ldfsr(void)
|
void OPPROTO op_ldfsr(void)
|
||||||
{
|
{
|
||||||
env->fsr = *((uint32_t *) &FT0);
|
env->fsr = *((uint32_t *) &FT0);
|
||||||
FORCE_RET();
|
helper_ldfsr();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OPPROTO op_stfsr(void)
|
void OPPROTO op_stfsr(void)
|
||||||
{
|
{
|
||||||
*((uint32_t *) &FT0) = env->fsr;
|
*((uint32_t *) &FT0) = env->fsr;
|
||||||
helper_stfsr();
|
|
||||||
FORCE_RET();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OPPROTO op_wry(void)
|
void OPPROTO op_wry(void)
|
||||||
|
@ -609,16 +520,17 @@ void OPPROTO op_wrwim(void)
|
||||||
void OPPROTO op_rdpsr(void)
|
void OPPROTO op_rdpsr(void)
|
||||||
{
|
{
|
||||||
T0 = GET_PSR(env);
|
T0 = GET_PSR(env);
|
||||||
FORCE_RET();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OPPROTO op_wrpsr(void)
|
void OPPROTO op_wrpsr(void)
|
||||||
{
|
{
|
||||||
|
int cwp;
|
||||||
env->psr = T0 & ~PSR_ICC;
|
env->psr = T0 & ~PSR_ICC;
|
||||||
env->psrs = (T0 & PSR_S)? 1 : 0;
|
env->psrs = (T0 & PSR_S)? 1 : 0;
|
||||||
env->psrps = (T0 & PSR_PS)? 1 : 0;
|
env->psrps = (T0 & PSR_PS)? 1 : 0;
|
||||||
env->psret = (T0 & PSR_ET)? 1 : 0;
|
env->psret = (T0 & PSR_ET)? 1 : 0;
|
||||||
env->cwp = (T0 & PSR_CWP);
|
cwp = (T0 & PSR_CWP) & (NWINDOWS - 1);
|
||||||
|
set_cwp(cwp);
|
||||||
FORCE_RET();
|
FORCE_RET();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,27 @@ void OPPROTO helper_st_asi(int asi, int size, int sign)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
void do_ldd_raw(uint32_t addr)
|
||||||
|
{
|
||||||
|
T1 = ldl_raw((void *) addr);
|
||||||
|
T0 = ldl_raw((void *) (addr + 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
|
void do_ldd_user(uint32_t addr)
|
||||||
|
{
|
||||||
|
T1 = ldl_user((void *) addr);
|
||||||
|
T0 = ldl_user((void *) (addr + 4));
|
||||||
|
}
|
||||||
|
void do_ldd_kernel(uint32_t addr)
|
||||||
|
{
|
||||||
|
T1 = ldl_kernel((void *) addr);
|
||||||
|
T0 = ldl_kernel((void *) (addr + 4));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
void OPPROTO helper_rett()
|
void OPPROTO helper_rett()
|
||||||
{
|
{
|
||||||
int cwp;
|
int cwp;
|
||||||
|
@ -116,7 +137,7 @@ void OPPROTO helper_rett()
|
||||||
env->psrs = env->psrps;
|
env->psrs = env->psrps;
|
||||||
}
|
}
|
||||||
|
|
||||||
void helper_stfsr(void)
|
void helper_ldfsr(void)
|
||||||
{
|
{
|
||||||
switch (env->fsr & FSR_RD_MASK) {
|
switch (env->fsr & FSR_RD_MASK) {
|
||||||
case FSR_RD_NEAREST:
|
case FSR_RD_NEAREST:
|
||||||
|
|
|
@ -43,8 +43,12 @@ void OPPROTO glue(op_swap, MEMSUFFIX)(void)
|
||||||
|
|
||||||
void OPPROTO glue(op_ldd, MEMSUFFIX)(void)
|
void OPPROTO glue(op_ldd, MEMSUFFIX)(void)
|
||||||
{
|
{
|
||||||
|
#if 1
|
||||||
T1 = glue(ldl, MEMSUFFIX)((void *) T0);
|
T1 = glue(ldl, MEMSUFFIX)((void *) T0);
|
||||||
T0 = glue(ldl, MEMSUFFIX)((void *) (T0 + 4));
|
T0 = glue(ldl, MEMSUFFIX)((void *) (T0 + 4));
|
||||||
|
#else
|
||||||
|
glue(do_ldd, MEMSUFFIX)(T0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** Floating-point store ***/
|
/*** Floating-point store ***/
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
include ../config-host.mak
|
-include ../config-host.mak
|
||||||
|
|
||||||
CFLAGS=-Wall -O2 -g
|
CFLAGS=-Wall -O2 -g
|
||||||
LDFLAGS=
|
LDFLAGS=
|
||||||
|
|
11
vl.h
11
vl.h
|
@ -673,20 +673,23 @@ void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
|
||||||
const char *initrd_filename);
|
const char *initrd_filename);
|
||||||
|
|
||||||
/* iommu.c */
|
/* iommu.c */
|
||||||
void iommu_init();
|
void iommu_init(uint32_t addr);
|
||||||
uint32_t iommu_translate(uint32_t addr);
|
uint32_t iommu_translate(uint32_t addr);
|
||||||
|
|
||||||
/* lance.c */
|
/* lance.c */
|
||||||
void lance_init(NetDriverState *nd, int irq);
|
void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr);
|
||||||
|
|
||||||
/* tcx.c */
|
/* tcx.c */
|
||||||
void tcx_init(DisplayState *ds);
|
void tcx_init(DisplayState *ds, uint32_t addr);
|
||||||
|
|
||||||
/* sched.c */
|
/* sched.c */
|
||||||
void sched_init();
|
void sched_init();
|
||||||
|
|
||||||
/* magic-load.c */
|
/* magic-load.c */
|
||||||
void magic_init(const char *kfn, int kloadaddr);
|
void magic_init(const char *kfn, int kloadaddr, uint32_t addr);
|
||||||
|
|
||||||
|
/* timer.c */
|
||||||
|
void timer_init(uint32_t addr, int irq);
|
||||||
|
|
||||||
/* NVRAM helpers */
|
/* NVRAM helpers */
|
||||||
#include "hw/m48t59.h"
|
#include "hw/m48t59.h"
|
||||||
|
|
Loading…
Reference in New Issue