SPARC merge
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 19 Dec 2004 23:18:01 +0000 (23:18 +0000)
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 19 Dec 2004 23:18:01 +0000 (23:18 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1179 c046a42c-6fe2-441c-8c8c-71466251a162

37 files changed:
Makefile
Makefile.target
cpu-exec.c
disas.c
disas.h
gdbstub.c
hw/fdc.c
hw/iommu.c
hw/lance.c
hw/m48t08.c
hw/m48t08.h
hw/magic-load.c
hw/sched.c [deleted file]
hw/slavio_intctl.c [new file with mode: 0644]
hw/slavio_serial.c [new file with mode: 0644]
hw/slavio_timer.c [new file with mode: 0644]
hw/sun4m.c
hw/tcx.c
hw/timer.c [deleted file]
linux-user/elfload.c
linux-user/main.c
linux-user/signal.c
pc-bios/proll.bin [deleted file]
pc-bios/proll.elf [new file with mode: 0644]
pc-bios/proll.patch
qemu-doc.texi
qemu-tech.texi
target-sparc/cpu.h
target-sparc/exec.h
target-sparc/fop_template.h
target-sparc/helper.c
target-sparc/op.c
target-sparc/op_helper.c
target-sparc/op_mem.h
target-sparc/translate.c
vl.c
vl.h

index 3659819fbe9254fd03e80c4a111a291b366ce7f6..3cf7e504cd372b04a44cb0764be8c9f285b87926 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -50,7 +50,7 @@ install: all
        install -m 644 pc-bios/bios.bin pc-bios/vgabios.bin \
                        pc-bios/vgabios-cirrus.bin \
                        pc-bios/ppc_rom.bin \
-                       pc-bios/proll.bin \
+                       pc-bios/proll.elf \
                        pc-bios/linux_boot.bin "$(datadir)"
        mkdir -p "$(docdir)"
        install -m 644 qemu-doc.html  qemu-tech.html "$(docdir)"
@@ -107,7 +107,7 @@ tarbin:
        $(datadir)/vgabios.bin \
        $(datadir)/vgabios-cirrus.bin \
        $(datadir)/ppc_rom.bin \
-       $(datadir)/proll.bin \
+       $(datadir)/proll.elf \
        $(datadir)/linux_boot.bin \
        $(docdir)/qemu-doc.html \
        $(docdir)/qemu-tech.html \
index a5c697ddc98ac0e253b8926507af760584041a9c..edf76cffbe89fa788b1edae632189a6f742f6bc6 100644 (file)
@@ -175,6 +175,7 @@ endif
 
 ifeq ($(CONFIG_DARWIN),yes)
 OP_CFLAGS+= -mdynamic-no-pic
+LIBS+=-lmx
 endif
 
 #########################################################
@@ -300,7 +301,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 mixeng.o
 endif
 ifeq ($(TARGET_ARCH), sparc)
-VL_OBJS+= sun4m.o tcx.o lance.o iommu.o sched.o m48t08.o magic-load.o timer.o
+VL_OBJS+= sun4m.o tcx.o lance.o iommu.o m48t08.o magic-load.o slavio_intctl.o slavio_timer.o slavio_serial.o fdc.o
 endif
 ifdef CONFIG_GDBSTUB
 VL_OBJS+=gdbstub.o 
index b98c22c58e857661186ad2e860529dae6c9ccc3b..cc6324ca107f8043dc9923c95e19e3ffc8f2af7c 100644 (file)
@@ -261,7 +261,7 @@ int cpu_exec(CPUState *env1)
                     }
 #elif defined(TARGET_SPARC)
                     if (interrupt_request & CPU_INTERRUPT_HARD) {
-                       do_interrupt(0, 0, 0, 0, 0);
+                       do_interrupt(env->interrupt_index, 0, 0, 0, 0);
                         env->interrupt_request &= ~CPU_INTERRUPT_HARD;
                    } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
                        //do_interrupt(0, 0, 0, 0, 0);
diff --git a/disas.c b/disas.c
index 86f29d24580a4d0ade69454f09c73a7fcb9a94bc..bfab8c3bb76e6c23006232d0f86aa96739b343c6 100644 (file)
--- a/disas.c
+++ b/disas.c
@@ -9,9 +9,7 @@
 #include "disas.h"
 
 /* Filled in by elfload.c.  Simplistic, but will do for now. */
-unsigned int disas_num_syms;
-void *disas_symtab;
-const char *disas_strtab;
+struct syminfo *syminfos = NULL;
 
 /* Get LENGTH bytes from info's buffer, at target address memaddr.
    Transfer them to myaddr.  */
@@ -203,19 +201,23 @@ const char *lookup_symbol(void *orig_addr)
 {
     unsigned int i;
     /* Hack, because we know this is x86. */
-    Elf32_Sym *sym = disas_symtab;
-
-    for (i = 0; i < disas_num_syms; i++) {
-       if (sym[i].st_shndx == SHN_UNDEF
-           || sym[i].st_shndx >= SHN_LORESERVE)
-           continue;
-
-       if (ELF_ST_TYPE(sym[i].st_info) != STT_FUNC)
-           continue;
-
-       if ((long)orig_addr >= sym[i].st_value
-           && (long)orig_addr < sym[i].st_value + sym[i].st_size)
-           return disas_strtab + sym[i].st_name;
+    Elf32_Sym *sym;
+    struct syminfo *s;
+    
+    for (s = syminfos; s; s = s->next) {
+       sym = s->disas_symtab;
+       for (i = 0; i < s->disas_num_syms; i++) {
+           if (sym[i].st_shndx == SHN_UNDEF
+               || sym[i].st_shndx >= SHN_LORESERVE)
+               continue;
+
+           if (ELF_ST_TYPE(sym[i].st_info) != STT_FUNC)
+               continue;
+
+           if ((long)orig_addr >= sym[i].st_value
+               && (long)orig_addr < sym[i].st_value + sym[i].st_size)
+               return s->disas_strtab + sym[i].st_name;
+       }
     }
     return "";
 }
diff --git a/disas.h b/disas.h
index c4a251ff8f0c2b7a9b42d9ce04962eb75c8019e0..5d383faab6ddaa1416746ef093bb6ba1cb4e570b 100644 (file)
--- a/disas.h
+++ b/disas.h
@@ -9,7 +9,11 @@ void monitor_disas(target_ulong pc, int nb_insn, int is_physical, int flags);
 const char *lookup_symbol(void *orig_addr);
 
 /* Filled in by elfload.c.  Simplistic, but will do for now. */
-extern unsigned int disas_num_syms;
-extern void *disas_symtab;  /* FIXME: includes are a mess --RR */
-extern const char *disas_strtab;
+extern struct syminfo {
+    unsigned int disas_num_syms;
+    void *disas_symtab;
+    const char *disas_strtab;
+    struct syminfo *next;
+} *syminfos;
+
 #endif /* _QEMU_DISAS_H */
index 2491c2cd772d6a3ca8d59b588a5dd0b38566f317..e2c8b2dfa8691c2cdc9c5512908dc733e6013b79 100644 (file)
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -298,11 +298,7 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
     }
     /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
     registers[64] = tswapl(env->y);
-    tmp = (0<<28) | (4<<24) | env->psr         \
-       | (env->psrs? PSR_S : 0)                \
-       | (env->psrs? PSR_PS : 0)               \
-       | (env->psret? PSR_ET : 0)              \
-       | env->cwp;
+    tmp = GET_PSR(env);
     registers[65] = tswapl(tmp);
     registers[66] = tswapl(env->wim);
     registers[67] = tswapl(env->tbr);
@@ -317,7 +313,7 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
 
 static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
 {
-    uint32_t *registers = (uint32_t *)mem_buf, tmp;
+    uint32_t *registers = (uint32_t *)mem_buf;
     int i;
 
     /* fill in g0..g7 */
@@ -334,12 +330,7 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
     }
     /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
     env->y = tswapl(registers[64]);
-    tmp = tswapl(registers[65]);
-    env->psr = tmp & ~PSR_ICC;
-    env->psrs = (tmp & PSR_S)? 1 : 0;
-    env->psrps = (tmp & PSR_PS)? 1 : 0;
-    env->psret = (tmp & PSR_ET)? 1 : 0;
-    env->cwp = (tmp & PSR_CWP);
+    PUT_PSR(env, tswapl(registers[65]));
     env->wim = tswapl(registers[66]);
     env->tbr = tswapl(registers[67]);
     env->pc = tswapl(registers[68]);
@@ -495,8 +486,10 @@ static void gdb_vm_stopped(void *opaque, int reason)
     /* disable single step if it was enable */
     cpu_single_step(cpu_single_env, 0);
 
-    if (reason == EXCP_DEBUG)
+    if (reason == EXCP_DEBUG) {
+       tb_flush(cpu_single_env);
         ret = SIGTRAP;
+    }
     else
         ret = 0;
     snprintf(buf, sizeof(buf), "S%02x", ret);
index d512b1ca98bbca5e6846712b4b881b19caaa4bfe..ee07328481b5423989f4434305fd9b7a146f6911 100644 (file)
--- a/hw/fdc.c
+++ b/hw/fdc.c
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+/*
+ * The controller is used in Sun4m systems in a slightly different
+ * way. There are changes in DOR register and DMA is not available.
+ */
 #include "vl.h"
 
 /********************************************************/
@@ -90,6 +94,16 @@ typedef struct fdrive_t {
     uint8_t ro;               /* Is read-only           */
 } fdrive_t;
 
+#ifdef TARGET_SPARC
+#define DMA_read_memory(a,b,c,d)
+#define DMA_write_memory(a,b,c,d)
+#define DMA_register_channel(a,b,c)
+#define DMA_hold_DREQ(a)
+#define DMA_release_DREQ(a)
+#define DMA_get_channel_mode(a) (0)
+#define DMA_schedule(a)
+#endif
+
 static void fd_init (fdrive_t *drv, BlockDriverState *bs)
 {
     /* Drive */
@@ -455,6 +469,18 @@ static void fdctrl_write (void *opaque, uint32_t reg, uint32_t value)
     }
 }
 
