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,23 +26,28 @@ | ||
26 | #include <ctype.h> | 26 | #include <ctype.h> |
27 | #include "hw.h" | 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 | static uint32_t ser_readb (void *opaque, target_phys_addr_t addr) | 36 | static uint32_t ser_readb (void *opaque, target_phys_addr_t addr) |
35 | { | 37 | { |
36 | - CPUState *env = opaque; | 38 | + CPUState *env; |
37 | uint32_t r = 0; | 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 | return r; | 43 | return r; |
40 | } | 44 | } |
41 | static uint32_t ser_readw (void *opaque, target_phys_addr_t addr) | 45 | static uint32_t ser_readw (void *opaque, target_phys_addr_t addr) |
42 | { | 46 | { |
43 | - CPUState *env = opaque; | 47 | + CPUState *env; |
44 | uint32_t r = 0; | 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 | return r; | 51 | return r; |
47 | } | 52 | } |
48 | 53 | ||
@@ -51,7 +56,7 @@ static uint32_t ser_readl (void *opaque, target_phys_addr_t addr) | @@ -51,7 +56,7 @@ static uint32_t ser_readl (void *opaque, target_phys_addr_t addr) | ||
51 | CPUState *env = opaque; | 56 | CPUState *env = opaque; |
52 | uint32_t r = 0; | 57 | uint32_t r = 0; |
53 | 58 | ||
54 | - switch (addr) | 59 | + switch (addr & 0xfff) |
55 | { | 60 | { |
56 | case RW_TR_DMA_EN: | 61 | case RW_TR_DMA_EN: |
57 | break; | 62 | break; |
@@ -70,21 +75,23 @@ static uint32_t ser_readl (void *opaque, target_phys_addr_t addr) | @@ -70,21 +75,23 @@ static uint32_t ser_readl (void *opaque, target_phys_addr_t addr) | ||
70 | static void | 75 | static void |
71 | ser_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) | 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 | static void | 82 | static void |
77 | ser_writew (void *opaque, target_phys_addr_t addr, uint32_t value) | 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 | static void | 89 | static void |
83 | ser_writel (void *opaque, target_phys_addr_t addr, uint32_t value) | 90 | ser_writel (void *opaque, target_phys_addr_t addr, uint32_t value) |
84 | { | 91 | { |
85 | CPUState *env = opaque; | 92 | CPUState *env = opaque; |
86 | 93 | ||
87 | - switch (addr) | 94 | + switch (addr & 0xfff) |
88 | { | 95 | { |
89 | case RW_TR_DMA_EN: | 96 | case RW_TR_DMA_EN: |
90 | break; | 97 | break; |
@@ -119,4 +126,7 @@ void etraxfs_ser_init(CPUState *env, qemu_irq *irqs) | @@ -119,4 +126,7 @@ void etraxfs_ser_init(CPUState *env, qemu_irq *irqs) | ||
119 | 126 | ||
120 | ser_regs = cpu_register_io_memory(0, ser_read, ser_write, env); | 127 | ser_regs = cpu_register_io_memory(0, ser_read, ser_write, env); |
121 | cpu_register_physical_memory (0xb0026000, 0x3c, ser_regs); | 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,6 +26,8 @@ | ||
26 | #include "hw.h" | 26 | #include "hw.h" |
27 | #include "qemu-timer.h" | 27 | #include "qemu-timer.h" |
28 | 28 | ||
29 | +#define D(x) | ||
30 | + | ||
29 | void etrax_ack_irq(CPUState *env, uint32_t mask); | 31 | void etrax_ack_irq(CPUState *env, uint32_t mask); |
30 | 32 | ||
31 | #define R_TIME 0xb001e038 | 33 | #define R_TIME 0xb001e038 |
@@ -54,9 +56,18 @@ struct fs_timer_t { | @@ -54,9 +56,18 @@ struct fs_timer_t { | ||
54 | CPUState *env; | 56 | CPUState *env; |
55 | qemu_irq *irq; | 57 | qemu_irq *irq; |
56 | uint32_t mask; | 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 | /* diff two timevals. Return a single int in us. */ | 72 | /* diff two timevals. Return a single int in us. */ |
62 | int diff_timeval_us(struct timeval *a, struct timeval *b) | 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,16 +82,20 @@ int diff_timeval_us(struct timeval *a, struct timeval *b) | ||
71 | 82 | ||
72 | static uint32_t timer_readb (void *opaque, target_phys_addr_t addr) | 83 | static uint32_t timer_readb (void *opaque, target_phys_addr_t addr) |
73 | { | 84 | { |
74 | - CPUState *env = opaque; | 85 | + CPUState *env; |
75 | uint32_t r = 0; | 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 | return r; | 90 | return r; |
78 | } | 91 | } |
79 | static uint32_t timer_readw (void *opaque, target_phys_addr_t addr) | 92 | static uint32_t timer_readw (void *opaque, target_phys_addr_t addr) |
80 | { | 93 | { |
81 | - CPUState *env = opaque; | 94 | + CPUState *env; |
82 | uint32_t r = 0; | 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 | return r; | 99 | return r; |
85 | } | 100 | } |
86 | 101 | ||
@@ -88,24 +103,25 @@ static uint32_t timer_readl (void *opaque, target_phys_addr_t addr) | @@ -88,24 +103,25 @@ static uint32_t timer_readl (void *opaque, target_phys_addr_t addr) | ||
88 | { | 103 | { |
89 | CPUState *env = opaque; | 104 | CPUState *env = opaque; |
90 | uint32_t r = 0; | 105 | uint32_t r = 0; |
106 | + int t = timer_index(addr); | ||
91 | 107 | ||
92 | switch (addr) { | 108 | switch (addr) { |
93 | case R_TMR0_DATA: | 109 | case R_TMR0_DATA: |
94 | break; | 110 | break; |
95 | case R_TMR1_DATA: | 111 | case R_TMR1_DATA: |
96 | - printf ("R_TMR1_DATA\n"); | 112 | + D(printf ("R_TMR1_DATA\n")); |
97 | break; | 113 | break; |
98 | case R_TIME: | 114 | case R_TIME: |
99 | { | 115 | { |
100 | - static struct timeval last; | ||
101 | struct timeval now; | 116 | struct timeval now; |
102 | gettimeofday(&now, NULL); | 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 | r *= 1000; /* convert to ns. */ | 121 | r *= 1000; /* convert to ns. */ |
106 | r++; /* make sure we increase for each call. */ | 122 | r++; /* make sure we increase for each call. */ |
107 | } | 123 | } |
108 | - last = now; | 124 | + timer[t].last = now; |
109 | break; | 125 | break; |
110 | } | 126 | } |
111 | 127 | ||
@@ -125,14 +141,16 @@ static uint32_t timer_readl (void *opaque, target_phys_addr_t addr) | @@ -125,14 +141,16 @@ static uint32_t timer_readl (void *opaque, target_phys_addr_t addr) | ||
125 | static void | 141 | static void |
126 | timer_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) | 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 | static void | 148 | static void |
132 | timer_writew (void *opaque, target_phys_addr_t addr, uint32_t value) | 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 | static void write_ctrl(struct fs_timer_t *t, uint32_t v) | 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,7 +183,7 @@ static void write_ctrl(struct fs_timer_t *t, uint32_t v) | ||
165 | if (t->limit > 2048) | 183 | if (t->limit > 2048) |
166 | { | 184 | { |
167 | t->scale = 2048; | 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 | printf ("op=%d\n", op); | 189 | printf ("op=%d\n", op); |
@@ -187,11 +205,11 @@ static void write_ctrl(struct fs_timer_t *t, uint32_t v) | @@ -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,31 +217,33 @@ static void | ||
199 | timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) | 217 | timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) |
200 | { | 218 | { |
201 | CPUState *env = opaque; | 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 | switch (addr) | 224 | switch (addr) |
205 | { | 225 | { |
206 | case RW_TMR0_DIV: | 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 | break; | 229 | break; |
210 | case RW_TMR0_CTRL: | 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 | break; | 233 | break; |
214 | case RW_TMR1_DIV: | 234 | case RW_TMR1_DIV: |
215 | - printf ("RW_TMR1_DIV=%x\n", value); | 235 | + D(printf ("RW_TMR1_DIV=%x\n", value)); |
216 | break; | 236 | break; |
217 | case RW_TMR1_CTRL: | 237 | case RW_TMR1_CTRL: |
218 | - printf ("RW_TMR1_CTRL=%x\n", value); | 238 | + D(printf ("RW_TMR1_CTRL=%x\n", value)); |
219 | break; | 239 | break; |
220 | case RW_INTR_MASK: | 240 | case RW_INTR_MASK: |
221 | - printf ("RW_INTR_MASK=%x\n", value); | 241 | + D(printf ("RW_INTR_MASK=%x\n", value)); |
222 | rw_intr_mask = value; | 242 | rw_intr_mask = value; |
223 | break; | 243 | break; |
224 | case RW_ACK_INTR: | 244 | case RW_ACK_INTR: |
225 | r_intr &= ~value; | 245 | r_intr &= ~value; |
226 | - timer_ack_irq(); | 246 | + timer_ack_irq(&timer[t]); |
227 | break; | 247 | break; |
228 | default: | 248 | default: |
229 | printf ("%s %x %x pc=%x\n", | 249 | printf ("%s %x %x pc=%x\n", |
@@ -247,7 +267,6 @@ static CPUWriteMemoryFunc *timer_write[] = { | @@ -247,7 +267,6 @@ static CPUWriteMemoryFunc *timer_write[] = { | ||
247 | static void timer_irq(void *opaque) | 267 | static void timer_irq(void *opaque) |
248 | { | 268 | { |
249 | struct fs_timer_t *t = opaque; | 269 | struct fs_timer_t *t = opaque; |
250 | - | ||
251 | r_intr |= t->mask; | 270 | r_intr |= t->mask; |
252 | if (t->mask & rw_intr_mask) { | 271 | if (t->mask & rw_intr_mask) { |
253 | qemu_irq_raise(t->irq[0]); | 272 | qemu_irq_raise(t->irq[0]); |
@@ -258,12 +277,19 @@ void etraxfs_timer_init(CPUState *env, qemu_irq *irqs) | @@ -258,12 +277,19 @@ void etraxfs_timer_init(CPUState *env, qemu_irq *irqs) | ||
258 | { | 277 | { |
259 | int timer_regs; | 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 | timer_regs = cpu_register_io_memory(0, timer_read, timer_write, env); | 292 | timer_regs = cpu_register_io_memory(0, timer_read, timer_write, env); |
268 | cpu_register_physical_memory (0xb001e000, 0x5c, timer_regs); | 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,22 +32,23 @@ | ||
32 | 32 | ||
33 | void do_interrupt (CPUState *env) | 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 | int cpu_cris_handle_mmu_fault(CPUState * env, target_ulong address, int rw, | 39 | int cpu_cris_handle_mmu_fault(CPUState * env, target_ulong address, int rw, |
39 | int mmu_idx, int is_softmmu) | 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 | target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr) | 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 | #else /* !CONFIG_USER_ONLY */ | 54 | #else /* !CONFIG_USER_ONLY */ |
@@ -61,7 +62,6 @@ int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | @@ -61,7 +62,6 @@ int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | ||
61 | 62 | ||
62 | address &= TARGET_PAGE_MASK; | 63 | address &= TARGET_PAGE_MASK; |
63 | prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; | 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 | miss = cris_mmu_translate(&res, env, address, rw, mmu_idx); | 65 | miss = cris_mmu_translate(&res, env, address, rw, mmu_idx); |
66 | if (miss) | 66 | if (miss) |
67 | { | 67 | { |
@@ -73,7 +73,6 @@ int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | @@ -73,7 +73,6 @@ int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | ||
73 | { | 73 | { |
74 | phy = res.phy; | 74 | phy = res.phy; |
75 | } | 75 | } |
76 | -// printf ("a=%x phy=%x\n", address, phy); | ||
77 | return tlb_set_page(env, address, phy, prot, mmu_idx, is_softmmu); | 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,7 +112,6 @@ void do_interrupt(CPUState *env) | ||
113 | 112 | ||
114 | break; | 113 | break; |
115 | case EXCP_MMU_MISS: | 114 | case EXCP_MMU_MISS: |
116 | -// printf ("MMU miss\n"); | ||
117 | irqnum = 4; | 115 | irqnum = 4; |
118 | ebp = env->pregs[PR_EBP]; | 116 | ebp = env->pregs[PR_EBP]; |
119 | isr = ldl_code(ebp + irqnum * 4); | 117 | isr = ldl_code(ebp + irqnum * 4); |
target-cris/op.c
@@ -967,6 +967,8 @@ void OPPROTO op_btst_T0_T1 (void) | @@ -967,6 +967,8 @@ void OPPROTO op_btst_T0_T1 (void) | ||
967 | The N flag is set according to the selected bit in the dest reg. | 967 | The N flag is set according to the selected bit in the dest reg. |
968 | The Z flag is set if the selected bit and all bits to the right are | 968 | The Z flag is set if the selected bit and all bits to the right are |
969 | zero. | 969 | zero. |
970 | + The X flag is cleared. | ||
971 | + Other flags are left untouched. | ||
970 | The destination reg is not affected.*/ | 972 | The destination reg is not affected.*/ |
971 | unsigned int fz, sbit, bset, mask, masked_t0; | 973 | unsigned int fz, sbit, bset, mask, masked_t0; |
972 | 974 | ||
@@ -975,8 +977,11 @@ void OPPROTO op_btst_T0_T1 (void) | @@ -975,8 +977,11 @@ void OPPROTO op_btst_T0_T1 (void) | ||
975 | mask = sbit == 31 ? -1 : (1 << (sbit + 1)) - 1; | 977 | mask = sbit == 31 ? -1 : (1 << (sbit + 1)) - 1; |
976 | masked_t0 = T0 & mask; | 978 | masked_t0 = T0 & mask; |
977 | fz = !(masked_t0 | bset); | 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 | /* Set the N and Z flags accordingly. */ | 983 | /* Set the N and Z flags accordingly. */ |
979 | - T0 = (bset << 3) | (fz << 2); | 984 | + T0 |= (bset << 3) | (fz << 2); |
980 | RETURN(); | 985 | RETURN(); |
981 | } | 986 | } |
982 | 987 |