diff options
-rw-r--r-- | hw/etraxfs_ser.c | 38 | ||||
-rw-r--r-- | hw/etraxfs_timer.c | 96 | ||||
-rw-r--r-- | target-cris/helper.c | 18 | ||||
-rw-r--r-- | target-cris/op.c | 7 |
4 files changed, 99 insertions, 60 deletions
diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c index bb2aeb76aa..44e75cc15c 100644 --- a/hw/etraxfs_ser.c +++ b/hw/etraxfs_ser.c @@ -26,23 +26,28 @@ #include <ctype.h> #include "hw.h" -#define RW_TR_DMA_EN 0xb0026004 -#define RW_DOUT 0xb002601c -#define RW_STAT_DIN 0xb0026020 -#define R_STAT_DIN 0xb0026024 +#define D(x) + +#define RW_TR_DMA_EN 0x04 +#define RW_DOUT 0x1c +#define RW_STAT_DIN 0x20 +#define R_STAT_DIN 0x24 static uint32_t ser_readb (void *opaque, target_phys_addr_t addr) { - CPUState *env = opaque; + CPUState *env; uint32_t r = 0; - printf ("%s %x pc=%x\n", __func__, addr, env->pc); + + env = opaque; + D(printf ("%s %x pc=%x\n", __func__, addr, env->pc)); return r; } static uint32_t ser_readw (void *opaque, target_phys_addr_t addr) { - CPUState *env = opaque; + CPUState *env; uint32_t r = 0; - printf ("%s %x pc=%x\n", __func__, addr, env->pc); + env = opaque; + D(printf ("%s %x pc=%x\n", __func__, addr, env->pc)); return r; } @@ -51,7 +56,7 @@ static uint32_t ser_readl (void *opaque, target_phys_addr_t addr) CPUState *env = opaque; uint32_t r = 0; - switch (addr) + switch (addr & 0xfff) { case RW_TR_DMA_EN: break; @@ -70,21 +75,23 @@ static uint32_t ser_readl (void *opaque, target_phys_addr_t addr) static void ser_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) { - CPUState *env = opaque; - printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); + CPUState *env; + env = opaque; + D(printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc)); } static void ser_writew (void *opaque, target_phys_addr_t addr, uint32_t value) { - CPUState *env = opaque; - printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); + CPUState *env; + env = opaque; + D(printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc)); } static void ser_writel (void *opaque, target_phys_addr_t addr, uint32_t value) { CPUState *env = opaque; - switch (addr) + switch (addr & 0xfff) { case RW_TR_DMA_EN: break; @@ -119,4 +126,7 @@ void etraxfs_ser_init(CPUState *env, qemu_irq *irqs) ser_regs = cpu_register_io_memory(0, ser_read, ser_write, env); cpu_register_physical_memory (0xb0026000, 0x3c, ser_regs); + cpu_register_physical_memory (0xb0028000, 0x3c, ser_regs); + cpu_register_physical_memory (0xb002a000, 0x3c, ser_regs); + cpu_register_physical_memory (0xb002c000, 0x3c, ser_regs); } diff --git a/hw/etraxfs_timer.c b/hw/etraxfs_timer.c index efa6bf9b61..bf7a23f7f9 100644 --- a/hw/etraxfs_timer.c +++ b/hw/etraxfs_timer.c @@ -26,6 +26,8 @@ #include "hw.h" #include "qemu-timer.h" +#define D(x) + void etrax_ack_irq(CPUState *env, uint32_t mask); #define R_TIME 0xb001e038 @@ -54,9 +56,18 @@ struct fs_timer_t { CPUState *env; qemu_irq *irq; uint32_t mask; + struct timeval last; }; -static struct fs_timer_t timer0; +static struct fs_timer_t timer[2]; + +static inline int timer_index(target_phys_addr_t addr) +{ + int t = 0; + if (addr >= 0xb005e000) + t = 1; + return t; +} /* diff two timevals. Return a single int in us. */ int diff_timeval_us(struct timeval *a, struct timeval *b) @@ -71,16 +82,20 @@ int diff_timeval_us(struct timeval *a, struct timeval *b) static uint32_t timer_readb (void *opaque, target_phys_addr_t addr) { - CPUState *env = opaque; + CPUState *env; uint32_t r = 0; - printf ("%s %x pc=%x\n", __func__, addr, env->pc); + + env = opaque; + D(printf ("%s %x pc=%x\n", __func__, addr, env->pc)); return r; } static uint32_t timer_readw (void *opaque, target_phys_addr_t addr) { - CPUState *env = opaque; + CPUState *env; uint32_t r = 0; - printf ("%s %x pc=%x\n", __func__, addr, env->pc); + + env = opaque; + D(printf ("%s %x pc=%x\n", __func__, addr, env->pc)); return r; } @@ -88,24 +103,25 @@ static uint32_t timer_readl (void *opaque, target_phys_addr_t addr) { CPUState *env = opaque; uint32_t r = 0; + int t = timer_index(addr); switch (addr) { case R_TMR0_DATA: break; case R_TMR1_DATA: - printf ("R_TMR1_DATA\n"); + D(printf ("R_TMR1_DATA\n")); break; case R_TIME: { - static struct timeval last; struct timeval now; gettimeofday(&now, NULL); - if (!(last.tv_sec == 0 && last.tv_usec == 0)) { - r = diff_timeval_us(&now, &last); + if (!(timer[t].last.tv_sec == 0 + && timer[t].last.tv_usec == 0)) { + r = diff_timeval_us(&now, &timer[t].last); r *= 1000; /* convert to ns. */ r++; /* make sure we increase for each call. */ } - last = now; + timer[t].last = now; break; } @@ -125,14 +141,16 @@ static uint32_t timer_readl (void *opaque, target_phys_addr_t addr) static void timer_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) { - CPUState *env = opaque; - printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); + CPUState *env; + env = opaque; + D(printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc)); } static void timer_writew (void *opaque, target_phys_addr_t addr, uint32_t value) { - CPUState *env = opaque; - printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); + CPUState *env; + env = opaque; + D(printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc)); } static void write_ctrl(struct fs_timer_t *t, uint32_t v) @@ -165,7 +183,7 @@ static void write_ctrl(struct fs_timer_t *t, uint32_t v) if (t->limit > 2048) { t->scale = 2048; - ptimer_set_period(timer0.ptimer, freq_hz / t->scale); + ptimer_set_period(t->ptimer, freq_hz / t->scale); } printf ("op=%d\n", op); @@ -187,11 +205,11 @@ static void write_ctrl(struct fs_timer_t *t, uint32_t v) } } -static void timer_ack_irq(void) +static void timer_ack_irq(struct fs_timer_t *t) { - if (!(r_intr & timer0.mask & rw_intr_mask)) { - qemu_irq_lower(timer0.irq[0]); - etrax_ack_irq(timer0.env, 1 << 0x1b); + if (!(r_intr & t->mask & rw_intr_mask)) { + qemu_irq_lower(t->irq[0]); + etrax_ack_irq(t->env, 1 << 0x1b); } } @@ -199,31 +217,33 @@ static void timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) { CPUState *env = opaque; - printf ("%s %x %x pc=%x\n", - __func__, addr, value, env->pc); + int t = timer_index(addr); + + D(printf ("%s %x %x pc=%x\n", + __func__, addr, value, env->pc)); switch (addr) { case RW_TMR0_DIV: - printf ("RW_TMR0_DIV=%x\n", value); - timer0.limit = value; + D(printf ("RW_TMR0_DIV=%x\n", value)); + timer[t].limit = value; break; case RW_TMR0_CTRL: - printf ("RW_TMR0_CTRL=%x\n", value); - write_ctrl(&timer0, value); + D(printf ("RW_TMR0_CTRL=%x\n", value)); + write_ctrl(&timer[t], value); break; case RW_TMR1_DIV: - printf ("RW_TMR1_DIV=%x\n", value); + D(printf ("RW_TMR1_DIV=%x\n", value)); break; case RW_TMR1_CTRL: - printf ("RW_TMR1_CTRL=%x\n", value); + D(printf ("RW_TMR1_CTRL=%x\n", value)); break; case RW_INTR_MASK: - printf ("RW_INTR_MASK=%x\n", value); + D(printf ("RW_INTR_MASK=%x\n", value)); rw_intr_mask = value; break; case RW_ACK_INTR: r_intr &= ~value; - timer_ack_irq(); + timer_ack_irq(&timer[t]); break; default: printf ("%s %x %x pc=%x\n", @@ -247,7 +267,6 @@ static CPUWriteMemoryFunc *timer_write[] = { static void timer_irq(void *opaque) { struct fs_timer_t *t = opaque; - r_intr |= t->mask; if (t->mask & rw_intr_mask) { qemu_irq_raise(t->irq[0]); @@ -258,12 +277,19 @@ void etraxfs_timer_init(CPUState *env, qemu_irq *irqs) { int timer_regs; - timer0.bh = qemu_bh_new(timer_irq, &timer0); - timer0.ptimer = ptimer_init(timer0.bh); - timer0.irq = irqs + 0x1b; - timer0.mask = 1; - timer0.env = env; + timer[0].bh = qemu_bh_new(timer_irq, &timer[0]); + timer[0].ptimer = ptimer_init(timer[0].bh); + timer[0].irq = irqs + 0x1b; + timer[0].mask = 1; + timer[0].env = env; + + timer[1].bh = qemu_bh_new(timer_irq, &timer[1]); + timer[1].ptimer = ptimer_init(timer[1].bh); + timer[1].irq = irqs + 0x1b; + timer[1].mask = 1; + timer[1].env = env; timer_regs = cpu_register_io_memory(0, timer_read, timer_write, env); cpu_register_physical_memory (0xb001e000, 0x5c, timer_regs); + cpu_register_physical_memory (0xb005e000, 0x5c, timer_regs); } diff --git a/target-cris/helper.c b/target-cris/helper.c index e7eac08e68..7482e0893f 100644 --- a/target-cris/helper.c +++ b/target-cris/helper.c @@ -32,22 +32,23 @@ void do_interrupt (CPUState *env) { - env->exception_index = -1; + env->exception_index = -1; + env->pregs[PR_ERP] = env->pc; } int cpu_cris_handle_mmu_fault(CPUState * env, target_ulong address, int rw, int mmu_idx, int is_softmmu) { - env->exception_index = 0xaa; - env->debug1 = address; - cpu_dump_state(env, stderr, fprintf, 0); - printf("%s addr=%x env->pc=%x\n", __func__, address, env->pc); - return 1; + env->exception_index = 0xaa; + env->debug1 = address; + cpu_dump_state(env, stderr, fprintf, 0); + env->pregs[PR_ERP] = env->pc; + return 1; } target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr) { - return addr; + return addr; } #else /* !CONFIG_USER_ONLY */ @@ -61,7 +62,6 @@ int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw, address &= TARGET_PAGE_MASK; prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; -// printf ("%s pc=%x %x w=%d smmu=%d\n", __func__, env->pc, address, rw, is_softmmu); miss = cris_mmu_translate(&res, env, address, rw, mmu_idx); if (miss) { @@ -73,7 +73,6 @@ int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw, { phy = res.phy; } -// printf ("a=%x phy=%x\n", address, phy); return tlb_set_page(env, address, phy, prot, mmu_idx, is_softmmu); } @@ -113,7 +112,6 @@ void do_interrupt(CPUState *env) break; case EXCP_MMU_MISS: -// printf ("MMU miss\n"); irqnum = 4; ebp = env->pregs[PR_EBP]; isr = ldl_code(ebp + irqnum * 4); diff --git a/target-cris/op.c b/target-cris/op.c index 36cfa3f20c..aeb80de4a3 100644 --- a/target-cris/op.c +++ b/target-cris/op.c @@ -967,6 +967,8 @@ void OPPROTO op_btst_T0_T1 (void) The N flag is set according to the selected bit in the dest reg. The Z flag is set if the selected bit and all bits to the right are zero. + The X flag is cleared. + Other flags are left untouched. The destination reg is not affected.*/ unsigned int fz, sbit, bset, mask, masked_t0; @@ -975,8 +977,11 @@ void OPPROTO op_btst_T0_T1 (void) mask = sbit == 31 ? -1 : (1 << (sbit + 1)) - 1; masked_t0 = T0 & mask; fz = !(masked_t0 | bset); + + /* Clear the X, N and Z flags. */ + T0 = env->pregs[PR_CCS] & ~(X_FLAG | N_FLAG | Z_FLAG); /* Set the N and Z flags accordingly. */ - T0 = (bset << 3) | (fz << 2); + T0 |= (bset << 3) | (fz << 2); RETURN(); } |