+static CPUReadMemoryFunc *fdctrl_mem_read[3] = {
+    fdctrl_read,
+    fdctrl_read,
+    fdctrl_read,
+};
+
+static CPUWriteMemoryFunc *fdctrl_mem_write[3] = {
+    fdctrl_write,
+    fdctrl_write,
+    fdctrl_write,
+};
+
 static void fd_change_cb (void *opaque)
 {
     fdrive_t *drv = opaque;
@@ -473,7 +499,7 @@ fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped,
                        BlockDriverState **fds)
 {
     fdctrl_t *fdctrl;
-//    int io_mem;
+    int io_mem;
     int i;
 
     FLOPPY_DPRINTF("init controller\n");
@@ -504,11 +530,8 @@ fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped,
     fdctrl_reset(fdctrl, 0);
     fdctrl->state = FD_CTRL_ACTIVE;
     if (mem_mapped) {
-        FLOPPY_ERROR("memory mapped floppy not supported by now !\n");
-#if 0
-        io_mem = cpu_register_io_memory(0, fdctrl_mem_read, fdctrl_mem_write);
-        cpu_register_physical_memory(base, 0x08, io_mem);
-#endif
+        io_mem = cpu_register_io_memory(0, fdctrl_mem_read, fdctrl_mem_write, fdctrl);
+        cpu_register_physical_memory(io_base, 0x08, io_mem);
     } else {
         register_ioport_read(io_base + 0x01, 5, 1, &fdctrl_read, fdctrl);
         register_ioport_read(io_base + 0x07, 1, 1, &fdctrl_read, fdctrl);
index a9249c4ba72a5c39ea508df0e3f09eecd2f96bc7..62927acd54e0e6303d277fac597b7c468dc02c7d 100644 (file)
@@ -117,8 +117,6 @@ typedef struct IOMMUState {
     uint32_t iostart;
 } IOMMUState;
 
-static IOMMUState *ps;
-
 static uint32_t iommu_mem_readw(void *opaque, target_phys_addr_t addr)
 {
     IOMMUState *s = opaque;
@@ -187,25 +185,61 @@ static CPUWriteMemoryFunc *iommu_mem_write[3] = {
     iommu_mem_writew,
 };
 
-uint32_t iommu_translate(uint32_t addr)
+uint32_t iommu_translate_local(void *opaque, uint32_t addr)
 {
-    uint32_t *iopte = (void *)(ps->regs[1] << 4), pa;
+    IOMMUState *s = opaque;
+    uint32_t *iopte = (void *)(s->regs[1] << 4), pa;
 
-    iopte += ((addr - ps->iostart) >> PAGE_SHIFT);
-    cpu_physical_memory_rw((uint32_t)iopte, (void *) &pa, 4, 0);
+    iopte += ((addr - s->iostart) >> PAGE_SHIFT);
+    cpu_physical_memory_read((uint32_t)iopte, (void *) &pa, 4);
     bswap32s(&pa);
     pa = (pa & IOPTE_PAGE) << 4;               /* Loose higher bits of 36 */
     return pa + (addr & PAGE_MASK);
 }
 
-void iommu_init(uint32_t addr)
+static void iommu_save(QEMUFile *f, void *opaque)
+{
+    IOMMUState *s = opaque;
+    int i;
+    
+    qemu_put_be32s(f, &s->addr);
+    for (i = 0; i < sizeof(struct iommu_regs); i += 4)
+       qemu_put_be32s(f, &s->regs[i]);
+    qemu_put_be32s(f, &s->iostart);
+}
+
+static int iommu_load(QEMUFile *f, void *opaque, int version_id)
+{
+    IOMMUState *s = opaque;
+    int i;
+    
+    if (version_id != 1)
+        return -EINVAL;
+
+    qemu_get_be32s(f, &s->addr);
+    for (i = 0; i < sizeof(struct iommu_regs); i += 4)
+       qemu_put_be32s(f, &s->regs[i]);
+    qemu_get_be32s(f, &s->iostart);
+
+    return 0;
+}
+
+static void iommu_reset(void *opaque)
+{
+    IOMMUState *s = opaque;
+
+    memset(s->regs, 0, sizeof(struct iommu_regs));
+    s->iostart = 0;
+}
+
+void *iommu_init(uint32_t addr)
 {
     IOMMUState *s;
     int iommu_io_memory;
 
     s = qemu_mallocz(sizeof(IOMMUState));
     if (!s)
-        return;
+        return NULL;
 
     s->addr = addr;
 
@@ -213,6 +247,8 @@ void iommu_init(uint32_t addr)
     cpu_register_physical_memory(addr, sizeof(struct iommu_regs),
                                  iommu_io_memory);
     
-    ps = s;
+    register_savevm("iommu", addr, 1, iommu_save, iommu_load, s);
+    qemu_register_reset(iommu_reset, s);
+    return s;
 }
 
index 25ad8c45b2a973607c7813dc6556934413f5e70c..c594c52e832de9ddd3ab7cd20ed528075b8a5301 100644 (file)
@@ -147,6 +147,7 @@ struct lance_init_block {
 };
 
 #define LEDMA_REGS 4
+#define LEDMA_MAXADDR (LEDMA_REGS * 4 - 1)
 #if 0
 /* Structure to describe the current status of DMA registers on the Sparc */
 struct sparc_dma_registers {
@@ -157,32 +158,28 @@ struct sparc_dma_registers {
 };
 #endif
 
-typedef struct LEDMAState {
-    uint32_t addr;
-    uint32_t regs[LEDMA_REGS];
-} LEDMAState;
-
 typedef struct LANCEState {
-    uint32_t paddr;
     NetDriverState *nd;
     uint32_t leptr;
     uint16_t addr;
     uint16_t regs[LE_MAXREG];
     uint8_t phys[6]; /* mac address */
     int irq;
-    LEDMAState *ledma;
+    unsigned int rxptr, txptr;
+    uint32_t ledmaregs[LEDMA_REGS];
 } LANCEState;
 
-static unsigned int rxptr, txptr;
-
 static void lance_send(void *opaque);
 
-static void lance_reset(LANCEState *s)
+static void lance_reset(void *opaque)
 {
+    LANCEState *s = opaque;
     memcpy(s->phys, s->nd->macaddr, 6);
-    rxptr = 0;
-    txptr = 0;
+    s->rxptr = 0;
+    s->txptr = 0;
+    memset(s->regs, 0, LE_MAXREG * 2);
     s->regs[LE_CSR0] = LE_C0_STOP;
+    memset(s->ledmaregs, 0, LEDMA_REGS * 4);
 }
 
 static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr)
@@ -190,7 +187,7 @@ static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr)
     LANCEState *s = opaque;
     uint32_t saddr;
 
-    saddr = addr - s->paddr;
+    saddr = addr & LE_MAXREG;
     switch (saddr >> 1) {
     case LE_RDP:
        return s->regs[s->addr];
@@ -208,7 +205,7 @@ static void lance_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val
     uint32_t saddr;
     uint16_t reg;
 
-    saddr = addr - s->paddr;
+    saddr = addr & LE_MAXREG;
     switch (saddr >> 1) {
     case LE_RDP:
        switch(s->addr) {
@@ -292,7 +289,7 @@ static CPUWriteMemoryFunc *lance_mem_write[3] = {
 static int lance_can_receive(void *opaque)
 {
     LANCEState *s = opaque;
-    void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
+    uint32_t dmaptr = s->leptr + s->ledmaregs[3];
     struct lance_init_block *ib;
     int i;
     uint16_t temp;
@@ -303,7 +300,7 @@ static int lance_can_receive(void *opaque)
     ib = (void *) iommu_translate(dmaptr);
 
     for (i = 0; i < RX_RING_SIZE; i++) {
-       cpu_physical_memory_read(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
+       cpu_physical_memory_read((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
        temp &= 0xff;
        if (temp == (LE_R1_OWN)) {
 #ifdef DEBUG_LANCE
@@ -323,7 +320,7 @@ static int lance_can_receive(void *opaque)
 static void lance_receive(void *opaque, const uint8_t *buf, int size)
 {
     LANCEState *s = opaque;
-    void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
+    uint32_t dmaptr = s->leptr + s->ledmaregs[3];
     struct lance_init_block *ib;
     unsigned int i, old_rxptr, j;
     uint16_t temp;
@@ -333,23 +330,23 @@ static void lance_receive(void *opaque, const uint8_t *buf, int size)
 
     ib = (void *) iommu_translate(dmaptr);
 
-    old_rxptr = rxptr;
-    for (i = rxptr; i != ((old_rxptr - 1) & RX_RING_MOD_MASK); i = (i + 1) & RX_RING_MOD_MASK) {
-       cpu_physical_memory_read(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
+    old_rxptr = s->rxptr;
+    for (i = s->rxptr; i != ((old_rxptr - 1) & RX_RING_MOD_MASK); i = (i + 1) & RX_RING_MOD_MASK) {
+       cpu_physical_memory_read((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
        if (temp == (LE_R1_OWN)) {
-           rxptr = (rxptr + 1) & RX_RING_MOD_MASK;
+           s->rxptr = (s->rxptr + 1) & RX_RING_MOD_MASK;
            temp = size;
            bswap16s(&temp);
-           cpu_physical_memory_write(&ib->brx_ring[i].mblength, (void *) &temp, 2);
+           cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].mblength, (void *) &temp, 2);
 #if 0
-           cpu_physical_memory_write(&ib->rx_buf[i], buf, size);
+           cpu_physical_memory_write((uint32_t)&ib->rx_buf[i], buf, size);
 #else
            for (j = 0; j < size; j++) {
-               cpu_physical_memory_write(((void *)&ib->rx_buf[i]) + j, &buf[j], 1);
+               cpu_physical_memory_write(((uint32_t)&ib->rx_buf[i]) + j, &buf[j], 1);
            }
 #endif
            temp = LE_R1_POK;
-           cpu_physical_memory_write(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
+           cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
            s->regs[LE_CSR0] |= LE_C0_RINT | LE_C0_INTR;
            if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA))
                pic_set_irq(s->irq, 1);
@@ -364,7 +361,7 @@ static void lance_receive(void *opaque, const uint8_t *buf, int size)
 static void lance_send(void *opaque)
 {
     LANCEState *s = opaque;
-    void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
+    uint32_t dmaptr = s->leptr + s->ledmaregs[3];
     struct lance_init_block *ib;
     unsigned int i, old_txptr, j;
     uint16_t temp;
@@ -375,18 +372,18 @@ static void lance_send(void *opaque)
 
     ib = (void *) iommu_translate(dmaptr);
 
-    old_txptr = txptr;
-    for (i = txptr; i != ((old_txptr - 1) & TX_RING_MOD_MASK); i = (i + 1) & TX_RING_MOD_MASK) {
-       cpu_physical_memory_read(&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1);
+    old_txptr = s->txptr;
+    for (i = s->txptr; i != ((old_txptr - 1) & TX_RING_MOD_MASK); i = (i + 1) & TX_RING_MOD_MASK) {
+       cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1);
        if (temp == (LE_T1_POK|LE_T1_OWN)) {
-           cpu_physical_memory_read(&ib->btx_ring[i].length, (void *) &temp, 2);
+           cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].length, (void *) &temp, 2);
            bswap16s(&temp);
            temp = (~temp) + 1;
 #if 0
-           cpu_physical_memory_read(&ib->tx_buf[i], pkt_buf, temp);
+           cpu_physical_memory_read((uint32_t)&ib->tx_buf[i], pkt_buf, temp);
 #else
            for (j = 0; j < temp; j++) {
-               cpu_physical_memory_read(((void *)&ib->tx_buf[i]) + j, &pkt_buf[j], 1);
+               cpu_physical_memory_read((uint32_t)&ib->tx_buf[i] + j, &pkt_buf[j], 1);
            }
 #endif
 
@@ -395,8 +392,8 @@ static void lance_send(void *opaque)
 #endif
            qemu_send_packet(s->nd, pkt_buf, temp);
            temp = LE_T1_POK;
-           cpu_physical_memory_write(&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1);
-           txptr = (txptr + 1) & TX_RING_MOD_MASK;
+           cpu_physical_memory_write((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1);
+           s->txptr = (s->txptr + 1) & TX_RING_MOD_MASK;
            s->regs[LE_CSR0] |= LE_C0_TINT | LE_C0_INTR;
        }
     }
@@ -404,24 +401,20 @@ static void lance_send(void *opaque)
 
 static uint32_t ledma_mem_readl(void *opaque, target_phys_addr_t addr)
 {
-    LEDMAState *s = opaque;
+    LANCEState *s = opaque;
     uint32_t saddr;
 
-    saddr = (addr - s->addr) >> 2;
-    if (saddr < LEDMA_REGS)
-       return s->regs[saddr];
-    else
-       return 0;
+    saddr = (addr & LEDMA_MAXADDR) >> 2;
+    return s->ledmaregs[saddr];
 }
 
 static void ledma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
 {
-    LEDMAState *s = opaque;
+    LANCEState *s = opaque;
     uint32_t saddr;
 
-    saddr = (addr - s->addr) >> 2;
-    if (saddr < LEDMA_REGS)
-       s->regs[saddr] = val;
+    saddr = (addr & LEDMA_MAXADDR) >> 2;
+    s->ledmaregs[saddr] = val;
 }
 
 static CPUReadMemoryFunc *ledma_mem_read[3] = {
@@ -436,33 +429,61 @@ static CPUWriteMemoryFunc *ledma_mem_write[3] = {
     ledma_mem_writel,
 };
 
+static void lance_save(QEMUFile *f, void *opaque)
+{
+    LANCEState *s = opaque;
+    int i;
+    
+    qemu_put_be32s(f, &s->leptr);
+    qemu_put_be16s(f, &s->addr);
+    for (i = 0; i < LE_MAXREG; i ++)
+       qemu_put_be16s(f, &s->regs[i]);
+    qemu_put_buffer(f, s->phys, 6);
+    qemu_put_be32s(f, &s->irq);
+    for (i = 0; i < LEDMA_REGS; i ++)
+       qemu_put_be32s(f, &s->ledmaregs[i]);
+}
+
+static int lance_load(QEMUFile *f, void *opaque, int version_id)
+{
+    LANCEState *s = opaque;
+    int i;
+    
+    if (version_id != 1)
+        return -EINVAL;
+
+    qemu_get_be32s(f, &s->leptr);
+    qemu_get_be16s(f, &s->addr);
+    for (i = 0; i < LE_MAXREG; i ++)
+       qemu_get_be16s(f, &s->regs[i]);
+    qemu_get_buffer(f, s->phys, 6);
+    qemu_get_be32s(f, &s->irq);
+    for (i = 0; i < LEDMA_REGS; i ++)
+       qemu_get_be32s(f, &s->ledmaregs[i]);
+    return 0;
+}
+
 void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr)
 {
     LANCEState *s;
-    LEDMAState *led;
     int lance_io_memory, ledma_io_memory;
 
     s = qemu_mallocz(sizeof(LANCEState));
     if (!s)
         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);
     cpu_register_physical_memory(leaddr, 8, lance_io_memory);
 
-    led = qemu_mallocz(sizeof(LEDMAState));
-    if (!led)
-        return;
-
-    s->ledma = led;
-    led->addr = ledaddr;
-    ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, led);
+    ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, s);
     cpu_register_physical_memory(ledaddr, 16, ledma_io_memory);
 
     lance_reset(s);
     qemu_add_read_packet(nd, lance_can_receive, lance_receive, s);
+    register_savevm("lance", leaddr, 1, lance_save, lance_load, s);
+    qemu_register_reset(lance_reset, s);
 }
 
index 46ec665570dc19f1afd11f9eb801971906f27011..0945879532d5a9fae172a7eccf067ab8c5f452ad 100644 (file)
 #define NVRAM_PRINTF(fmt, args...) do { } while (0)
 #endif
 
-#define NVRAM_MAX_MEM 0xfff0
+#define NVRAM_MAX_MEM 0x1ff0
+#define NVRAM_MAXADDR 0x1fff
 
 struct m48t08_t {
-    /* Hardware parameters */
-    int mem_index;
-    uint32_t mem_base;
-    uint16_t size;
     /* RTC management */
     time_t   time_offset;
     time_t   stop_time;
     /* NVRAM storage */
-    uint8_t  lock;
-    uint16_t addr;
     uint8_t *buffer;
 };
 
@@ -83,14 +78,13 @@ static void set_time (m48t08_t *NVRAM, struct tm *tm)
 }
 
 /* Direct access to NVRAM */
-void m48t08_write (m48t08_t *NVRAM, uint32_t val)
+void m48t08_write (m48t08_t *NVRAM, uint32_t addr, uint8_t val)
 {
     struct tm tm;
     int tmp;
 
-    if (NVRAM->addr > NVRAM_MAX_MEM && NVRAM->addr < 0x2000)
-       NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, NVRAM->addr, val);
-    switch (NVRAM->addr) {
+    addr &= NVRAM_MAXADDR;
+    switch (addr) {
     case 0x1FF8:
         /* control */
        NVRAM->buffer[0x1FF8] = (val & ~0xA0) | 0x90;
@@ -167,25 +161,18 @@ void m48t08_write (m48t08_t *NVRAM, uint32_t val)
        }
         break;
     default:
-        /* Check lock registers state */
-        if (NVRAM->addr >= 0x20 && NVRAM->addr <= 0x2F && (NVRAM->lock & 1))
-            break;
-        if (NVRAM->addr >= 0x30 && NVRAM->addr <= 0x3F && (NVRAM->lock & 2))
-            break;
-        if (NVRAM->addr < NVRAM_MAX_MEM ||
-           (NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) {
-            NVRAM->buffer[NVRAM->addr] = val & 0xFF;
-       }
+       NVRAM->buffer[addr] = val & 0xFF;
         break;
     }
 }
 
-uint32_t m48t08_read (m48t08_t *NVRAM)
+uint8_t m48t08_read (m48t08_t *NVRAM, uint32_t addr)
 {
     struct tm tm;
-    uint32_t retval = 0xFF;
+    uint8_t retval = 0xFF;
 
-    switch (NVRAM->addr) {
+    addr &= NVRAM_MAXADDR;
+    switch (addr) {
     case 0x1FF8:
         /* control */
        goto do_read;
@@ -225,65 +212,36 @@ uint32_t m48t08_read (m48t08_t *NVRAM)
         retval = toBCD(tm.tm_year);
         break;
     default:
-        /* Check lock registers state */
-        if (NVRAM->addr >= 0x20 && NVRAM->addr <= 0x2F && (NVRAM->lock & 1))
-            break;
-        if (NVRAM->addr >= 0x30 && NVRAM->addr <= 0x3F && (NVRAM->lock & 2))
-            break;
-        if (NVRAM->addr < NVRAM_MAX_MEM ||
-           (NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) {
-       do_read:
-            retval = NVRAM->buffer[NVRAM->addr];
-       }
+    do_read:
+       retval = NVRAM->buffer[addr];
         break;
     }
-    if (NVRAM->addr > NVRAM_MAX_MEM + 1 && NVRAM->addr < 0x2000)
-       NVRAM_PRINTF("0x%08x <= 0x%08x\n", NVRAM->addr, retval);
-
     return retval;
 }
 
-void m48t08_set_addr (m48t08_t *NVRAM, uint32_t addr)
-{
-    NVRAM->addr = addr;
-}
-
-void m48t08_toggle_lock (m48t08_t *NVRAM, int lock)
-{
-    NVRAM->lock ^= 1 << lock;
-}
-
 static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
 {
     m48t08_t *NVRAM = opaque;
     
-    addr -= NVRAM->mem_base;
-    if (addr < NVRAM_MAX_MEM)
-        NVRAM->buffer[addr] = value;
+    m48t08_write(NVRAM, addr, value);
 }
 
 static void nvram_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
 {
     m48t08_t *NVRAM = opaque;
     
-    addr -= NVRAM->mem_base;
-    if (addr < NVRAM_MAX_MEM) {
-        NVRAM->buffer[addr] = value >> 8;
-        NVRAM->buffer[addr + 1] = value;
-    }
+    m48t08_write(NVRAM, addr, value);
+    m48t08_write(NVRAM, addr + 1, value >> 8);
 }
 
 static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
 {
     m48t08_t *NVRAM = opaque;
     
-    addr -= NVRAM->mem_base;
-    if (addr < NVRAM_MAX_MEM) {
-        NVRAM->buffer[addr] = value >> 24;
-        NVRAM->buffer[addr + 1] = value >> 16;
-        NVRAM->buffer[addr + 2] = value >> 8;
-        NVRAM->buffer[addr + 3] = value;
-    }
+    m48t08_write(NVRAM, addr, value);
+    m48t08_write(NVRAM, addr + 1, value >> 8);
+    m48t08_write(NVRAM, addr + 2, value >> 16);
+    m48t08_write(NVRAM, addr + 3, value >> 24);
 }
 
 static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
@@ -291,10 +249,7 @@ static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
     m48t08_t *NVRAM = opaque;
     uint32_t retval = 0;
     
-    addr -= NVRAM->mem_base;
-    if (addr < NVRAM_MAX_MEM)
-        retval = NVRAM->buffer[addr];
-
+    retval = m48t08_read(NVRAM, addr);
     return retval;
 }
 
@@ -303,12 +258,8 @@ static uint32_t nvram_readw (void *opaque, target_phys_addr_t addr)
     m48t08_t *NVRAM = opaque;
     uint32_t retval = 0;
     
-    addr -= NVRAM->mem_base;
-    if (addr < NVRAM_MAX_MEM) {
-        retval = NVRAM->buffer[addr] << 8;
-        retval |= NVRAM->buffer[addr + 1];
-    }
-
+    retval = m48t08_read(NVRAM, addr) << 8;
+    retval |= m48t08_read(NVRAM, addr + 1);
     return retval;
 }
 
@@ -317,14 +268,10 @@ static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr)
     m48t08_t *NVRAM = opaque;
     uint32_t retval = 0;
     
-    addr -= NVRAM->mem_base;
-    if (addr < NVRAM_MAX_MEM) {
-        retval = NVRAM->buffer[addr] << 24;
-        retval |= NVRAM->buffer[addr + 1] << 16;
-        retval |= NVRAM->buffer[addr + 2] << 8;
-        retval |= NVRAM->buffer[addr + 3];
-    }
-
+    retval = m48t08_read(NVRAM, addr) << 24;
+    retval |= m48t08_read(NVRAM, addr + 1) << 16;
+    retval |= m48t08_read(NVRAM, addr + 2) << 8;
+    retval |= m48t08_read(NVRAM, addr + 3);
     return retval;
 }
 
@@ -340,12 +287,42 @@ static CPUReadMemoryFunc *nvram_read[] = {
     &nvram_readl,
 };
 
+static void nvram_save(QEMUFile *f, void *opaque)
+{
+    m48t08_t *s = opaque;
+    
+    qemu_put_be32s(f, (uint32_t *)&s->time_offset);
+    qemu_put_be32s(f, (uint32_t *)&s->stop_time);
+    qemu_put_buffer(f, s->buffer, 0x2000);
+}
+
+static int nvram_load(QEMUFile *f, void *opaque, int version_id)
+{
+    m48t08_t *s = opaque;
+    
+    if (version_id != 1)
+        return -EINVAL;
+
+    qemu_get_be32s(f, (uint32_t *)&s->time_offset);
+    qemu_get_be32s(f, (uint32_t *)&s->stop_time);
+    qemu_get_buffer(f, s->buffer, 0x2000);
+    return 0;
+}
+
+static void m48t08_reset(void *opaque)
+{
+    m48t08_t *s = opaque;
+
+    s->time_offset = 0;
+    s->stop_time = 0;
+}
+
+
 /* Initialisation routine */
-m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size, uint8_t *macaddr)
+m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size)
 {
     m48t08_t *s;
-    int i;
-    unsigned char tmp = 0;
+    int mem_index;
 
     s = qemu_mallocz(sizeof(m48t08_t));
     if (!s)
@@ -355,25 +332,13 @@ m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size, uint8_t *macaddr)
         qemu_free(s);
         return NULL;
     }
-    s->size = size;
-    s->mem_base = mem_base;
-    s->addr = 0;
     if (mem_base != 0) {
-        s->mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s);
-        cpu_register_physical_memory(mem_base, 0x4000, s->mem_index);
+        mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s);
+        cpu_register_physical_memory(mem_base, 0x2000, mem_index);
     }
-    s->lock = 0;
 
-    i = 0x1fd8;
-    s->buffer[i++] = 0x01;
-    s->buffer[i++] = 0x80; /* Sun4m OBP */
-    memcpy(&s->buffer[i], macaddr, 6);
-
-    /* Calculate checksum */
-    for (i = 0x1fd8; i < 0x1fe7; i++) {
-       tmp ^= s->buffer[i];
-    }
-    s->buffer[0x1fe7] = tmp;
+    register_savevm("nvram", mem_base, 1, nvram_save, nvram_load, s);
+    qemu_register_reset(m48t08_reset, s);
     return s;
 }
 
index 9b44bc0d160d27f979f9fc4a883ea0cce9c3bb7c..985116a0995ff692fe922462a597ba3b01ecfc30 100644 (file)
@@ -3,10 +3,8 @@
 
 typedef struct m48t08_t m48t08_t;
 
-void m48t08_write (m48t08_t *NVRAM, uint32_t val);
-uint32_t m48t08_read (m48t08_t *NVRAM);
-void m48t08_set_addr (m48t08_t *NVRAM, uint32_t addr);
-void m48t08_toggle_lock (m48t08_t *NVRAM, int lock);
-m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size, uint8_t *macaddr);
+void m48t08_write (m48t08_t *NVRAM, uint32_t addr, uint8_t val);
+uint8_t m48t08_read (m48t08_t *NVRAM, uint32_t addr);
+m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size);
 
 #endif /* !defined (__M48T08_H__) */
index 06a5f743af6f4c729c17f0ce92aad263f4ed105a..713343a75899121d90b81318b7ce7fb5965aadcd 100644 (file)
@@ -1,5 +1,54 @@
 #include "vl.h"
 #include "disas.h"
+#include "exec-all.h"
+
+struct exec
+{
+  uint32_t a_info;   /* Use macros N_MAGIC, etc for access */
+  uint32_t a_text;   /* length of text, in bytes */
+  uint32_t a_data;   /* length of data, in bytes */
+  uint32_t a_bss;    /* length of uninitialized data area, in bytes */
+  uint32_t a_syms;   /* length of symbol table data in file, in bytes */
+  uint32_t a_entry;  /* start address */
+  uint32_t a_trsize; /* length of relocation info for text, in bytes */
+  uint32_t a_drsize; /* length of relocation info for data, in bytes */
+};
+
+#ifdef BSWAP_NEEDED
+static void bswap_ahdr(struct exec *e)
+{
+    bswap32s(&e->a_info);
+    bswap32s(&e->a_text);
+    bswap32s(&e->a_data);
+    bswap32s(&e->a_bss);
+    bswap32s(&e->a_syms);
+    bswap32s(&e->a_entry);
+    bswap32s(&e->a_trsize);
+    bswap32s(&e->a_drsize);
+}
+#else
+#define bswap_ahdr(x) do { } while (0)
+#endif
+
+#define N_MAGIC(exec) ((exec).a_info & 0xffff)
+#define OMAGIC 0407
+#define NMAGIC 0410
+#define ZMAGIC 0413
+#define QMAGIC 0314
+#define _N_HDROFF(x) (1024 - sizeof (struct exec))
+#define N_TXTOFF(x)                                                    \
+    (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) :    \
+     (N_MAGIC(x) == QMAGIC ? 0 : sizeof (struct exec)))
+#define N_TXTADDR(x) (N_MAGIC(x) == QMAGIC ? TARGET_PAGE_SIZE : 0)
+#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
+#define _N_SEGMENT_ROUND(x) (((x) + TARGET_PAGE_SIZE - 1) & ~(TARGET_PAGE_SIZE - 1))
+
+#define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
+
+#define N_DATADDR(x) \
+    (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \
+     : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
+
 
 #define ELF_CLASS   ELFCLASS32
 #define ELF_DATA    ELFDATA2MSB
@@ -103,27 +152,27 @@ static void *find_shdr(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, uint3
     return NULL;
 }
 
-static int find_strtab(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
+static void *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;
+       return NULL;
 
     retval = read(fd, shdr, sizeof(*shdr));
     if (retval < 0)
-       return -1;
+       return NULL;
     bswap_shdr(shdr);
     if (shdr->sh_type == SHT_STRTAB)
        return qemu_malloc(shdr->sh_size);;
-    return 0;
+    return NULL;
 }
 
-static int read_program(int fd, struct elf_phdr *phdr, void *dst)
+static int read_program(int fd, struct elf_phdr *phdr, void *dst, uint32_t entry)
 {
     int retval;
-    retval = lseek(fd, 0x4000, SEEK_SET);
+    retval = lseek(fd, phdr->p_offset + entry - phdr->p_vaddr, SEEK_SET);
     if (retval < 0)
        return -1;
     return read(fd, dst, phdr->p_filesz);
@@ -178,6 +227,7 @@ static void load_symbols(struct elfhdr *ehdr, int fd)
 {
     struct elf_shdr symtab, strtab;
     struct elf_sym *syms;
+    struct syminfo *s;
     int nsyms, i;
     char *str;
 
@@ -196,20 +246,19 @@ static void load_symbols(struct elfhdr *ehdr, int fd)
        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;
+    s = qemu_mallocz(sizeof(*s));
+    s->disas_symtab = syms;
+    s->disas_num_syms = nsyms;
+    s->disas_strtab = str;
+    s->next = syminfos;
+    syminfos = s;
     return;
  error_freesyms:
     qemu_free(syms);
     return;
 }
 
-int load_elf(const char * filename, uint8_t *addr)
+int load_elf(const char *filename, uint8_t *addr)
 {
     struct elfhdr ehdr;
     struct elf_phdr phdr;
@@ -227,12 +276,13 @@ int load_elf(const char * filename, uint8_t *addr)
 
     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)
+       || (ehdr.e_machine != EM_SPARC
+           && ehdr.e_machine != EM_SPARC32PLUS))
        goto error;
 
     if (find_phdr(&ehdr, fd, &phdr, PT_LOAD))
        goto error;
-    retval = read_program(fd, &phdr, addr);
+    retval = read_program(fd, &phdr, addr, ehdr.e_entry);
     if (retval < 0)
        goto error;
 
@@ -245,17 +295,45 @@ int load_elf(const char * filename, uint8_t *addr)
     return -1;
 }
 
-int load_kernel(const char *filename, uint8_t *addr)
+int load_aout(const char *filename, uint8_t *addr)
 {
-    int fd, size;
+    int fd, size, ret;
+    struct exec e;
+    uint32_t magic;
 
     fd = open(filename, O_RDONLY | O_BINARY);
     if (fd < 0)
         return -1;
-    /* load 32 bit code */
-    size = read(fd, addr, 16 * 1024 * 1024);
+
+    size = read(fd, &e, sizeof(e));
     if (size < 0)
         goto fail;
+
+    bswap_ahdr(&e);
+
+    magic = N_MAGIC(e);
+    switch (magic) {
+    case ZMAGIC:
+    case QMAGIC:
+    case OMAGIC:
+       lseek(fd, N_TXTOFF(e), SEEK_SET);
+       size = read(fd, addr, e.a_text + e.a_data);
+       if (size < 0)
+           goto fail;
+       break;
+    case NMAGIC:
+       lseek(fd, N_TXTOFF(e), SEEK_SET);
+       size = read(fd, addr, e.a_text);
+       if (size < 0)
+           goto fail;
+       ret = read(fd, addr + N_DATADDR(e), e.a_data);
+       if (ret < 0)
+           goto fail;
+       size += ret;
+       break;
+    default:
+       goto fail;
+    }
     close(fd);
     return size;
  fail:
@@ -263,64 +341,3 @@ int load_kernel(const char *filename, uint8_t *addr)
     return -1;
 }
 
-typedef struct MAGICState {
-    uint32_t addr;
-    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)
-{
-    int ret;
-    MAGICState *s = opaque;
-
-    if (s->magic_state == 0) {
-        ret = load_elf(s->saved_kfn, (uint8_t *)s->saved_addr);
-       if (ret < 0)
-           ret = load_kernel(s->saved_kfn, (uint8_t *)s->saved_addr);
-        if (ret < 0) {
-            fprintf(stderr, "qemu: could not load kernel '%s'\n", 
-                    s->saved_kfn);
-        }
-       s->magic_state = 1; /* No more magic */
-       tb_flush();
-       return bswap32(ret);
-    }
-    return 0;
-}
-
-static void magic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-}
-
-
-static CPUReadMemoryFunc *magic_mem_read[3] = {
-    magic_mem_readl,
-    magic_mem_readl,
-    magic_mem_readl,
-};
-
-static CPUWriteMemoryFunc *magic_mem_write[3] = {
-    magic_mem_writel,
-    magic_mem_writel,
-    magic_mem_writel,
-};
-
-void magic_init(const char *kfn, int kloadaddr, uint32_t addr)
-{
-    int magic_io_memory;
-    MAGICState *s;
-
-    s = qemu_mallocz(sizeof(MAGICState));
-    if (!s)
-        return;
-
-    strcpy(s->saved_kfn, kfn);
-    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);
-}
-
diff --git a/hw/sched.c b/hw/sched.c
deleted file mode 100644 (file)
index 2ab966d..0000000
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * QEMU interrupt controller emulation
- * 
- * Copyright (c) 2003-2004 Fabrice Bellard
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-//#define DEBUG_IRQ_COUNT
-
-/* These registers are used for sending/receiving irqs from/to
- * different cpu's.
- */
-struct sun4m_intreg_percpu {
-       unsigned int tbt;        /* Intrs pending for this cpu, by PIL. */
-       /* These next two registers are WRITE-ONLY and are only
-        * "on bit" sensitive, "off bits" written have NO affect.
-        */
-       unsigned int clear;  /* Clear this cpus irqs here. */
-       unsigned int set;    /* Set this cpus irqs here. */
-};
-/*
- * djhr
- * Actually the clear and set fields in this struct are misleading..
- * according to the SLAVIO manual (and the same applies for the SEC)
- * the clear field clears bits in the mask which will ENABLE that IRQ
- * the set field sets bits in the mask to DISABLE the IRQ.
- *
- * Also the undirected_xx address in the SLAVIO is defined as
- * RESERVED and write only..
- *
- * DAVEM_NOTE: The SLAVIO only specifies behavior on uniprocessor
- *             sun4m machines, for MP the layout makes more sense.
- */
-struct sun4m_intreg_master {
-       unsigned int tbt;        /* IRQ's that are pending, see sun4m masks. */
-       unsigned int irqs;       /* Master IRQ bits. */
-
-       /* Again, like the above, two these registers are WRITE-ONLY. */
-       unsigned int clear;      /* Clear master IRQ's by setting bits here. */
-       unsigned int set;        /* Set master IRQ's by setting bits here. */
-
-       /* This register is both READ and WRITE. */
-       unsigned int undirected_target;  /* Which cpu gets undirected irqs. */
-};
-
-#define SUN4M_INT_ENABLE        0x80000000
-#define SUN4M_INT_E14           0x00000080
-#define SUN4M_INT_E10           0x00080000
-
-#define SUN4M_HARD_INT(x)       (0x000000001 << (x))
-#define SUN4M_SOFT_INT(x)       (0x000010000 << (x))
-
-#define SUN4M_INT_MASKALL       0x80000000        /* mask all interrupts */
-#define SUN4M_INT_MODULE_ERR    0x40000000        /* module error */
-#define SUN4M_INT_M2S_WRITE     0x20000000        /* write buffer error */
-#define SUN4M_INT_ECC           0x10000000        /* ecc memory error */
-#define SUN4M_INT_FLOPPY        0x00400000        /* floppy disk */
-#define SUN4M_INT_MODULE        0x00200000        /* module interrupt */
-#define SUN4M_INT_VIDEO         0x00100000        /* onboard video */
-#define SUN4M_INT_REALTIME      0x00080000        /* system timer */
-#define SUN4M_INT_SCSI          0x00040000        /* onboard scsi */
-#define SUN4M_INT_AUDIO         0x00020000        /* audio/isdn */
-#define SUN4M_INT_ETHERNET      0x00010000        /* onboard ethernet */
-#define SUN4M_INT_SERIAL        0x00008000        /* serial ports */
-#define SUN4M_INT_SBUSBITS      0x00003F80        /* sbus int bits */
-
-#define SUN4M_INT_SBUS(x)       (1 << (x+7))
-#define SUN4M_INT_VME(x)        (1 << (x))
-
-typedef struct SCHEDState {
-    uint32_t addr, addrg;
-    uint32_t intreg_pending;
-    uint32_t intreg_enabled;
-    uint32_t intregm_pending;
-    uint32_t intregm_enabled;
-} SCHEDState;
-
-static SCHEDState *ps;
-
-#ifdef DEBUG_IRQ_COUNT
-static uint64_t irq_count[32];
-#endif
-
-static uint32_t intreg_mem_readl(void *opaque, target_phys_addr_t addr)
-{
-    SCHEDState *s = opaque;
-    uint32_t saddr;
-
-    saddr = (addr - s->addr) >> 2;
-    switch (saddr) {
-    case 0:
-       return s->intreg_pending;
-       break;
-    default:
-       break;
-    }
-    return 0;
-}
-
-static void intreg_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    SCHEDState *s = opaque;
-    uint32_t saddr;
-
-    saddr = (addr - s->addr) >> 2;
-    switch (saddr) {
-    case 0:
-       s->intreg_pending = val;
-       break;
-    case 1: // clear
-       s->intreg_enabled &= ~val;
-       break;
-    case 2: // set
-       s->intreg_enabled |= val;
-       break;
-    default:
-       break;
-    }
-}
-
-static CPUReadMemoryFunc *intreg_mem_read[3] = {
-    intreg_mem_readl,
-    intreg_mem_readl,
-    intreg_mem_readl,
-};
-
-static CPUWriteMemoryFunc *intreg_mem_write[3] = {
-    intreg_mem_writel,
-    intreg_mem_writel,
-    intreg_mem_writel,
-};
-
-static uint32_t intregm_mem_readl(void *opaque, target_phys_addr_t addr)
-{
-    SCHEDState *s = opaque;
-    uint32_t saddr;
-
-    saddr = (addr - s->addrg) >> 2;
-    switch (saddr) {
-    case 0:
-       return s->intregm_pending;
-       break;
-    case 1:
-       return s->intregm_enabled;
-       break;
-    default:
-       break;
-    }
-    return 0;
-}
-
-static void intregm_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    SCHEDState *s = opaque;
-    uint32_t saddr;
-
-    saddr = (addr - s->addrg) >> 2;
-    switch (saddr) {
-    case 0:
-       s->intregm_pending = val;
-       break;
-    case 1:
-       s->intregm_enabled = val;
-       break;
-    case 2: // clear
-       s->intregm_enabled &= ~val;
-       break;
-    case 3: // set
-       s->intregm_enabled |= val;
-       break;
-    default:
-       break;
-    }
-}
-
-static CPUReadMemoryFunc *intregm_mem_read[3] = {
-    intregm_mem_readl,
-    intregm_mem_readl,
-    intregm_mem_readl,
-};
-
-static CPUWriteMemoryFunc *intregm_mem_write[3] = {
-    intregm_mem_writel,
-    intregm_mem_writel,
-    intregm_mem_writel,
-};
-
-void pic_info(void)
-{
-    term_printf("per-cpu: pending 0x%08x, enabled 0x%08x\n", ps->intreg_pending, ps->intreg_enabled);
-    term_printf("master: pending 0x%08x, enabled 0x%08x\n", ps->intregm_pending, ps->intregm_enabled);
-}
-
-void irq_info(void)
-{
-#ifndef DEBUG_IRQ_COUNT
-    term_printf("irq statistic code not compiled.\n");
-#else
-    int i;
-    int64_t count;
-
-    term_printf("IRQ statistics:\n");
-    for (i = 0; i < 32; i++) {
-        count = irq_count[i];
-        if (count > 0)
-            term_printf("%2d: %lld\n", i, count);
-    }
-#endif
-}
-
-static const unsigned int intr_to_mask[16] = {
-       0,      0,      0,      0,      0,      0, SUN4M_INT_ETHERNET,  0,
-       0,      0,      0,      0,      0,      0,      0,      0,
-};
-
-void pic_set_irq(int irq, int level)
-{
-    if (irq < 16) {
-       unsigned int mask = intr_to_mask[irq];
-       ps->intreg_pending |= 1 << irq;
-       if (ps->intregm_enabled & mask) {
-           cpu_single_env->interrupt_index = irq;
-           cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
-       }
-    }
-#ifdef DEBUG_IRQ_COUNT
-    if (level == 1)
-       irq_count[irq]++;
-#endif
-}
-
-void sched_init(uint32_t addr, uint32_t addrg)
-{
-    int intreg_io_memory, intregm_io_memory;
-    SCHEDState *s;
-
-    s = qemu_mallocz(sizeof(SCHEDState));
-    if (!s)
-        return;
-    s->addr = addr;
-    s->addrg = addrg;
-
-    intreg_io_memory = cpu_register_io_memory(0, intreg_mem_read, intreg_mem_write, s);
-    cpu_register_physical_memory(addr, 3, intreg_io_memory);
-
-    intregm_io_memory = cpu_register_io_memory(0, intregm_mem_read, intregm_mem_write, s);
-    cpu_register_physical_memory(addrg, 5, intregm_io_memory);
-
-    ps = s;
-}
-
diff --git a/hw/slavio_intctl.c b/hw/slavio_intctl.c
new file mode 100644 (file)
index 0000000..7454672
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+ * QEMU Sparc SLAVIO interrupt controller emulation
+ * 
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+//#define DEBUG_IRQ_COUNT
+
+/*
+ * Registers of interrupt controller in sun4m.
+ *
+ * This is the interrupt controller part of chip STP2001 (Slave I/O), also
+ * produced as NCR89C105. See
+ * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
+ *
+ * There is a system master controller and one for each cpu.
+ * 
+ */
+
+#define MAX_CPUS 16
+
+typedef struct SLAVIO_INTCTLState {
+    uint32_t intreg_pending[MAX_CPUS];
+    uint32_t intregm_pending;
+    uint32_t intregm_disabled;
+    uint32_t target_cpu;
+#ifdef DEBUG_IRQ_COUNT
+    uint64_t irq_count[32];
+#endif
+} SLAVIO_INTCTLState;
+
+#define INTCTL_MAXADDR 0xf
+#define INTCTLM_MAXADDR 0xf
+
+// per-cpu interrupt controller
+static uint32_t slavio_intctl_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+    SLAVIO_INTCTLState *s = opaque;
+    uint32_t saddr;
+    int cpu;
+
+    cpu = (addr & (MAX_CPUS - 1) * TARGET_PAGE_SIZE) >> 12;
+    saddr = (addr & INTCTL_MAXADDR) >> 2;
+    switch (saddr) {
+    case 0:
+       return s->intreg_pending[cpu];
+    default:
+       break;
+    }
+    return 0;
+}
+
+static void slavio_intctl_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+    SLAVIO_INTCTLState *s = opaque;
+    uint32_t saddr;
+    int cpu;
+
+    cpu = (addr & (MAX_CPUS - 1) * TARGET_PAGE_SIZE) >> 12;
+    saddr = (addr & INTCTL_MAXADDR) >> 2;
+    switch (saddr) {
+    case 1: // clear pending softints
+       if (val & 0x4000)
+           val |= 80000000;
+       val &= 0xfffe0000;
+       s->intreg_pending[cpu] &= ~val;
+       break;
+    case 2: // set softint
+       val &= 0xfffe0000;
+       s->intreg_pending[cpu] |= val;
+       break;
+    default:
+       break;
+    }
+}
+
+static CPUReadMemoryFunc *slavio_intctl_mem_read[3] = {
+    slavio_intctl_mem_readl,
+    slavio_intctl_mem_readl,
+    slavio_intctl_mem_readl,
+};
+
+static CPUWriteMemoryFunc *slavio_intctl_mem_write[3] = {
+    slavio_intctl_mem_writel,
+    slavio_intctl_mem_writel,
+    slavio_intctl_mem_writel,
+};
+
+// master system interrupt controller
+static uint32_t slavio_intctlm_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+    SLAVIO_INTCTLState *s = opaque;
+    uint32_t saddr;
+
+    saddr = (addr & INTCTLM_MAXADDR) >> 2;
+    switch (saddr) {
+    case 0:
+       return s->intregm_pending;
+    case 1:
+       return s->intregm_disabled;
+    case 4:
+       return s->target_cpu;
+    default:
+       break;
+    }
+    return 0;
+}
+
+static void slavio_intctlm_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+    SLAVIO_INTCTLState *s = opaque;
+    uint32_t saddr;
+
+    saddr = (addr & INTCTLM_MAXADDR) >> 2;
+    switch (saddr) {
+    case 2: // clear (enable)
+       // Force unused bits
+       val |= 0x7fb2007f;
+       s->intregm_disabled &= ~val;
+       break;
+    case 3: // set (disable, clear pending)
+       // Force unused bits
+       val &= ~0x7fb2007f;
+       s->intregm_disabled |= val;
+       s->intregm_pending &= ~val;
+       break;
+    case 4:
+       s->target_cpu = val & (MAX_CPUS - 1);
+       break;
+    default:
+       break;
+    }
+}
+
+static CPUReadMemoryFunc *slavio_intctlm_mem_read[3] = {
+    slavio_intctlm_mem_readl,
+    slavio_intctlm_mem_readl,
+    slavio_intctlm_mem_readl,
+};
+
+static CPUWriteMemoryFunc *slavio_intctlm_mem_write[3] = {
+    slavio_intctlm_mem_writel,
+    slavio_intctlm_mem_writel,
+    slavio_intctlm_mem_writel,
+};
+
+void slavio_pic_info(void *opaque)
+{
+    SLAVIO_INTCTLState *s = opaque;
+    int i;
+
+    for (i = 0; i < MAX_CPUS; i++) {
+       term_printf("per-cpu %d: pending 0x%08x\n", i, s->intreg_pending[i]);
+    }
+    term_printf("master: pending 0x%08x, disabled 0x%08x\n", s->intregm_pending, s->intregm_disabled);
+}
+
+void slavio_irq_info(void *opaque)
+{
+#ifndef DEBUG_IRQ_COUNT
+    term_printf("irq statistic code not compiled.\n");
+#else
+    SLAVIO_INTCTLState *s = opaque;
+    int i;
+    int64_t count;
+
+    term_printf("IRQ statistics:\n");
+    for (i = 0; i < 32; i++) {
+        count = s->irq_count[i];
+        if (count > 0)
+            term_printf("%2d: %lld\n", i, count);
+    }
+#endif
+}
+
+static const uint32_t intbit_to_level[32] = {
+    2, 3, 5, 7, 9, 11, 0, 14,  3, 5, 7, 9, 11, 13, 12, 12,
+    6, 0, 4, 10, 8, 0, 11, 0,  0, 0, 0, 0, 15, 0, 0, 0,
+};
+
+/*
+ * "irq" here is the bit number in the system interrupt register to
+ * separate serial and keyboard interrupts sharing a level.
+ */
+void slavio_pic_set_irq(void *opaque, int irq, int level)
+{
+    SLAVIO_INTCTLState *s = opaque;
+
+    if (irq < 32) {
+       uint32_t mask = 1 << irq;
+       uint32_t pil = intbit_to_level[irq];
+       if (pil > 0) {
+           if (level) {
+               s->intregm_pending |= mask;
+               s->intreg_pending[s->target_cpu] |= 1 << pil;
+           }
+           else {
+               s->intregm_pending &= ~mask;
+               s->intreg_pending[s->target_cpu] &= ~(1 << pil);
+           }
+           if (level &&
+               !(s->intregm_disabled & mask) &&
+               !(s->intregm_disabled & 0x80000000) &&
+               (pil == 15 || (pil > cpu_single_env->psrpil && cpu_single_env->psret == 1))) {
+#ifdef DEBUG_IRQ_COUNT
+               if (level == 1)
+                   s->irq_count[pil]++;
+#endif
+               cpu_single_env->interrupt_index = TT_EXTINT | pil;
+               cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
+           }
+       }
+    }
+}
+
+static void slavio_intctl_save(QEMUFile *f, void *opaque)
+{
+    SLAVIO_INTCTLState *s = opaque;
+    int i;
+    
+    for (i = 0; i < MAX_CPUS; i++) {
+       qemu_put_be32s(f, &s->intreg_pending[i]);
+    }
+    qemu_put_be32s(f, &s->intregm_pending);
+    qemu_put_be32s(f, &s->intregm_disabled);
+    qemu_put_be32s(f, &s->target_cpu);
+}
+
+static int slavio_intctl_load(QEMUFile *f, void *opaque, int version_id)
+{
+    SLAVIO_INTCTLState *s = opaque;
+    int i;
+
+    if (version_id != 1)
+        return -EINVAL;
+
+    for (i = 0; i < MAX_CPUS; i++) {
+       qemu_get_be32s(f, &s->intreg_pending[i]);
+    }
+    qemu_get_be32s(f, &s->intregm_pending);
+    qemu_get_be32s(f, &s->intregm_disabled);
+    qemu_get_be32s(f, &s->target_cpu);
+    return 0;
+}
+
+static void slavio_intctl_reset(void *opaque)
+{
+    SLAVIO_INTCTLState *s = opaque;
+    int i;
+
+    for (i = 0; i < MAX_CPUS; i++) {
+       s->intreg_pending[i] = 0;
+    }
+    s->intregm_disabled = 0xffffffff;
+    s->intregm_pending = 0;
+    s->target_cpu = 0;
+}
+
+void *slavio_intctl_init(uint32_t addr, uint32_t addrg)
+{
+    int slavio_intctl_io_memory, slavio_intctlm_io_memory, i;
+    SLAVIO_INTCTLState *s;
+
+    s = qemu_mallocz(sizeof(SLAVIO_INTCTLState));
+    if (!s)
+        return NULL;
+
+    for (i = 0; i < MAX_CPUS; i++) {
+       slavio_intctl_io_memory = cpu_register_io_memory(0, slavio_intctl_mem_read, slavio_intctl_mem_write, s);
+       cpu_register_physical_memory(addr + i * TARGET_PAGE_SIZE, INTCTL_MAXADDR, slavio_intctl_io_memory);
+    }
+
+    slavio_intctlm_io_memory = cpu_register_io_memory(0, slavio_intctlm_mem_read, slavio_intctlm_mem_write, s);
+    cpu_register_physical_memory(addrg, INTCTLM_MAXADDR, slavio_intctlm_io_memory);
+
+    register_savevm("slavio_intctl", addr, 1, slavio_intctl_save, slavio_intctl_load, s);
+    qemu_register_reset(slavio_intctl_reset, s);
+    slavio_intctl_reset(s);
+    return s;
+}
+
diff --git a/hw/slavio_serial.c b/hw/slavio_serial.c
new file mode 100644 (file)
index 0000000..348f328
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * QEMU Sparc SLAVIO serial port emulation
+ * 
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+//#define DEBUG_SERIAL
+
+/* debug keyboard */
+//#define DEBUG_KBD
+
+/* debug keyboard : only mouse */
+//#define DEBUG_MOUSE
+
+/*
+ * This is the serial port, mouse and keyboard part of chip STP2001
+ * (Slave I/O), also produced as NCR89C105. See
+ * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
+ * 
+ * The serial ports implement full AMD AM8530 or Zilog Z8530 chips,
+ * mouse and keyboard ports don't implement all functions and they are
+ * only asynchronous. There is no DMA.
+ *
+ */
+
+typedef struct ChannelState {
+    int irq;
+    int reg;
+    int rxint, txint;
+    uint8_t rx, tx, wregs[16], rregs[16];
+    CharDriverState *chr;
+} ChannelState;
+
+struct SerialState {
+    struct ChannelState chn[2];
+};
+
+#define SERIAL_MAXADDR 7
+
+static void slavio_serial_update_irq(ChannelState *s)
+{
+    if ((s->wregs[1] & 1) && // interrupts enabled
+       (((s->wregs[1] & 2) && s->txint == 1) || // tx ints enabled, pending
+        ((((s->wregs[1] & 0x18) == 8) || ((s->wregs[1] & 0x18) == 0x10)) &&
+         s->rxint == 1) || // rx ints enabled, pending
+        ((s->wregs[15] & 0x80) && (s->rregs[0] & 0x80)))) { // break int e&p
+        pic_set_irq(s->irq, 1);
+    } else {
+        pic_set_irq(s->irq, 0);
+    }
+}
+
+static void slavio_serial_reset_chn(ChannelState *s)
+{
+    int i;
+
+    s->reg = 0;
+    for (i = 0; i < SERIAL_MAXADDR; i++) {
+       s->rregs[i] = 0;
+       s->wregs[i] = 0;
+    }
+    s->wregs[4] = 4;
+    s->wregs[9] = 0xc0;
+    s->wregs[11] = 8;
+    s->wregs[14] = 0x30;
+    s->wregs[15] = 0xf8;
+    s->rregs[0] = 0x44;
+    s->rregs[1] = 6;
+
+    s->rx = s->tx = 0;
+    s->rxint = s->txint = 0;
+}
+
+static void slavio_serial_reset(void *opaque)
+{
+    SerialState *s = opaque;
+    slavio_serial_reset_chn(&s->chn[0]);
+    slavio_serial_reset_chn(&s->chn[1]);
+}
+
+static void slavio_serial_mem_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+    SerialState *ser = opaque;
+    ChannelState *s;
+    uint32_t saddr;
+    int newreg, channel;
+
+    val &= 0xff;
+    saddr = (addr & 3) >> 1;
+    channel = (addr & SERIAL_MAXADDR) >> 2;
+    s = &ser->chn[channel];
+    switch (saddr) {
+    case 0:
+       newreg = 0;
+       switch (s->reg) {
+       case 0:
+           newreg = val & 7;
+           val &= 0x38;
+           switch (val) {
+           case 8:
+               s->reg |= 0x8;
+               break;
+           case 0x20:
+               s->rxint = 0;
+               break;
+           case 0x28:
+               s->txint = 0;
+               break;
+           default:
+               break;
+           }
+           break;
+       case 1 ... 8:
+       case 10 ... 15:
+           s->wregs[s->reg] = val;
+           break;
+       case 9:
+           switch (val & 0xc0) {
+           case 0:
+           default:
+               break;
+           case 0x40:
+               slavio_serial_reset_chn(&ser->chn[1]);
+               return;
+           case 0x80:
+               slavio_serial_reset_chn(&ser->chn[0]);
+               return;
+           case 0xc0:
+               slavio_serial_reset(ser);
+               return;
+           }
+           break;
+       default:
+           break;
+       }
+       if (s->reg == 0)
+           s->reg = newreg;
+       else
+           s->reg = 0;
+       break;
+    case 1:
+       if (s->wregs[5] & 8) { // tx enabled
+           s->tx = val;
+           if (s->chr)
+               qemu_chr_write(s->chr, &s->tx, 1);
+           s->txint = 1;
+       }
+       break;
+    default:
+       break;
+    }
+}
+
+static uint32_t slavio_serial_mem_readb(void *opaque, uint32_t addr)
+{
+    SerialState *ser = opaque;
+    ChannelState *s;
+    uint32_t saddr;
+    uint32_t ret;
+    int channel;
+
+    saddr = (addr & 3) >> 1;
+    channel = (addr & SERIAL_MAXADDR) >> 2;
+    s = &ser->chn[channel];
+    switch (saddr) {
+    case 0:
+       ret = s->rregs[s->reg];
+       s->reg = 0;
+       return ret;
+    case 1:
+       s->rregs[0] &= ~1;
+       return s->rx;
+    default:
+       break;
+    }
+    return 0;
+}
+
+static int serial_can_receive(void *opaque)
+{
+    ChannelState *s = opaque;
+    if (((s->wregs[3] & 1) == 0) // Rx not enabled
+       || ((s->rregs[0] & 1) == 1)) // char already available
+       return 0;
+    else
+       return 1;
+}
+
+static void serial_receive_byte(ChannelState *s, int ch)
+{
+    s->rregs[0] |= 1;
+    s->rx = ch;
+    s->rxint = 1;
+    slavio_serial_update_irq(s);
+}
+
+static void serial_receive_break(ChannelState *s)
+{
+    s->rregs[0] |= 0x80;
+    slavio_serial_update_irq(s);
+}
+
+static void serial_receive1(void *opaque, const uint8_t *buf, int size)
+{
+    ChannelState *s = opaque;
+    serial_receive_byte(s, buf[0]);
+}
+
+static void serial_event(void *opaque, int event)
+{
+    ChannelState *s = opaque;
+    if (event == CHR_EVENT_BREAK)
+        serial_receive_break(s);
+}
+
+static CPUReadMemoryFunc *slavio_serial_mem_read[3] = {
+    slavio_serial_mem_readb,
+    slavio_serial_mem_readb,
+    slavio_serial_mem_readb,
+};
+
+static CPUWriteMemoryFunc *slavio_serial_mem_write[3] = {
+    slavio_serial_mem_writeb,
+    slavio_serial_mem_writeb,
+    slavio_serial_mem_writeb,
+};
+
+static void slavio_serial_save_chn(QEMUFile *f, ChannelState *s)
+{
+    qemu_put_be32s(f, &s->irq);
+    qemu_put_be32s(f, &s->reg);
+    qemu_put_be32s(f, &s->rxint);
+    qemu_put_be32s(f, &s->txint);
+    qemu_put_8s(f, &s->rx);
+    qemu_put_8s(f, &s->tx);
+    qemu_put_buffer(f, s->wregs, 16);
+    qemu_put_buffer(f, s->rregs, 16);
+}
+
+static void slavio_serial_save(QEMUFile *f, void *opaque)
+{
+    SerialState *s = opaque;
+
+    slavio_serial_save_chn(f, &s->chn[0]);
+    slavio_serial_save_chn(f, &s->chn[1]);
+}
+
+static int slavio_serial_load_chn(QEMUFile *f, ChannelState *s, int version_id)
+{
+    if (version_id != 1)
+        return -EINVAL;
+
+    qemu_get_be32s(f, &s->irq);
+    qemu_get_be32s(f, &s->reg);
+    qemu_get_be32s(f, &s->rxint);
+    qemu_get_be32s(f, &s->txint);
+    qemu_get_8s(f, &s->rx);
+    qemu_get_8s(f, &s->tx);
+    qemu_get_buffer(f, s->wregs, 16);
+    qemu_get_buffer(f, s->rregs, 16);
+    return 0;
+}
+
+static int slavio_serial_load(QEMUFile *f, void *opaque, int version_id)
+{
+    SerialState *s = opaque;
+    int ret;
+
+    ret = slavio_serial_load_chn(f, &s->chn[0], version_id);
+    if (ret != 0)
+       return ret;
+    ret = slavio_serial_load_chn(f, &s->chn[1], version_id);
+    return ret;
+
+}
+
+SerialState *slavio_serial_init(int base, int irq, CharDriverState *chr1, CharDriverState *chr2)
+{
+    int slavio_serial_io_memory;
+    SerialState *s;
+
+    s = qemu_mallocz(sizeof(SerialState));
+    if (!s)
+        return NULL;
+    s->chn[0].irq = irq;
+    s->chn[1].irq = irq;
+    s->chn[0].chr = chr1;
+    s->chn[1].chr = chr2;
+
+    slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
+    cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory);
+
+    if (chr1) {
+       qemu_chr_add_read_handler(chr1, serial_can_receive, serial_receive1, &s->chn[0]);
+       qemu_chr_add_event_handler(chr1, serial_event);
+    }
+    if (chr2) {
+       qemu_chr_add_read_handler(chr2, serial_can_receive, serial_receive1, &s->chn[1]);
+       qemu_chr_add_event_handler(chr2, serial_event);
+    }
+    register_savevm("slavio_serial", base, 1, slavio_serial_save, slavio_serial_load, s);
+    qemu_register_reset(slavio_serial_reset, s);
+    slavio_serial_reset(s);
+    return s;
+}
+
+static void sunkbd_event(void *opaque, int ch)
+{
+    ChannelState *s = opaque;
+    // XXX: PC -> Sun Type 5 translation?
+    serial_receive_byte(s, ch);
+}
+
+static void sunmouse_event(void *opaque, 
+                               int dx, int dy, int dz, int buttons_state)
+{
+    ChannelState *s = opaque;
+    int ch;
+
+    // XXX
+    ch = 0x42;
+    serial_receive_byte(s, ch);
+}
+
+void slavio_serial_ms_kbd_init(int base, int irq)
+{
+    int slavio_serial_io_memory;
+    SerialState *s;
+
+    s = qemu_mallocz(sizeof(SerialState));
+    if (!s)
+        return;
+    s->chn[0].irq = irq;
+    s->chn[1].irq = irq;
+    s->chn[0].chr = NULL;
+    s->chn[1].chr = NULL;
+
+    slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
+    cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory);
+
+    qemu_add_kbd_event_handler(sunkbd_event, &s->chn[0]);
+    qemu_add_mouse_event_handler(sunmouse_event, &s->chn[1]);
+    qemu_register_reset(slavio_serial_reset, s);
+    slavio_serial_reset(s);
+}
diff --git a/hw/slavio_timer.c b/hw/slavio_timer.c
new file mode 100644 (file)
index 0000000..43f59d2
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+ * QEMU Sparc SLAVIO timer controller emulation
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+//#define DEBUG_TIMER
+
+/*
+ * Registers of hardware timer in sun4m.
+ *
+ * This is the timer/counter part of chip STP2001 (Slave I/O), also
+ * produced as NCR89C105. See
+ * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
+ * 
+ * The 31-bit counter is incremented every 500ns by bit 9. Bits 8..0
+ * are zero. Bit 31 is 1 when count has been reached.
+ *
+ */
+
+typedef struct SLAVIO_TIMERState {
+    uint32_t limit, count, counthigh;
+    int64_t count_load_time;
+    int64_t expire_time;
+    int64_t stop_time, tick_offset;
+    QEMUTimer *irq_timer;
+    int irq;
+    int reached, stopped;
+    int mode; // 0 = processor, 1 = user, 2 = system
+} SLAVIO_TIMERState;
+
+#define TIMER_MAXADDR 0x1f
+#define CNT_FREQ 2000000
+#define MAX_CPUS 16
+
+// Update count, set irq, update expire_time
+static void slavio_timer_get_out(SLAVIO_TIMERState *s)
+{
+    int out;
+    int64_t diff, ticks, count;
+    uint32_t limit;
+
+    // There are three clock tick units: CPU ticks, register units
+    // (nanoseconds), and counter ticks (500 ns).
+    if (s->mode == 1 && s->stopped)
+       ticks = s->stop_time;
+    else
+       ticks = qemu_get_clock(vm_clock) - s->tick_offset;
+
+    out = (ticks >= s->expire_time);
+    if (out)
+       s->reached = 0x80000000;
+    if (!s->limit)
+       limit = 0x7fffffff;
+    else
+       limit = s->limit;
+
+    // Convert register units to counter ticks
+    limit = limit >> 9;
+
+    // Convert cpu ticks to counter ticks
+    diff = muldiv64(ticks - s->count_load_time, CNT_FREQ, ticks_per_sec);
+
+    // Calculate what the counter should be, convert to register
+    // units
+    count = diff % limit;
+    s->count = count << 9;
+    s->counthigh = count >> 22;
+
+    // Expire time: CPU ticks left to next interrupt
+    // Convert remaining counter ticks to CPU ticks
+    s->expire_time = ticks + muldiv64(limit - count, ticks_per_sec, CNT_FREQ);
+
+#ifdef DEBUG_TIMER
+    term_printf("timer: irq %d limit %d reached %d d %lld count %d s->c %x diff %lld stopped %d mode %d\n", s->irq, limit, s->reached?1:0, (ticks-s->count_load_time), count, s->count, s->expire_time - ticks, s->stopped, s->mode);
+#endif
+    if (s->mode != 1)
+       pic_set_irq(s->irq, out);
+}
+
+// timer callback
+static void slavio_timer_irq(void *opaque)
+{
+    SLAVIO_TIMERState *s = opaque;
+
+    if (!s->irq_timer)
+        return;
+    slavio_timer_get_out(s);
+    if (s->mode != 1)
+       qemu_mod_timer(s->irq_timer, s->expire_time);
+}
+
+static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+    SLAVIO_TIMERState *s = opaque;
+    uint32_t saddr;
+
+    saddr = (addr & TIMER_MAXADDR) >> 2;
+    switch (saddr) {
+    case 0:
+       // read limit (system counter mode) or read most signifying
+       // part of counter (user mode)
+       if (s->mode != 1) {
+           // clear irq
+           pic_set_irq(s->irq, 0);
+           s->count_load_time = qemu_get_clock(vm_clock);
+           s->reached = 0;
+           return s->limit;
+       }
+       else {
+           slavio_timer_get_out(s);
+           return s->counthigh & 0x7fffffff;
+       }
+    case 1:
+       // read counter and reached bit (system mode) or read lsbits
+       // of counter (user mode)
+       slavio_timer_get_out(s);
+       if (s->mode != 1)
+           return (s->count & 0x7fffffff) | s->reached;
+       else
+           return s->count;
+    case 3:
+       // read start/stop status
+       return s->stopped;
+    case 4:
+       // read user/system mode
+       return s->mode & 1;
+    default:
+       return 0;
+    }
+}
+
+static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+    SLAVIO_TIMERState *s = opaque;
+    uint32_t saddr;
+
+    saddr = (addr & TIMER_MAXADDR) >> 2;
+    switch (saddr) {
+    case 0:
+       // set limit, reset counter
+       s->count_load_time = qemu_get_clock(vm_clock);
+       // fall through
+    case 2:
+       // set limit without resetting counter
+       if (!val)
+           s->limit = 0x7fffffff;
+       else
+           s->limit = val & 0x7fffffff;
+       slavio_timer_irq(s);
+       break;
+    case 3:
+       // start/stop user counter
+       if (s->mode == 1) {
+           if (val & 1) {
+               s->stop_time = qemu_get_clock(vm_clock);
+               s->stopped = 1;
+           }
+           else {
+               if (s->stopped)
+                   s->tick_offset += qemu_get_clock(vm_clock) - s->stop_time;
+               s->stopped = 0;
+           }
+       }
+       break;
+    case 4:
+       // bit 0: user (1) or system (0) counter mode
+       if (s->mode == 0 || s->mode == 1)
+           s->mode = val & 1;
+       break;
+    default:
+       break;
+    }
+}
+
+static CPUReadMemoryFunc *slavio_timer_mem_read[3] = {
+    slavio_timer_mem_readl,
+    slavio_timer_mem_readl,
+    slavio_timer_mem_readl,
+};
+
+static CPUWriteMemoryFunc *slavio_timer_mem_write[3] = {
+    slavio_timer_mem_writel,
+    slavio_timer_mem_writel,
+    slavio_timer_mem_writel,
+};
+
+static void slavio_timer_save(QEMUFile *f, void *opaque)
+{
+    SLAVIO_TIMERState *s = opaque;
+
+    qemu_put_be32s(f, &s->limit);
+    qemu_put_be32s(f, &s->count);
+    qemu_put_be32s(f, &s->counthigh);
+    qemu_put_be64s(f, &s->count_load_time);
+    qemu_put_be64s(f, &s->expire_time);
+    qemu_put_be64s(f, &s->stop_time);
+    qemu_put_be64s(f, &s->tick_offset);
+    qemu_put_be32s(f, &s->irq);
+    qemu_put_be32s(f, &s->reached);
+    qemu_put_be32s(f, &s->stopped);
+    qemu_put_be32s(f, &s->mode);
+}
+
+static int slavio_timer_load(QEMUFile *f, void *opaque, int version_id)
+{
+    SLAVIO_TIMERState *s = opaque;
+    
+    if (version_id != 1)
+        return -EINVAL;
+
+    qemu_get_be32s(f, &s->limit);
+    qemu_get_be32s(f, &s->count);
+    qemu_get_be32s(f, &s->counthigh);
+    qemu_get_be64s(f, &s->count_load_time);
+    qemu_get_be64s(f, &s->expire_time);
+    qemu_get_be64s(f, &s->stop_time);
+    qemu_get_be64s(f, &s->tick_offset);
+    qemu_get_be32s(f, &s->irq);
+    qemu_get_be32s(f, &s->reached);
+    qemu_get_be32s(f, &s->stopped);
+    qemu_get_be32s(f, &s->mode);
+    return 0;
+}
+
+static void slavio_timer_reset(void *opaque)
+{
+    SLAVIO_TIMERState *s = opaque;
+
+    s->limit = 0;
+    s->count = 0;
+    s->count_load_time = qemu_get_clock(vm_clock);;
+    s->stop_time = s->count_load_time;
+    s->tick_offset = 0;
+    s->reached = 0;
+    s->mode &= 2;
+    s->stopped = 1;
+    slavio_timer_get_out(s);
+}
+
+static void slavio_timer_init_internal(uint32_t addr, int irq, int mode)
+{
+    int slavio_timer_io_memory;
+    SLAVIO_TIMERState *s;
+
+    s = qemu_mallocz(sizeof(SLAVIO_TIMERState));
+    if (!s)
+        return;
+    s->irq = irq;
+    s->mode = mode;
+    s->irq_timer = qemu_new_timer(vm_clock, slavio_timer_irq, s);
+
+    slavio_timer_io_memory = cpu_register_io_memory(0, slavio_timer_mem_read,
+                                                   slavio_timer_mem_write, s);
+    cpu_register_physical_memory(addr, TIMER_MAXADDR, slavio_timer_io_memory);
+    register_savevm("slavio_timer", addr, 1, slavio_timer_save, slavio_timer_load, s);
+    qemu_register_reset(slavio_timer_reset, s);
+    slavio_timer_reset(s);
+}
+
+void slavio_timer_init(uint32_t addr1, int irq1, uint32_t addr2, int irq2)
+{
+    int i;
+
+    for (i = 0; i < MAX_CPUS; i++) {
+       slavio_timer_init_internal(addr1 + i * TARGET_PAGE_SIZE, irq1, 0);
+    }
+
+    slavio_timer_init_internal(addr2, irq2, 2);
+}
index 80305e09c393a0facd9cae2fa363a70830119c9d..7cc5bd8d9c6eb8908a5354f43b0f1926eb4a3c6a 100644 (file)
 #include "m48t08.h"
 
 #define KERNEL_LOAD_ADDR     0x00004000
