Commit bbaf29c76994ef762523bc8893a88cac701c87e7
1 parent
bffd92fe
* target-cris/op.c: Make sure the bit-test insn only updates the XNZ flags.
* target-cris/helper.c: Update ERP for user-mode simulation aswell. * hw/etraxfs_timer.c: Support multiple timers. * hw/etraxfs_ser.c: Multiple ports, the data just goes to stdout. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4004 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
99 additions
and
60 deletions
hw/etraxfs_ser.c
| ... | ... | @@ -26,23 +26,28 @@ |
| 26 | 26 | #include <ctype.h> |
| 27 | 27 | #include "hw.h" |
| 28 | 28 | |
| 29 | -#define RW_TR_DMA_EN 0xb0026004 | |
| 30 | -#define RW_DOUT 0xb002601c | |
| 31 | -#define RW_STAT_DIN 0xb0026020 | |
| 32 | -#define R_STAT_DIN 0xb0026024 | |
| 29 | +#define D(x) | |
| 30 | + | |
| 31 | +#define RW_TR_DMA_EN 0x04 | |
| 32 | +#define RW_DOUT 0x1c | |
| 33 | +#define RW_STAT_DIN 0x20 | |
| 34 | +#define R_STAT_DIN 0x24 | |
| 33 | 35 | |
| 34 | 36 | static uint32_t ser_readb (void *opaque, target_phys_addr_t addr) |
| 35 | 37 | { |
| 36 | - CPUState *env = opaque; | |
| 38 | + CPUState *env; | |
| 37 | 39 | uint32_t r = 0; |
| 38 | - printf ("%s %x pc=%x\n", __func__, addr, env->pc); | |
| 40 | + | |
| 41 | + env = opaque; | |
| 42 | + D(printf ("%s %x pc=%x\n", __func__, addr, env->pc)); | |
| 39 | 43 | return r; |
| 40 | 44 | } |
| 41 | 45 | static uint32_t ser_readw (void *opaque, target_phys_addr_t addr) |
| 42 | 46 | { |
| 43 | - CPUState *env = opaque; | |
| 47 | + CPUState *env; | |
| 44 | 48 | uint32_t r = 0; |
| 45 | - printf ("%s %x pc=%x\n", __func__, addr, env->pc); | |
| 49 | + env = opaque; | |
| 50 | + D(printf ("%s %x pc=%x\n", __func__, addr, env->pc)); | |
| 46 | 51 | return r; |
| 47 | 52 | } |
| 48 | 53 | |
| ... | ... | @@ -51,7 +56,7 @@ static uint32_t ser_readl (void *opaque, target_phys_addr_t addr) |
| 51 | 56 | CPUState *env = opaque; |
| 52 | 57 | uint32_t r = 0; |
| 53 | 58 | |
| 54 | - switch (addr) | |
| 59 | + switch (addr & 0xfff) | |
| 55 | 60 | { |
| 56 | 61 | case RW_TR_DMA_EN: |
| 57 | 62 | break; |
| ... | ... | @@ -70,21 +75,23 @@ static uint32_t ser_readl (void *opaque, target_phys_addr_t addr) |
| 70 | 75 | static void |
| 71 | 76 | ser_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) |
| 72 | 77 | { |
| 73 | - CPUState *env = opaque; | |
| 74 | - printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); | |
| 78 | + CPUState *env; | |
| 79 | + env = opaque; | |
| 80 | + D(printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc)); | |
| 75 | 81 | } |
| 76 | 82 | static void |
| 77 | 83 | ser_writew (void *opaque, target_phys_addr_t addr, uint32_t value) |
| 78 | 84 | { |
| 79 | - CPUState *env = opaque; | |
| 80 | - printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); | |
| 85 | + CPUState *env; | |
| 86 | + env = opaque; | |
| 87 | + D(printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc)); | |
| 81 | 88 | } |
| 82 | 89 | static void |
| 83 | 90 | ser_writel (void *opaque, target_phys_addr_t addr, uint32_t value) |
| 84 | 91 | { |
| 85 | 92 | CPUState *env = opaque; |
| 86 | 93 | |
| 87 | - switch (addr) | |
| 94 | + switch (addr & 0xfff) | |
| 88 | 95 | { |
| 89 | 96 | case RW_TR_DMA_EN: |
| 90 | 97 | break; |
| ... | ... | @@ -119,4 +126,7 @@ void etraxfs_ser_init(CPUState *env, qemu_irq *irqs) |
| 119 | 126 | |
| 120 | 127 | ser_regs = cpu_register_io_memory(0, ser_read, ser_write, env); |
| 121 | 128 | cpu_register_physical_memory (0xb0026000, 0x3c, ser_regs); |
| 129 | + cpu_register_physical_memory (0xb0028000, 0x3c, ser_regs); | |
| 130 | + cpu_register_physical_memory (0xb002a000, 0x3c, ser_regs); | |
| 131 | + cpu_register_physical_memory (0xb002c000, 0x3c, ser_regs); | |
| 122 | 132 | } | ... | ... |
hw/etraxfs_timer.c
| ... | ... | @@ -26,6 +26,8 @@ |
| 26 | 26 | #include "hw.h" |
| 27 | 27 | #include "qemu-timer.h" |
| 28 | 28 | |
| 29 | +#define D(x) | |
| 30 | + | |
| 29 | 31 | void etrax_ack_irq(CPUState *env, uint32_t mask); |
| 30 | 32 | |
| 31 | 33 | #define R_TIME 0xb001e038 |
| ... | ... | @@ -54,9 +56,18 @@ struct fs_timer_t { |
| 54 | 56 | CPUState *env; |
| 55 | 57 | qemu_irq *irq; |
| 56 | 58 | uint32_t mask; |
| 59 | + struct timeval last; | |
| 57 | 60 | }; |
| 58 | 61 | |
| 59 | -static struct fs_timer_t timer0; | |
| 62 | +static struct fs_timer_t timer[2]; | |
| 63 | + | |
| 64 | +static inline int timer_index(target_phys_addr_t addr) | |
| 65 | +{ | |
| 66 | + int t = 0; | |
| 67 | + if (addr >= 0xb005e000) | |
| 68 | + t = 1; | |
| 69 | + return t; | |
| 70 | +} | |
| 60 | 71 | |
| 61 | 72 | /* diff two timevals. Return a single int in us. */ |
| 62 | 73 | int diff_timeval_us(struct timeval *a, struct timeval *b) |
| ... | ... | @@ -71,16 +82,20 @@ int diff_timeval_us(struct timeval *a, struct timeval *b) |
| 71 | 82 | |
| 72 | 83 | static uint32_t timer_readb (void *opaque, target_phys_addr_t addr) |
| 73 | 84 | { |
| 74 | - CPUState *env = opaque; | |
| 85 | + CPUState *env; | |
| 75 | 86 | uint32_t r = 0; |
| 76 | - printf ("%s %x pc=%x\n", __func__, addr, env->pc); | |
| 87 | + | |
| 88 | + env = opaque; | |
| 89 | + D(printf ("%s %x pc=%x\n", __func__, addr, env->pc)); | |
| 77 | 90 | return r; |
| 78 | 91 | } |
| 79 | 92 | static uint32_t timer_readw (void *opaque, target_phys_addr_t addr) |
| 80 | 93 | { |
| 81 | - CPUState *env = opaque; | |
| 94 | + CPUState *env; | |
| 82 | 95 | uint32_t r = 0; |
| 83 | - printf ("%s %x pc=%x\n", __func__, addr, env->pc); | |
| 96 | + | |
| 97 | + env = opaque; | |
| 98 | + D(printf ("%s %x pc=%x\n", __func__, addr, env->pc)); | |
| 84 | 99 | return r; |
| 85 | 100 | } |
| 86 | 101 | |
| ... | ... | @@ -88,24 +103,25 @@ static uint32_t timer_readl (void *opaque, target_phys_addr_t addr) |
| 88 | 103 | { |
| 89 | 104 | CPUState *env = opaque; |
| 90 | 105 | uint32_t r = 0; |
| 106 | + int t = timer_index(addr); | |
| 91 | 107 | |
| 92 | 108 | switch (addr) { |
| 93 | 109 | case R_TMR0_DATA: |
| 94 | 110 | break; |
| 95 | 111 | case R_TMR1_DATA: |
| 96 | - printf ("R_TMR1_DATA\n"); | |
| 112 | + D(printf ("R_TMR1_DATA\n")); | |
| 97 | 113 | break; |
| 98 | 114 | case R_TIME: |
| 99 | 115 | { |
| 100 | - static struct timeval last; | |
| 101 | 116 | struct timeval now; |
| 102 | 117 | gettimeofday(&now, NULL); |
| 103 | - if (!(last.tv_sec == 0 && last.tv_usec == 0)) { | |
| 104 | - r = diff_timeval_us(&now, &last); | |
| 118 | + if (!(timer[t].last.tv_sec == 0 | |
| 119 | + && timer[t].last.tv_usec == 0)) { | |
| 120 | + r = diff_timeval_us(&now, &timer[t].last); | |
| 105 | 121 | r *= 1000; /* convert to ns. */ |
| 106 | 122 | r++; /* make sure we increase for each call. */ |
| 107 | 123 | } |
| 108 | - last = now; | |
| 124 | + timer[t].last = now; | |
| 109 | 125 | break; |
| 110 | 126 | } |
| 111 | 127 | |
| ... | ... | @@ -125,14 +141,16 @@ static uint32_t timer_readl (void *opaque, target_phys_addr_t addr) |
| 125 | 141 | static void |
| 126 | 142 | timer_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) |
| 127 | 143 | { |
| 128 | - CPUState *env = opaque; | |
| 129 | - printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); | |
| 144 | + CPUState *env; | |
| 145 | + env = opaque; | |
| 146 | + D(printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc)); | |
| 130 | 147 | } |
| 131 | 148 | static void |
| 132 | 149 | timer_writew (void *opaque, target_phys_addr_t addr, uint32_t value) |
| 133 | 150 | { |
| 134 | - CPUState *env = opaque; | |
| 135 | - printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); | |
| 151 | + CPUState *env; | |
| 152 | + env = opaque; | |
| 153 | + D(printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc)); | |
| 136 | 154 | } |
| 137 | 155 | |
| 138 | 156 | 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) |
| 165 | 183 | if (t->limit > 2048) |
| 166 | 184 | { |
| 167 | 185 | t->scale = 2048; |
| 168 | - ptimer_set_period(timer0.ptimer, freq_hz / t->scale); | |
| 186 | + ptimer_set_period(t->ptimer, freq_hz / t->scale); | |
| 169 | 187 | } |
| 170 | 188 | |
| 171 | 189 | printf ("op=%d\n", op); |
| ... | ... | @@ -187,11 +205,11 @@ static void write_ctrl(struct fs_timer_t *t, uint32_t v) |
| 187 | 205 | } |
| 188 | 206 | } |
| 189 | 207 | |
| 190 | -static void timer_ack_irq(void) | |
| 208 | +static void timer_ack_irq(struct fs_timer_t *t) | |
| 191 | 209 | { |
| 192 | - if (!(r_intr & timer0.mask & rw_intr_mask)) { | |
| 193 | - qemu_irq_lower(timer0.irq[0]); | |
| 194 | - etrax_ack_irq(timer0.env, 1 << 0x1b); | |
| 210 | + if (!(r_intr & t->mask & rw_intr_mask)) { | |
| 211 | + qemu_irq_lower(t->irq[0]); | |
| 212 | + etrax_ack_irq(t->env, 1 << 0x1b); | |
| 195 | 213 | } |
| 196 | 214 | } |
| 197 | 215 | |
| ... | ... | @@ -199,31 +217,33 @@ static void |
| 199 | 217 | timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) |
| 200 | 218 | { |
| 201 | 219 | CPUState *env = opaque; |
| 202 | - printf ("%s %x %x pc=%x\n", | |
| 203 | - __func__, addr, value, env->pc); | |
| 220 | + int t = timer_index(addr); | |
| 221 | + | |
| 222 | + D(printf ("%s %x %x pc=%x\n", | |
| 223 | + __func__, addr, value, env->pc)); | |
| 204 | 224 | switch (addr) |
| 205 | 225 | { |
| 206 | 226 | case RW_TMR0_DIV: |
| 207 | - printf ("RW_TMR0_DIV=%x\n", value); | |
| 208 | - timer0.limit = value; | |
| 227 | + D(printf ("RW_TMR0_DIV=%x\n", value)); | |
| 228 | + timer[t].limit = value; | |
| 209 | 229 | break; |
| 210 | 230 | case RW_TMR0_CTRL: |
| 211 | - printf ("RW_TMR0_CTRL=%x\n", value); | |
| 212 | - write_ctrl(&timer0, value); | |
| 231 | + D(printf ("RW_TMR0_CTRL=%x\n", value)); | |
| 232 | + write_ctrl(&timer[t], value); | |
| 213 | 233 | break; |
| 214 | 234 | case RW_TMR1_DIV: |
| 215 | - printf ("RW_TMR1_DIV=%x\n", value); | |
| 235 | + D(printf ("RW_TMR1_DIV=%x\n", value)); | |
| 216 | 236 | break; |
| 217 | 237 | case RW_TMR1_CTRL: |
| 218 | - printf ("RW_TMR1_CTRL=%x\n", value); | |
| 238 | + D(printf ("RW_TMR1_CTRL=%x\n", value)); | |
| 219 | 239 | break; |
| 220 | 240 | case RW_INTR_MASK: |
| 221 | - printf ("RW_INTR_MASK=%x\n", value); | |
| 241 | + D(printf ("RW_INTR_MASK=%x\n", value)); | |
| 222 | 242 | rw_intr_mask = value; |
| 223 | 243 | break; |
| 224 | 244 | case RW_ACK_INTR: |
| 225 | 245 | r_intr &= ~value; |
| 226 | - timer_ack_irq(); | |
| 246 | + timer_ack_irq(&timer[t]); | |
| 227 | 247 | break; |
| 228 | 248 | default: |
| 229 | 249 | printf ("%s %x %x pc=%x\n", |
| ... | ... | @@ -247,7 +267,6 @@ static CPUWriteMemoryFunc *timer_write[] = { |
| 247 | 267 | static void timer_irq(void *opaque) |
| 248 | 268 | { |
| 249 | 269 | struct fs_timer_t *t = opaque; |
| 250 | - | |
| 251 | 270 | r_intr |= t->mask; |
| 252 | 271 | if (t->mask & rw_intr_mask) { |
| 253 | 272 | qemu_irq_raise(t->irq[0]); |
| ... | ... | @@ -258,12 +277,19 @@ void etraxfs_timer_init(CPUState *env, qemu_irq *irqs) |
| 258 | 277 | { |
| 259 | 278 | int timer_regs; |
| 260 | 279 | |
| 261 | - timer0.bh = qemu_bh_new(timer_irq, &timer0); | |
| 262 | - timer0.ptimer = ptimer_init(timer0.bh); | |
| 263 | - timer0.irq = irqs + 0x1b; | |
| 264 | - timer0.mask = 1; | |
| 265 | - timer0.env = env; | |
| 280 | + timer[0].bh = qemu_bh_new(timer_irq, &timer[0]); | |
| 281 | + timer[0].ptimer = ptimer_init(timer[0].bh); | |
| 282 | + timer[0].irq = irqs + 0x1b; | |
| 283 | + timer[0].mask = 1; | |
| 284 | + timer[0].env = env; | |
| 285 | + | |
| 286 | + timer[1].bh = qemu_bh_new(timer_irq, &timer[1]); | |
| 287 | + timer[1].ptimer = ptimer_init(timer[1].bh); | |
| 288 | + timer[1].irq = irqs + 0x1b; | |
| 289 | + timer[1].mask = 1; | |
| 290 | + timer[1].env = env; | |
| 266 | 291 | |
| 267 | 292 | timer_regs = cpu_register_io_memory(0, timer_read, timer_write, env); |
| 268 | 293 | cpu_register_physical_memory (0xb001e000, 0x5c, timer_regs); |
| 294 | + cpu_register_physical_memory (0xb005e000, 0x5c, timer_regs); | |
| 269 | 295 | } | ... | ... |
target-cris/helper.c
| ... | ... | @@ -32,22 +32,23 @@ |
| 32 | 32 | |
| 33 | 33 | void do_interrupt (CPUState *env) |
| 34 | 34 | { |
| 35 | - env->exception_index = -1; | |
| 35 | + env->exception_index = -1; | |
| 36 | + env->pregs[PR_ERP] = env->pc; | |
| 36 | 37 | } |
| 37 | 38 | |
| 38 | 39 | int cpu_cris_handle_mmu_fault(CPUState * env, target_ulong address, int rw, |
| 39 | 40 | int mmu_idx, int is_softmmu) |
| 40 | 41 | { |
| 41 | - env->exception_index = 0xaa; | |
| 42 | - env->debug1 = address; | |
| 43 | - cpu_dump_state(env, stderr, fprintf, 0); | |
| 44 | - printf("%s addr=%x env->pc=%x\n", __func__, address, env->pc); | |
| 45 | - return 1; | |
| 42 | + env->exception_index = 0xaa; | |
| 43 | + env->debug1 = address; | |
| 44 | + cpu_dump_state(env, stderr, fprintf, 0); | |
| 45 | + env->pregs[PR_ERP] = env->pc; | |
| 46 | + return 1; | |
| 46 | 47 | } |
| 47 | 48 | |
| 48 | 49 | target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr) |
| 49 | 50 | { |
| 50 | - return addr; | |
| 51 | + return addr; | |
| 51 | 52 | } |
| 52 | 53 | |
| 53 | 54 | #else /* !CONFIG_USER_ONLY */ |
| ... | ... | @@ -61,7 +62,6 @@ int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw, |
| 61 | 62 | |
| 62 | 63 | address &= TARGET_PAGE_MASK; |
| 63 | 64 | prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; |
| 64 | -// printf ("%s pc=%x %x w=%d smmu=%d\n", __func__, env->pc, address, rw, is_softmmu); | |
| 65 | 65 | miss = cris_mmu_translate(&res, env, address, rw, mmu_idx); |
| 66 | 66 | if (miss) |
| 67 | 67 | { |
| ... | ... | @@ -73,7 +73,6 @@ int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw, |
| 73 | 73 | { |
| 74 | 74 | phy = res.phy; |
| 75 | 75 | } |
| 76 | -// printf ("a=%x phy=%x\n", address, phy); | |
| 77 | 76 | return tlb_set_page(env, address, phy, prot, mmu_idx, is_softmmu); |
| 78 | 77 | } |
| 79 | 78 | |
| ... | ... | @@ -113,7 +112,6 @@ void do_interrupt(CPUState *env) |
| 113 | 112 | |
| 114 | 113 | break; |
| 115 | 114 | case EXCP_MMU_MISS: |
| 116 | -// printf ("MMU miss\n"); | |
| 117 | 115 | irqnum = 4; |
| 118 | 116 | ebp = env->pregs[PR_EBP]; |
| 119 | 117 | isr = ldl_code(ebp + irqnum * 4); | ... | ... |
target-cris/op.c
| ... | ... | @@ -967,6 +967,8 @@ void OPPROTO op_btst_T0_T1 (void) |
| 967 | 967 | The N flag is set according to the selected bit in the dest reg. |
| 968 | 968 | The Z flag is set if the selected bit and all bits to the right are |
| 969 | 969 | zero. |
| 970 | + The X flag is cleared. | |
| 971 | + Other flags are left untouched. | |
| 970 | 972 | The destination reg is not affected.*/ |
| 971 | 973 | unsigned int fz, sbit, bset, mask, masked_t0; |
| 972 | 974 | |
| ... | ... | @@ -975,8 +977,11 @@ void OPPROTO op_btst_T0_T1 (void) |
| 975 | 977 | mask = sbit == 31 ? -1 : (1 << (sbit + 1)) - 1; |
| 976 | 978 | masked_t0 = T0 & mask; |
| 977 | 979 | fz = !(masked_t0 | bset); |
| 980 | + | |
| 981 | + /* Clear the X, N and Z flags. */ | |
| 982 | + T0 = env->pregs[PR_CCS] & ~(X_FLAG | N_FLAG | Z_FLAG); | |
| 978 | 983 | /* Set the N and Z flags accordingly. */ |
| 979 | - T0 = (bset << 3) | (fz << 2); | |
| 984 | + T0 |= (bset << 3) | (fz << 2); | |
| 980 | 985 | RETURN(); |
| 981 | 986 | } |
| 982 | 987 | ... | ... |