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 | ... | ... |