-#define MMU_CONTEXT_TBL      0x00003000
-#define MMU_L1PTP            (MMU_CONTEXT_TBL + 0x0400)
-#define MMU_L2PTP            (MMU_CONTEXT_TBL + 0x0800)
-#define PROM_ADDR           0xffd04000
+#define PROM_ADDR           0xffd00000
 #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      /* m48t08 */
 #define PHYS_JJ_IDPROM_OFF     0x1FD8
 #define PHYS_JJ_EEPROM_SIZE    0x2000
-#define PHYS_JJ_IOMMU  0x10000000      /* First page of sun4m IOMMU */
+// IRQs are not PIL ones, but master interrupt controller register
+// bits
+#define PHYS_JJ_IOMMU  0x10000000      /* I/O MMU */
 #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_LEDMA   0x78400010      /* Lance DMA controller */
+#define PHYS_JJ_LE      0x78C00000      /* Lance ethernet */
+#define PHYS_JJ_LE_IRQ     16
+#define PHYS_JJ_CLOCK  0x71D00000      /* Per-CPU timer/counter, L14 */
+#define PHYS_JJ_CLOCK_IRQ  7
+#define PHYS_JJ_CLOCK1 0x71D10000      /* System timer/counter, L10 */
+#define PHYS_JJ_CLOCK1_IRQ 19
+#define PHYS_JJ_INTR0  0x71E00000      /* Per-CPU interrupt control registers */
 #define PHYS_JJ_INTR_G 0x71E10000      /* Master interrupt control registers */
+#define PHYS_JJ_MS_KBD 0x71000000      /* Mouse and keyboard */
+#define PHYS_JJ_MS_KBD_IRQ    14
+#define PHYS_JJ_SER    0x71100000      /* Serial */
+#define PHYS_JJ_SER_IRQ    15
+#define PHYS_JJ_SCSI_IRQ   18
+#define PHYS_JJ_FDC    0x71400000      /* Floppy */
+#define PHYS_JJ_FLOPPY_IRQ 22
 
 /* TSC handling */
 
@@ -57,13 +60,73 @@ uint64_t cpu_get_tsc()
 }
 
 void DMA_run() {}
-void SB16_run() {}
-int serial_can_receive(SerialState *s) { return 0; }
-void serial_receive_byte(SerialState *s, int ch) {}
-void serial_receive_break(SerialState *s) {}
 
 static m48t08_t *nvram;
 
+static void nvram_init(m48t08_t *nvram, uint8_t *macaddr)
+{
+    unsigned char tmp = 0;
+    int i, j;
+
+    i = 0x1fd8;
+    m48t08_write(nvram, i++, 0x01);
+    m48t08_write(nvram, i++, 0x80); /* Sun4m OBP */
+    j = 0;
+    m48t08_write(nvram, i++, macaddr[j++]);
+    m48t08_write(nvram, i++, macaddr[j++]);
+    m48t08_write(nvram, i++, macaddr[j++]);
+    m48t08_write(nvram, i++, macaddr[j++]);
+    m48t08_write(nvram, i++, macaddr[j++]);
+    m48t08_write(nvram, i, macaddr[j]);
+
+    /* Calculate checksum */
+    for (i = 0x1fd8; i < 0x1fe7; i++) {
+       tmp ^= m48t08_read(nvram, i);
+    }
+    m48t08_write(nvram, 0x1fe7, tmp);
+}
+
+static void *slavio_intctl;
+
+void pic_info()
+{
+    slavio_pic_info(slavio_intctl);
+}
+
+void irq_info()
+{
+    slavio_irq_info(slavio_intctl);
+}
+
+void pic_set_irq(int irq, int level)
+{
+    slavio_pic_set_irq(slavio_intctl, irq, level);
+}
+
+static void *tcx;
+
+void vga_update_display()
+{
+    tcx_update_display(tcx);
+}
+
+void vga_invalidate_display()
+{
+    tcx_invalidate_display(tcx);
+}
+
+void vga_screen_dump(const char *filename)
+{
+    tcx_screen_dump(tcx, filename);
+}
+
+static void *iommu;
+
+uint32_t iommu_translate(uint32_t addr)
+{
+    return iommu_translate_local(iommu, addr);
+}
+
 /* Sun4m hardware initialisation */
 void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
              DisplayState *ds, const char **fd_filename, int snapshot,
@@ -72,42 +135,50 @@ void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
 {
     char buf[1024];
     int ret, linux_boot;
-    unsigned long bios_offset;
+    unsigned long vram_size = 0x100000, prom_offset;
 
     linux_boot = (kernel_filename != NULL);
 
     /* allocate RAM */
     cpu_register_physical_memory(0, ram_size, 0);
-    bios_offset = ram_size;
 
-    iommu_init(PHYS_JJ_IOMMU);
-    sched_init(PHYS_JJ_INTR0, PHYS_JJ_INTR_G);
-    tcx_init(ds, PHYS_JJ_TCX_FB);
+    iommu = iommu_init(PHYS_JJ_IOMMU);
+    slavio_intctl = slavio_intctl_init(PHYS_JJ_INTR0, PHYS_JJ_INTR_G);
+    tcx = tcx_init(ds, PHYS_JJ_TCX_FB, phys_ram_base + ram_size, ram_size, vram_size);
     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, &nd_table[0].macaddr);
-    timer_init(PHYS_JJ_CLOCK, PHYS_JJ_CLOCK_IRQ);
-    timer_init(PHYS_JJ_CLOCK1, PHYS_JJ_CLOCK1_IRQ);
-    magic_init(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR, PROLL_MAGIC_ADDR);
+    nvram = m48t08_init(PHYS_JJ_EEPROM, PHYS_JJ_EEPROM_SIZE);
+    nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr);
+    slavio_timer_init(PHYS_JJ_CLOCK, PHYS_JJ_CLOCK_IRQ, PHYS_JJ_CLOCK1, PHYS_JJ_CLOCK1_IRQ);
+    slavio_serial_ms_kbd_init(PHYS_JJ_MS_KBD, PHYS_JJ_MS_KBD_IRQ);
+    slavio_serial_init(PHYS_JJ_SER, PHYS_JJ_SER_IRQ, serial_hds[0], serial_hds[1]);
+    fdctrl_init(PHYS_JJ_FLOPPY_IRQ, 0, 1, PHYS_JJ_FDC, fd_table);
 
-    /* We load Proll as the kernel and start it. It will issue a magic
-       IO to load the real kernel */
-    if (linux_boot) {
+    prom_offset = ram_size + vram_size;
+
+    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEE);
+    ret = load_elf(buf, phys_ram_base + prom_offset);
+    if (ret < 0) {
        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEB);
-        ret = load_kernel(buf, 
-                      phys_ram_base + KERNEL_LOAD_ADDR);
+       ret = load_image(buf, phys_ram_base + prom_offset);
+    }
+    if (ret < 0) {
+       fprintf(stderr, "qemu: could not load prom '%s'\n", 
+               buf);
+       exit(1);
+    }
+    cpu_register_physical_memory(PROM_ADDR, (ret + TARGET_PAGE_SIZE) & TARGET_PAGE_MASK, 
+                                 prom_offset | IO_MEM_ROM);
+
+    if (linux_boot) {
+        ret = load_elf(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
+        if (ret < 0)
+           ret = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
+       if (ret < 0)
+           ret = load_image(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
         if (ret < 0) {
             fprintf(stderr, "qemu: could not load kernel '%s'\n", 
-                    buf);
-            exit(1);
+                    kernel_filename);
+           exit(1);
         }
     }
-    /* 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_L1PTP, (MMU_L2PTP >> 4) | 1);
-    stl_raw(phys_ram_base + MMU_L1PTP + (0x01 << 2), (MMU_L2PTP >> 4) | 1); // 01.. == 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 */
-    stl_raw(phys_ram_base + MMU_L2PTP, (3 << PTE_ACCESS_SHIFT) | 2);
-    stl_raw(phys_ram_base + MMU_L2PTP, ((0x01 << PTE_PPN_SHIFT) >> 4 ) | (3 << PTE_ACCESS_SHIFT) | 2);
 }
index 7f979946fc93d49678e06b58b0ecd314a0e17d46..ccac0bffa6dd9c0fdafb51ebb6a536f133987c60 100644 (file)
--- a/hw/tcx.c
+++ b/hw/tcx.c
 
 #define MAXX 1024
 #define MAXY 768
+/*
+ * Proll uses only small part of display, we need to switch to full
+ * display when we get linux framebuffer console or X11 running. For
+ * now it's just slower and awkward.
+*/
+#if 1
 #define XSZ (8*80)
 #define YSZ (24*11)
 #define XOFF (MAXX-XSZ)
 #define YOFF (MAXY-YSZ)
+#else
+#define XSZ MAXX
+#define YSZ MAXY
+#define XOFF 0
+#define YOFF 0
+#endif
 
 typedef struct TCXState {
     uint32_t addr;
     DisplayState *ds;
     uint8_t *vram;
+    unsigned long vram_offset;
+    uint8_t r[256], g[256], b[256];
 } TCXState;
 
-static TCXState *ts;
-
-void vga_update_display()
+static void tcx_draw_line32(TCXState *s1, uint8_t *d, 
+                           const uint8_t *s, int width)
 {
-    dpy_update(ts->ds, 0, 0, XSZ, YSZ);
+    int x;
+    uint8_t val;
+
+    for(x = 0; x < width; x++) {
+       val = *s++;
+       *d++ = s1->r[val];
+       *d++ = s1->g[val];
+       *d++ = s1->b[val];
+       d++;
+    }
 }
 
-void vga_invalidate_display() {}
+static void tcx_draw_line24(TCXState *s1, uint8_t *d, 
+                           const uint8_t *s, int width)
+{
+    int x;
+    uint8_t val;
 
-static uint32_t tcx_mem_readb(void *opaque, target_phys_addr_t addr)
+    for(x = 0; x < width; x++) {
+       val = *s++;
+       *d++ = s1->r[val];
+       *d++ = s1->g[val];
+       *d++ = s1->b[val];
+    }
+}
+
+static void tcx_draw_line8(TCXState *s1, uint8_t *d, 
+                          const uint8_t *s, int width)
 {
-    TCXState *s = opaque;
-    uint32_t saddr;
-    unsigned int x, y;
-
-    saddr = addr - s->addr - YOFF*MAXX - XOFF;
-    y = saddr / MAXX;
-    x = saddr - y * MAXX;
-    if (x < XSZ && y < YSZ) {
-       return s->vram[y * XSZ + x];
+    int x;
+    uint8_t val;
+
+    for(x = 0; x < width; x++) {
+       val = *s++;
+       /* XXX translate between palettes? */
+       *d++ = val;
     }
-    return 0;
 }
 
-static uint32_t tcx_mem_readw(void *opaque, target_phys_addr_t addr)
+/* Fixed line length 1024 allows us to do nice tricks not possible on
+   VGA... */
+void tcx_update_display(void *opaque)
 {
-    uint32_t v;
-#ifdef TARGET_WORDS_BIGENDIAN
-    v = tcx_mem_readb(opaque, addr) << 8;
-    v |= tcx_mem_readb(opaque, addr + 1);
+    TCXState *ts = opaque;
+    uint32_t page;
+    int y, page_min, page_max, y_start, dd, ds;
+    uint8_t *d, *s;
+    void (*f)(TCXState *s1, uint8_t *d, const uint8_t *s, int width);
+
+    if (ts->ds->depth == 0)
+       return;
+#ifdef LD_BYPASS_OK
+    page = ts->vram_offset + YOFF*MAXX;
 #else
-    v = tcx_mem_readb(opaque, addr);
-    v |= tcx_mem_readb(opaque, addr + 1) << 8;
+    page = ts->addr + YOFF*MAXX;
 #endif
-    return v;
+    y_start = -1;
+    page_min = 0x7fffffff;
+    page_max = -1;
+    d = ts->ds->data;
+    s = ts->vram + YOFF*MAXX + XOFF;
+    dd = ts->ds->linesize;
+    ds = 1024;
+
+    switch (ts->ds->depth) {
+    case 32:
+       f = tcx_draw_line32;
+       break;
+    case 24:
+       f = tcx_draw_line24;
+       break;
+    default:
+    case 8:
+       f = tcx_draw_line8;
+       break;
+    case 0:
+       return;
+    }
+
+    for(y = 0; y < YSZ; y += 4, page += TARGET_PAGE_SIZE) {
+       if (cpu_physical_memory_is_dirty(page)) {
+           if (y_start < 0)
+                y_start = y;
+            if (page < page_min)
+                page_min = page;
+            if (page > page_max)
+                page_max = page;
+           f(ts, d, s, XSZ);
+           d += dd;
+           s += ds;
+           f(ts, d, s, XSZ);
+           d += dd;
+           s += ds;
+           f(ts, d, s, XSZ);
+           d += dd;
+           s += ds;
+           f(ts, d, s, XSZ);
+           d += dd;
+           s += ds;
+       } else {
+            if (y_start >= 0) {
+                /* flush to display */
+                dpy_update(ts->ds, 0, y_start, 
+                           XSZ, y - y_start);
+                y_start = -1;
+            }
+           d += dd * 4;
+           s += ds * 4;
+       }
+    }
+    if (y_start >= 0) {
+       /* flush to display */
+       dpy_update(ts->ds, 0, y_start, 
+                  XSZ, y - y_start);
+    }
+    /* reset modified pages */
+    if (page_max != -1) {
+        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE);
+    }
 }
 
-static uint32_t tcx_mem_readl(void *opaque, target_phys_addr_t addr)
+void tcx_invalidate_display(void *opaque)
 {
-    uint32_t v;
-#ifdef TARGET_WORDS_BIGENDIAN
-    v = tcx_mem_readb(opaque, addr) << 24;
-    v |= tcx_mem_readb(opaque, addr + 1) << 16;
-    v |= tcx_mem_readb(opaque, addr + 2) << 8;
-    v |= tcx_mem_readb(opaque, addr + 3);
+    TCXState *s = opaque;
+    int i;
+
+    for (i = 0; i < MAXX*MAXY; i += TARGET_PAGE_SIZE) {
+#ifdef LD_BYPASS_OK
+       cpu_physical_memory_set_dirty(s->vram_offset + i);
 #else
-    v = tcx_mem_readb(opaque, addr);
-    v |= tcx_mem_readb(opaque, addr + 1) << 8;
-    v |= tcx_mem_readb(opaque, addr + 2) << 16;
-    v |= tcx_mem_readb(opaque, addr + 3) << 24;
+       cpu_physical_memory_set_dirty(s->addr + i);
 #endif
-    return v;
+    }
 }
 
-static void tcx_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void tcx_save(QEMUFile *f, void *opaque)
 {
     TCXState *s = opaque;
-    uint32_t saddr;
-    unsigned int x, y;
-    char *sptr;
-
-    saddr = addr - s->addr - YOFF*MAXX - XOFF;
-    y = saddr / MAXX;
-    x = saddr - y * MAXX;
-    if (x < XSZ && y < YSZ) {
-       sptr =  s->ds->data;
-       if (sptr) {
-           if (s->ds->depth == 24 || s->ds->depth == 32) {
-               /* XXX need to do CLUT translation */
-               sptr[y * s->ds->linesize + x*4] = val & 0xff;
-               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;
-    }
+    
+    qemu_put_be32s(f, (uint32_t *)&s->addr);
+    qemu_put_be32s(f, (uint32_t *)&s->vram);
+    qemu_put_buffer(f, s->r, 256);
+    qemu_put_buffer(f, s->g, 256);
+    qemu_put_buffer(f, s->b, 256);
 }
 
-static void tcx_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
+static int tcx_load(QEMUFile *f, void *opaque, int version_id)
 {
-#ifdef TARGET_WORDS_BIGENDIAN
-    tcx_mem_writeb(opaque, addr, (val >> 8) & 0xff);
-    tcx_mem_writeb(opaque, addr + 1, val & 0xff);
-#else
-    tcx_mem_writeb(opaque, addr, val & 0xff);
-    tcx_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-#endif
+    TCXState *s = opaque;
+    
+    if (version_id != 1)
+        return -EINVAL;
+
+    qemu_get_be32s(f, (uint32_t *)&s->addr);
+    qemu_get_be32s(f, (uint32_t *)&s->vram);
+    qemu_get_buffer(f, s->r, 256);
+    qemu_get_buffer(f, s->g, 256);
+    qemu_get_buffer(f, s->b, 256);
+    return 0;
 }
 
-static void tcx_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void tcx_reset(void *opaque)
 {
-#ifdef TARGET_WORDS_BIGENDIAN
-    tcx_mem_writeb(opaque, addr, (val >> 24) & 0xff);
-    tcx_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
-    tcx_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
-    tcx_mem_writeb(opaque, addr + 3, val & 0xff);
-#else
-    tcx_mem_writeb(opaque, addr, val & 0xff);
-    tcx_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-    tcx_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
-    tcx_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
+    TCXState *s = opaque;
+
+    /* Initialize palette */
+    memset(s->r, 0, 256);
+    memset(s->g, 0, 256);
+    memset(s->b, 0, 256);
+    s->r[255] = s->g[255] = s->b[255] = 255;
+    memset(s->vram, 0, MAXX*MAXY);
+#ifdef LD_BYPASS_OK
+    cpu_physical_memory_reset_dirty(s->vram_offset, s->vram_offset + MAXX*MAXY - 1);
 #endif
 }
 
-static CPUReadMemoryFunc *tcx_mem_read[3] = {
-    tcx_mem_readb,
-    tcx_mem_readw,
-    tcx_mem_readl,
-};
-
-static CPUWriteMemoryFunc *tcx_mem_write[3] = {
-    tcx_mem_writeb,
-    tcx_mem_writew,
-    tcx_mem_writel,
-};
-
-void tcx_init(DisplayState *ds, uint32_t addr)
+void *tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base,
+             unsigned long vram_offset, int vram_size)
 {
     TCXState *s;
-    int tcx_io_memory;
 
     s = qemu_mallocz(sizeof(TCXState));
     if (!s)
-        return;
+        return NULL;
     s->ds = ds;
     s->addr = addr;
-    ts = s;
-    tcx_io_memory = cpu_register_io_memory(0, tcx_mem_read, tcx_mem_write, s);
-    cpu_register_physical_memory(addr, 0x100000, 
-                                 tcx_io_memory);
-    s->vram = qemu_mallocz(XSZ*YSZ);
+    s->vram = vram_base;
+    s->vram_offset = vram_offset;
+
+    cpu_register_physical_memory(addr, vram_size, vram_offset);
+
+    register_savevm("tcx", addr, 1, tcx_save, tcx_load, s);
+    qemu_register_reset(tcx_reset, s);
+    tcx_reset(s);
     dpy_resize(s->ds, XSZ, YSZ);
+    return s;
 }
 
-void vga_screen_dump(const char *filename)
+void tcx_screen_dump(void *opaque, const char *filename)
 {
-    TCXState *s = ts;
+    TCXState *s = opaque;
     FILE *f;
-    uint8_t *d, *d1;
-    unsigned int v;
+    uint8_t *d, *d1, 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;
+        return;
+    fprintf(f, "P6\n%d %d\n%d\n", XSZ, YSZ, 255);
+    d1 = s->vram + YOFF*MAXX + XOFF;
     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);
+            fputc(s->r[v], f);
+            fputc(s->g[v], f);
+            fputc(s->b[v], f);
             d++;
         }
-        d1 += XSZ;
+        d1 += MAXX;
     }
     fclose(f);
     return;
diff --git a/hw/timer.c b/hw/timer.c
deleted file mode 100644 (file)
index e393fa3..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * QEMU Sparc timer controller emulation
- * 
- * Copyright (c) 2003-2004 Fabrice Bellard
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-
-/*
- * 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;
-};
-
-typedef struct TIMERState {
-    uint32_t addr;
-    uint32_t timer_regs[2];
-    int irq;
-} TIMERState;
-
-static uint32_t timer_mem_readl(void *opaque, target_phys_addr_t addr)
-{
-    TIMERState *s = opaque;
-    uint32_t saddr;
-
-    saddr = (addr - s->addr) >> 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)
-{
-    TIMERState *s = opaque;
-    uint32_t saddr;
-
-    saddr = (addr - s->addr) >> 2;
-    switch (saddr) {
-    default:
-       s->timer_regs[saddr] = val;
-       break;
-    }
-}
-
-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,
-};
-
-void timer_init(uint32_t addr, int irq)
-{
-    int timer_io_memory;
-    TIMERState *s;
-
-    s = qemu_mallocz(sizeof(TIMERState));
-    if (!s)
-        return;
-    s->addr = addr;
-    s->irq = irq;
-
-    timer_io_memory = cpu_register_io_memory(0, timer_mem_read, timer_mem_write, s);
-    cpu_register_physical_memory(addr, 2, timer_io_memory);
-}
index cfc425697403d068321281f4037b4379450b75c4..09c33aa90b08fedba63aaec58007ee0b18462ee7 100644 (file)
@@ -841,6 +841,7 @@ static void load_symbols(struct elfhdr *hdr, int fd)
     unsigned int i;
     struct elf_shdr sechdr, symtab, strtab;
     char *strings;
+    struct syminfo *s;
 
     lseek(fd, hdr->e_shoff, SEEK_SET);
     for (i = 0; i < hdr->e_shnum; i++) {
@@ -866,24 +867,27 @@ static void load_symbols(struct elfhdr *hdr, int fd)
 
  found:
     /* Now know where the strtab and symtab are.  Snarf them. */
-    disas_symtab = malloc(symtab.sh_size);
-    disas_strtab = strings = malloc(strtab.sh_size);
-    if (!disas_symtab || !disas_strtab)
+    s = malloc(sizeof(*s));
+    s->disas_symtab = malloc(symtab.sh_size);
+    s->disas_strtab = strings = malloc(strtab.sh_size);
+    if (!s->disas_symtab || !s->disas_strtab)
        return;
        
     lseek(fd, symtab.sh_offset, SEEK_SET);
-    if (read(fd, disas_symtab, symtab.sh_size) != symtab.sh_size)
+    if (read(fd, s->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);
+       bswap_sym(s->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);
+    s->disas_num_syms = symtab.sh_size / sizeof(struct elf_sym);
+    s->next = syminfos;
+    syminfos = s;
 }
 
 static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
index 6ab024e0bf89db5dc09566f223e19d54064cbc41..3d99dda1ad644ee00b5f0d9077492bbd3a4ce728 100644 (file)
@@ -497,6 +497,8 @@ void cpu_loop (CPUSPARCState *env)
         case TT_WIN_UNF: /* window underflow */
             restore_window(env);
             break;
+       case 0x100: // XXX, why do we get these?
+           break;
         default:
             printf ("Unhandled trap: 0x%x\n", trapnr);
             cpu_dump_state(env, stderr, fprintf, 0);
index 50f2ba10a0a86b749c5493201293da7784320445..49278208c5714a87beb3c3fb7242343943a59655 100644 (file)
@@ -1354,13 +1354,14 @@ struct target_rt_signal_frame {
        __siginfo_fpu_t         fpu_state;
 };
 
-#define UREG_O0        0
-#define UREG_O6        6
-#define UREG_I0        16
-#define UREG_I1        17
-#define UREG_I2        18
-#define UREG_I6        22
-#define UREG_I7        23
+#define UREG_O0        16
+#define UREG_O6        22
+#define UREG_I0        0
+#define UREG_I1        1
+#define UREG_I2        2
+#define UREG_I6        6
+#define UREG_I7        7
+#define UREG_L0               8
 #define UREG_FP        UREG_I6
 #define UREG_SP        UREG_O6
 
@@ -1385,23 +1386,20 @@ setup___siginfo(__siginfo_t *si, CPUState *env, target_ulong mask)
 {
        int err = 0, i;
 
-       fprintf(stderr, "2.a %lx psr: %lx regs: %lx\n", si, env->psr, si->si_regs.psr);
        err |= __put_user(env->psr, &si->si_regs.psr);
-       fprintf(stderr, "2.a1 pc:%lx\n", si->si_regs.pc);
        err |= __put_user(env->pc, &si->si_regs.pc);
        err |= __put_user(env->npc, &si->si_regs.npc);
        err |= __put_user(env->y, &si->si_regs.y);
-       fprintf(stderr, "2.b\n");
        for (i=0; i < 7; i++) {
                err |= __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
        }
        for (i=0; i < 7; i++) {
-               err |= __put_user(env->regwptr[i+16], &si->si_regs.u_regs[i+8]);
+               err |= __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
        }
-       fprintf(stderr, "2.c\n");
        err |= __put_user(mask, &si->si_mask);
        return err;
 }
+
 static int
 setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
                 CPUState *env, unsigned long mask)
@@ -1434,6 +1432,7 @@ static void setup_frame(int sig, struct emulated_sigaction *ka,
        sf = (struct target_signal_frame *)
                get_sigframe(ka, env, sigframe_size);
 
+       //fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]);
 #if 0
        if (invalid_frame_pointer(sf, sigframe_size))
                goto sigill_and_return;
@@ -1451,13 +1450,11 @@ static void setup_frame(int sig, struct emulated_sigaction *ka,
        }
 
        for (i = 0; i < 7; i++) {
-               err |= __put_user(env->regwptr[i + 8], &sf->ss.locals[i]);
+               err |= __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
        }
        for (i = 0; i < 7; i++) {
-               err |= __put_user(env->regwptr[i + 16], &sf->ss.ins[i]);
+               err |= __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
        }
-       //err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP],
-       //                    sizeof(struct reg_window));
        if (err)
                goto sigsegv;
 
@@ -1486,13 +1483,15 @@ static void setup_frame(int sig, struct emulated_sigaction *ka,
 
                /* Flush instruction space. */
                //flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
-               //tb_flush(env);
+               tb_flush(env);
        }
+       //cpu_dump_state(env, stderr, fprintf, 0);
        return;
 
 sigill_and_return:
        force_sig(TARGET_SIGILL);
 sigsegv:
+       //fprintf(stderr, "force_sig\n");
        force_sig(TARGET_SIGSEGV);
 }
 static inline int
@@ -1542,13 +1541,16 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka,
 long do_sigreturn(CPUState *env)
 {
         struct target_signal_frame *sf;
-        unsigned long up_psr, pc, npc;
+        uint32_t up_psr, pc, npc;
         target_sigset_t set;
+        sigset_t host_set;
         __siginfo_fpu_t *fpu_save;
-        int err;
+        int err, i;
 
-        sf = (struct new_signal_frame *) env->regwptr[UREG_FP];
-       fprintf(stderr, "sigreturn sf: %lx\n", &sf);
+        sf = (struct target_signal_frame *) env->regwptr[UREG_FP];
+       fprintf(stderr, "sigreturn\n");
+       fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]);
+       //cpu_dump_state(env, stderr, fprintf, 0);
 
         /* 1. Make sure we are not getting garbage from the user */
 #if 0
@@ -1567,36 +1569,41 @@ long do_sigreturn(CPUState *env)
                 goto segv_and_exit;
 
         /* 2. Restore the state */
-        up_psr = env->psr;
-        //err |= __copy_from_user(regs, &sf->info.si_regs, sizeof (struct pt_regs)
-       //);
+        err |= __get_user(up_psr, &sf->info.si_regs.psr);
+
         /* User can only change condition codes and FPU enabling in %psr. */
         env->psr = (up_psr & ~(PSR_ICC /* | PSR_EF */))
                   | (env->psr & (PSR_ICC /* | PSR_EF */));
-       fprintf(stderr, "psr: %lx\n", env->psr);
+       fprintf(stderr, "psr: %x\n", env->psr);
+       env->pc = pc-4;
+       env->npc = pc;
+        err |= __get_user(env->y, &sf->info.si_regs.y);
+       for (i=0; i < 7; i++) {
+               err |= __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
+       }
+       for (i=0; i < 7; i++) {
+               err |= __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
+       }
 
         err |= __get_user(fpu_save, &sf->fpu_save);
 
-        if (fpu_save)
-                err |= restore_fpu_state(env, fpu_save);
+        //if (fpu_save)
+        //        err |= restore_fpu_state(env, fpu_save);
 
         /* This is pretty much atomic, no amount locking would prevent
          * the races which exist anyways.
          */
         err |= __get_user(set.sig[0], &sf->info.si_mask);
-        //err |= __copy_from_user(&set.sig[1], &sf->extramask,
-        //                        (_NSIG_WORDS-1) * sizeof(unsigned int));
+        for(i = 1; i < TARGET_NSIG_WORDS; i++) {
+            err |= (__get_user(set.sig[i], &sf->extramask[i - 1]));
+        }
+
+        target_to_host_sigset_internal(&host_set, &set);
+        sigprocmask(SIG_SETMASK, &host_set, NULL);
 
         if (err)
                 goto segv_and_exit;
 
-#if 0
-        sigdelsetmask(&set, ~_BLOCKABLE);
-        spin_lock_irq(&current->sigmask_lock);
-        current->blocked = set;
-        recalc_sigpending(current);
-        spin_unlock_irq(&current->sigmask_lock);
-#endif
        fprintf(stderr, "returning %lx\n", env->regwptr[0]);
         return env->regwptr[0];
 
diff --git a/pc-bios/proll.bin b/pc-bios/proll.bin
deleted file mode 100644 (file)
index 0489cc2..0000000
Binary files a/pc-bios/proll.bin and /dev/null differ
diff --git a/pc-bios/proll.elf b/pc-bios/proll.elf
new file mode 100644 (file)
index 0000000..e274b0d
Binary files /dev/null and b/pc-bios/proll.elf differ
index b0860e26f47c1172ea35aa5617378ca407649eb2..18a157512a9ab1bef95a44a403fb5b27aecc8b42 100644 (file)
-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();
+diff -ruN proll_18.orig/Makefile proll-patch4/Makefile
+--- proll_18.orig/Makefile     2002-09-13 14:16:59.000000000 +0000
++++ proll-patch4/Makefile      2004-11-13 15:50:49.000000000 +0000
+@@ -4,6 +4,7 @@
+       make -C krups-ser    all
+       make -C espresso     all
+       make -C espresso-ser all
++      make -C qemu all
  
+ clean:
+       make -C mrcoffee clean
+@@ -11,3 +12,4 @@
+       make -C krups-ser    clean
+       make -C espresso     clean
+       make -C espresso-ser clean
++      make -C qemu clean
+diff -ruN proll_18.orig/qemu/head.S proll-patch4/qemu/head.S
+--- proll_18.orig/qemu/head.S  1970-01-01 00:00:00.000000000 +0000
++++ proll-patch4/qemu/head.S   2004-11-13 15:50:49.000000000 +0000
+@@ -0,0 +1,515 @@
++/**
++ ** Standalone startup code for Linux PROM emulator.
++ ** Copyright 1999 Pete A. Zaitcev
++ ** This code is licensed under GNU General Public License.
++ **/
++/*
++ * $Id: proll.patch,v 1.2 2004-12-19 23:18:01 bellard Exp $
++ */
++
++#include <psr.h>
++#include <asi.h>
++#include <crs.h>
++/* #include <asm/head.h> */   /* Trap entries. Do not use. */
++#include "phys_jj.h"
++
++#define C_LABEL(name) name
++#define REGWIN_SZ   0x40
++
++#define WRITE_PAUSE    nop; nop; nop; /* Have to do this after %wim/%psr chg */
++
++  /* 22 is 24-2, (va)>>(SRMMU_PGDIR_SHIFT-PTESIZESHFT) */
++#define VATOPGDOFF(va) (((va)>>22)&0x3FC)
++#define VATOPMDOFF(va) (((va)>>16)&0xFC)
++
++#define NOP_INSN       0x01000000     /* Used to patch sparc_save_state */
++
++/* Here are some trap goodies */
++
++#if 0
++/* Generic trap entry. */
++#define TRAP_ENTRY(type, label) \
++      rd %psr, %l0; b label; rd %wim, %l3; nop;
++#endif
++
++/* Data/text faults. */
++#define SRMMU_TFAULT rd %psr, %l0; rd %wim, %l3; b C_LABEL(srmmu_fault); mov 1, %l7;
++#define SRMMU_DFAULT rd %psr, %l0; rd %wim, %l3; b C_LABEL(srmmu_fault); mov 0, %l7;
++
++#if 0
++/* This is for traps we should NEVER get. */
++#define BAD_TRAP(num) \
++        rd %psr, %l0; mov num, %l7; b bad_trap_handler; rd %wim, %l3;
++
++/* This is for traps when we want just skip the instruction which caused it */
++#define SKIP_TRAP(type, name) \
++      jmpl %l2, %g0; rett %l2 + 4; nop; nop;
++
++/* Notice that for the system calls we pull a trick.  We load up a
++ * different pointer to the system call vector table in %l7, but call
++ * the same generic system call low-level entry point.  The trap table
++ * entry sequences are also HyperSparc pipeline friendly ;-)
++ */
++
++/* Software trap for Linux system calls. */
++#define LINUX_SYSCALL_TRAP \
++        sethi %hi(C_LABEL(sys_call_table)), %l7; \
++        or %l7, %lo(C_LABEL(sys_call_table)), %l7; \
++        b linux_sparc_syscall; \
++        rd %psr, %l0;
++
++/* Software trap for SunOS4.1.x system calls. */
++#define SUNOS_SYSCALL_TRAP \
++        rd %psr, %l0; \
++        sethi %hi(C_LABEL(sunos_sys_table)), %l7; \
++        b linux_sparc_syscall; \
++        or %l7, %lo(C_LABEL(sunos_sys_table)), %l7;
++
++/* Software trap for Slowaris system calls. */
++#define SOLARIS_SYSCALL_TRAP \
++        b solaris_syscall; \
++        rd %psr, %l0; \
++        nop; \
++        nop;
++
++#define INDIRECT_SOLARIS_SYSCALL(x) \
++      mov x, %g1; \
++      b solaris_syscall; \
++      rd %psr, %l0; \
++      nop;
++
++#define BREAKPOINT_TRAP \
++      b breakpoint_trap; \
++      rd %psr,%l0; \
++      nop; \
++      nop;
++
++/* Software trap for Sparc-netbsd system calls. */
++#define NETBSD_SYSCALL_TRAP \
++        sethi %hi(C_LABEL(sys_call_table)), %l7; \
++        or %l7, %lo(C_LABEL(sys_call_table)), %l7; \
++        b bsd_syscall; \
++        rd %psr, %l0;
++
++/* The Get Condition Codes software trap for userland. */
++#define GETCC_TRAP \
++        b getcc_trap_handler; mov %psr, %l0; nop; nop;
++
++/* The Set Condition Codes software trap for userland. */
++#define SETCC_TRAP \
++        b setcc_trap_handler; mov %psr, %l0; nop; nop;
++
++/* This is for hard interrupts from level 1-14, 15 is non-maskable (nmi) and
++ * gets handled with another macro.
++ */
++#define TRAP_ENTRY_INTERRUPT(int_level) \
++        mov int_level, %l7; rd %psr, %l0; b real_irq_entry; rd %wim, %l3;
++
++/* NMI's (Non Maskable Interrupts) are special, you can't keep them
++ * from coming in, and basically if you get one, the shows over. ;(
++ * On the sun4c they are usually asynchronous memory errors, on the
++ * the sun4m they could be either due to mem errors or a software
++ * initiated interrupt from the prom/kern on an SMP box saying "I
++ * command you to do CPU tricks, read your mailbox for more info."
++ */
++#define NMI_TRAP \
++        rd %wim, %l3; b linux_trap_nmi_sun4c; mov %psr, %l0; nop;
++
++#endif
++
++/* Window overflows/underflows are special and we need to try to be as
++ * efficient as possible here....
++ */
++#define WINDOW_SPILL \
++        rd %psr, %l0; rd %wim, %l3; b spill_window_entry; nop;
++
++#define WINDOW_FILL \
++        rd %psr, %l0; rd %wim, %l3; b fill_window_entry; nop;
++
++#define STUB_TRAP     ba stub_trap; nop; nop; nop;
++
++#define TRAP_ENTRY(a,b)               STUB_TRAP
++#define SKIP_TRAP(a,b)                STUB_TRAP
++#define SUNOS_SYSCALL_TRAP    STUB_TRAP
++#define SOLARIS_SYSCALL_TRAP  STUB_TRAP
++#define NETBSD_SYSCALL_TRAP   STUB_TRAP
++#define LINUX_SYSCALL_TRAP    STUB_TRAP
++#define BREAKPOINT_TRAP               STUB_TRAP
++#define NMI_TRAP              STUB_TRAP
++#define GETCC_TRAP            STUB_TRAP
++#define SETCC_TRAP            STUB_TRAP
++#define BAD_TRAP(n)           STUB_TRAP
++#define       TRAP_ENTRY_INTERRUPT(i)         STUB_TRAP
++#define       INDIRECT_SOLARIS_SYSCALL(i)     STUB_TRAP
++
++      .section ".text"
++      .globl start, _start
++_start:
++start:
++      .globl spill_window_entry, fill_window_entry
++C_LABEL(trapbase):
++t_zero:       b goprol; nop; nop; nop;
++t_tflt:       SRMMU_TFAULT                        /* Inst. Access Exception        */
++t_bins:       TRAP_ENTRY(0x2, bad_instruction)    /* Illegal Instruction           */
++t_pins:       TRAP_ENTRY(0x3, priv_instruction)   /* Privileged Instruction        */
++t_fpd:        TRAP_ENTRY(0x4, fpd_trap_handler)   /* Floating Point Disabled       */
++t_wovf:       WINDOW_SPILL                        /* Window Overflow               */
++t_wunf:       WINDOW_FILL                         /* Window Underflow              */
++t_mna:        TRAP_ENTRY(0x7, mna_handler)        /* Memory Address Not Aligned    */
++t_fpe:        TRAP_ENTRY(0x8, fpe_trap_handler)   /* Floating Point Exception      */
++t_dflt:       SRMMU_DFAULT                        /* Data Miss Exception           */
++t_tio:        TRAP_ENTRY(0xa, do_tag_overflow)    /* Tagged Instruction Ovrflw     */
++t_wpt:        TRAP_ENTRY(0xb, do_watchpoint)      /* Watchpoint Detected           */
++t_badc:       BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
++t_irq1:       TRAP_ENTRY_INTERRUPT(1)             /* IRQ Software/SBUS Level 1     */
++t_irq2:       TRAP_ENTRY_INTERRUPT(2)             /* IRQ SBUS Level 2              */
++t_irq3:       TRAP_ENTRY_INTERRUPT(3)             /* IRQ SCSI/DMA/SBUS Level 3     */
++t_irq4:       TRAP_ENTRY_INTERRUPT(4)             /* IRQ Software Level 4          */
++t_irq5:       TRAP_ENTRY_INTERRUPT(5)             /* IRQ SBUS/Ethernet Level 5     */
++t_irq6:       TRAP_ENTRY_INTERRUPT(6)             /* IRQ Software Level 6          */
++t_irq7:       TRAP_ENTRY_INTERRUPT(7)             /* IRQ Video/SBUS Level 5        */
++t_irq8:       TRAP_ENTRY_INTERRUPT(8)             /* IRQ SBUS Level 6              */
++t_irq9:       TRAP_ENTRY_INTERRUPT(9)             /* IRQ SBUS Level 7              */
++t_irq10:TRAP_ENTRY_INTERRUPT(10)            /* IRQ Timer #1 (one we use)     */
++t_irq11:TRAP_ENTRY_INTERRUPT(11)            /* IRQ Floppy Intr.              */
++t_irq12:TRAP_ENTRY_INTERRUPT(12)            /* IRQ Zilog serial chip         */
++t_irq13:TRAP_ENTRY_INTERRUPT(13)            /* IRQ Audio Intr.               */
++t_irq14:TRAP_ENTRY_INTERRUPT(14)            /* IRQ Timer #2                  */
++t_nmi:        NMI_TRAP                            /* Level 15 (NMI)                */
++t_racc:       TRAP_ENTRY(0x20, do_reg_access)     /* General Register Access Error */
++t_iacce:BAD_TRAP(0x21)                      /* Instr Access Error            */
++t_bad22:BAD_TRAP(0x22) BAD_TRAP(0x23)
++t_cpdis:TRAP_ENTRY(0x24, do_cp_disabled)    /* Co-Processor Disabled         */
++t_uflsh:SKIP_TRAP(0x25, unimp_flush)        /* Unimplemented FLUSH inst.     */
++t_bad26:BAD_TRAP(0x26) BAD_TRAP(0x27)
++t_cpexc:TRAP_ENTRY(0x28, do_cp_exception)   /* Co-Processor Exception        */
++t_dacce:SRMMU_DFAULT                        /* Data Access Error             */
++t_hwdz:       TRAP_ENTRY(0x2a, do_hw_divzero)     /* Division by zero, you lose... */
++t_dserr:BAD_TRAP(0x2b)                      /* Data Store Error              */
++t_daccm:BAD_TRAP(0x2c)                      /* Data Access MMU-Miss          */
++t_bad2d:               BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f)
++        BAD_TRAP(0x30) BAD_TRAP(0x31) BAD_TRAP(0x32) BAD_TRAP(0x33)
++        BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36) BAD_TRAP(0x37)
++        BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
++t_iaccm:BAD_TRAP(0x3c)                      /* Instr Access MMU-Miss         */
++ BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f)
++ BAD_TRAP(0x40) BAD_TRAP(0x41) BAD_TRAP(0x42) BAD_TRAP(0x43)
++ BAD_TRAP(0x44) BAD_TRAP(0x45) BAD_TRAP(0x46) BAD_TRAP(0x47)
++ BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a) BAD_TRAP(0x4b)
++ BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f)
++ BAD_TRAP(0x50) BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53)
++ BAD_TRAP(0x54) BAD_TRAP(0x55) BAD_TRAP(0x56) BAD_TRAP(0x57)
++ BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a) BAD_TRAP(0x5b)
++ BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
++ BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63)
++ BAD_TRAP(0x64) BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67)
++ BAD_TRAP(0x68) BAD_TRAP(0x69) BAD_TRAP(0x6a) BAD_TRAP(0x6b)
++ BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e) BAD_TRAP(0x6f)
++ BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
++ BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77)
++ BAD_TRAP(0x78) BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b)
++ BAD_TRAP(0x7c) BAD_TRAP(0x7d) BAD_TRAP(0x7e) BAD_TRAP(0x7f)
++t_sunos:SUNOS_SYSCALL_TRAP                  /* SunOS System Call             */
++t_sbkpt:BREAKPOINT_TRAP                     /* Software Breakpoint/KGDB      */
++t_divz:       BAD_TRAP(0x82)                      /* Divide by zero trap           */
++t_flwin:TRAP_ENTRY(0x83, do_flush_windows)  /* Flush Windows Trap            */
++t_clwin:BAD_TRAP(0x84)                      /* Clean Windows Trap            */
++t_rchk:       BAD_TRAP(0x85)                      /* Range Check                   */
++t_funal:BAD_TRAP(0x86)                      /* Fix Unaligned Access Trap     */
++t_iovf:       BAD_TRAP(0x87)                      /* Integer Overflow Trap         */
++t_slowl:SOLARIS_SYSCALL_TRAP                /* Slowaris System Call          */
++t_netbs:NETBSD_SYSCALL_TRAP                 /* Net-B.S. System Call          */
++t_bad8a:BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c) BAD_TRAP(0x8d)
++ BAD_TRAP(0x8e) BAD_TRAP(0x8f)
++t_linux:LINUX_SYSCALL_TRAP                  /* Linux System Call             */
++t_bad91:BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93)
++ BAD_TRAP(0x94) BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97)
++ BAD_TRAP(0x98) BAD_TRAP(0x99) BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e) BAD_TRAP(0x9f)
++t_getcc:GETCC_TRAP                          /* Get Condition Codes           */
++t_setcc:SETCC_TRAP                          /* Set Condition Codes           */
++t_bada2:BAD_TRAP(0xa2) BAD_TRAP(0xa3)
++ BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
++t_slowi:INDIRECT_SOLARIS_SYSCALL(156)
++ BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
++ BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf)
++ BAD_TRAP(0xb0) BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3)
++ BAD_TRAP(0xb4) BAD_TRAP(0xb5) BAD_TRAP(0xb6) BAD_TRAP(0xb7)
++ BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba) BAD_TRAP(0xbb)
++ BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
++t_badc0:BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3)
++ BAD_TRAP(0xc4) BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7)
++ BAD_TRAP(0xc8) BAD_TRAP(0xc9) BAD_TRAP(0xca) BAD_TRAP(0xcb)
++ BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce) BAD_TRAP(0xcf)
++ BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
++t_badd4:BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7)
++ BAD_TRAP(0xd8) BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb)
++ BAD_TRAP(0xdc) BAD_TRAP(0xdd) BAD_TRAP(0xde) BAD_TRAP(0xdf)
++ BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2) BAD_TRAP(0xe3)
++ BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
++t_bade8:BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb)
++ BAD_TRAP(0xec) BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef)
++ BAD_TRAP(0xf0) BAD_TRAP(0xf1) BAD_TRAP(0xf2) BAD_TRAP(0xf3)
++ BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6) BAD_TRAP(0xf7)
++ BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
++t_badfc:BAD_TRAP(0xfc) BAD_TRAP(0xfd)
++dbtrap:       BAD_TRAP(0xfe)                      /* Debugger/PROM breakpoint #1   */
++dbtrap2:BAD_TRAP(0xff)                      /* Debugger/PROM breakpoint #2   */       
++
++stub_trap:
++   set (PHYS_JJ_TCX_FB + 0xbf0), %g5  /* 2 cells from side */
++   set 0x00ffffff, %g4
++   sta %g4, [%g5] ASI_M_BYPASS
++1:    ba 1b; nop
++
++      .section ".bss"
++      .align 8
++bss_start:
++      .align  0x1000          ! PAGE_SIZE
++      .globl C_LABEL(bootup_user_stack)
++        .type   bootup_user_stack,#object
++        .size   bootup_user_stack,0x2000
++C_LABEL(bootup_user_stack):           .skip 0x2000
++
++      .section ".text"
++
++goprol:
++      ! %g1 contains end of memory
++      ! map PROLDATA to PROLBASE+PROLSIZE to end of ram
++      set     PROLSIZE+0x1000-PROLDATA+PROLBASE, %g2  ! add 0x1000 for temp tables
++      sub     %g1, %g2, %g2                   ! start of private memory
++      srl     %g2, 0x4, %g7                   ! ctx table at s+0x0
++      add     %g2, 0x400, %g3                 ! l1 table at s+0x400
++      srl     %g3, 0x4, %g3
++      or      %g3, 0x1, %g3
++      sta     %g3, [%g2] ASI_M_BYPASS
++      add     %g2, 0x400, %g2                 ! s+0x400
++      add     %g2, 0x800, %g3                 ! l2 table for ram (00xxxxxx) at s+0x800
++      srl     %g3, 0x4, %g3
++      or      %g3, 0x1, %g3
++      sta     %g3, [%g2] ASI_M_BYPASS
++      add     %g2, 0x500, %g3                 ! l2 table for rom (ffxxxxxx) at s+0x900
++      add     %g2, 0x3fc, %g2                 ! s+0x7fc
++      srl     %g3, 0x4, %g3
++      or      %g3, 0x1, %g3
++      sta     %g3, [%g2] ASI_M_BYPASS
++      add     %g2, 0x4, %g2                   ! s+0x800
++      set     ((7 << 2) | 2), %g3             ! 7 = U: --- S: RWX (main memory)
++      sta     %g3, [%g2] ASI_M_BYPASS
++      add     %g2, 0x200, %g3                 ! l3 table for rom at s+0xa00
++      add     %g2, 0x1d0, %g2                 ! s+0x9d0
++      srl     %g3, 0x4, %g3
++      or      %g3, 0x1, %g3
++      sta     %g3, [%g2] ASI_M_BYPASS
++      add     %g2, 0x30, %g2                  ! s+0xa00
++
++      set     PROLBASE, %g3
++      set     0x1000, %g5
++      set     (PROLDATA-PROLBASE)/0x1000, %g6 ! # of .text pages
++1:    srl     %g3, 0x4, %g4
++      or      %g4, ((7 << 2) | 2), %g4        ! 4 = U: --X S: --X (rom, execute only)
++      sta     %g4, [%g2] ASI_M_BYPASS
++      add     %g2, 4, %g2
++      add     %g3, %g5, %g3
++      deccc   %g6
++      bne     1b
++       nop
++#if 0 
++      set     (PROLDATA-PROLRODATA)/0x1000, %g6 ! # of .rodata pages
++1:    srl     %g3, 0x4, %g4
++      or      %g4, ((0 << 2) | 2), %g4        ! 0 = U: R-- S: R-- (rom, read only)
++      sta     %g4, [%g2] ASI_M_BYPASS
++      add     %g2, 4, %g2
++      add     %g3, %g5, %g3
++      deccc   %g6
++      bne     1b
++       nop
++#endif
++      set     (PROLBASE+PROLSIZE-PROLDATA)/0x1000, %g6 ! # of .bss pages
++      set     0x1000, %g4
++      sll     %g7, 0x4, %g3
++      add     %g4, %g3, %g3
++1:    srl     %g3, 0x4, %g4
++      or      %g4, ((7 << 2) | 2), %g4        ! 5 = U: R-- S: RW- (data area, read/write)
++      sta     %g4, [%g2] ASI_M_BYPASS
++      add     %g2, 4, %g2
++      add     %g3, %g5, %g3
++      deccc   %g6
++      bne     1b
++       nop
++
++      mov     %g1, %g3
++
++      set     AC_M_CTPR, %g2
++      sta     %g7, [%g2] ASI_M_MMUREGS        ! set ctx table ptr
++      set     1, %g1
++      sta     %g1, [%g0] ASI_M_MMUREGS        ! enable mmu
++
++      /*
++       * The code which enables traps is a simplified version of
++       * kernel head.S.
++       *
++       * We know number of windows as 8 so we do not calculate them.
++       * The deadwood is here for any case.
++       */
++
++      /* Turn on Supervisor, EnableFloating, and all the PIL bits.
++       * Also puts us in register window zero with traps off.
++       */
++      set     (PSR_PS | PSR_S | PSR_PIL | PSR_EF), %g2
++      wr      %g2, 0x0, %psr
++      WRITE_PAUSE
++
++      /* I want a kernel stack NOW! */
++      set     C_LABEL(bootup_user_stack), %g1
++      set     (0x2000 - REGWIN_SZ), %g2
++      add     %g1, %g2, %sp
++      mov     0, %fp                  /* And for good luck */
++
++      /* Zero out our BSS section. */
++      set     C_LABEL(bss_start) , %o0        ! First address of BSS
++      set     C_LABEL(end) , %o1              ! Last address of BSS
++      ba      2f
++       nop
++1:
++      st      %g0, [%o0]
++2:
++      subcc   %o0, %o1, %g0
++      bl      1b
++       add    %o0, 0x4, %o0
++
++      sethi   %hi( C_LABEL(ram_size) ), %o0
++      st      %g3, [%o0 + %lo( C_LABEL(ram_size) )]
++
++      mov     2, %g1
++      wr      %g1, 0x0, %wim                  ! make window 1 invalid
++      WRITE_PAUSE
++
++#if 0
++      wr  %g0, 0x0, %wim
++      WRITE_PAUSE
++      save
++      rd  %psr, %g3
++      restore
++      and  %g3, PSR_CWP, %g3
++      add  %g3, 0x1, %g3
++#else
++      or      %g0, 8, %g3
++#endif
++
++#if 0
++      sethi   %hi( C_LABEL(cputyp) ), %o0
++      st      %g7, [%o0 + %lo( C_LABEL(cputyp) )]
++
++      sethi   %hi( C_LABEL(nwindows) ), %g4
++      st      %g3, [%g4 + %lo( C_LABEL(nwindows) )]
++
++      sub     %g3, 0x1, %g3
++      sethi   %hi( C_LABEL(nwindowsm1) ), %g4
++      st      %g3, [%g4 + %lo( C_LABEL(nwindowsm1) )]
++#endif
++
++      /* Here we go, start using Linux's trap table... */
++      set     C_LABEL(trapbase), %g3
++      wr      %g3, 0x0, %tbr
++      WRITE_PAUSE
++
++      /* Finally, turn on traps so that we can call c-code. */
++      rd      %psr, %g3
++      wr      %g3, 0x0, %psr
++      WRITE_PAUSE
++
++      wr      %g3, PSR_ET, %psr
++      WRITE_PAUSE
++
++      .globl prolmain
++      call C_LABEL(prolmain)
++       nop
++
++3:
++      b       3b
++       nop
++
++/*
++ * Memory access trap handler
++ *   %l0  program %psr from trap table entry
++ *   %l1  program %pc from hardware
++ *   %l2  program %npc from hardware
++ *   %l3  program %wim from trap table entry
++ *   %l4
++ *   %l5
++ *   %l6
++ *   %l7  text flag from trap table entry
++ */
++
++      .section ".text"
++      .globl srmmu_fault
++C_LABEL(srmmu_fault):
++
++      set AC_M_SFAR, %l6
++      set AC_M_SFSR, %l5
++      lda [%l6] ASI_M_MMUREGS, %l6
++      lda [%l5] ASI_M_MMUREGS, %l5
++
++      set ignore_fault, %l5
++      ld [%l5], %l5
++      subcc %l5, %g0, %g0             /* NULL pointer trap faults always */
++      be 3f
++       nop
++      subcc %l5, %l6, %g0
++      be 2f
++       nop
++3:
++
++   set (PHYS_JJ_TCX_FB + 0xbf0), %g5  /* 2 cells from side */
++   set 0x00ffffff, %g4
++   sta %g4, [%g5] ASI_M_BYPASS
++   add %g5, 8, %g5                    /* On right side */
++   sta %g4, [%g5] ASI_M_BYPASS
++1:    ba 1b; nop
++
++2:
++      set C_LABEL(fault_ignored), %l5
++      mov 1, %l6
++      st %l6, [%l5]
++
++      /*
++       * Skip the faulting instruction.
++       * I think it works when next instruction is a branch even.
++       */
++      or %l2, 0, %l1
++      add %l2, 4, %l2
++
++      wr %l0, 0, %psr
++      WRITE_PAUSE
++      jmp %l1
++      rett %l2
++
++/*
++ * Slow external versions of st_bypass and ld_bypass.
++ * rconsole.c uses inlines. We call these in places which are not speed
++ * critical, to avoid compiler bugs.
++ */
++      .globl C_LABEL(st_bypass)
++C_LABEL(st_bypass):
++      retl
++       sta %o1, [%o0] ASI_M_BYPASS
++      .globl C_LABEL(ld_bypass)
++C_LABEL(ld_bypass):
++      retl
++       lda [%o0] ASI_M_BYPASS, %o0
++      .globl C_LABEL(sth_bypass)
++C_LABEL(sth_bypass):
++      retl
++       stha %o1, [%o0] ASI_M_BYPASS
++      .globl C_LABEL(ldh_bypass)
++C_LABEL(ldh_bypass):
++      retl
++       lduha [%o0] ASI_M_BYPASS, %o0
++      .globl C_LABEL(stb_bypass)
++C_LABEL(stb_bypass):
++      retl
++       stba %o1, [%o0] ASI_M_BYPASS
++      .globl C_LABEL(ldb_bypass)
++C_LABEL(ldb_bypass):
++      retl
++       lduba [%o0] ASI_M_BYPASS, %o0
+diff -ruN proll_18.orig/qemu/main.c proll-patch4/qemu/main.c
+--- proll_18.orig/qemu/main.c  1970-01-01 00:00:00.000000000 +0000
++++ proll-patch4/qemu/main.c   2004-11-23 19:05:34.000000000 +0000
+@@ -0,0 +1,178 @@
++/**
++ ** Proll (PROM replacement)
++ ** Copyright 1999 Pete Zaitcev
++ ** This code is licensed under GNU General Public License.
++ **/
++#include <stdarg.h>
++
++// #include <asm/contregs.h>
++#include <asi.h>
++#include "pgtsrmmu.h"
++#include "iommu.h"            /* Typical SBus IOMMU for sun4m */
++#include "phys_jj.h"
++#include "vconsole.h"
++#include "version.h"
++#include <general.h>          /* __P() */
++#include <net.h>              /* init_net() */
++#include <romlib.h>           /* we are a provider for part of this. */
++#include <netpriv.h>          /* myipaddr */
++#include <arpa.h>
++#include <system.h>           /* our own prototypes */
++
++static void init_idprom(void);
++static void makepages_q(struct phym *t, unsigned int highbase);
++
++struct vconterm dp0;
++struct mem cmem;              /* Current memory, virtual */
++struct mem cio;                       /* Current I/O space */
++struct phym pmem;             /* Current phys. mem. */
++struct iommu ciommu;          /* Our IOMMU on sun4m */
++
++static char *hw_idprom;
++int ignore_fault, fault_ignored, ram_size;
++
++/*
++ */
++void prolmain()
++{
++      //static const char fname[14] = "00000000.PROL";
++      static struct banks bb;
++      unsigned int hiphybas;
++      const void *romvec;
++
++      vcon_init(&dp0, PHYS_JJ_TCX_FB);
++      printk("PROLL %s QEMU\n", PROLL_VERSION_STRING);
++      printk("%d MB total\n", ram_size/(1024*1024));
++
++      bb.nbanks = 1;
++      bb.bankv[0].start = 0;
++      bb.bankv[0].length = ram_size;
++
++      hiphybas = ram_size - PROLSIZE;
++
++      mem_init(&cmem, (char *) &_end, (char *)(PROLBASE+PROLSIZE));
++      makepages_q(&pmem, hiphybas);
++      init_mmu_swift((unsigned int)pmem.pctp - PROLBASE + hiphybas);
++
++      mem_init(&cio, (char *)(PROLBASE+PROLSIZE),
++          (char *)(PROLBASE+PROLSIZE+IOMAPSIZE));
++
++      iommu_init(&ciommu, hiphybas);
++
++      /*
++       */
++      init_idprom();
++      sched_init();
++      le_probe();
++      init_net();
++
++#if 0
++#if 0 /* RARP */
++      if (rarp() != 0) fatal();
++      /* printrarp(); */
++      xtoa(myipaddr, fname, 8);
++      if (load(servaddr, fname) != 0) fatal();
++#else
++      if (bootp() != 0) fatal();
++      /*
++       * boot_rec.bp_file cannot be used because system PROM
++       * uses it to locate ourselves. If we load from boot_rec.bp_file,
++       * we will loop reloading PROLL over and over again.
++       * Thus we use traditional PROLL scheme HEXIPADDR.PROL (single L).
++       */
++      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);
++      //set_timeout(5);  while (!chk_timeout()) { }  /* P3: let me read */
++
++      {
++              void (*entry)(const void *, int, int, int, int) = (void (*)(const void*, int, int, int, int)) LOADBASE;
++              entry(romvec, 0, 0, 0, 0);
++      }
++
++      mem_fini(&cmem);
++      vcon_fini(&dp0);
++}
++
++/*
++ * dvma_alloc over iommu_alloc.
++ */
++void *dvma_alloc(int size, unsigned int *pphys)
++{
++      return iommu_alloc(&ciommu, size, pphys);
++}
++
++/*
++ */
++void udelay(unsigned long usecs)
++{
++      int i, n;
++      n = usecs*50;
++      for (i = 0; i < n; i++) { }
++}
++
++static void init_idprom()
++{
++      char *va_prom;
++
++      if ((va_prom = map_io(PHYS_JJ_EEPROM, PHYS_JJ_EEPROM_SIZE)) == NULL) {
++              printk("init_idprom: cannot map eeprom\n");
++              fatal();
++      }
++      bcopy(va_prom + PHYS_JJ_IDPROM_OFF, idprom, IDPROM_SIZE);
++      /*
++       * hw_idprom is not used anywhere.
++       * It's just as we hate to leave hanging pointers (I/O page here).
++       */
++      hw_idprom = va_prom; 
++}
++
++/*
++ * Make CPU page tables.
++ * Returns pointer to context table.
++ * Here we ignore memory allocation errors which "should not happen"
++ * because we cannot print anything anyways if memory initialization fails.
++ */
++void makepages_q(struct phym *t, unsigned int highbase)
++{
++      unsigned int *ctp, *l1, pte;
++      int i;
++      unsigned int pa, va;
++
++      ctp = mem_zalloc(&cmem, NCTX_SWIFT*sizeof(int), NCTX_SWIFT*sizeof(int));
++      l1 = mem_zalloc(&cmem, 256*sizeof(int), 256*sizeof(int));
++
++      pte = SRMMU_ET_PTD | (((unsigned int)l1 - PROLBASE + highbase) >> 4);
++      for (i = 0; i < NCTX_SWIFT; i++) {
++              ctp[i] = pte;
++      }
++
++      pa = PROLBASE;
++      for (va = PROLBASE; va < PROLDATA; va += PAGE_SIZE) {
++              map_page(l1, va, pa, 0, highbase);
++              pa += PAGE_SIZE;
++      }
++      pa = highbase + PROLDATA - PROLBASE;
++      for (va = PROLDATA; va < PROLBASE + PROLSIZE; va += PAGE_SIZE) {
++              map_page(l1, va, pa, 0, highbase);
++              pa += PAGE_SIZE;
++      }
++
++      /* We need to start from LOADBASE, but kernel wants PAGE_SIZE. */
++      pa = 0;
++      for (va = 0; va < LOWMEMSZ; va += PAGE_SIZE) {
++              map_page(l1, va, pa, 0, highbase);
++              pa += PAGE_SIZE;
++      }
++
++      t->pctp = ctp;
++      t->pl1 = l1;
++      t->pbas = highbase;
++}
+diff -ruN proll_18.orig/qemu/Makefile proll-patch4/qemu/Makefile
+--- proll_18.orig/qemu/Makefile        1970-01-01 00:00:00.000000000 +0000
++++ proll-patch4/qemu/Makefile 2004-11-13 15:50:49.000000000 +0000
+@@ -0,0 +1,119 @@
++#
++# proll:
++# qemu/Makefile - make PROLL for QEMU
++# $Id: proll.patch,v 1.2 2004-12-19 23:18:01 bellard Exp $
++#
++# Copyright 1999 Pete Zaitcev
++# This is Free Software is licensed under terms of GNU General Public License.
++#
++
++CC = gcc
++
++#CROSS = /usr/local/sparc/bin/sparc-sun-linux-
++CROSS = sparc-unknown-linux-gnu-
++
++CROSSCC = $(CROSS)gcc
++CROSSLD = $(CROSS)ld
++CROSSNM = $(CROSS)nm
++
++RM = /bin/rm -f
++ELFTOAOUT = elftoaout
++
++#
++SRC = ../src
++
++# Due to remapping algorithm PROLBASE should be algned on PMD.
++# We make PROLBASE a define instead of using _start because we
++# want to shift it to form a PGD entry. A relocatable label will not work.
++# Linux kernel expects us to be at LINUX_OPPROM_BEGVM <asm-sparc/openprom.h>.
++PROLBASE =   0xffd00000
++PROLRODATA = 0xffd07000
++PROLDATA =   0xffd09000
++PROLSIZE = (240*1024)
++
++# Linux
++# Fixed %g6 is for arch/sparc/kernel/head.S, it seems ok w/o -ffixed-g6.
++# Kernel uses -fcall-used-g5 -fcall-used-g7, we probably do not need them.
++# __ANSI__ is supposed to be on by default but it is not.
++CFLAGS = -O2 -Wall -DPROLBASE=$(PROLBASE) -DPROLDATA=$(PROLDATA) -DPROLRODATA=$(PROLRODATA) -D__ANSI__=1 -I$(SRC) -mcpu=hypersparc -g
++ASFLAGS = -D__ASSEMBLY__ -I$(SRC) -DPROLRODATA=$(PROLRODATA) -DPROLDATA=$(PROLDATA) -DPROLSIZE=$(PROLSIZE) -g
++# Solaris or Linux/i386 cross compilation
++#CFLAGS = -Iinclude -O
++
++LDFLAGS = -N -Ttext $(PROLBASE) --section-start .rodata=$(PROLRODATA) -Tdata $(PROLDATA) -Tbss $(PROLDATA)
++
++ALL = proll.aout
++PROLLEXE = proll.elf
++
++OBJS = head.o wuf.o wof.o main.o vconsole.o hconsole.o rconsole.o \
++ printf.o le.o system.o iommu.o \
++ arp.o netinit.o bootp.o packet.o tftp.o udp.o sched_4m.o openprom.o
++
++all:           $(ALL)
++
++$(PROLLEXE):   $(OBJS)
++      $(CROSSLD) $(LDFLAGS) -o $(PROLLEXE) $(OBJS)
++
++head.o:         head.S $(SRC)/phys_jj.h \
++  $(SRC)/asi.h $(SRC)/psr.h $(SRC)/crs.h
++      $(CROSSCC) $(ASFLAGS) -DPROLBASE=$(PROLBASE) -o $*.o -c $*.S
++
++main.o:         main.c $(SRC)/asi.h $(SRC)/pgtsrmmu.h $(SRC)/iommu.h \
++  $(SRC)/phys_jj.h $(SRC)/vconsole.h $(SRC)/version.h $(SRC)/general.h \
++  $(SRC)/net.h $(SRC)/romlib.h $(SRC)/netpriv.h $(SRC)/arpa.h $(SRC)/system.h
++      $(CROSSCC) $(CFLAGS) -c $*.c
++openprom.o:   openprom.c $(SRC)/openprom.h $(SRC)/general.h $(SRC)/romlib.h \
++  $(SRC)/vconsole.h $(SRC)/system.h $(SRC)/phys_jj.h
++      $(CROSSCC) $(CFLAGS) -c $*.c
++
++system.o:       $(SRC)/system.c $(SRC)/vconsole.h $(SRC)/pgtsrmmu.h \
++  $(SRC)/timer.h $(SRC)/general.h $(SRC)/net.h $(SRC)/romlib.h $(SRC)/asi.h \
++  $(SRC)/netpriv.h $(SRC)/arpa.h $(SRC)/system.h $(SRC)/crs.h
++      $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
++iommu.o:        $(SRC)/iommu.c $(SRC)/pgtsrmmu.h $(SRC)/phys_jj.h $(SRC)/iommu.h \
++ $(SRC)/vconsole.h $(SRC)/general.h $(SRC)/romlib.h $(SRC)/system.h $(SRC)/asi.h
++      $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
++vconsole.o:   $(SRC)/vconsole.c $(SRC)/vconsole.h $(SRC)/hconsole.h
++      $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
++hconsole.o:   $(SRC)/hconsole.c $(SRC)/hconsole.h $(SRC)/rconsole.h $(SRC)/phys_jj.h
++      $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
++rconsole.o:   $(SRC)/rconsole.c $(SRC)/rconsole.h
++      $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
++printf.o:       $(SRC)/printf.c
++      $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
++le.o:         $(SRC)/le.c $(SRC)/dma.h $(SRC)/system.h $(SRC)/netpriv.h $(SRC)/romlib.h $(SRC)/general.h $(SRC)/net.h $(SRC)/phys_jj.h
++      $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
++
++arp.o:                $(SRC)/arp.c $(SRC)/general.h $(SRC)/net.h $(SRC)/romlib.h $(SRC)/netpriv.h $(SRC)/arp.h
++      $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
++netinit.o:    $(SRC)/netinit.c $(SRC)/general.h $(SRC)/net.h $(SRC)/romlib.h $(SRC)/netpriv.h $(SRC)/arp.h $(SRC)/ip.h $(SRC)/udp.h
++      $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
++tftp.o:               $(SRC)/tftp.c $(SRC)/general.h $(SRC)/net.h $(SRC)/arpa.h $(SRC)/romlib.h $(SRC)/tftp.h
++      $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
++udp.o:                $(SRC)/udp.c $(SRC)/general.h $(SRC)/net.h $(SRC)/romlib.h $(SRC)/netpriv.h $(SRC)/arp.h $(SRC)/ip.h $(SRC)/udp.h
++      $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
++packet.o:     $(SRC)/packet.c $(SRC)/general.h $(SRC)/net.h $(SRC)/romlib.h $(SRC)/netpriv.h
++      $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
++sched_4m.o:   $(SRC)/sched_4m.c $(SRC)/system.h $(SRC)/general.h $(SRC)/romlib.h $(SRC)/phys_jj.h
++      $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
++bootp.o:      $(SRC)/bootp.c $(SRC)/general.h $(SRC)/net.h \
++  $(SRC)/arpa.h $(SRC)/romlib.h $(SRC)/system.h $(SRC)/bootp.h
++      $(CROSSCC) $(CFLAGS) -DNOBPEXT=1 -c $(SRC)/$*.c
++
++wuf.o:                $(SRC)/wuf.S
++      $(CROSSCC) $(ASFLAGS) -o $*.o -c $(SRC)/$*.S
++wof.o:                $(SRC)/wof.S
++      $(CROSSCC) $(ASFLAGS) -o $*.o -c $(SRC)/$*.S
++
++#genlab.o:      genlab.c
++#     $(CC) -c $*.c
++#
++#genlab:        genlab.o
++#     $(CC) -o genlab genlab.o
++
++clean:
++      $(RM) $(OBJS)
++      $(RM) $(PROLLEXE) proll.aout
++
++proll.aout:   $(PROLLEXE)
++      $(ELFTOAOUT) -o proll.aout $(PROLLEXE)
+diff -ruN proll_18.orig/qemu/openprom.c proll-patch4/qemu/openprom.c
+--- proll_18.orig/qemu/openprom.c      1970-01-01 00:00:00.000000000 +0000
++++ proll-patch4/qemu/openprom.c       2004-11-23 19:14:05.000000000 +0000
+@@ -0,0 +1,596 @@
++/*
++ * PROM interface support
++ * Copyright 1996 The Australian National University.
++ * Copyright 1996 Fujitsu Laboratories Limited
++ * Copyright 1999 Pete A. Zaitcev
++ * This software may be distributed under the terms of the Gnu
++ * Public License version 2 or later
++ */
++
++#include <openprom.h>
++#include <general.h>
++#include <romlib.h>
++#include <system.h>
++#include <vconsole.h>
++#include "phys_jj.h"
++
++struct property {
++      const char *name;
++      const char *value;
++      const int length;
++};
++
++struct node {
++      const struct property *properties;
++      /* short */ const int sibling;
++      /* short */ const int child;
++};
++
++static int obp_nextnode(int node);
++static int obp_child(int node);
++static int obp_proplen(int node, char *name);
++static int obp_getprop(int node, char *name, char *val);
++static int obp_setprop(int node, char *name, char *val, int len);
++static const char *obp_nextprop(int node, char *name);
++
++static char obp_idprom[IDPROM_SIZE];
++static const struct property null_properties = { NULL, NULL, -1 };
++static const int prop_true = -1;
++
++static const struct property propv_root[] = {
++      {"name",        "SUNW,JavaStation-1", sizeof("SUNW,JavaStation-1") },
++      {"idprom",      obp_idprom, IDPROM_SIZE},
++      {"banner-name", "JavaStation", sizeof("JavaStation")},
++      {"compatible",  "sun4m", 6},
++      {NULL, NULL, -1}
++};
++
++static const int prop_iommu_reg[] = {
++      0x0, 0x10000000, 0x00000300,
++};
++static const struct property propv_iommu[] = {
++      {"name",        "iommu", sizeof("iommu")},
++      {"reg",         (char*)&prop_iommu_reg[0], sizeof(prop_iommu_reg) },
++      {NULL, NULL, -1}
++};
++
++static const int prop_sbus_ranges[] = {
++      0x0, 0x0, 0x0, 0x30000000, 0x10000000,
++      0x1, 0x0, 0x0, 0x40000000, 0x10000000,
++      0x2, 0x0, 0x0, 0x50000000, 0x10000000,
++      0x3, 0x0, 0x0, 0x60000000, 0x10000000,
++      0x4, 0x0, 0x0, 0x70000000, 0x10000000,
++};
++static const struct property propv_sbus[] = {
++      {"name",        "sbus", 5},
++      {"ranges",      (char*)&prop_sbus_ranges[0], sizeof(prop_sbus_ranges)},
++      {NULL, NULL, -1}
++};
++
++static const int prop_tcx_regs[] = {
++      0x2, 0x00800000, 0x00100000,
++      0x2, 0x02000000, 0x00000001,
++      0x2, 0x04000000, 0x00800000,
++      0x2, 0x06000000, 0x00800000,
++      0x2, 0x0a000000, 0x00000001,
++      0x2, 0x0c000000, 0x00000001,
++      0x2, 0x0e000000, 0x00000001,
++      0x2, 0x00700000, 0x00001000,
++      0x2, 0x00200000, 0x00000004,
++      0x2, 0x00300000, 0x0000081c,
++      0x2, 0x00000000, 0x00010000,
++      0x2, 0x00240000, 0x00000004,
++      0x2, 0x00280000, 0x00000001,
++};
++
++#if 1 /* Zaitcev */
++static const int pixfreq = 0x03dfd240;
++static const int hbporch = 0xa0;
++static const int vfreq = 0x3c;
++#endif
++#if 0 /* Kevin Boone - 70Hz refresh */
++static const int pixfreq = 0x047868C0;
++static const int hbporch = 0x90;
++static const int vfreq = 0x46;
++#endif
++
++static const int vbporch = 0x1d;
++static const int vsync = 0x6;
++static const int hsync = 0x88;
++static const int vfporch = 0x3;
++static const int hfporch = 0x18;
++static const int height = 0x300;
++static const int width = 0x400;
++static const int linebytes = 0x400;
++static const int depth = 8;
++static const int tcx_intr[] = { 5, 0 };
++static const int tcx_interrupts = 5;
++static const struct property propv_sbus_tcx[] = {
++      {"name",        "SUNW,tcx", sizeof("SUNW,tcx")},
++      {"vbporch",     (char*)&vbporch, sizeof(int)},
++      {"hbporch",     (char*)&hbporch, sizeof(int)},
++      {"vsync",       (char*)&vsync, sizeof(int)},
++      {"hsync",       (char*)&hsync, sizeof(int)},
++      {"vfporch",     (char*)&vfporch, sizeof(int)},
++      {"hfporch",     (char*)&hfporch, sizeof(int)},
++      {"pixfreq",     (char*)&pixfreq, sizeof(int)},
++      {"vfreq",       (char*)&vfreq, sizeof(int)},
++      {"height",      (char*)&height, sizeof(int)},
++      {"width",       (char*)&width, sizeof(int)},
++      {"linebytes",   (char*)&linebytes, sizeof(int)},
++      {"depth",       (char*)&depth, sizeof(int)},
++      {"reg",         (char*)&prop_tcx_regs[0], sizeof(prop_tcx_regs)},
++      {"tcx-8-bit",   (char*)&prop_true, 0},
++      {"intr",        (char*)&tcx_intr[0], sizeof(tcx_intr)},
++      {"interrupts",  (char*)&tcx_interrupts, sizeof(tcx_interrupts)},
++      {"device_type", "display", sizeof("display")},
++      {NULL, NULL, -1}
++};
++
++static const int prop_cs4231_reg[] = {
++      0x3, 0x0C000000, 0x00000040
++};
++static const int cs4231_interrupts = 5;
++static const int cs4231_intr[] = { 5, 0 };
++
++static const struct property propv_sbus_cs4231[] = {
++      {"name",        "SUNW,CS4231", sizeof("SUNW,CS4231") },
++      {"intr",        (char*)&cs4231_intr[0], sizeof(cs4231_intr) },
++      {"interrupts",  (char*)&cs4231_interrupts, sizeof(cs4231_interrupts) }, 
++      {"reg",         (char*)&prop_cs4231_reg[0], sizeof(prop_cs4231_reg) },
++      {"device_type", "serial", sizeof("serial") },
++      {"alias",       "audio", sizeof("audio") },
++      {NULL, NULL, -1}
++};
++
++static const int cpu_nctx = NCTX_SWIFT;
++static const int cpu_cache_line_size = 0x20;
++static const int cpu_cache_nlines = 0x200;
++static const 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}
++};
++
++static const int prop_obio_ranges[] = {
++      0x0, 0x0, 0x0, 0x71000000, 0x01000000,
++};
++static const struct property propv_obio[] = {
++      {"name",        "obio", 5 },
++      {"ranges",      (char*)&prop_obio_ranges[0], sizeof(prop_obio_ranges) },
++      {NULL, NULL, -1}
++};
++
++static const int prop_auxio_reg[] = {
++      0x0, 0x00900000, 0x00000001,
++};
++static const struct property propv_obio_auxio[] = {
++      {"name",        "auxio", sizeof("auxio") },
++      {"reg",         (char*)&prop_auxio_reg[0], sizeof(prop_auxio_reg) },
++      {NULL, NULL, -1}
++};
++
++static const int prop_int_reg[] = {
++      0x0, 0x00e00000, 0x00000010,
++      0x0, 0x00e10000, 0x00000010,
++};
++static const struct property propv_obio_int[] = {
++      {"name",        "interrupt", sizeof("interrupt")},
++      {"reg",         (char*)&prop_int_reg[0], sizeof(prop_int_reg) },
++      {NULL, NULL, -1}
++};
++
++static const int prop_cnt_reg[] = {
++      0x0, 0x00d00000, 0x00000010,
++      0x0, 0x00d10000, 0x00000010,
++};
++static const struct property propv_obio_cnt[] = {
++      {"name",        "counter", sizeof("counter")},
++      {"reg",         (char*)&prop_cnt_reg[0], sizeof(prop_cnt_reg) },
++      {NULL, NULL, -1}
++};
++
++static const int prop_eeprom_reg[] = {
++      0x0, 0x00200000, 0x00002000,
++};
++static const struct property propv_obio_eep[] = {
++      {"name",        "eeprom", sizeof("eeprom")},
++      {"reg",         (char*)&prop_eeprom_reg[0], sizeof(prop_eeprom_reg) },
++      {"model",       "mk48t08", sizeof("mk48t08")},
++      {NULL, NULL, -1}
++};
++
++static const int prop_su_reg[] = {
++      0x0, 0x003002f8, 0x00000008,
++};
++static const struct property propv_obio_su[] = {
++      {"name",        "su", sizeof("su")},
++      {"reg",         (char*)&prop_su_reg[0], sizeof(prop_su_reg) },
++      {NULL, NULL, -1}
++};
++
++static const int prop_zs_intr[] = { 0x26, 0x0 };
++static const int prop_zs_reg[] = {
++      0x4, 0x00000000, 0x0000000f,
++};
++static const int prop_zs_slave[] = { 0x1 };
++static const struct property propv_obio_zs[] = {
++      {"name",        "zs", sizeof("zs")},
++      {"reg",         (char*)&prop_zs_reg[0], sizeof(prop_zs_reg) },
++      {"reg",         (char*)&prop_zs_slave[0], sizeof(prop_zs_slave) },
++      {"device_type", "serial", sizeof("serial") },
++      {NULL, NULL, -1}
++};
++
++static const int prop_zs1_intr[] = { 0x26, 0x0 };
++static const int prop_zs1_reg[] = {
++      0x4, 0x00100000, 0x0000000f,
++};
++static const int prop_zs1_slave[] = { 0x0 };
++static const struct property propv_obio_zs1[] = {
++      {"name",        "zs", sizeof("zs")},
++      {"reg",         (char*)&prop_zs1_reg[0], sizeof(prop_zs1_reg) },
++      {"reg",         (char*)&prop_zs1_slave[0], sizeof(prop_zs1_slave) },
++      {"device_type", "serial", sizeof("serial") },
++      {NULL, NULL, -1}
++};
++
++static const int prop_ledma_reg[] = {
++      0x4, 0x08400010, 0x00000020,
++};
++static const int prop_ledma_burst = 0x3f;
++static const struct property propv_sbus_ledma[] = {
++      {"name",        "ledma", sizeof("ledma")},
++      {"reg",         (char*)&prop_ledma_reg[0], sizeof(prop_ledma_reg) },
++      {"burst-sizes", (char*)&prop_ledma_burst, sizeof(int) },
++      {NULL, NULL, -1}
++};
++
++static const int prop_le_reg[] = {
++      0x4, 0x08c00000, 0x00000004,
++};
++static const int prop_le_busmaster_regval = 0x7;
++static const int prop_le_intr[] = { 0x26, 0x0 };
++static const struct property propv_sbus_ledma_le[] = {
++      {"name",        "le", sizeof("le")},
++      {"reg",         (char*)&prop_le_reg[0], sizeof(prop_le_reg) },
++      {"busmaster-regval",    (char*)&prop_le_busmaster_regval, sizeof(int)},
++      {"intr",        (char*)&prop_le_intr[0], sizeof(prop_le_intr) },
++      {NULL, NULL, -1}
++};
++
++static const struct node nodes[] = {
++      { &null_properties,      1,  0 }, /* 0 = big brother of root */
++      { propv_root,            0,  2 }, /*  1 "/" */
++      { propv_iommu,           8,  3 }, /*  2 "/iommu" */
++      { propv_sbus,            0,  4 }, /*  3 "/iommu/sbus" */
++      { propv_sbus_tcx,        5,  0 }, /*  4 "/iommu/sbus/SUNW,tcx" */
++      { propv_sbus_ledma,      7,  6 }, /*  5 "/iommu/sbus/ledma" */
++      { propv_sbus_ledma_le,   0,  0 }, /*  6 "/iommu/sbus/ledma/le" */
++      { propv_sbus_cs4231,     0,  0 }, /*  7 "/iommu/sbus/SUNW,CS4231 */
++      { propv_cpu,             9,  0 }, /*  8 "/STP1012PGA" */
++      { propv_obio,            0, 10 }, /*  9 "/obio" */
++      { propv_obio_int,       11,  0 }, /* 10 "/obio/interrupt" */
++      { propv_obio_cnt,       12,  0 }, /* 11 "/obio/counter" */
++      { propv_obio_eep,       13,  0 }, /* 12 "/obio/eeprom" */
++      { propv_obio_su,        14,  0 }, /* 13 "/obio/su" */
++      { propv_obio_auxio,      0,  0 }, /* 14 "/obio/auxio" */
++      { propv_obio_zs,         0,  0 }, /* 14 "/obio/zs@0,0" */
++      { propv_obio_zs1,        0,  0 }, /* 14 "/obio/zs@0,100000" */
++};
++
++static struct linux_mlist_v0 totphys[MAX_BANKS];
++static struct linux_mlist_v0 totmap[1];
++static struct linux_mlist_v0 totavail[MAX_BANKS];
++
++static struct linux_mlist_v0 *ptphys;
++static struct linux_mlist_v0 *ptmap;
++static struct linux_mlist_v0 *ptavail;
++
++static const struct linux_nodeops nodeops0 = {
++        obp_nextnode, /* int (*no_nextnode)(int node); */
++        obp_child,    /* int (*no_child)(int node); */
++        obp_proplen,  /* int (*no_proplen)(int node, char *name); */
++        obp_getprop,  /* int (*no_getprop)(int node,char *name,char *val); */
++        obp_setprop,  /* int (*no_setprop)(int node, char *name,
++                               char *val, int len); */
++        obp_nextprop  /* char * (*no_nextprop)(int node, char *name); */
++};
++
++static const char arg_nfsroot[] = "console=ttyS0 ip=bootp root=nfs";
++
++static const struct linux_arguments_v0 obp_arg = {
++      { "le()", arg_nfsroot, NULL, NULL, NULL, NULL, NULL, NULL },
++      { "" },
++      { 'l', 'e' },  0, 0, 0, NULL,
++      NULL
++};
++static const struct linux_arguments_v0 * const obp_argp = &obp_arg;
++
++static const void * const synch_hook = NULL;
++#if 0
++static const char obp_stdin = PROMDEV_KBD;
++static const char obp_stdout = PROMDEV_SCREEN;
++#else
++static const char obp_stdin = PROMDEV_TTYA;
++static const char obp_stdout = PROMDEV_TTYA;
++#endif
++
++static int obp_nbgetchar(void);
++static int obp_nbputchar(int ch);
++static void obp_reboot(char *);
++static void obp_abort(void);
++static void obp_halt(void);
++static int obp_devopen(char *str);
++static int obp_devclose(int dev_desc);
++static int obp_rdblkdev(int dev_desc, int num_blks, int blk_st, char *buf);
++
++static void doublewalk(unsigned ptab1, unsigned va)
++{
++unsigned int proc_tablewalk(int ctx, unsigned int va);
++unsigned int mem_tablewalk(unsigned int pa, unsigned int va);
++
++      proc_tablewalk(0, va);
++      if (ptab1 != 0) mem_tablewalk(ptab1, va);
++}
++
 +#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();
++static const struct linux_romvec romvec0 = {
++      LINUX_OPPROM_MAGIC,             /* pv_magic_cookie */
++      0,                              /* pv_romvers - Format selector! */
++      77,                             /* pv_plugin_revision */
++      0x10203,                        /* pv_printrev */
++      {                               /* pv_v0mem */
++              &ptphys,                /* v0_totphys */
++              &ptmap,                 /* v0_prommap */
++              &ptavail                /* v0_available */
++      },
++        &nodeops0,                    /* struct linux_nodeops *pv_nodeops; */
++        (void*)doublewalk, /* P3 */   /* char **pv_bootstr; */
++      {                               /* struct linux_dev_v0_funcs pv_v0devops; */
++              &obp_devopen,           /* v0_devopen */
++              &obp_devclose,          /* v0_devclose */
++              &obp_rdblkdev,          /* v0_rdblkdev */
++              NULL,                   /* v0_wrblkdev */
++              NULL,                   /* v0_wrnetdev */
++              NULL,                   /* v0_rdnetdev */
++              NULL,                   /* v0_rdchardev */
++              NULL,                   /* v0_wrchardev */
++              NULL                    /* v0_seekdev */
++      },
++        &obp_stdin,                   /* char *pv_stdin */
++        &obp_stdout,                  /* char *pv_stdout; */
++        obp_nbgetchar,                        /* int (*pv_getchar)(void); */
++        obp_nbputchar,                        /* void (*pv_putchar)(int ch); */
++        obp_nbgetchar,                        /* int (*pv_nbgetchar)(void); */
++        obp_nbputchar,                        /* int (*pv_nbputchar)(int ch); */
++        NULL,                 /* void (*pv_putstr)(char *str, int len); */
++        obp_reboot,                   /* void (*pv_reboot)(char *bootstr); */
++        NULL,         /* void (*pv_printf)(__const__ char *fmt, ...); */
++        obp_abort,                    /* void (*pv_abort)(void); */
++        NULL,                         /* __volatile__ int *pv_ticks; */
++        obp_halt,                     /* void (*pv_halt)(void); */
++        (void *)&synch_hook,          /* void (**pv_synchook)(void); */
++
++#if 0
++        /* Evaluate a forth string, not different proto for V0 and V2->up. */
++        union {
++                void (*v0_eval)(int len, char *str);
++                void (*v2_eval)(char *str);
++        } pv_fortheval;
++#endif
++      { 0 },                  /* pv_fortheval */
++
++        &obp_argp,            /* struct linux_arguments_v0 **pv_v0bootargs; */
++      NULL,                   /* pv_enaddr */
++      {                       /* pv_v2bootargs */
++              NULL,           /* char **bootpath; */
++              NULL,           /* char **bootargs; */
++              NULL,           /* fd_stdin; */
++              NULL,           /* fd_stdout */
++      },
++      {                       /* pv_v2devops */
++              NULL,           /* v2_inst2pkg */
++              NULL,           /* v2_dumb_mem_alloc */
++              NULL,           /* v2_dumb_mem_free */
++              NULL,           /* v2_dumb_mmap */
++              NULL,           /* v2_dumb_munmap */
++              NULL,           /* v2_dev_open */
++              NULL,           /* v2_dev_close */
++              NULL,           /* v2_dev_read */
++              NULL,           /* v2_dev_write */
++              NULL,           /* v2_dev_seek */
++              NULL,           /* v2_wheee2 */
++              NULL,           /* v2_wheee3 */
++      },
++      { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },        /* filler[15] */
++        NULL,                 /* pv_setctxt */
++        NULL,                 /* v3_cpustart */
++        NULL,                 /* v3_cpustop */
++        NULL,                 /* v3_cpuidle */
++        NULL                  /* v3_cpuresume */
++};
++#endif
++
++static struct linux_romvec romvec0;
++
++void *
++init_openprom(int bankc, struct bank *bankv, unsigned hiphybas)
++{
++      int i;
++
++      /*
++       * Avoid data segment allocations
++       */
++      ptphys = totphys;
++      ptmap = totmap;
++      ptavail = totavail;
++      /*
++       * Form memory descriptors.
++       */
++      for (i = 0; i < bankc; i++) {
++              totphys[i].theres_more = &totphys[i+1];
++              totphys[i].start_adr = (char*) bankv[i].start;
++              totphys[i].num_bytes = bankv[i].length;
++      }
++      totphys[i-1].theres_more = 0;
++
++      /*
++       * XXX Merged in normal PROM when full banks touch.
++       */
++      for (i = 0; i < bankc; i++) {
++              unsigned bankbase = bankv[i].start;
++              unsigned banksize = bankv[i].length;
++              if (hiphybas > bankbase &&
++                  hiphybas < bankbase + banksize) {
++                      banksize = hiphybas - bankbase;
++              }
++              totavail[i].theres_more = &totavail[i+1];
++              totavail[i].start_adr = (char*) bankbase;
++              totavail[i].num_bytes = banksize;
++      }
++      totavail[i-1].theres_more = 0;
++
++      totmap[0].theres_more = 0;
++      totmap[0].start_adr = (char*) PROLBASE;
++      totmap[0].num_bytes = PROLSIZE;
++
++      /*
++       * idprom
++       */
++      bcopy(idprom, obp_idprom, IDPROM_SIZE);
++
++      // Linux wants a R/W romvec table
++      romvec0.pv_magic_cookie = LINUX_OPPROM_MAGIC;
++      romvec0.pv_plugin_revision = 77;
++      romvec0.pv_printrev = 0x10203;
++      romvec0.pv_v0mem.v0_totphys = &ptphys;
++      romvec0.pv_v0mem.v0_prommap = &ptmap;
++      romvec0.pv_v0mem.v0_available = &ptavail;
++      romvec0.pv_nodeops = &nodeops0;
++      romvec0.pv_bootstr = (void *)doublewalk;
++      romvec0.pv_stdin = &obp_stdin;
++      romvec0.pv_stdout = &obp_stdout;
++      romvec0.pv_getchar = obp_nbgetchar;
++      romvec0.pv_putchar = obp_nbputchar;
++      romvec0.pv_nbgetchar = obp_nbgetchar;
++      romvec0.pv_nbputchar = obp_nbputchar;
++      romvec0.pv_reboot = obp_reboot;
++      romvec0.pv_abort = obp_abort;
++      romvec0.pv_halt = obp_halt;
++      romvec0.pv_synchook = &synch_hook;
++      romvec0.pv_v0bootargs = &obp_argp;
++      return &romvec0;
++}
++
++static const struct property *find_property(int node,char *name)
++{
++      const struct property *prop = &nodes[node].properties[0];
++      while (prop && prop->name) {
++              if (bcmp(prop->name, name, 128) == 0) return prop;
++              prop++;
++      }
++      return NULL;
++}
++
++static int obp_nextnode(int node)
++{
++      return nodes[node].sibling;
++}
++
++static int obp_child(int node)
++{
++      return nodes[node].child;
++}
++
++static int obp_proplen(int node, char *name)
++{
++      const struct property *prop = find_property(node,name);
++      if (prop) return prop->length;
++      return -1;
++}
++
++static int obp_getprop(int node, char *name, char *value)
++{
++      const struct property *prop;
++
++      prop = find_property(node,name);
++      if (prop) {
++              memcpy(value,prop->value,prop->length);
++              //printk("obp_getprop '%s'= %s\n", name, value);
++              return prop->length;
++      }
++        //printk("obp_getprop: not found\n");
++      return -1;
++}
++
++static int obp_setprop(int node, char *name, char *value, int len)
++{
++      return -1;
++}
++
++static const char *obp_nextprop(int node,char *name)
++{
++      const struct property *prop = find_property(node,name);
++      if (prop) return prop[1].name;
++      return NULL;
++}
++
++#if 0
++static unsigned char calc_idprom_cksum(struct idprom *idprom)
++{
++        unsigned char cksum, i, *ptr = (unsigned char *)idprom;
++
++        for (i = cksum = 0; i <= 0x0E; i++)
++                cksum ^= *ptr++;
++
++        return cksum;
++}
++#endif
++
++static int obp_nbgetchar(void) {
++      return -1;
++}
++
++static int obp_nbputchar(int ch) {
++      extern struct vconterm dp0;
++      char buf = ch;
++
++      /* We do not use printk() in order to reduce stack depth. */
++      vcon_write(&dp0, &buf, 1);
++      return 0;
++}
++
++static void obp_reboot(char *str) {
++      printk("rebooting (%s): not implemented, freezing\n", str);
++      for (;;) {}
++}
++
++static void obp_abort() {
++      printk("abort, freezing\n");
++      for (;;) {}
++}
++
++static void obp_halt() {
++      printk("halt, freezing\n");
++      for (;;) {}
++}
++
++static int obp_devopen(char *str) {
++        //printk("open %s\n", str);
++      return 0;
++}
++
++static int obp_devclose(int dev_desc) {
++        //printk("close %d\n", dev_desc);
++      return 0;
++}
++
++static int obp_rdblkdev(int dev_desc, int num_blks, int blk_st, char *buf) {
++    //printk("rdblkdev: fd %d, num_blks %d, blk_st %d, buf 0x%x\n", dev_desc, num_blks, blk_st, buf);
++    //buf[8] = 'L';
++    return num_blks;
++}
+diff -ruN proll_18.orig/src/arp.c proll-patch4/src/arp.c
+--- proll_18.orig/src/arp.c    2001-12-24 05:12:31.000000000 +0000
++++ proll-patch4/src/arp.c     2004-11-13 15:50:49.000000000 +0000
+@@ -45,7 +45,7 @@
+ #endif
+ static struct arp_cache arp_list[ARPNUM];     /* ARP address cache    */
+ static int next_arp;                          /* next table entry     */
+-static t_ipaddr def_gw = IP_ANY;              /* default routing      */
++static t_ipaddr def_gw;                               /* default routing      */
+@@ -144,7 +144,7 @@
+  * 
+  * Resolve IP address and return pointer to hardware address.
+  */
+-unsigned char *ip_resolve(ip)
++const unsigned char *ip_resolve(ip)
+ t_ipaddr ip;
+ {
+   int i;
+@@ -230,14 +230,11 @@
+  */
+ int init_arp()
+ {
+-  /* Set name of module for error messages */
+-  net_module_name = "arp";
+-
+ #ifndef NOARP
+   /* Register ARP packet type and set send buffer pointer */
+   if ((arpbuf = (struct arphdr *)reg_type(htons(ETH_P_ARP), arp_recv)) == NULL)
+       return(FALSE);
  #endif
+-
++  def_gw = IP_ANY;
+   return(TRUE);
+ }
+diff -ruN proll_18.orig/src/arp.h proll-patch4/src/arp.h
+--- proll_18.orig/src/arp.h    1999-03-18 03:39:43.000000000 +0000
++++ proll-patch4/src/arp.h     2004-11-13 15:50:49.000000000 +0000
+@@ -104,7 +104,7 @@
+ extern int init_arp __P((void));
+ /* Resolve IP address and return pointer to hardware address */
+-extern unsigned char *ip_resolve __P((t_ipaddr ip));
++extern const unsigned char *ip_resolve __P((t_ipaddr ip));
+ /* Add a new antry to the ARP cache */
+ extern void addcache __P((unsigned char *ha, t_ipaddr ip));
+diff -ruN proll_18.orig/src/hconsole.c proll-patch4/src/hconsole.c
+--- proll_18.orig/src/hconsole.c       2002-07-23 05:52:48.000000000 +0000
++++ proll-patch4/src/hconsole.c        2004-11-13 15:50:49.000000000 +0000
+@@ -42,7 +42,11 @@
+        * No probing sequence or argument passing, hardcode everything. XXX
+        */
+       raster8_cons_a(q, 768, 1024, (char *)a0);
++#if 1
+       raster_cons_2(r, q, 768-(24*11)-1, 1024-(8*80)-1, (24*11), (8*80));
++#else
++      raster_cons_2(r, q, 0, 0, 768, 1024);
 +#endif
+       t->r_ = r;
+       t->r0_ = q;
+       t->f_ = &f_master;
+diff -ruN proll_18.orig/src/lat7_2.bm proll-patch4/src/lat7_2.bm
+--- proll_18.orig/src/lat7_2.bm        1999-02-27 05:48:54.000000000 +0000
++++ proll-patch4/src/lat7_2.bm 2004-11-13 15:50:49.000000000 +0000
+@@ -1,6 +1,6 @@
+ #define lat7_2_width 128
+ #define lat7_2_height 88
+-static unsigned char lat7_2_bits[] = {
++static unsigned const char lat7_2_bits[] = {
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x12, 0x1e, 0x0c, 0x02, 0x70, 0x18,
+    0x22, 0x22, 0x18, 0x00, 0x00, 0x18, 0x18, 0xff, 0x18, 0x00, 0x12, 0x02,
+diff -ruN proll_18.orig/src/lat7_2_swapped.bm proll-patch4/src/lat7_2_swapped.bm
+--- proll_18.orig/src/lat7_2_swapped.bm        1970-01-01 00:00:00.000000000 +0000
++++ proll-patch4/src/lat7_2_swapped.bm 2004-11-13 15:50:49.000000000 +0000
+@@ -0,0 +1,121 @@
++#define lat7_2_width 128
++#define lat7_2_height 88
++static unsigned const char lat7_2_bits[] = {
++   0x00, 0x00, 0x18, 0x3c, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 
++   0x55, 0x00, 0x2a, 0x00, 0x55, 0x00, 0x2a, 0x00, 0x55, 0x00, 0x00, 0x48, 
++   0x48, 0x78, 0x48, 0x5f, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x78, 0x40, 
++   0x70, 0x40, 0x4f, 0x08, 0x0e, 0x08, 0x08, 0x00, 0x00, 0x30, 0x40, 0x40, 
++   0x40, 0x3e, 0x09, 0x0e, 0x0a, 0x09, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 
++   0x7f, 0x08, 0x0e, 0x08, 0x08, 0x00, 0x00, 0x0e, 0x0a, 0x0e, 0x00, 0x00, 
++   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 
++   0x7e, 0x00, 0x00, 0x00, 0x00, 0x44, 0x64, 0x54, 0x4c, 0x54, 0x10, 0x10, 
++   0x10, 0x1f, 0x00, 0x00, 0x44, 0x44, 0x44, 0x28, 0x1f, 0x04, 0x04, 0x04, 
++   0x04, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 
++   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x00, 
++   0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 
++   0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 
++   0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 
++   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 
++   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
++   0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
++   0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
++   0x00, 0x00, 0xff, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 
++   0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 
++   0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 
++   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x00, 
++   0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 
++   0x06, 0x0c, 0x18, 0x30, 0x18, 0x6c, 0x36, 0x18, 0x0c, 0x00, 0x00, 0x60, 
++   0x30, 0x18, 0x0c, 0x18, 0x36, 0x6c, 0x18, 0x30, 0x00, 0x00, 0x7f, 0x36, 
++   0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x7e, 
++   0x18, 0x7e, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x36, 0x30, 0x78, 
++   0x30, 0x72, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 
++   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 
++   0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
++   0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x00, 
++   0x00, 0x00, 0x00, 0x66, 0x66, 0x22, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 
++   0x00, 0x00, 0x36, 0x7f, 0x36, 0x36, 0x36, 0x7f, 0x36, 0x00, 0x00, 0x00, 
++   0x00, 0x66, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 
++   0x72, 0x56, 0x6c, 0x18, 0x36, 0x6a, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x18, 
++   0x24, 0x28, 0x30, 0x4a, 0x44, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 
++   0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x18, 
++   0x18, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, 0x18, 0x18, 
++   0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0x7e, 0x3c, 
++   0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 
++   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 
++   0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 
++   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 
++   0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x40, 0x00, 0x00, 0x00, 
++   0x00, 0x3c, 0x46, 0x4e, 0x5a, 0x72, 0x62, 0x3c, 0x00, 0x00, 0x00, 0x00, 
++   0x18, 0x38, 0x58, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x3c, 
++   0x66, 0x06, 0x0c, 0x18, 0x32, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 
++   0x06, 0x1c, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 
++   0x66, 0x7e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x60, 0x7c, 0x66, 
++   0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x60, 0x7c, 0x66, 0x66, 
++   0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x46, 0x06, 0x0c, 0x18, 0x30, 
++   0x30, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x3c, 
++   0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x3c, 0x00, 
++   0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 
++   0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x08, 0x10, 0x00, 
++   0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 
++   0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 
++   0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 
++   0x06, 0x0c, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x5e, 
++   0x56, 0x5e, 0x40, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, 0x66, 
++   0x7e, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x66, 
++   0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x60, 0x66, 
++   0x3c, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 
++   0x00, 0x00, 0x00, 0x00, 0x7e, 0x62, 0x60, 0x78, 0x60, 0x62, 0x7e, 0x00, 
++   0x00, 0x00, 0x00, 0x7e, 0x62, 0x60, 0x78, 0x60, 0x60, 0x60, 0x00, 0x00, 
++   0x00, 0x00, 0x3c, 0x66, 0x60, 0x6e, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 
++   0x00, 0x66, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 
++   0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x7e, 
++   0x46, 0x06, 0x06, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x66, 0x6c, 
++   0x78, 0x70, 0x78, 0x6c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x60, 
++   0x60, 0x60, 0x62, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x41, 0x63, 0x77, 0x7f, 
++   0x6b, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x76, 0x7e, 0x6e, 
++   0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 
++   0x3c, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 
++   0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x6e, 0x3c, 0x02, 
++   0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x00, 0x00, 
++   0x00, 0x00, 0x3c, 0x66, 0x60, 0x3c, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 
++   0x00, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 
++   0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x66, 
++   0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 
++   0x63, 0x6b, 0x6b, 0x7f, 0x36, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x3c, 
++   0x18, 0x3c, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3c, 
++   0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x46, 0x0c, 0x18, 0x30, 
++   0x62, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 
++   0x3c, 0x00, 0x00, 0x00, 0x00, 0x40, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 
++   0x00, 0x00, 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 
++   0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
++   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 
++   0x00, 0x08, 0x10, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
++   0x00, 0x3c, 0x06, 0x3e, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x60, 
++   0x60, 0x60, 0x7c, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
++   0x3c, 0x66, 0x60, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 
++   0x3e, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 
++   0x7e, 0x60, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x36, 0x30, 0x30, 0x78, 
++   0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 
++   0x3e, 0x06, 0x3c, 0x00, 0x00, 0x60, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 
++   0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x1c, 0x00, 
++   0x00, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x6c, 0x38, 
++   0x00, 0x00, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x7c, 0x66, 0x00, 0x00, 0x00, 
++   0x00, 0x60, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, 
++   0x00, 0x00, 0x76, 0x7f, 0x6b, 0x6b, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 
++   0x00, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
++   0x3c, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 
++   0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 
++   0x66, 0x66, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x72, 0x60, 
++   0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x60, 0x3c, 0x06, 
++   0x3c, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x78, 0x30, 0x30, 0x36, 0x1c, 
++   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3a, 0x00, 
++   0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 
++   0x00, 0x00, 0x00, 0x00, 0x63, 0x6b, 0x6b, 0x6b, 0x36, 0x00, 0x00, 0x00, 
++   0x00, 0x00, 0x00, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 
++   0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x3c, 0x00, 0x00, 0x00, 
++   0x00, 0x7e, 0x0c, 0x18, 0x30, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 
++   0x18, 0x30, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 
++   0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x30, 0x18, 0x18, 0x0c, 
++   0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0x00, 0x00, 0x00, 
++   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x42, 0x00, 0x00, 0x00, 0x00, 
++   0x00, 0x00, 0x00, 0x00};
+diff -ruN proll_18.orig/src/le.c proll-patch4/src/le.c
+--- proll_18.orig/src/le.c     2002-07-23 05:52:49.000000000 +0000
++++ proll-patch4/src/le.c      2004-11-13 15:50:49.000000000 +0000
+@@ -185,8 +185,6 @@
+       unsigned short rap;                     /* register address port */
+ };
+-int sparc_lance_debug = 2;
+-
+ /* The Lance uses 24 bit addresses */
+ /* On the Sun4c the DVMA will provide the remaining bytes for us */
+ /* On the Sun4m we have to instruct the ledma to provide them    */
+diff -ruN proll_18.orig/src/netinit.c proll-patch4/src/netinit.c
+--- proll_18.orig/src/netinit.c        2002-09-13 21:53:33.000000000 +0000
++++ proll-patch4/src/netinit.c 2004-11-13 15:50:49.000000000 +0000
+@@ -49,13 +49,20 @@
+ unsigned char     myhwaddr[ETH_ALEN];         /* my own hardware addr */
+          t_ipaddr myipaddr;                   /* my own IP address    */
+          t_ipaddr mynetmask;                  /* my own netmask       */
+-         char    *net_module_name;            /* name of init module  */
+          t_ipaddr servaddr;                   /* IP of RARP&TFTP server */
+ /* Broadcast hardware address */
+-unsigned char bcasthw[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
++const unsigned char bcasthw[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
++unsigned int seed;
++
++/* This is taken from x86 to be used in network kernel. Returns 15 bits. */
++short int random()
++{
++      seed = (seed + 23968)*0x015A4E35 >> 1;
++      return seed & 0x7FFF;
++}
+ /*
+  **************************************************************************
+@@ -104,10 +111,17 @@
+  */
+ void init_net()
+ {
++  /* Avoid data segment allocations */
++  seed = 151;
++
+   /* Initialize the different network layer modules */
+   init_packet();
+-  if (!init_arp() || !init_udp()) {
+-      printf("\nERROR: init_%s\n", net_module_name);
++  if (!init_arp()) {
++      printf("\nERROR: init_arp\n");
++      fatal();
++  }
++  if (!init_udp()) {
++      printf("\nERROR: init_udp\n");
+       fatal();
+   }
+ }
+diff -ruN proll_18.orig/src/netpriv.h proll-patch4/src/netpriv.h
+--- proll_18.orig/src/netpriv.h        1999-04-27 05:39:37.000000000 +0000
++++ proll-patch4/src/netpriv.h 2004-11-13 15:50:49.000000000 +0000
+@@ -130,10 +130,9 @@
+  *
+  */
+ extern unsigned char myhwaddr[ETH_ALEN]; /* my own hardware address   */
+-extern unsigned char bcasthw[ETH_ALEN];  /* broadcast hardware addr   */
++extern const unsigned char bcasthw[ETH_ALEN];  /* broadcast hardware addr     */
+ extern t_ipaddr      myipaddr;           /* my own IP address         */
+ extern t_ipaddr      mynetmask;                /* netmask for my network      */
+-extern char         *net_module_name;  /* initialized module's name   */
+ extern t_ipaddr      servaddr;           /* server IP address         */
+@@ -150,7 +149,7 @@
+ extern unsigned char *reg_type __P((int typeval, int (* receive)()));
+ /* Write a packet to the network */
+-extern int write_packet __P((int bufsize, int typeval, unsigned char *addr));
++extern int write_packet __P((int bufsize, int typeval, const unsigned char *addr));
+ /* Empty read buffer */
+ extern void empty_buf __P((void));
+diff -ruN proll_18.orig/src/openprom.h proll-patch4/src/openprom.h
+--- proll_18.orig/src/openprom.h       2002-07-14 02:26:30.000000000 +0000
++++ proll-patch4/src/openprom.h        2004-11-13 15:50:49.000000000 +0000
+@@ -54,20 +54,20 @@
+ };
+ struct linux_mem_v0 {
+-      struct linux_mlist_v0 **v0_totphys;
+-      struct linux_mlist_v0 **v0_prommap;
+-      struct linux_mlist_v0 **v0_available; /* What we can use */
++      struct linux_mlist_v0 * const *v0_totphys;
++      struct linux_mlist_v0 * const *v0_prommap;
++      struct linux_mlist_v0 * const *v0_available; /* What we can use */
+ };
+ /* Arguments sent to the kernel from the boot prompt. */
+ struct linux_arguments_v0 {
+-      char *argv[8];
++      const char *argv[8];
+       char args[100];
+       char boot_dev[2];
+       int boot_dev_ctrl;
+       int boot_dev_unit;
+       int dev_partition;
+-      char *kernel_file_name;
++      const char *kernel_file_name;
+       void *aieee1;           /* XXX */
+ };
  
-       romvec = init_openprom(bb.nbanks, bb.bankv, hiphybas);
+@@ -91,13 +91,13 @@
+       struct linux_mem_v0 pv_v0mem;
  
-       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);
+       /* Node operations. */
+-      struct linux_nodeops *pv_nodeops;
++      const struct linux_nodeops *pv_nodeops;
+       char **pv_bootstr;
+       struct linux_dev_v0_funcs pv_v0devops;
+-      char *pv_stdin;
+-      char *pv_stdout;
++      const char *pv_stdin;
++      const char *pv_stdout;
+ #define       PROMDEV_KBD     0               /* input from keyboard */
+ #define       PROMDEV_SCREEN  0               /* output to screen */
+ #define       PROMDEV_TTYA    1               /* in/out to ttya */
+@@ -127,7 +127,7 @@
+               void (*v2_eval)(char *str);
+       } pv_fortheval;
+-      struct linux_arguments_v0 **pv_v0bootargs;
++      const struct linux_arguments_v0 * const *pv_v0bootargs;
+       /* Get ether address. */
+       unsigned int (*pv_enaddr)(int d, char *enaddr);
+@@ -175,7 +175,7 @@
+       int (*no_proplen)(int node, char *name);
+       int (*no_getprop)(int node, char *name, char *val);
+       int (*no_setprop)(int node, char *name, char *val, int len);
+-      char * (*no_nextprop)(int node, char *name);
++      const char * (*no_nextprop)(int node, char *name);
+ };
+ /* More fun PROM structures for device probing. */
+diff -ruN proll_18.orig/src/packet.c proll-patch4/src/packet.c
+--- proll_18.orig/src/packet.c 2000-02-11 04:56:45.000000000 +0000
++++ proll-patch4/src/packet.c  2004-11-13 15:50:49.000000000 +0000
+@@ -41,7 +41,7 @@
+       int aligner;
+ } wbuf;
+ static struct sk_buff *rskb;
+-static int nqskb = 0;
++static int nqskb;
+ void init_packet()
+@@ -62,6 +62,8 @@
+       for (i = 0; i < MAXSKBS; i++) {
+               skev[i].skb.allocn = i;
+       }
++
++      nqskb = 0;
+ }
+ unsigned char *reg_type(int ptype, int (*func)())
+@@ -81,7 +83,7 @@
+       return wbuf.s;
+ }
+-int write_packet(int leng, int type, unsigned char *dst)
++int write_packet(int leng, int type, const unsigned char *dst)
+ {
+       struct sk_buff *skb;
+       unsigned char *s;
+diff -ruN proll_18.orig/src/printf.c proll-patch4/src/printf.c
+--- proll_18.orig/src/printf.c 1999-03-19 07:03:59.000000000 +0000
++++ proll-patch4/src/printf.c  2004-11-13 15:50:49.000000000 +0000
+@@ -19,7 +19,7 @@
+ static void printn(struct prf_fp *, unsigned long, unsigned int);
+ static void putchar(char, struct prf_fp *);
+-static char hextab[] = "0123456789ABCDEF";
++static const char hextab[] = "0123456789ABCDEF";
+ /*
+  * Scaled down version of C Library printf.
+@@ -41,7 +41,7 @@
+ void
+ prf(struct prf_fp *filog, char *fmt, va_list adx)
+ {
+-        register c;
++        register int c;
+         char *s;
+       for(;;) {
+@@ -60,7 +60,7 @@
+                       putchar(va_arg(adx,unsigned), filog);
+               } else if(c == 's') {
+                       s = va_arg(adx,char*);
+-                              while(c = *s++)
++                              while((c = *s++))
+                               putchar(c,filog);
+                       } else if (c == 'l' || c == 'O') {
+                       printn(filog, (long)va_arg(adx,long), c=='l'?10:8);
+diff -ruN proll_18.orig/src/rconsole.c proll-patch4/src/rconsole.c
+--- proll_18.orig/src/rconsole.c       1999-01-16 07:16:55.000000000 +0000
++++ proll-patch4/src/rconsole.c        2004-11-13 15:50:49.000000000 +0000
+@@ -28,12 +28,18 @@
+  * move to California. Only plain lat7 survived. 
+  * I recreated lat7-1 changes in lat7-2.  --zaitcev
+  */
 +#ifdef ORIG
      set_timeout(5);  while (!chk_timeout()) { }  /* P3: let me read */
#include "lat7_2.bm"  /* lat7_1.bm */
 +#else
-+      printk("loading kernel:");
-+      i = ld_bypass(0x20000000);
-+      printk(" done, size %d\n", i);
++#include "lat7_2_swapped.bm"  /* lat7_1.bm */
 +#endif
+ #define LAT7_NCHARS  128
+ #define LAT7_HEIGHT   11
+ #define LAT7_WIDTH     8
  
-       {
-               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 @@
- };
++#ifdef ORIG
+ static Rf_scan lat7_body[ LAT7_NCHARS*LAT7_HEIGHT ];
++#endif
  
- 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}
+ #if 1
+ /*
+@@ -94,6 +100,7 @@
+ #endif
++#ifdef ORIG
+ static inline int swapbits(int w0)
+ {
+   int w1 = 0;
+@@ -105,13 +112,16 @@
+   }
+   return w1;
+ }
++#endif
+ void font_cons_7(struct rfont *p)
+ {
++#ifdef ORIG
+   int x;
+   int col = 0;
+   int row = 0;
+   int erow = 0;
++
+   for (x = 0; x < LAT7_NCHARS*LAT7_HEIGHT; x++ ) {
+     lat7_body[ (erow * lat7_2_width/8 + col) * LAT7_HEIGHT + row ] =
+                                             swapbits(lat7_2_bits[x]) & 0xFF;
+@@ -124,6 +134,9 @@
+     }
+   }
+   p->body_ = lat7_body;
++#else
++  p->body_ = lat7_2_bits;
++#endif
+   p->nchars_ = LAT7_NCHARS;
+   p->width_ = LAT7_WIDTH;
+   p->height_ = LAT7_HEIGHT;
+diff -ruN proll_18.orig/src/rconsole.h proll-patch4/src/rconsole.h
+--- proll_18.orig/src/rconsole.h       1999-01-16 05:00:59.000000000 +0000
++++ proll-patch4/src/rconsole.h        2004-11-13 15:50:49.000000000 +0000
+@@ -13,10 +13,10 @@
+  */
+ #define RF_MAXWIDTH  16
+-typedef unsigned short Rf_scan;        /*  __w16 to be used */
++typedef unsigned char Rf_scan;        /*  __w16 to be used */
+ struct rfont {
+-  Rf_scan *body_;
++  const Rf_scan *body_;
+   int nchars_;                 /* 128 for ASCII ...  65536 for Unicode   */
+   int width_;                  /* [Pixels]. Maximum size is 16.          */
+   int height_;                 /* [Pixels == scan lines].                */
+diff -ruN proll_18.orig/src/romlib.h proll-patch4/src/romlib.h
+--- proll_18.orig/src/romlib.h 1999-04-20 04:26:45.000000000 +0000
++++ proll-patch4/src/romlib.h  2004-11-13 15:50:49.000000000 +0000
+@@ -73,12 +73,12 @@
+ #define memcpy(dst, src, len) bcopy(src, dst, len)
+ #define memcmp(x1, x2, len)   bcmp(x1, x2, len)
+ #define memset(p, len, zero)  bzero(p, len)
+-extern void bcopy(void *b1, void *b2, int length);
+-extern int  bcmp(void *b1, void *b2, int length);
++extern void bcopy(const void *b1, void *b2, int length);
++extern int  bcmp(const void *b1, const void *b2, int length);
+ extern void bzero(void *b, int c);
+ /* gcc complains about "conflicting types for builtin function strlen". */
+ #define strlen(s)             ssize(s)
+-extern int ssize(char *s);
++extern int ssize(const char *s);
+ /*
+diff -ruN proll_18.orig/src/sched_4m.c proll-patch4/src/sched_4m.c
+--- proll_18.orig/src/sched_4m.c       1999-04-27 05:48:51.000000000 +0000
++++ proll-patch4/src/sched_4m.c        2004-11-13 15:50:49.000000000 +0000
+@@ -108,7 +108,7 @@
+ static int set_bolt;                  /* Tick counter limit */
+ static struct handsc hndv[16];
+-static unsigned int intr_to_mask[16] = {
++static unsigned const int intr_to_mask[16] = {
+       0,      0,      0,      0,      0,      0, SUN4M_INT_ETHERNET,  0,
+       0,      0,      0,      0,      0,      0,      0,      0,
  };
+diff -ruN proll_18.orig/src/swap.c proll-patch4/src/swap.c
+--- proll_18.orig/src/swap.c   1970-01-01 00:00:00.000000000 +0000
++++ proll-patch4/src/swap.c    2004-11-13 15:50:49.000000000 +0000
+@@ -0,0 +1,21 @@
++// Convert the lat7 font so that no conversion is needed at runtime.
++#define ORIG
++#include "rconsole.c"
++
++#include <stdio.h>
++
++int main()
++{
++    struct rfont p;
++    int i;
++
++    font_cons_7(&p);
++
++    printf("   ");
++    for (i = 0; i < LAT7_NCHARS*LAT7_HEIGHT; i++) {
++      printf("0x%02x, ", p.body_[i]);
++      if ((i % 12) == 11)
++          printf("\n   ");
++    }
++    printf("\n");
++}
+diff -ruN proll_18.orig/src/system.c proll-patch4/src/system.c
+--- proll_18.orig/src/system.c 2002-07-23 05:52:49.000000000 +0000
++++ proll-patch4/src/system.c  2004-11-13 15:50:49.000000000 +0000
+@@ -298,8 +298,8 @@
+       }
+       /* We need to start from LOADBASE, but kernel wants PAGE_SIZE. */
+-      pa = PAGE_SIZE;
+-      for (va = PAGE_SIZE; va < LOWMEMSZ; va += PAGE_SIZE) {
++      pa = 0;
++      for (va = 0; va < LOWMEMSZ; va += PAGE_SIZE) {
+               map_page(l1, va, pa, 0, highbase);
+               pa += PAGE_SIZE;
+       }
+@@ -518,12 +518,12 @@
+       while (len--) *((char *)s)++ = 0;
+ }
+-void bcopy(void *f, void *t, int len) {
++void bcopy(const void *f, void *t, int len) {
+       while (len--) *((char *)t)++ = *((char *)f)++;
+ }
+ /* Comparison is 7-bit */
+-int bcmp(void *s1, void *s2, int len)
++int bcmp(const void *s1, const void *s2, int len)
+ {
+       int i;
+       char ch;
+@@ -538,8 +538,8 @@
+       return 0;
+ }
+-int strlen(char *s) {
+-      char *p;
++int strlen(const char *s) {
++      const char *p;
+       for (p = s; *p != 0; p++) { }
+       return p - s;
+ }
+@@ -560,14 +560,6 @@
+       va_end(x1);
+ }
+-/* This is taken from x86 to be used in network kernel. Returns 15 bits. */
+-short int random()
+-{
+-      static unsigned int seed = 151;
+-      seed = (seed + 23968)*0x015A4E35 >> 1;
+-      return seed & 0x7FFF;
+-}
+-
+ void fatal()
+ {
+       printk("fatal.");
+diff -ruN proll_18.orig/src/system.h proll-patch4/src/system.h
+--- proll_18.orig/src/system.h 2002-09-13 21:53:32.000000000 +0000
++++ proll-patch4/src/system.h  2004-11-13 15:50:49.000000000 +0000
+@@ -16,7 +16,7 @@
+ #define IOMAPSIZE (1*1024*1024) /* 1 Meg maximum: we do not map framebuffer. */
+ #define NCTX_SWIFT  0x100
+-#define MAX_BANKS      3              /* Allocation for all machines */
++#define MAX_BANKS      8              /* Allocation for all machines */
+ #ifndef __ASSEMBLY__
+ struct bank {
+diff -ruN proll_18.orig/src/udp.c proll-patch4/src/udp.c
+--- proll_18.orig/src/udp.c    2001-12-24 05:12:53.000000000 +0000
++++ proll-patch4/src/udp.c     2004-11-13 15:50:49.000000000 +0000
+@@ -81,7 +81,7 @@
+ int      source;
+ int      dest;
+ {
+-  register unsigned char *addr;
++  const register unsigned char *addr;
  
+   /* Set global variables */
+   usource = source;
+@@ -299,9 +299,6 @@
+  */
+ int init_udp()
+ {
+-  /* Set module name for error handling */
+-  net_module_name = "udp";
+-
+   /* Register IP packet type and set write buffer pointer */
+   if ((writebuf = reg_type(htons(ETH_P_IP), ip_recv)) == NULL)
+       return(FALSE);
index 367beb80a82999ae8bf75e68854bc9e303eac21b..ca5cb09b054d40025e2cc62399259c6619151b9c 100644 (file)
@@ -1099,6 +1099,29 @@ Set the initial VGA graphic mode. The default is 800x600x15.
 More information is available at
 @url{http://jocelyn.mayer.free.fr/qemu-ppc/}.
 
+@chapter Sparc System emulator invocation
+
+Use the executable @file{qemu-system-sparc} to simulate a JavaStation
+(sun4m architecture). The emulation is far from complete.
+
+QEMU emulates the following sun4m peripherials:
+
+@itemize @minus
+@item 
+IOMMU
+@item
+TCX Frame buffer
+@item 
+Lance (Am7990) Ethernet
+@item
+Non Volatile RAM M48T08
+@item
+Slave I/O: timers, interrupt controllers, Zilog serial ports
+@end itemize
+
+QEMU uses the Proll, a PROM replacement available at
+@url{http://people.redhat.com/zaitcev/linux/}.
+
 @chapter QEMU User space emulator invocation
 
 @section Quick Start
index 4e6f507c74cd6a318abdc089a747c209ade5fe04..987b3c3efff65830a83229eb3204df3ba2aa2975 100644 (file)
@@ -126,7 +126,7 @@ maximum performances.
 
 @itemize
 
-@item Full PowerPC 32 bit emulation, including priviledged instructions, 
+@item Full PowerPC 32 bit emulation, including privileged instructions, 
 FPU and MMU.
 
 @item Can run most PowerPC Linux binaries.
@@ -137,7 +137,8 @@ FPU and MMU.
 
 @itemize
 
-@item SPARC V8 user support, except FPU instructions.
+@item Somewhat complete SPARC V8 emulation, including privileged
+instructions, FPU and MMU.
 
 @item Can run some SPARC Linux binaries.
 
index adf8df2c9db87a52823731419c284d4616aa606b..a66d2e36d7b553dfd59443da4905b66636d5d321 100644 (file)
 /* trap definitions */
 #define TT_ILL_INSN 0x02
 #define TT_PRIV_INSN 0x03
+#define TT_NFPU_INSN 0x04
 #define TT_WIN_OVF  0x05
 #define TT_WIN_UNF  0x06 
 #define TT_FP_EXCP  0x08
 #define TT_DIV_ZERO 0x2a
 #define TT_TRAP     0x80
+#define TT_EXTINT   0x10
 
 #define PSR_NEG   (1<<23)
 #define PSR_ZERO  (1<<22)
 #define PSR_OVF   (1<<21)
 #define PSR_CARRY (1<<20)
 #define PSR_ICC   (PSR_NEG|PSR_ZERO|PSR_OVF|PSR_CARRY)
+#define PSR_EF    (1<<12)
+#define PSR_PIL   0xf00
 #define PSR_S     (1<<7)
 #define PSR_PS    (1<<6)
 #define PSR_ET    (1<<5)
 #define PSR_CWP   0x1f
 /* Fake impl 0, version 4 */
-#define GET_PSR(env) ((0<<28) | (4<<24) | env->psr | (env->psrs? PSR_S : 0) | (env->psrs? PSR_PS : 0) |(env->psret? PSR_ET : 0) | env->cwp)
+#define GET_PSR(env) ((0 << 28) | (4 << 24) | env->psr |               \
+                     (env->psref? PSR_EF : 0) |                        \
+                     (env->psrpil << 8) |                              \
+                     (env->psrs? PSR_S : 0) |                          \
+                     (env->psrs? PSR_PS : 0) |                         \
+                     (env->psret? PSR_ET : 0) | env->cwp)
+
+#define PUT_PSR(env, val) do { int _tmp = val;                         \
+       env->psr = _tmp & ~PSR_ICC;                                     \
+       env->psref = (_tmp & PSR_EF)? 1 : 0;                            \
+       env->psrpil = (_tmp & PSR_PIL) >> 8;                            \
+       env->psrs = (_tmp & PSR_S)? 1 : 0;                              \
+       env->psrps = (_tmp & PSR_PS)? 1 : 0;                            \
+       env->psret = (_tmp & PSR_ET)? 1 : 0;                            \
+       set_cwp(_tmp & PSR_CWP & (NWINDOWS - 1));                       \
+    } while (0)
 
 /* Trap base register */
 #define TBR_BASE_MASK 0xfffff000
@@ -65,6 +84,9 @@
 #define FSR_FTT1   (1<<15)
 #define FSR_FTT0   (1<<14)
 #define FSR_FTT_MASK (FSR_FTT2 | FSR_FTT1 | FSR_FTT0)
+#define FSR_FTT_IEEE_EXCP (1 << 14)
+#define FSR_FTT_UNIMPFPOP (3 << 14)
+#define FSR_FTT_INVAL_FPR (6 << 14)
 
 #define FSR_FCC1  (1<<11)
 #define FSR_FCC0  (1<<10)
@@ -106,6 +128,8 @@ typedef struct CPUSPARCState {
     int      psrs;     /* supervisor mode (extracted from PSR) */
     int      psrps;    /* previous supervisor mode */
     int      psret;    /* enable traps */
+    int      psrpil;   /* interrupt level */
+    int      psref;    /* enable fpu */
     jmp_buf  jmp_env;
     int user_mode_only;
     int exception_index;
@@ -144,6 +168,8 @@ typedef struct CPUSPARCState {
 CPUSPARCState *cpu_sparc_init(void);
 int cpu_sparc_exec(CPUSPARCState *s);
 int cpu_sparc_close(CPUSPARCState *s);
+void cpu_get_fp64(uint64_t *pmant, uint16_t *pexp, double f);
+double cpu_put_fp64(uint64_t mant, uint16_t exp);
 
 struct siginfo;
 int cpu_sparc_signal_handler(int hostsignum, struct siginfo *info, void *puc);
index 1b3d9a08067d893549eb8659948bffbf697a5ada..f8edc17153d603d4077a1c4da8e446d0b867a711 100644 (file)
@@ -40,6 +40,9 @@ void do_interrupt(int intno, int is_int, int error_code,
 void raise_exception_err(int exception_index, int error_code);
 void raise_exception(int tt);
 void memcpy32(uint32_t *dst, const uint32_t *src);
+uint32_t mmu_probe(uint32_t address, int mmulev);
+void dump_mmu(void);
+void helper_debug();
 
 /* XXX: move that to a generic header */
 #if !defined(CONFIG_USER_ONLY)
index 2987b68d64b34359df8f9a0a4f3c12c73646559a..eb1e1e3112571b68235a94eddc7b801897f6caab 100644 (file)
@@ -51,18 +51,6 @@ void OPPROTO glue(op_store_FT2_fpr_fpr, REGNAME)(void)
 }
 
 /* double floating point registers moves */
-#if 0
-#define CPU_DOUBLE_U_DEF
-typedef union {
-    double d;
-    struct {
-        uint32_t lower;
-        uint32_t upper;
-    } l;
-    uint64_t ll;
-} CPU_DoubleU;
-#endif /* CPU_DOUBLE_U_DEF */
-
 void OPPROTO glue(op_load_fpr_DT0_fpr, REGNAME)(void)
 {
     CPU_DoubleU u;
index 93ef930fbdf0c1ec4f08bbdc012564c28536cf1a..76ad643ebb72130c458e1f924885b6f23d6781bc 100644 (file)
@@ -19,7 +19,8 @@
  */
 #include "exec.h"
 
-#define DEBUG_PCALL
+//#define DEBUG_PCALL
+//#define DEBUG_MMU
 
 /* Sparc MMU emulation */
 int cpu_sparc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
@@ -108,80 +109,71 @@ static const int rw_table[2][8] = {
     { 0, 1, 0, 1, 0, 0, 0, 0 }
 };
 
-
-/* Perform address translation */
-int cpu_sparc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
-                              int is_user, int is_softmmu)
+int get_physical_address (CPUState *env, uint32_t *physical, int *prot,
+                         int *access_index, uint32_t address, int rw,
+                         int is_user)
 {
-    int exception = 0;
-    int access_perms = 0, access_index = 0;
-    uint8_t *pde_ptr;
+    int access_perms = 0;
+    target_phys_addr_t pde_ptr;
     uint32_t pde, virt_addr;
-    int error_code = 0, is_dirty, prot, ret = 0;
-    unsigned long paddr, vaddr, page_offset;
-
-    if (env->user_mode_only) {
-        /* user mode only emulation */
-        ret = -2;
-        goto do_fault;
-    }
+    int error_code = 0, is_dirty;
+    unsigned long page_offset;
 
     virt_addr = address & TARGET_PAGE_MASK;
     if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
-       paddr = address;
-       page_offset = address & (TARGET_PAGE_SIZE - 1);
-        prot = PAGE_READ | PAGE_WRITE;
-        goto do_mapping;
+       *physical = address;
+        *prot = PAGE_READ | PAGE_WRITE;
+        return 0;
     }
 
     /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
     /* Context base + context number */
-    pde_ptr = phys_ram_base + (env->mmuregs[1] << 4) + (env->mmuregs[2] << 4);
-    pde = ldl_raw(pde_ptr);
+    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 4);
+    cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
+    bswap32s(&pde);
 
     /* Ctx pde */
     switch (pde & PTE_ENTRYTYPE_MASK) {
+    default:
     case 0: /* Invalid */
-        error_code = 1;
-        goto do_fault;
-    case 2: /* PTE, maybe should not happen? */
+       return 1;
+    case 2: /* L0 PTE, maybe should not happen? */
     case 3: /* Reserved */
-        error_code = 4;
-        goto do_fault;
-    case 1: /* L1 PDE */
-       pde_ptr = phys_ram_base + ((address >> 22) & ~3) + ((pde & ~3) << 4);
-       pde = ldl_raw(pde_ptr);
+        return 4;
+    case 1: /* L0 PDE */
+       pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
+       cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
+       bswap32s(&pde);
 
        switch (pde & PTE_ENTRYTYPE_MASK) {
+       default:
        case 0: /* Invalid */
-           error_code = 1;
-           goto do_fault;
+           return 1;
        case 3: /* Reserved */
-           error_code = 4;
-           goto do_fault;
-       case 1: /* L2 PDE */
-           pde_ptr = phys_ram_base + ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
-           pde = ldl_raw(pde_ptr);
+           return 4;
+       case 1: /* L1 PDE */
+           pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
+           cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
+           bswap32s(&pde);
 
            switch (pde & PTE_ENTRYTYPE_MASK) {
+           default:
            case 0: /* Invalid */
-               error_code = 1;
-               goto do_fault;
+               return 1;
            case 3: /* Reserved */
-               error_code = 4;
-               goto do_fault;
-           case 1: /* L3 PDE */
-               pde_ptr = phys_ram_base + ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
-               pde = ldl_raw(pde_ptr);
+               return 4;
+           case 1: /* L2 PDE */
+               pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
+               cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
+               bswap32s(&pde);
 
                switch (pde & PTE_ENTRYTYPE_MASK) {
+               default:
                case 0: /* Invalid */
-                   error_code = 1;
-                   goto do_fault;
+                   return 1;
                case 1: /* PDE, should not happen */
                case 3: /* Reserved */
-                   error_code = 4;
-                   goto do_fault;
+                   return 4;
                case 2: /* L3 PTE */
                    virt_addr = address & TARGET_PAGE_MASK;
                    page_offset = (address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1);
@@ -201,40 +193,58 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
     /* update page modified and dirty bits */
     is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
     if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
+       uint32_t tmppde;
        pde |= PG_ACCESSED_MASK;
        if (is_dirty)
            pde |= PG_MODIFIED_MASK;
-       stl_raw(pde_ptr, pde);
+       tmppde = bswap32(pde);
+       cpu_physical_memory_write(pde_ptr, (uint8_t *)&tmppde, 4);
     }
-
     /* check access */
-    access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
+    *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
     access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
-    error_code = access_table[access_index][access_perms];
+    error_code = access_table[*access_index][access_perms];
     if (error_code)
-       goto do_fault;
+       return error_code;
 
     /* the page can be put in the TLB */
-    prot = PAGE_READ;
+    *prot = PAGE_READ;
     if (pde & PG_MODIFIED_MASK) {
         /* only set write access if already dirty... otherwise wait
            for dirty access */
        if (rw_table[is_user][access_perms])
-               prot |= PAGE_WRITE;
+               *prot |= PAGE_WRITE;
     }
 
     /* Even if large ptes, we map only one 4KB page in the cache to
        avoid filling it too fast */
-    virt_addr = address & TARGET_PAGE_MASK;
-    paddr = ((pde & PTE_ADDR_MASK) << 4) + page_offset;
+    *physical = ((pde & PTE_ADDR_MASK) << 4) + page_offset;
+    return 0;
+}
+
+/* Perform address translation */
+int cpu_sparc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
+                              int is_user, int is_softmmu)
+{
+    int exception = 0;
+    uint32_t virt_addr, paddr;
+    unsigned long vaddr;
+    int error_code = 0, prot, ret = 0, access_index;
 
- do_mapping:
-    vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1));
+    if (env->user_mode_only) {
+        /* user mode only emulation */
+        error_code = -2;
+       goto do_fault_user;
+    }
 
-    ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu);
-    return ret;
+    error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, is_user);
+    if (error_code == 0) {
+       virt_addr = address & TARGET_PAGE_MASK;
+       vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1));
+       ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu);
+       return ret;
+    }
 
- do_fault:
     if (env->mmuregs[3]) /* Fault status register */
        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
     env->mmuregs[3] |= (access_index << 5) | (error_code << 2) | 2;
@@ -242,7 +252,7 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
 
     if (env->mmuregs[0] & MMU_NF || env->psret == 0) // No fault
        return 0;
-
+ do_fault_user:
     env->exception_index = exception;
     env->error_code = error_code;
     return error_code;
@@ -289,13 +299,14 @@ void do_interrupt(int intno, int is_int, int error_code,
                     count, intno, error_code, is_int,
                     env->pc,
                     env->npc, env->regwptr[6]);
-#if 0
+#if 1
        cpu_dump_state(env, logfile, fprintf, 0);
        {
            int i;
            uint8_t *ptr;
+
            fprintf(logfile, "       code=");
-           ptr = env->pc;
+           ptr = (uint8_t *)env->pc;
            for(i = 0; i < 16; i++) {
                fprintf(logfile, " %02x", ldub(ptr + i));
            }
@@ -304,12 +315,19 @@ void do_interrupt(int intno, int is_int, int error_code,
 #endif
        count++;
     }
+#endif
+#if !defined(CONFIG_USER_ONLY) 
+    if (env->psret == 0) {
+       fprintf(logfile, "Trap while interrupts disabled, Error state!\n");
+       qemu_system_shutdown_request();
+       return;
+    }
 #endif
     env->psret = 0;
     cwp = (env->cwp - 1) & (NWINDOWS - 1); 
     set_cwp(cwp);
-    env->regwptr[9] = env->pc;
-    env->regwptr[10] = env->npc;
+    env->regwptr[9] = env->pc - 4; // XXX?
+    env->regwptr[10] = env->pc;
     env->psrps = env->psrs;
     env->psrs = 1;
     env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
@@ -322,3 +340,106 @@ void raise_exception_err(int exception_index, int error_code)
 {
     raise_exception(exception_index);
 }
+
+uint32_t mmu_probe(uint32_t address, int mmulev)
+{
+    target_phys_addr_t pde_ptr;
+    uint32_t pde;
+
+    /* Context base + context number */
+    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 4);
+    cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
+    bswap32s(&pde);
+    switch (pde & PTE_ENTRYTYPE_MASK) {
+    default:
+    case 0: /* Invalid */
+    case 2: /* PTE, maybe should not happen? */
+    case 3: /* Reserved */
+       return 0;
+    case 1: /* L1 PDE */
+       if (mmulev == 3)
+           return pde;
+       pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
+       cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
+       bswap32s(&pde);
+
+       switch (pde & PTE_ENTRYTYPE_MASK) {
+       default:
+       case 0: /* Invalid */
+       case 3: /* Reserved */
+           return 0;
+       case 2: /* L1 PTE */
+           return pde;
+       case 1: /* L2 PDE */
+           if (mmulev == 2)
+               return pde;
+           pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
+           cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
+           bswap32s(&pde);
+
+           switch (pde & PTE_ENTRYTYPE_MASK) {
+           default:
+           case 0: /* Invalid */
+           case 3: /* Reserved */
+               return 0;
+           case 2: /* L2 PTE */
+               return pde;
+           case 1: /* L3 PDE */
+               if (mmulev == 1)
+                   return pde;
+               pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
+               cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
+               bswap32s(&pde);
+
+               switch (pde & PTE_ENTRYTYPE_MASK) {
+               default:
+               case 0: /* Invalid */
+               case 1: /* PDE, should not happen */
+               case 3: /* Reserved */
+                   return 0;
+               case 2: /* L3 PTE */
+                   return pde;
+               }
+           }
+       }
+    }
+    return 0;
+}
+
+void dump_mmu(void)
+{
+#ifdef DEBUG_MMU
+    uint32_t pa, va, va1, va2;
+    int n, m, o;
+    target_phys_addr_t pde_ptr;
+    uint32_t pde;
+
+    printf("MMU dump:\n");
+    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 4);
+    cpu_physical_memory_read(pde_ptr, (uint8_t *)&pde, 4);
+    bswap32s(&pde);
+    printf("Root ptr: 0x%08x, ctx: %d\n", env->mmuregs[1] << 4, env->mmuregs[2]);
+    for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
+       pde_ptr = mmu_probe(va, 2);
+       if (pde_ptr) {
+           pa = cpu_get_phys_page_debug(env, va);
+           printf("VA: 0x%08x, PA: 0x%08x PDE: 0x%08x\n", va, pa, pde_ptr);
+           for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
+               pde_ptr = mmu_probe(va1, 1);
+               if (pde_ptr) {
+                   pa = cpu_get_phys_page_debug(env, va1);
+                   printf(" VA: 0x%08x, PA: 0x%08x PDE: 0x%08x\n", va1, pa, pde_ptr);
+                   for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
+                       pde_ptr = mmu_probe(va2, 0);
+                       if (pde_ptr) {
+                           pa = cpu_get_phys_page_debug(env, va2);
+                           printf("  VA: 0x%08x, PA: 0x%08x PTE: 0x%08x\n", va2, pa, pde_ptr);
+                       }
+                   }
+               }
+           }
+       }
+    }
+    printf("MMU dump ends\n");
+#endif
+}
index 2cf4ed841188ccff49346ad778d58a16d0a7b9d9..f8cf2f893465820269262d05611679b417beeb7e 100644 (file)
@@ -524,13 +524,7 @@ void OPPROTO op_rdpsr(void)
 
 void OPPROTO op_wrpsr(void)
 {
-    int cwp;
-    env->psr = T0 & ~PSR_ICC;
-    env->psrs = (T0 & PSR_S)? 1 : 0;
-    env->psrps = (T0 & PSR_PS)? 1 : 0;
-    env->psret = (T0 & PSR_ET)? 1 : 0;
-    cwp = (T0 & PSR_CWP) & (NWINDOWS - 1);
-    set_cwp(cwp);
+    PUT_PSR(env,T0);
     FORCE_RET();
 }
 
@@ -602,10 +596,27 @@ void OPPROTO op_trapcc_T0(void)
     FORCE_RET();
 }
 
-void OPPROTO op_debug(void)
+void OPPROTO op_trap_ifnofpu(void)
+{
+    if (!env->psref) {
+        env->exception_index = TT_NFPU_INSN;
+        cpu_loop_exit();
+    }
+    FORCE_RET();
+}
+
+void OPPROTO op_fpexception_im(void)
 {
-    env->exception_index = EXCP_DEBUG;
+    env->exception_index = TT_FP_EXCP;
+    env->fsr &= ~FSR_FTT_MASK;
+    env->fsr |= PARAM1;
     cpu_loop_exit();
+    FORCE_RET();
+}
+
+void OPPROTO op_debug(void)
+{
+    helper_debug();
 }
 
 void OPPROTO op_exit_tb(void)
index 3a6de7cfc24a99649cf9abc55600e9220b065686..6dead66a8ca56524994e8be49e614c116e7611e9 100644 (file)
@@ -2,6 +2,8 @@
 #include <fenv.h>
 #include "exec.h"
 
+//#define DEBUG_MMU
+
 #ifdef USE_INT_TO_FLOAT_HELPERS
 void do_fitos(void)
 {
@@ -33,6 +35,13 @@ void do_fcmps (void)
 {
     if (isnan(FT0) || isnan(FT1)) {
         T0 = FSR_FCC1 | FSR_FCC0;
+       env->fsr &= ~(FSR_FCC1 | FSR_FCC0);
+       env->fsr |= T0;
+       if (env->fsr & FSR_NVM) {
+           raise_exception(TT_FP_EXCP);
+       } else {
+           env->fsr |= FSR_NVA;
+       }
     } else if (FT0 < FT1) {
         T0 = FSR_FCC0;
     } else if (FT0 > FT1) {
@@ -47,6 +56,13 @@ void do_fcmpd (void)
 {
     if (isnan(DT0) || isnan(DT1)) {
         T0 = FSR_FCC1 | FSR_FCC0;
+       env->fsr &= ~(FSR_FCC1 | FSR_FCC0);
+       env->fsr |= T0;
+       if (env->fsr & FSR_NVM) {
+           raise_exception(TT_FP_EXCP);
+       } else {
+           env->fsr |= FSR_NVA;
+       }
     } else if (DT0 < DT1) {
         T0 = FSR_FCC0;
     } else if (DT0 > DT1) {
@@ -59,55 +75,131 @@ void do_fcmpd (void)
 
 void helper_ld_asi(int asi, int size, int sign)
 {
-    switch(asi) {
+    uint32_t ret;
+
+    switch (asi) {
     case 3: /* MMU probe */
-       T1 = 0;
-       return;
+       {
+           int mmulev;
+
+           mmulev = (T0 >> 8) & 15;
+           if (mmulev > 4)
+               ret = 0;
+           else {
+               ret = mmu_probe(T0, mmulev);
+               //bswap32s(&ret);
+           }
+#ifdef DEBUG_MMU
+           printf("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret);
+#endif
+       }
+       break;
     case 4: /* read MMU regs */
        {
-           int temp, reg = (T0 >> 8) & 0xf;
+           int reg = (T0 >> 8) & 0xf;
            
-           temp = env->mmuregs[reg];
+           ret = env->mmuregs[reg];
            if (reg == 3 || reg == 4) /* Fault status, addr cleared on read*/
-               env->mmuregs[reg] = 0;
-           T1 = temp;
+               env->mmuregs[4] = 0;
        }
-       return;
+       break;
     case 0x20 ... 0x2f: /* MMU passthrough */
-       {
-           int temp;
-           
-           cpu_physical_memory_read(T0, (void *) &temp, size);
-           bswap32s(&temp);
-           T1 = temp;
-       }
-       return;
+       cpu_physical_memory_read(T0, (void *) &ret, size);
+       if (size == 4)
+           bswap32s(&ret);
+       else if (size == 2)
+           bswap16s(&ret);
+       break;
     default:
-       T1 = 0;
-       return;
+       ret = 0;
+       break;
     }
+    T1 = ret;
 }
 
 void helper_st_asi(int asi, int size, int sign)
 {
     switch(asi) {
     case 3: /* MMU flush */
-       return;
+       {
+           int mmulev;
+
+           mmulev = (T0 >> 8) & 15;
+           switch (mmulev) {
+           case 0: // flush page
+               tlb_flush_page(cpu_single_env, T0 & 0xfffff000);
+               break;
+           case 1: // flush segment (256k)
+           case 2: // flush region (16M)
+           case 3: // flush context (4G)
+           case 4: // flush entire
+               tlb_flush(cpu_single_env, 1);
+               break;
+           default:
+               break;
+           }
+           dump_mmu();
+           return;
+       }
     case 4: /* write MMU regs */
        {
-           int reg = (T0 >> 8) & 0xf;
+           int reg = (T0 >> 8) & 0xf, oldreg;
+           
+           oldreg = env->mmuregs[reg];
            if (reg == 0) {
                env->mmuregs[reg] &= ~(MMU_E | MMU_NF);
                env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF);
            } else
                env->mmuregs[reg] = T1;
+           if (oldreg != env->mmuregs[reg]) {
+#if 0
+               // XXX: Only if MMU mapping change, we may need to flush?
+               tlb_flush(cpu_single_env, 1);
+               cpu_loop_exit();
+               FORCE_RET();
+#endif
+           }
+           dump_mmu();
            return;
        }
+    case 0x17: /* Block copy, sta access */
+       {
+           // value (T1) = src
+           // address (T0) = dst
+           // copy 32 bytes
+           int src = T1, dst = T0;
+           uint8_t temp[32];
+           
+           bswap32s(&src);
+
+           cpu_physical_memory_read(src, (void *) &temp, 32);
+           cpu_physical_memory_write(dst, (void *) &temp, 32);
+       }
+       return;
+    case 0x1f: /* Block fill, stda access */
+       {
+           // value (T1, T2)
+           // address (T0) = dst
+           // fill 32 bytes
+           int i, dst = T0;
+           uint64_t val;
+           
+           val = (((uint64_t)T1) << 32) | T2;
+           bswap64s(&val);
+
+           for (i = 0; i < 32; i += 8, dst += 8) {
+               cpu_physical_memory_write(dst, (void *) &val, 8);
+           }
+       }
+       return;
     case 0x20 ... 0x2f: /* MMU passthrough */
        {
            int temp = T1;
-           
-           bswap32s(&temp);
+           if (size == 4)
+               bswap32s(&temp);
+           else if (size == 2)
+               bswap16s(&temp);
+
            cpu_physical_memory_write(T0, (void *) &temp, size);
        }
        return;
@@ -116,27 +208,6 @@ void 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 helper_rett()
 {
     int cwp;
@@ -166,3 +237,22 @@ void helper_ldfsr(void)
        break;
     }
 }
+
+void cpu_get_fp64(uint64_t *pmant, uint16_t *pexp, double f)
+{
+    int exptemp;
+
+    *pmant = ldexp(frexp(f, &exptemp), 53);
+    *pexp = exptemp;
+}
+
+double cpu_put_fp64(uint64_t mant, uint16_t exp)
+{
+    return ldexp((double) mant, exp - 53);
+}
+
+void helper_debug()
+{
+    env->exception_index = EXCP_DEBUG;
+    cpu_loop_exit();
+}
index 2ae74f2cefcb5c02e9895422453bf0ab78da09f6..9c839a004739636e35d96e559e82889b2bf7f868 100644 (file)
@@ -43,12 +43,8 @@ void OPPROTO glue(op_swap, MEMSUFFIX)(void)
 
 void OPPROTO glue(op_ldd, MEMSUFFIX)(void)
 {
-#if 1
     T1 = glue(ldl, MEMSUFFIX)((void *) T0);
     T0 = glue(ldl, MEMSUFFIX)((void *) (T0 + 4));
-#else
-    glue(do_ldd, MEMSUFFIX)(T0);
-#endif
 }
 
 /***                         Floating-point store                          ***/
index 2440c0d22ecb5040b1ed9e7387787581b79b569e..2f067958d028afe3c7e3171a20eaf2328206aabb 100644 (file)
@@ -646,6 +646,7 @@ static void disas_sparc_insn(DisasContext * dc)
            switch (xop) {
            case 0x0:
            case 0x1:           /* UNIMPL */
+           case 0x5:           /*CBN+x */
            default:
                 goto illegal_insn;
            case 0x2:           /* BN+x */
@@ -657,16 +658,24 @@ static void disas_sparc_insn(DisasContext * dc)
                }
            case 0x6:           /* FBN+x */
                {
+#if !defined(CONFIG_USER_ONLY)
+                   gen_op_trap_ifnofpu();
+#endif
                    target <<= 2;
                    target = sign_extend(target, 22);
                    do_fbranch(dc, target, insn);
                    goto jmp_insn;
                }
            case 0x4:           /* SETHI */
-               gen_movl_imm_T0(target << 10);
-               gen_movl_T0_reg(rd);
-               break;
-           case 0x5:           /*CBN+x */
+#define OPTIM
+#if defined(OPTIM)
+               if (rd) { // nop
+#endif
+                   gen_movl_imm_T0(target << 10);
+                   gen_movl_T0_reg(rd);
+#if defined(OPTIM)
+               }
+#endif
                break;
            }
            break;
@@ -691,14 +700,24 @@ static void disas_sparc_insn(DisasContext * dc)
                 gen_movl_reg_T0(rs1);
                if (IS_IMM) {
                    rs2 = GET_FIELD(insn, 25, 31);
+#if defined(OPTIM)
                    if (rs2 != 0) {
-                        gen_movl_imm_T1(rs2);
-                        gen_op_add_T1_T0();
+#endif
+                       gen_movl_imm_T1(rs2);
+                       gen_op_add_T1_T0();
+#if defined(OPTIM)
                    }
+#endif
                 } else {
                     rs2 = GET_FIELD(insn, 27, 31);
-                    gen_movl_reg_T1(rs2);
-                    gen_op_add_T1_T0();
+#if defined(OPTIM)
+                   if (rs2 != 0) {
+#endif
+                       gen_movl_reg_T1(rs2);
+                       gen_op_add_T1_T0();
+#if defined(OPTIM)
+                   }
+#endif
                 }
                 save_state(dc);
                 cond = GET_FIELD(insn, 3, 6);
@@ -707,6 +726,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     dc->is_br = 1;
                     goto jmp_insn;
                 } else {
+                   gen_cond(cond);
                     gen_op_trapcc_T0();
                 }
             } else if (xop == 0x28) {
@@ -741,7 +761,10 @@ static void disas_sparc_insn(DisasContext * dc)
                 gen_movl_T0_reg(rd);
                 break;
 #endif
-           } else if (xop == 0x34 || xop == 0x35) {    /* FPU Operations */
+           } else if (xop == 0x34) {   /* FPU Operations */
+#if !defined(CONFIG_USER_ONLY)
+               gen_op_trap_ifnofpu();
+#endif
                 rs1 = GET_FIELD(insn, 13, 17);
                rs2 = GET_FIELD(insn, 27, 31);
                xop = GET_FIELD(insn, 18, 26);
@@ -770,6 +793,8 @@ static void disas_sparc_insn(DisasContext * dc)
                        gen_op_fsqrtd();
                        gen_op_store_DT0_fpr(rd);
                        break;
+                   case 0x2b: /* fsqrtq */
+                       goto nfpu_insn;
                    case 0x41:
                        gen_op_load_fpr_FT0(rs1);
                        gen_op_load_fpr_FT1(rs2);
@@ -782,6 +807,8 @@ static void disas_sparc_insn(DisasContext * dc)
                        gen_op_faddd();
                        gen_op_store_DT0_fpr(rd);
                        break;
+                   case 0x43: /* faddq */
+                       goto nfpu_insn;
                    case 0x45:
                        gen_op_load_fpr_FT0(rs1);
                        gen_op_load_fpr_FT1(rs2);
@@ -794,6 +821,8 @@ static void disas_sparc_insn(DisasContext * dc)
                        gen_op_fsubd();
                        gen_op_store_DT0_fpr(rd);
                        break;
+                   case 0x47: /* fsubq */
+                       goto nfpu_insn;
                    case 0x49:
                        gen_op_load_fpr_FT0(rs1);
                        gen_op_load_fpr_FT1(rs2);
@@ -806,6 +835,8 @@ static void disas_sparc_insn(DisasContext * dc)
                        gen_op_fmuld();
                        gen_op_store_DT0_fpr(rd);
                        break;
+                   case 0x4b: /* fmulq */
+                       goto nfpu_insn;
                    case 0x4d:
                        gen_op_load_fpr_FT0(rs1);
                        gen_op_load_fpr_FT1(rs2);
@@ -818,32 +849,16 @@ static void disas_sparc_insn(DisasContext * dc)
                        gen_op_fdivd();
                        gen_op_store_DT0_fpr(rd);
                        break;
-                   case 0x51:
-                       gen_op_load_fpr_FT0(rs1);
-                       gen_op_load_fpr_FT1(rs2);
-                       gen_op_fcmps();
-                       break;
-                   case 0x52:
-                       gen_op_load_fpr_DT0(rs1);
-                       gen_op_load_fpr_DT1(rs2);
-                       gen_op_fcmpd();
-                       break;
-                   case 0x55: /* fcmpes */
-                       gen_op_load_fpr_FT0(rs1);
-                       gen_op_load_fpr_FT1(rs2);
-                       gen_op_fcmps(); /* XXX */
-                       break;
-                   case 0x56: /* fcmped */
-                       gen_op_load_fpr_DT0(rs1);
-                       gen_op_load_fpr_DT1(rs2);
-                       gen_op_fcmpd(); /* XXX */
-                       break;
+                   case 0x4f: /* fdivq */
+                       goto nfpu_insn;
                    case 0x69:
                        gen_op_load_fpr_FT0(rs1);
                        gen_op_load_fpr_FT1(rs2);
                        gen_op_fsmuld();
                        gen_op_store_DT0_fpr(rd);
                        break;
+                   case 0x6e: /* fdmulq */
+                       goto nfpu_insn;
                    case 0xc4:
                        gen_op_load_fpr_FT1(rs2);
                        gen_op_fitos();
@@ -854,6 +869,8 @@ static void disas_sparc_insn(DisasContext * dc)
                        gen_op_fdtos();
                        gen_op_store_FT0_fpr(rd);
                        break;
+                   case 0xc7: /* fqtos */
+                       goto nfpu_insn;
                    case 0xc8:
                        gen_op_load_fpr_FT1(rs2);
                        gen_op_fitod();
@@ -864,6 +881,14 @@ static void disas_sparc_insn(DisasContext * dc)
                        gen_op_fstod();
                        gen_op_store_DT0_fpr(rd);
                        break;
+                   case 0xcb: /* fqtod */
+                       goto nfpu_insn;
+                   case 0xcc: /* fitoq */
+                       goto nfpu_insn;
+                   case 0xcd: /* fstoq */
+                       goto nfpu_insn;
+                   case 0xce: /* fdtoq */
+                       goto nfpu_insn;
                    case 0xd1:
                        gen_op_load_fpr_FT1(rs2);
                        gen_op_fstoi();
@@ -874,13 +899,85 @@ static void disas_sparc_insn(DisasContext * dc)
                        gen_op_fdtoi();
                        gen_op_store_FT0_fpr(rd);
                        break;
+                   case 0xd3: /* fqtoi */
+                       goto nfpu_insn;
                    default:
                        goto illegal_insn;
                }
-           } else {
+           } else if (xop == 0x35) {   /* FPU Operations */
+#if !defined(CONFIG_USER_ONLY)
+               gen_op_trap_ifnofpu();
+#endif
                 rs1 = GET_FIELD(insn, 13, 17);
-                gen_movl_reg_T0(rs1);
-                if (IS_IMM) {  /* immediate */
+               rs2 = GET_FIELD(insn, 27, 31);
+               xop = GET_FIELD(insn, 18, 26);
+               switch (xop) {
+                   case 0x51:
+                       gen_op_load_fpr_FT0(rs1);
+                       gen_op_load_fpr_FT1(rs2);
+                       gen_op_fcmps();
+                       break;
+                   case 0x52:
+                       gen_op_load_fpr_DT0(rs1);
+                       gen_op_load_fpr_DT1(rs2);
+                       gen_op_fcmpd();
+                       break;
+                   case 0x53: /* fcmpq */
+                       goto nfpu_insn;
+                   case 0x55: /* fcmpes */
+                       gen_op_load_fpr_FT0(rs1);
+                       gen_op_load_fpr_FT1(rs2);
+                       gen_op_fcmps(); /* XXX should trap if qNaN or sNaN  */
+                       break;
+                   case 0x56: /* fcmped */
+                       gen_op_load_fpr_DT0(rs1);
+                       gen_op_load_fpr_DT1(rs2);
+                       gen_op_fcmpd(); /* XXX should trap if qNaN or sNaN  */
+                       break;
+                   case 0x57: /* fcmpeq */
+                       goto nfpu_insn;
+                   default:
+                       goto illegal_insn;
+               }
+#if defined(OPTIM)
+           } else if (xop == 0x2) {
+               // clr/mov shortcut
+
+                rs1 = GET_FIELD(insn, 13, 17);
+               if (rs1 == 0) {
+                   // or %g0, x, y -> mov T1, x; mov y, T1
+                   if (IS_IMM) {       /* immediate */
+                       rs2 = GET_FIELDs(insn, 19, 31);
+                       gen_movl_imm_T1(rs2);
+                   } else {            /* register */
+                       rs2 = GET_FIELD(insn, 27, 31);
+                       gen_movl_reg_T1(rs2);
+                   }
+                   gen_movl_T1_reg(rd);
+               } else {
+                   gen_movl_reg_T0(rs1);
+                   if (IS_IMM) {       /* immediate */
+                       // or x, #0, y -> mov T1, x; mov y, T1
+                       rs2 = GET_FIELDs(insn, 19, 31);
+                       if (rs2 != 0) {
+                           gen_movl_imm_T1(rs2);
+                           gen_op_or_T1_T0();
+                       }
+                   } else {            /* register */
+                       // or x, %g0, y -> mov T1, x; mov y, T1
+                       rs2 = GET_FIELD(insn, 27, 31);
+                       if (rs2 != 0) {
+                           gen_movl_reg_T1(rs2);
+                           gen_op_or_T1_T0();
+                       }
+                   }
+                   gen_movl_T0_reg(rd);
+               }
+#endif
+           } else if (xop < 0x38) {
+                rs1 = GET_FIELD(insn, 13, 17);
+               gen_movl_reg_T0(rs1);
+               if (IS_IMM) {   /* immediate */
                     rs2 = GET_FIELDs(insn, 19, 31);
                     gen_movl_imm_T1(rs2);
                 } else {               /* register */
@@ -901,10 +998,10 @@ static void disas_sparc_insn(DisasContext * dc)
                             gen_op_logic_T0_cc();
                         break;
                     case 0x2:
-                        gen_op_or_T1_T0();
-                        if (xop & 0x10)
-                            gen_op_logic_T0_cc();
-                        break;
+                       gen_op_or_T1_T0();
+                       if (xop & 0x10)
+                           gen_op_logic_T0_cc();
+                       break;
                     case 0x3:
                         gen_op_xor_T1_T0();
                         if (xop & 0x10)
@@ -964,9 +1061,14 @@ static void disas_sparc_insn(DisasContext * dc)
                     default:
                         goto illegal_insn;
                     }
-                    gen_movl_T0_reg(rd);
+                   gen_movl_T0_reg(rd);
                 } else {
                     switch (xop) {
+                   case 0x20: /* taddcc */
+                   case 0x21: /* tsubcc */
+                   case 0x22: /* taddcctv */
+                   case 0x23: /* tsubcctv */
+                       goto illegal_insn;
                     case 0x24: /* mulscc */
                         gen_op_mulscc_T1_T0();
                         gen_movl_T0_reg(rd);
@@ -1021,56 +1123,72 @@ static void disas_sparc_insn(DisasContext * dc)
                         }
                         break;
 #endif
-                    case 0x38: /* jmpl */
-                        {
-                            gen_op_add_T1_T0();
-                            gen_op_movl_npc_T0();
-                            if (rd != 0) {
-                                gen_op_movl_T0_im((long) (dc->pc));
-                                gen_movl_T0_reg(rd);
-                            }
-                            dc->pc = dc->npc;
-                            dc->npc = DYNAMIC_PC;
-                        }
-                        goto jmp_insn;
-#if !defined(CONFIG_USER_ONLY)
-                    case 0x39: /* rett */
-                        {
-                           if (!supervisor(dc))
-                               goto priv_insn;
-                            gen_op_add_T1_T0();
-                            gen_op_movl_npc_T0();
-                            gen_op_rett();
-#if 0
-                           dc->pc = dc->npc;
-                           dc->npc = DYNAMIC_PC;
+                   default:
+                       goto illegal_insn;
+                   }
+               }
+           } else {
+                rs1 = GET_FIELD(insn, 13, 17);
+               gen_movl_reg_T0(rs1);
+                if (IS_IMM) {  /* immediate */
+                   rs2 = GET_FIELDs(insn, 19, 31);
+#if defined(OPTIM)
+                   if (rs2) {
 #endif
-                        }
-#if 0
-                        goto jmp_insn;
+                       gen_movl_imm_T1(rs2);
+                       gen_op_add_T1_T0();
+#if defined(OPTIM)
+                   }
 #endif
-                       break;
+                } else {               /* register */
+                    rs2 = GET_FIELD(insn, 27, 31);
+#if defined(OPTIM)
+                   if (rs2) {
+#endif
+                       gen_movl_reg_T1(rs2);
+                       gen_op_add_T1_T0();
+#if defined(OPTIM)
+                   }
 #endif
-                    case 0x3b: /* flush */
-                        gen_op_add_T1_T0();
-                        gen_op_flush_T0();
-                        break;
-                    case 0x3c: /* save */
-                        save_state(dc);
-                        gen_op_add_T1_T0();
-                        gen_op_save();
-                        gen_movl_T0_reg(rd);
-                        break;
-                    case 0x3d: /* restore */
-                        save_state(dc);
-                        gen_op_add_T1_T0();
-                        gen_op_restore();
-                        gen_movl_T0_reg(rd);
-                        break;
-                    default:
-                        goto illegal_insn;
-                    }
                 }
+               switch (xop) {
+               case 0x38:      /* jmpl */
+                   {
+                       gen_op_movl_npc_T0();
+                       if (rd != 0) {
+                           gen_op_movl_T0_im((long) (dc->pc));
+                           gen_movl_T0_reg(rd);
+                       }
+                       dc->pc = dc->npc;
+                       dc->npc = DYNAMIC_PC;
+                   }
+                   goto jmp_insn;
+#if !defined(CONFIG_USER_ONLY)
+               case 0x39:      /* rett */
+                   {
+                       if (!supervisor(dc))
+                           goto priv_insn;
+                       gen_op_movl_npc_T0();
+                       gen_op_rett();
+                   }
+                   break;
+#endif
+               case 0x3b: /* flush */
+                   gen_op_flush_T0();
+                   break;
+               case 0x3c:      /* save */
+                   save_state(dc);
+                   gen_op_save();
+                   gen_movl_T0_reg(rd);
+                   break;
+               case 0x3d:      /* restore */
+                   save_state(dc);
+                   gen_op_restore();
+                   gen_movl_T0_reg(rd);
+                   break;
+               default:
+                   goto illegal_insn;
+               }
             }
            break;
        }
@@ -1081,14 +1199,24 @@ static void disas_sparc_insn(DisasContext * dc)
            gen_movl_reg_T0(rs1);
            if (IS_IMM) {       /* immediate */
                rs2 = GET_FIELDs(insn, 19, 31);
+#if defined(OPTIM)
                if (rs2 != 0) {
+#endif
                    gen_movl_imm_T1(rs2);
                    gen_op_add_T1_T0();
+#if defined(OPTIM)
                }
+#endif
            } else {            /* register */
                rs2 = GET_FIELD(insn, 27, 31);
-               gen_movl_reg_T1(rs2);
-               gen_op_add_T1_T0();
+#if defined(OPTIM)
+               if (rs2 != 0) {
+#endif
+                   gen_movl_reg_T1(rs2);
+                   gen_op_add_T1_T0();
+#if defined(OPTIM)
+               }
+#endif
            }
            if (xop < 4 || (xop > 7 && xop < 0x14) || \
                    (xop > 0x17 && xop < 0x20)) {
@@ -1116,8 +1244,10 @@ static void disas_sparc_insn(DisasContext * dc)
                    gen_op_ldst(ldstub);
                    break;
                case 0x0f:      /* swap register with memory. Also atomically */
+                   gen_movl_reg_T1(rd);
                    gen_op_ldst(swap);
                    break;
+#if !defined(CONFIG_USER_ONLY)
                case 0x10:      /* load word alternate */
                    if (!supervisor(dc))
                        goto priv_insn;
@@ -1157,11 +1287,18 @@ static void disas_sparc_insn(DisasContext * dc)
                case 0x1f:      /* swap reg with alt. memory. Also atomically */
                    if (!supervisor(dc))
                        goto priv_insn;
+                   gen_movl_reg_T1(rd);
                    gen_op_swapa(insn, 1, 4, 0);
                    break;
+#endif
+               default:
+                   goto illegal_insn;
                }
                gen_movl_T1_reg(rd);
            } else if (xop >= 0x20 && xop < 0x24) {
+#if !defined(CONFIG_USER_ONLY)
+               gen_op_trap_ifnofpu();
+#endif
                switch (xop) {
                case 0x20:      /* load fpreg */
                    gen_op_ldst(ldf);
@@ -1169,11 +1306,14 @@ static void disas_sparc_insn(DisasContext * dc)
                    break;
                case 0x21:      /* load fsr */
                    gen_op_ldfsr();
+                   gen_op_store_FT0_fpr(rd);
                    break;
                case 0x23:      /* load double fpreg */
                    gen_op_ldst(lddf);
                    gen_op_store_DT0_fpr(rd);
                    break;
+               default:
+                   goto illegal_insn;
                }
            } else if (xop < 8 || (xop >= 0x14 && xop < 0x18)) {
                gen_movl_reg_T1(rd);
@@ -1192,6 +1332,7 @@ static void disas_sparc_insn(DisasContext * dc)
                    gen_movl_reg_T2(rd + 1);
                    gen_op_ldst(std);
                    break;
+#if !defined(CONFIG_USER_ONLY)
                case 0x14:
                    if (!supervisor(dc))
                        goto priv_insn;
@@ -1214,24 +1355,37 @@ static void disas_sparc_insn(DisasContext * dc)
                    gen_movl_reg_T2(rd + 1);
                    gen_op_stda(insn, 0, 8, 0);
                    break;
+#endif
+               default:
+                   goto illegal_insn;
                }
            } else if (xop > 0x23 && xop < 0x28) {
+#if !defined(CONFIG_USER_ONLY)
+               gen_op_trap_ifnofpu();
+#endif
                switch (xop) {
                case 0x24:
                     gen_op_load_fpr_FT0(rd);
                    gen_op_ldst(stf);
                    break;
                case 0x25:
+                    gen_op_load_fpr_FT0(rd);
                    gen_op_stfsr();
                    break;
                case 0x27:
                     gen_op_load_fpr_DT0(rd);
                    gen_op_ldst(stdf);
                    break;
+               case 0x26: /* stdfq */
+               default:
+                   goto illegal_insn;
                }
            } else if (xop > 0x33 && xop < 0x38) {
                /* Co-processor */
+               goto illegal_insn;
             }
+           else
+               goto illegal_insn;
        }
     }
     /* default case for non jump instructions */
@@ -1246,17 +1400,24 @@ static void disas_sparc_insn(DisasContext * dc)
        dc->pc = dc->npc;
        dc->npc = dc->npc + 4;
     }
-  jmp_insn:;
+ jmp_insn:
     return;
  illegal_insn:
     save_state(dc);
     gen_op_exception(TT_ILL_INSN);
     dc->is_br = 1;
     return;
+#if !defined(CONFIG_USER_ONLY)
  priv_insn:
     save_state(dc);
     gen_op_exception(TT_PRIV_INSN);
     dc->is_br = 1;
+    return;
+#endif
+ nfpu_insn:
+    save_state(dc);
+    gen_op_fpexception_im(FSR_FTT_UNIMPFPOP);
+    dc->is_br = 1;
 }
 
 static inline int gen_intermediate_code_internal(TranslationBlock * tb,
@@ -1271,6 +1432,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
     dc->tb = tb;
     pc_start = tb->pc;
     dc->pc = pc_start;
+    last_pc = dc->pc;
     dc->npc = (target_ulong) tb->cs_base;
 #if defined(CONFIG_USER_ONLY)
     dc->mem_idx = 0;
@@ -1285,8 +1447,13 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
         if (env->nb_breakpoints > 0) {
             for(j = 0; j < env->nb_breakpoints; j++) {
                 if (env->breakpoints[j] == dc->pc) {
-                    gen_debug(dc, dc->pc);
-                    break;
+                   if (dc->pc != pc_start)
+                       save_state(dc);
+                    gen_op_debug();
+                   gen_op_movl_T0_0();
+                   gen_op_exit_tb();
+                   dc->is_br = 1;
+                    goto exit_gen_loop;
                 }
             }
         }
@@ -1310,8 +1477,18 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
        /* if the next PC is different, we abort now */
        if (dc->pc != (last_pc + 4))
            break;
+        /* if single step mode, we generate only one instruction and
+           generate an exception */
+        if (env->singlestep_enabled) {
+            gen_op_jmp_im(dc->pc);
+            gen_op_movl_T0_0();
+            gen_op_exit_tb();
+            break;
+        }
     } while ((gen_opc_ptr < gen_opc_end) &&
             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
+
+ exit_gen_loop:
     if (!dc->is_br) {
         if (dc->pc != DYNAMIC_PC && 
             (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
@@ -1338,7 +1515,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
         }
 #endif
     } else {
-        tb->size = dc->npc - pc_start;
+        tb->size = last_pc + 4 - pc_start;
     }
 #ifdef DEBUG_DISAS
     if (loglevel & CPU_LOG_TB_IN_ASM) {
@@ -1366,14 +1543,10 @@ int gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
     return gen_intermediate_code_internal(tb, 1, env);
 }
 
-CPUSPARCState *cpu_sparc_init(void)
-{
-    CPUSPARCState *env;
-
-    cpu_exec_init();
+extern int ram_size;
 
-    if (!(env = malloc(sizeof(CPUSPARCState))))
-       return (NULL);
+void cpu_reset(CPUSPARCState *env)
+{
     memset(env, 0, sizeof(*env));
     env->cwp = 0;
     env->wim = 1;
@@ -1381,14 +1554,24 @@ CPUSPARCState *cpu_sparc_init(void)
 #if defined(CONFIG_USER_ONLY)
     env->user_mode_only = 1;
 #else
-    /* Emulate Prom */
     env->psrs = 1;
-    env->pc = 0x4000;
+    env->pc = 0xffd00000;
+    env->gregs[1] = ram_size;
+    env->mmuregs[0] = (0x04 << 24); /* Impl 0, ver 4, MMU disabled */
     env->npc = env->pc + 4;
-    env->mmuregs[0] = (0x10<<24) | MMU_E; /* Impl 1, ver 0, MMU Enabled */
-    env->mmuregs[1] = 0x3000 >> 4; /* MMU Context table */
 #endif
+}
+
+CPUSPARCState *cpu_sparc_init(void)
+{
+    CPUSPARCState *env;
+
+    cpu_exec_init();
+
+    if (!(env = malloc(sizeof(CPUSPARCState))))
+       return (NULL);
     cpu_single_env = env;
+    cpu_reset(env);
     return (env);
 }
 
@@ -1436,11 +1619,24 @@ void cpu_dump_state(CPUState *env, FILE *f,
     cpu_fprintf(f, "fsr: 0x%08x\n", env->fsr);
 }
 
+#if defined(CONFIG_USER_ONLY)
 target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 {
     return addr;
 }
 
+#else
+target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+{
+    uint32_t phys_addr;
+    int prot, access_index;
+
+    if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2, 0) != 0)
+        return -1;
+    return phys_addr;
+}
+#endif
+
 void helper_flush(target_ulong addr)
 {
     addr &= ~7;
diff --git a/vl.c b/vl.c
index 78f968eb17ac53d4c0b2bc2dcf7f79784f1921c8..a2e23a7a620316d1b1031c2f8ed4eeb1f3d7a7ea 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -2214,10 +2214,74 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
 #elif defined(TARGET_SPARC)
 void cpu_save(QEMUFile *f, void *opaque)
 {
+    CPUState *env = opaque;
+    int i;
+    uint32_t tmp;
+
+    for(i = 1; i < 8; i++)
+        qemu_put_be32s(f, &env->gregs[i]);
+    tmp = env->regwptr - env->regbase;
+    qemu_put_be32s(f, &tmp);
+    for(i = 1; i < NWINDOWS * 16 + 8; i++)
+        qemu_put_be32s(f, &env->regbase[i]);
+
+    /* FPU */
+    for(i = 0; i < 32; i++) {
+        uint64_t mant;
+        uint16_t exp;
+       cpu_get_fp64(&mant, &exp, env->fpr[i]);
+        qemu_put_be64(f, mant);
+        qemu_put_be16(f, exp);
+    }
+    qemu_put_be32s(f, &env->pc);
+    qemu_put_be32s(f, &env->npc);
+    qemu_put_be32s(f, &env->y);
+    tmp = GET_PSR(env);
+    qemu_put_be32s(f, &tmp);
+    qemu_put_be32s(f, &env->fsr);
+    qemu_put_be32s(f, &env->cwp);
+    qemu_put_be32s(f, &env->wim);
+    qemu_put_be32s(f, &env->tbr);
+    /* MMU */
+    for(i = 0; i < 16; i++)
+        qemu_put_be32s(f, &env->mmuregs[i]);
 }
 
 int cpu_load(QEMUFile *f, void *opaque, int version_id)
 {
+    CPUState *env = opaque;
+    int i;
+    uint32_t tmp;
+
+    for(i = 1; i < 8; i++)
+        qemu_get_be32s(f, &env->gregs[i]);
+    qemu_get_be32s(f, &tmp);
+    env->regwptr = env->regbase + tmp;
+    for(i = 1; i < NWINDOWS * 16 + 8; i++)
+        qemu_get_be32s(f, &env->regbase[i]);
+
+    /* FPU */
+    for(i = 0; i < 32; i++) {
+        uint64_t mant;
+        uint16_t exp;
+
+        qemu_get_be64s(f, &mant);
+        qemu_get_be16s(f, &exp);
+       env->fpr[i] = cpu_put_fp64(mant, exp);
+    }
+    qemu_get_be32s(f, &env->pc);
+    qemu_get_be32s(f, &env->npc);
+    qemu_get_be32s(f, &env->y);
+    qemu_get_be32s(f, &tmp);
+    PUT_PSR(env, tmp);
+    qemu_get_be32s(f, &env->fsr);
+    qemu_get_be32s(f, &env->cwp);
+    qemu_get_be32s(f, &env->wim);
+    qemu_get_be32s(f, &env->tbr);
+    /* MMU */
+    for(i = 0; i < 16; i++)
+        qemu_get_be32s(f, &env->mmuregs[i]);
+    tlb_flush(env, 1);
     return 0;
 }
 #else
@@ -2388,7 +2452,7 @@ void qemu_system_shutdown_request(void)
 
 static void main_cpu_reset(void *opaque)
 {
-#ifdef TARGET_I386
+#if defined(TARGET_I386) || defined(TARGET_SPARC)
     CPUState *env = opaque;
     cpu_reset(env);
 #endif
diff --git a/vl.h b/vl.h
index 3f3acf2ae719eb59e5fe981358bca7acffa15fd7..94266212766848e9aef4bb74a11dc876796d8e30 100644 (file)
--- a/vl.h
+++ b/vl.h
@@ -261,7 +261,7 @@ typedef void QEMUTimerCB(void *opaque);
    Hz. */
 extern QEMUClock *rt_clock;
 
-/* Rge virtual clock is only run during the emulation. It is stopped
+/* The virtual clock is only run during the emulation. It is stopped
    when the virtual machine is stopped. Virtual timers use a high
    precision clock, usually cpu cycles (use ticks_per_sec). */
 extern QEMUClock *vm_clock;
@@ -672,25 +672,38 @@ void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
              DisplayState *ds, const char **fd_filename, int snapshot,
              const char *kernel_filename, const char *kernel_cmdline,
              const char *initrd_filename);
+uint32_t iommu_translate(uint32_t addr);
 
 /* iommu.c */
-void iommu_init(uint32_t addr);
-uint32_t iommu_translate(uint32_t addr);
+void *iommu_init(uint32_t addr);
+uint32_t iommu_translate_local(void *opaque, uint32_t addr);
 
 /* lance.c */
 void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr);
 
 /* tcx.c */
-void tcx_init(DisplayState *ds, uint32_t addr);
-
-/* sched.c */
-void sched_init();
+void *tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base,
+             unsigned long vram_offset, int vram_size);
+void tcx_update_display(void *opaque);
+void tcx_invalidate_display(void *opaque);
+void tcx_screen_dump(void *opaque, const char *filename);
+
+/* slavio_intctl.c */
+void *slavio_intctl_init();
+void slavio_pic_info(void *opaque);
+void slavio_irq_info(void *opaque);
+void slavio_pic_set_irq(void *opaque, int irq, int level);
 
 /* magic-load.c */
-void magic_init(const char *kfn, int kloadaddr, uint32_t addr);
+int load_elf(const char *filename, uint8_t *addr);
+int load_aout(const char *filename, uint8_t *addr);
+
+/* slavio_timer.c */
+void slavio_timer_init(uint32_t addr1, int irq1, uint32_t addr2, int irq2);
 
-/* timer.c */
-void timer_init(uint32_t addr, int irq);
+/* slavio_serial.c */
+SerialState *slavio_serial_init(int base, int irq, CharDriverState *chr1, CharDriverState *chr2);
+void slavio_serial_ms_kbd_init(int base, int irq);
 
 /* NVRAM helpers */
 #include "hw/m48t59.h"