Revision e62b5b13
b/Makefile.target | ||
---|---|---|
565 | 565 |
endif |
566 | 566 |
ifeq ($(TARGET_BASE_ARCH), cris) |
567 | 567 |
OBJS+= etraxfs.o |
568 |
OBJS+= ptimer.o
|
|
568 |
OBJS+= etraxfs_pic.o
|
|
569 | 569 |
OBJS+= etraxfs_timer.o |
570 | 570 |
OBJS+= etraxfs_ser.o |
571 |
|
|
572 |
OBJS+= ptimer.o |
|
573 |
OBJS+= pflash_cfi01.o |
|
571 | 574 |
endif |
572 | 575 |
ifeq ($(TARGET_BASE_ARCH), sparc) |
573 | 576 |
ifeq ($(TARGET_ARCH), sparc64) |
b/cpu-exec.c | ||
---|---|---|
556 | 556 |
#elif defined(TARGET_CRIS) |
557 | 557 |
if (interrupt_request & CPU_INTERRUPT_HARD) { |
558 | 558 |
do_interrupt(env); |
559 |
env->interrupt_request &= ~CPU_INTERRUPT_HARD; |
|
560 | 559 |
BREAK_CHAIN; |
561 | 560 |
} |
562 | 561 |
#elif defined(TARGET_M68K) |
... | ... | |
1181 | 1180 |
a virtual CPU fault */ |
1182 | 1181 |
cpu_restore_state(tb, env, pc, puc); |
1183 | 1182 |
} |
1184 |
#if 0 |
|
1185 |
printf("PF exception: NIP=0x%08x error=0x%x %p\n", |
|
1186 |
env->nip, env->error_code, tb); |
|
1187 |
#endif |
|
1188 | 1183 |
/* we restore the process signal mask as the sigreturn should |
1189 | 1184 |
do it (XXX: use sigsetjmp) */ |
1190 | 1185 |
sigprocmask(SIG_SETMASK, old_set, NULL); |
b/hw/etraxfs.c | ||
---|---|---|
25 | 25 |
#include <sys/time.h> |
26 | 26 |
#include "hw.h" |
27 | 27 |
#include "sysemu.h" |
28 |
#include "flash.h" |
|
28 | 29 |
#include "boards.h" |
29 | 30 |
|
30 |
extern FILE *logfile; |
|
31 |
|
|
32 | 31 |
static void main_cpu_reset(void *opaque) |
33 | 32 |
{ |
34 | 33 |
CPUState *env = opaque; |
35 | 34 |
cpu_reset(env); |
36 | 35 |
} |
37 | 36 |
|
38 |
static uint32_t fs_mmio_readb (void *opaque, target_phys_addr_t addr) |
|
39 |
{ |
|
40 |
CPUState *env = opaque; |
|
41 |
uint32_t r = 0; |
|
42 |
printf ("%s %x pc=%x\n", __func__, addr, env->pc); |
|
43 |
return r; |
|
44 |
} |
|
45 |
static uint32_t fs_mmio_readw (void *opaque, target_phys_addr_t addr) |
|
46 |
{ |
|
47 |
CPUState *env = opaque; |
|
48 |
uint32_t r = 0; |
|
49 |
printf ("%s %x pc=%x\n", __func__, addr, env->pc); |
|
50 |
return r; |
|
51 |
} |
|
52 |
|
|
53 |
static uint32_t fs_mmio_readl (void *opaque, target_phys_addr_t addr) |
|
54 |
{ |
|
55 |
CPUState *env = opaque; |
|
56 |
uint32_t r = 0; |
|
57 |
printf ("%s %x p=%x\n", __func__, addr, env->pc); |
|
58 |
return r; |
|
59 |
} |
|
60 |
|
|
61 |
static void |
|
62 |
fs_mmio_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) |
|
63 |
{ |
|
64 |
CPUState *env = opaque; |
|
65 |
printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); |
|
66 |
} |
|
67 |
static void |
|
68 |
fs_mmio_writew (void *opaque, target_phys_addr_t addr, uint32_t value) |
|
69 |
{ |
|
70 |
CPUState *env = opaque; |
|
71 |
printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); |
|
72 |
} |
|
73 |
static void |
|
74 |
fs_mmio_writel (void *opaque, target_phys_addr_t addr, uint32_t value) |
|
75 |
{ |
|
76 |
CPUState *env = opaque; |
|
77 |
printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); |
|
78 |
} |
|
79 |
|
|
80 |
static CPUReadMemoryFunc *fs_mmio_read[] = { |
|
81 |
&fs_mmio_readb, |
|
82 |
&fs_mmio_readw, |
|
83 |
&fs_mmio_readl, |
|
84 |
}; |
|
85 |
|
|
86 |
static CPUWriteMemoryFunc *fs_mmio_write[] = { |
|
87 |
&fs_mmio_writeb, |
|
88 |
&fs_mmio_writew, |
|
89 |
&fs_mmio_writel, |
|
90 |
}; |
|
91 |
|
|
92 |
|
|
93 | 37 |
/* Init functions for different blocks. */ |
38 |
extern qemu_irq *etraxfs_pic_init(CPUState *env, target_ulong base); |
|
39 |
/* TODO: Make these blocks relocate:able. */ |
|
94 | 40 |
extern void etraxfs_timer_init(CPUState *env, qemu_irq *irqs); |
95 | 41 |
extern void etraxfs_ser_init(CPUState *env, qemu_irq *irqs); |
96 | 42 |
|
97 |
void etrax_ack_irq(CPUState *env, uint32_t mask) |
|
98 |
{ |
|
99 |
env->pending_interrupts &= ~mask; |
|
100 |
} |
|
101 |
|
|
102 |
static void dummy_cpu_set_irq(void *opaque, int irq, int level) |
|
103 |
{ |
|
104 |
CPUState *env = opaque; |
|
105 |
|
|
106 |
/* Hmm, should this really be done here? */ |
|
107 |
env->pending_interrupts |= 1 << irq; |
|
108 |
cpu_interrupt(env, CPU_INTERRUPT_HARD); |
|
109 |
} |
|
110 |
|
|
111 | 43 |
static |
112 | 44 |
void bareetraxfs_init (int ram_size, int vga_ram_size, |
113 | 45 |
const char *boot_device, DisplayState *ds, |
... | ... | |
115 | 47 |
const char *initrd_filename, const char *cpu_model) |
116 | 48 |
{ |
117 | 49 |
CPUState *env; |
118 |
qemu_irq *irqs;
|
|
50 |
qemu_irq *pic;
|
|
119 | 51 |
int kernel_size; |
120 |
int internal_regs; |
|
52 |
int flash_size = 0x800000; |
|
53 |
int index; |
|
54 |
ram_addr_t phys_flash; |
|
55 |
ram_addr_t phys_ram; |
|
121 | 56 |
|
122 | 57 |
/* init CPUs */ |
123 | 58 |
if (cpu_model == NULL) { |
... | ... | |
126 | 61 |
env = cpu_init(cpu_model); |
127 | 62 |
/* register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); */ |
128 | 63 |
qemu_register_reset(main_cpu_reset, env); |
129 |
irqs = qemu_allocate_irqs(dummy_cpu_set_irq, env, 32); |
|
130 | 64 |
|
131 |
internal_regs = cpu_register_io_memory(0, |
|
132 |
fs_mmio_read, fs_mmio_write, env); |
|
133 |
/* 0xb0050000 is the last reg. */ |
|
134 |
cpu_register_physical_memory (0xac000000, 0x4010000, internal_regs); |
|
135 | 65 |
/* allocate RAM */ |
136 |
cpu_register_physical_memory(0x40000000, ram_size, IO_MEM_RAM); |
|
137 |
|
|
138 |
etraxfs_timer_init(env, irqs); |
|
139 |
etraxfs_ser_init(env, irqs); |
|
66 |
phys_ram = qemu_ram_alloc(ram_size); |
|
67 |
cpu_register_physical_memory(0x40000000, ram_size, phys_ram | IO_MEM_RAM); |
|
68 |
/* Unached mapping. */ |
|
69 |
cpu_register_physical_memory(0xc0000000, ram_size, phys_ram | IO_MEM_RAM); |
|
70 |
|
|
71 |
phys_flash = qemu_ram_alloc(flash_size); |
|
72 |
cpu_register_physical_memory(0,flash_size, IO_MEM_ROM); |
|
73 |
cpu_register_physical_memory(0x80000000, flash_size, IO_MEM_ROM); |
|
74 |
cpu_register_physical_memory(0x04000000, flash_size, IO_MEM_ROM); |
|
75 |
cpu_register_physical_memory(0x84000000, flash_size, |
|
76 |
0x04000000 | IO_MEM_ROM); |
|
77 |
index = drive_get_index(IF_PFLASH, 0, 0); |
|
78 |
pflash_cfi01_register(0x80000000, flash_size, |
|
79 |
drives_table[index].bdrv, 65536, flash_size >> 16, |
|
80 |
4, 0x0000, 0x0000, 0x0000, 0x0000); |
|
81 |
index = drive_get_index(IF_PFLASH, 0, 1); |
|
82 |
pflash_cfi01_register(0x84000000, flash_size, |
|
83 |
drives_table[index].bdrv, 65536, flash_size >> 16, |
|
84 |
4, 0x0000, 0x0000, 0x0000, 0x0000); |
|
85 |
|
|
86 |
pic = etraxfs_pic_init(env, 0xb001c000); |
|
87 |
etraxfs_timer_init(env, pic); |
|
88 |
etraxfs_ser_init(env, pic); |
|
140 | 89 |
|
141 | 90 |
kernel_size = load_image(kernel_filename, phys_ram_base + 0x4000); |
142 | 91 |
/* magic for boot. */ |
... | ... | |
165 | 114 |
{ |
166 | 115 |
} |
167 | 116 |
|
168 |
void pic_info() |
|
169 |
{ |
|
170 |
} |
|
171 |
|
|
172 |
void irq_info() |
|
173 |
{ |
|
174 |
} |
|
175 |
|
|
176 | 117 |
QEMUMachine bareetraxfs_machine = { |
177 | 118 |
"bareetraxfs", |
178 | 119 |
"Bare ETRAX FS board", |
b/hw/etraxfs_pic.c | ||
---|---|---|
1 |
/* |
|
2 |
* QEMU ETRAX Interrupt Controller. |
|
3 |
* |
|
4 |
* Copyright (c) 2008 Edgar E. Iglesias, Axis Communications AB. |
|
5 |
* |
|
6 |
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|
7 |
* of this software and associated documentation files (the "Software"), to deal |
|
8 |
* in the Software without restriction, including without limitation the rights |
|
9 |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
10 |
* copies of the Software, and to permit persons to whom the Software is |
|
11 |
* furnished to do so, subject to the following conditions: |
|
12 |
* |
|
13 |
* The above copyright notice and this permission notice shall be included in |
|
14 |
* all copies or substantial portions of the Software. |
|
15 |
* |
|
16 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
17 |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
18 |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
19 |
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
20 |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
21 |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
22 |
* THE SOFTWARE. |
|
23 |
*/ |
|
24 |
|
|
25 |
#include <stdio.h> |
|
26 |
#include "hw.h" |
|
27 |
|
|
28 |
#define D(x) |
|
29 |
|
|
30 |
struct fs_pic_state_t |
|
31 |
{ |
|
32 |
CPUState *env; |
|
33 |
target_ulong base; |
|
34 |
|
|
35 |
uint32_t rw_mask; |
|
36 |
/* Active interrupt lines. */ |
|
37 |
uint32_t r_vect; |
|
38 |
/* Active lines, gated through the mask. */ |
|
39 |
uint32_t r_masked_vect; |
|
40 |
uint32_t r_nmi; |
|
41 |
uint32_t r_guru; |
|
42 |
}; |
|
43 |
|
|
44 |
static uint32_t pic_readb (void *opaque, target_phys_addr_t addr) |
|
45 |
{ |
|
46 |
return 0; |
|
47 |
} |
|
48 |
static uint32_t pic_readw (void *opaque, target_phys_addr_t addr) |
|
49 |
{ |
|
50 |
return 0; |
|
51 |
} |
|
52 |
|
|
53 |
static uint32_t pic_readl (void *opaque, target_phys_addr_t addr) |
|
54 |
{ |
|
55 |
struct fs_pic_state_t *fs = opaque; |
|
56 |
uint32_t rval; |
|
57 |
|
|
58 |
/* Transform this to a relative addr. */ |
|
59 |
addr -= fs->base; |
|
60 |
switch (addr) |
|
61 |
{ |
|
62 |
case 0x0: |
|
63 |
rval = fs->rw_mask; |
|
64 |
break; |
|
65 |
case 0x4: |
|
66 |
rval = fs->r_vect; |
|
67 |
break; |
|
68 |
case 0x8: |
|
69 |
rval = fs->r_masked_vect; |
|
70 |
break; |
|
71 |
case 0xc: |
|
72 |
rval = fs->r_nmi; |
|
73 |
break; |
|
74 |
case 0x10: |
|
75 |
rval = fs->r_guru; |
|
76 |
break; |
|
77 |
default: |
|
78 |
cpu_abort(fs->env, "invalid PIC register.\n"); |
|
79 |
break; |
|
80 |
|
|
81 |
} |
|
82 |
D(printf("%s %x=%x\n", __func__, addr, rval)); |
|
83 |
return rval; |
|
84 |
} |
|
85 |
|
|
86 |
static void |
|
87 |
pic_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) |
|
88 |
{ |
|
89 |
} |
|
90 |
|
|
91 |
static void |
|
92 |
pic_writew (void *opaque, target_phys_addr_t addr, uint32_t value) |
|
93 |
{ |
|
94 |
} |
|
95 |
|
|
96 |
static void |
|
97 |
pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value) |
|
98 |
{ |
|
99 |
struct fs_pic_state_t *fs = opaque; |
|
100 |
D(printf("%s addr=%x val=%x\n", __func__, addr, value)); |
|
101 |
/* Transform this to a relative addr. */ |
|
102 |
addr -= fs->base; |
|
103 |
switch (addr) |
|
104 |
{ |
|
105 |
case 0x0: |
|
106 |
fs->rw_mask = value; |
|
107 |
break; |
|
108 |
case 0x4: |
|
109 |
fs->r_vect = value; |
|
110 |
break; |
|
111 |
case 0x8: |
|
112 |
fs->r_masked_vect = value; |
|
113 |
break; |
|
114 |
case 0xc: |
|
115 |
fs->r_nmi = value; |
|
116 |
break; |
|
117 |
case 0x10: |
|
118 |
fs->r_guru = value; |
|
119 |
break; |
|
120 |
default: |
|
121 |
cpu_abort(fs->env, "invalid PIC register.\n"); |
|
122 |
break; |
|
123 |
} |
|
124 |
} |
|
125 |
|
|
126 |
static CPUReadMemoryFunc *pic_read[] = { |
|
127 |
&pic_readb, |
|
128 |
&pic_readw, |
|
129 |
&pic_readl, |
|
130 |
}; |
|
131 |
|
|
132 |
static CPUWriteMemoryFunc *pic_write[] = { |
|
133 |
&pic_writeb, |
|
134 |
&pic_writew, |
|
135 |
&pic_writel, |
|
136 |
}; |
|
137 |
|
|
138 |
void pic_info(void) |
|
139 |
{ |
|
140 |
} |
|
141 |
|
|
142 |
void irq_info(void) |
|
143 |
{ |
|
144 |
} |
|
145 |
|
|
146 |
static void etraxfs_pic_handler(void *opaque, int irq, int level) |
|
147 |
{ |
|
148 |
struct fs_pic_state_t *fs = (void *)opaque; |
|
149 |
CPUState *env = fs->env; |
|
150 |
int i; |
|
151 |
uint32_t vector = 0; |
|
152 |
|
|
153 |
D(printf("%s irq=%d level=%d mask=%x v=%x mv=%x\n", |
|
154 |
__func__, irq, level, |
|
155 |
fs->rw_mask, fs->r_vect, fs->r_masked_vect)); |
|
156 |
|
|
157 |
fs->r_vect &= ~(1 << irq); |
|
158 |
fs->r_vect |= (!!level << irq); |
|
159 |
fs->r_masked_vect = fs->r_vect & fs->rw_mask; |
|
160 |
|
|
161 |
/* The ETRAX interrupt controller signals interrupts to teh core |
|
162 |
through an interrupt request wire and an irq vector bus. If |
|
163 |
multiple interrupts are simultaneously active it chooses vector |
|
164 |
0x30 and lets the sw choose the priorities. */ |
|
165 |
if (fs->r_masked_vect) { |
|
166 |
uint32_t mv = fs->r_masked_vect; |
|
167 |
for (i = 0; i < 31; i++) { |
|
168 |
if (mv & 1) { |
|
169 |
vector = 0x31 + i; |
|
170 |
/* Check for multiple interrupts. */ |
|
171 |
if (mv > 1) |
|
172 |
vector = 0x30; |
|
173 |
break; |
|
174 |
} |
|
175 |
mv >>= 1; |
|
176 |
} |
|
177 |
if (vector) { |
|
178 |
env->interrupt_vector = vector; |
|
179 |
D(printf("%s vector=%x\n", __func__, vector)); |
|
180 |
cpu_interrupt(env, CPU_INTERRUPT_HARD); |
|
181 |
} |
|
182 |
} else { |
|
183 |
env->interrupt_vector = 0; |
|
184 |
cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); |
|
185 |
D(printf("%s reset irqs\n", __func__)); |
|
186 |
} |
|
187 |
} |
|
188 |
|
|
189 |
qemu_irq *etraxfs_pic_init(CPUState *env, target_ulong base) |
|
190 |
{ |
|
191 |
struct fs_pic_state_t *fs; |
|
192 |
qemu_irq *pic; |
|
193 |
int intr_vect_regs; |
|
194 |
|
|
195 |
fs = qemu_mallocz(sizeof *fs); |
|
196 |
if (!fs) |
|
197 |
return NULL; |
|
198 |
fs->env = env; |
|
199 |
|
|
200 |
pic = qemu_allocate_irqs(etraxfs_pic_handler, fs, 30); |
|
201 |
|
|
202 |
intr_vect_regs = cpu_register_io_memory(0, pic_read, pic_write, fs); |
|
203 |
cpu_register_physical_memory(base, 0x14, intr_vect_regs); |
|
204 |
fs->base = base; |
|
205 |
|
|
206 |
return pic; |
|
207 |
} |
b/hw/etraxfs_ser.c | ||
---|---|---|
66 | 66 |
break; |
67 | 67 |
|
68 | 68 |
default: |
69 |
printf ("%s %x p=%x\n", __func__, addr, env->pc);
|
|
69 |
D(printf ("%s %x p=%x\n", __func__, addr, env->pc));
|
|
70 | 70 |
break; |
71 | 71 |
} |
72 | 72 |
return r; |
... | ... | |
100 | 100 |
putchar(value); |
101 | 101 |
else |
102 | 102 |
putchar('.'); |
103 |
fflush(stdout); |
|
103 | 104 |
break; |
104 | 105 |
default: |
105 |
printf ("%s %x %x pc=%x\n", |
|
106 |
__func__, addr, value, env->pc);
|
|
106 |
D(printf ("%s %x %x pc=%x\n",
|
|
107 |
__func__, addr, value, env->pc));
|
|
107 | 108 |
break; |
108 | 109 |
} |
109 | 110 |
} |
b/hw/etraxfs_timer.c | ||
---|---|---|
1 | 1 |
/* |
2 |
* QEMU ETRAX System Emulator
|
|
2 |
* QEMU ETRAX Timers
|
|
3 | 3 |
* |
4 | 4 |
* Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB. |
5 | 5 |
* |
... | ... | |
28 | 28 |
|
29 | 29 |
#define D(x) |
30 | 30 |
|
31 |
void etrax_ack_irq(CPUState *env, uint32_t mask); |
|
32 |
|
|
33 | 31 |
#define R_TIME 0xb001e038 |
34 | 32 |
#define RW_TMR0_DIV 0xb001e000 |
35 | 33 |
#define R_TMR0_DATA 0xb001e004 |
... | ... | |
38 | 36 |
#define R_TMR1_DATA 0xb001e014 |
39 | 37 |
#define RW_TMR1_CTRL 0xb001e018 |
40 | 38 |
|
39 |
#define RW_WD_CTRL 0xb001e040 |
|
41 | 40 |
#define RW_INTR_MASK 0xb001e048 |
42 | 41 |
#define RW_ACK_INTR 0xb001e04c |
43 | 42 |
#define R_INTR 0xb001e050 |
44 | 43 |
#define R_MASKED_INTR 0xb001e054 |
45 | 44 |
|
46 |
|
|
47 |
uint32_t rw_intr_mask; |
|
48 |
uint32_t rw_ack_intr; |
|
49 |
uint32_t r_intr; |
|
50 |
|
|
51 | 45 |
struct fs_timer_t { |
52 | 46 |
QEMUBH *bh; |
53 | 47 |
unsigned int limit; |
... | ... | |
57 | 51 |
qemu_irq *irq; |
58 | 52 |
uint32_t mask; |
59 | 53 |
struct timeval last; |
54 |
|
|
55 |
uint32_t rw_intr_mask; |
|
56 |
uint32_t rw_ack_intr; |
|
57 |
uint32_t r_intr; |
|
60 | 58 |
}; |
61 | 59 |
|
62 | 60 |
static struct fs_timer_t timer[2]; |
... | ... | |
126 | 124 |
} |
127 | 125 |
|
128 | 126 |
case RW_INTR_MASK: |
129 |
r = rw_intr_mask; |
|
127 |
r = timer[t].rw_intr_mask;
|
|
130 | 128 |
break; |
131 | 129 |
case R_MASKED_INTR: |
132 |
r = r_intr & rw_intr_mask;
|
|
130 |
r = timer[t].r_intr & timer[t].rw_intr_mask;
|
|
133 | 131 |
break; |
134 | 132 |
default: |
135 |
printf ("%s %x p=%x\n", __func__, addr, env->pc);
|
|
133 |
D(printf ("%s %x p=%x\n", __func__, addr, env->pc));
|
|
136 | 134 |
break; |
137 | 135 |
} |
138 | 136 |
return r; |
... | ... | |
167 | 165 |
{ |
168 | 166 |
case 0: |
169 | 167 |
case 1: |
170 |
printf ("extern or disabled timer clock?\n");
|
|
168 |
D(printf ("extern or disabled timer clock?\n"));
|
|
171 | 169 |
break; |
172 | 170 |
case 4: freq_hz = 29493000; break; |
173 | 171 |
case 5: freq_hz = 32000000; break; |
... | ... | |
178 | 176 |
break; |
179 | 177 |
} |
180 | 178 |
|
181 |
printf ("freq_hz=%d limit=%d\n", freq_hz, t->limit);
|
|
179 |
D(printf ("freq_hz=%d limit=%d\n", freq_hz, t->limit));
|
|
182 | 180 |
t->scale = 0; |
183 | 181 |
if (t->limit > 2048) |
184 | 182 |
{ |
... | ... | |
186 | 184 |
ptimer_set_period(t->ptimer, freq_hz / t->scale); |
187 | 185 |
} |
188 | 186 |
|
189 |
printf ("op=%d\n", op); |
|
190 | 187 |
switch (op) |
191 | 188 |
{ |
192 | 189 |
case 0: |
193 |
printf ("limit=%d %d\n", t->limit, t->limit/t->scale); |
|
190 |
D(printf ("limit=%d %d\n", |
|
191 |
t->limit, t->limit/t->scale)); |
|
194 | 192 |
ptimer_set_limit(t->ptimer, t->limit / t->scale, 1); |
195 | 193 |
break; |
196 | 194 |
case 1: |
... | ... | |
207 | 205 |
|
208 | 206 |
static void timer_ack_irq(struct fs_timer_t *t) |
209 | 207 |
{ |
210 |
if (!(r_intr & t->mask & rw_intr_mask)) {
|
|
208 |
if (!(t->r_intr & t->mask & t->rw_intr_mask))
|
|
211 | 209 |
qemu_irq_lower(t->irq[0]); |
212 |
etrax_ack_irq(t->env, 1 << 0x1b); |
|
213 |
} |
|
214 | 210 |
} |
215 | 211 |
|
216 | 212 |
static void |
... | ... | |
239 | 235 |
break; |
240 | 236 |
case RW_INTR_MASK: |
241 | 237 |
D(printf ("RW_INTR_MASK=%x\n", value)); |
242 |
rw_intr_mask = value; |
|
238 |
timer[t].rw_intr_mask = value; |
|
239 |
break; |
|
240 |
case RW_WD_CTRL: |
|
241 |
D(printf ("RW_WD_CTRL=%x\n", value)); |
|
243 | 242 |
break; |
244 | 243 |
case RW_ACK_INTR: |
245 |
r_intr &= ~value; |
|
244 |
timer[t].r_intr &= ~value;
|
|
246 | 245 |
timer_ack_irq(&timer[t]); |
247 | 246 |
break; |
248 | 247 |
default: |
... | ... | |
267 | 266 |
static void timer_irq(void *opaque) |
268 | 267 |
{ |
269 | 268 |
struct fs_timer_t *t = opaque; |
270 |
r_intr |= t->mask; |
|
271 |
if (t->mask & rw_intr_mask) { |
|
269 |
t->r_intr |= t->mask; |
|
270 |
if (t->mask & t->rw_intr_mask) { |
|
271 |
D(printf("%s raise\n", __func__)); |
|
272 | 272 |
qemu_irq_raise(t->irq[0]); |
273 | 273 |
} |
274 | 274 |
} |
... | ... | |
279 | 279 |
|
280 | 280 |
timer[0].bh = qemu_bh_new(timer_irq, &timer[0]); |
281 | 281 |
timer[0].ptimer = ptimer_init(timer[0].bh); |
282 |
timer[0].irq = irqs + 0x1b;
|
|
282 |
timer[0].irq = irqs + 26;
|
|
283 | 283 |
timer[0].mask = 1; |
284 | 284 |
timer[0].env = env; |
285 | 285 |
|
286 | 286 |
timer[1].bh = qemu_bh_new(timer_irq, &timer[1]); |
287 | 287 |
timer[1].ptimer = ptimer_init(timer[1].bh); |
288 |
timer[1].irq = irqs + 0x1b;
|
|
288 |
timer[1].irq = irqs + 26;
|
|
289 | 289 |
timer[1].mask = 1; |
290 | 290 |
timer[1].env = env; |
291 | 291 |
|
b/target-cris/helper.c | ||
---|---|---|
28 | 28 |
#include "exec-all.h" |
29 | 29 |
#include "host-utils.h" |
30 | 30 |
|
31 |
#define D(x) |
|
32 |
|
|
31 | 33 |
#if defined(CONFIG_USER_ONLY) |
32 | 34 |
|
33 | 35 |
void do_interrupt (CPUState *env) |
... | ... | |
53 | 55 |
|
54 | 56 |
#else /* !CONFIG_USER_ONLY */ |
55 | 57 |
|
58 |
|
|
59 |
static void cris_shift_ccs(CPUState *env) |
|
60 |
{ |
|
61 |
uint32_t ccs; |
|
62 |
/* Apply the ccs shift. */ |
|
63 |
ccs = env->pregs[PR_CCS]; |
|
64 |
ccs = (ccs & 0xc0000000) | ((ccs << 12) >> 2); |
|
65 |
env->pregs[PR_CCS] = ccs; |
|
66 |
} |
|
67 |
|
|
56 | 68 |
int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw, |
57 | 69 |
int mmu_idx, int is_softmmu) |
58 | 70 |
{ |
59 | 71 |
struct cris_mmu_result_t res; |
60 | 72 |
int prot, miss; |
73 |
int r = -1; |
|
61 | 74 |
target_ulong phy; |
62 | 75 |
|
76 |
D(printf ("%s addr=%x pc=%x\n", __func__, address, env->pc)); |
|
63 | 77 |
address &= TARGET_PAGE_MASK; |
64 | 78 |
prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; |
65 | 79 |
miss = cris_mmu_translate(&res, env, address, rw, mmu_idx); |
66 | 80 |
if (miss) |
67 | 81 |
{ |
68 |
/* handle the miss. */
|
|
69 |
phy = 0;
|
|
70 |
env->exception_index = EXCP_MMU_MISS;
|
|
82 |
env->exception_index = EXCP_MMU_FAULT;
|
|
83 |
env->fault_vector = res.bf_vec;
|
|
84 |
r = 1;
|
|
71 | 85 |
} |
72 | 86 |
else |
73 | 87 |
{ |
74 | 88 |
phy = res.phy; |
89 |
prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; |
|
90 |
r = tlb_set_page(env, address, phy, prot, mmu_idx, is_softmmu); |
|
75 | 91 |
} |
76 |
return tlb_set_page(env, address, phy, prot, mmu_idx, is_softmmu); |
|
77 |
} |
|
78 |
|
|
79 |
|
|
80 |
static void cris_shift_ccs(CPUState *env) |
|
81 |
{ |
|
82 |
uint32_t ccs; |
|
83 |
/* Apply the ccs shift. */ |
|
84 |
ccs = env->pregs[PR_CCS]; |
|
85 |
ccs = (ccs & 0xc0000000) | ((ccs << 12) >> 2); |
|
86 |
env->pregs[PR_CCS] = ccs; |
|
92 |
D(printf("%s returns %d irqreq=%x addr=%x ismmu=%d\n", |
|
93 |
__func__, r, env->interrupt_request, |
|
94 |
address, is_softmmu)); |
|
95 |
return r; |
|
87 | 96 |
} |
88 | 97 |
|
89 | 98 |
void do_interrupt(CPUState *env) |
90 | 99 |
{ |
91 |
uint32_t ebp, isr; |
|
92 |
int irqnum; |
|
93 |
|
|
94 |
fflush(NULL); |
|
100 |
int ex_vec = -1; |
|
95 | 101 |
|
96 |
#if 0 |
|
97 |
printf ("exception index=%d interrupt_req=%d\n", |
|
98 |
env->exception_index, |
|
99 |
env->interrupt_request); |
|
100 |
#endif |
|
102 |
D(fprintf (stderr, "exception index=%d interrupt_req=%d\n", |
|
103 |
env->exception_index, |
|
104 |
env->interrupt_request)); |
|
101 | 105 |
|
102 | 106 |
switch (env->exception_index) |
103 | 107 |
{ |
104 | 108 |
case EXCP_BREAK: |
105 |
irqnum = env->trapnr;
|
|
106 |
ebp = env->pregs[PR_EBP];
|
|
107 |
isr = ldl_code(ebp + irqnum * 4);
|
|
109 |
/* These exceptions are genereated by the core itself.
|
|
110 |
ERP should point to the insn following the brk. */
|
|
111 |
ex_vec = env->trap_vector;
|
|
108 | 112 |
env->pregs[PR_ERP] = env->pc + 2; |
109 |
env->pc = isr; |
|
110 |
|
|
111 |
cris_shift_ccs(env); |
|
112 |
|
|
113 | 113 |
break; |
114 |
case EXCP_MMU_MISS: |
|
115 |
irqnum = 4; |
|
116 |
ebp = env->pregs[PR_EBP]; |
|
117 |
isr = ldl_code(ebp + irqnum * 4); |
|
118 |
env->pregs[PR_ERP] = env->pc; |
|
119 |
env->pc = isr; |
|
120 |
cris_shift_ccs(env); |
|
114 |
|
|
115 |
case EXCP_MMU_FAULT: |
|
116 |
/* ERP is already setup by translate-all.c through |
|
117 |
re-translation of the aborted TB combined with |
|
118 |
pc searching. */ |
|
119 |
ex_vec = env->fault_vector; |
|
121 | 120 |
break; |
122 | 121 |
|
123 | 122 |
default: |
... | ... | |
125 | 124 |
/* Maybe the irq was acked by sw before we got a |
126 | 125 |
change to take it. */ |
127 | 126 |
if (env->interrupt_request & CPU_INTERRUPT_HARD) { |
128 |
if (!env->pending_interrupts) |
|
127 |
/* Vectors below 0x30 are internal |
|
128 |
exceptions, i.e not interrupt requests |
|
129 |
from the interrupt controller. */ |
|
130 |
if (env->interrupt_vector < 0x30) |
|
129 | 131 |
return; |
132 |
/* Is the core accepting interrupts? */ |
|
130 | 133 |
if (!(env->pregs[PR_CCS] & I_FLAG)) { |
131 | 134 |
return; |
132 | 135 |
} |
133 |
|
|
134 |
irqnum = 31 - clz32(env->pending_interrupts);
|
|
135 |
irqnum += 0x30;
|
|
136 |
ebp = env->pregs[PR_EBP];
|
|
137 |
isr = ldl_code(ebp + irqnum * 4);
|
|
136 |
/* The interrupt controller gives us the |
|
137 |
vector. */
|
|
138 |
ex_vec = env->interrupt_vector;
|
|
139 |
/* Normal interrupts are taken between
|
|
140 |
TB's. env->pc is valid here. */
|
|
138 | 141 |
env->pregs[PR_ERP] = env->pc; |
139 |
env->pc = isr; |
|
140 |
|
|
141 |
cris_shift_ccs(env); |
|
142 |
#if 0 |
|
143 |
printf ("%s ebp=%x %x isr=%x %d" |
|
144 |
" ir=%x pending=%x\n", |
|
145 |
__func__, |
|
146 |
ebp, ebp + irqnum * 4, |
|
147 |
isr, env->exception_index, |
|
148 |
env->interrupt_request, |
|
149 |
env->pending_interrupts); |
|
150 |
#endif |
|
151 | 142 |
} |
152 |
|
|
153 | 143 |
} |
154 | 144 |
break; |
155 | 145 |
} |
146 |
env->pc = ldl_code(env->pregs[PR_EBP] + ex_vec * 4); |
|
147 |
/* Apply the CRIS CCS shift. */ |
|
148 |
cris_shift_ccs(env); |
|
149 |
D(printf ("%s ebp=%x isr=%x vec=%x\n", __func__, ebp, isr, ex_vec)); |
|
156 | 150 |
} |
157 | 151 |
|
158 | 152 |
target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr) |
... | ... | |
163 | 157 |
miss = cris_mmu_translate(&res, env, addr, 0, 0); |
164 | 158 |
if (!miss) |
165 | 159 |
phy = res.phy; |
160 |
D(fprintf(stderr, "%s %x -> %x\n", __func__, addr, phy)); |
|
166 | 161 |
return phy; |
167 | 162 |
} |
168 | 163 |
#endif |
b/translate-all.c | ||
---|---|---|
286 | 286 |
#elif defined(TARGET_SH4) |
287 | 287 |
env->pc = gen_opc_pc[j]; |
288 | 288 |
env->flags = gen_opc_hflags[j]; |
289 |
#elif defined(TARGET_CRIS) |
|
290 |
env->pregs[PR_ERP] = gen_opc_pc[j]; |
|
289 | 291 |
#endif |
290 | 292 |
|
291 | 293 |
#ifdef CONFIG_PROFILER |
Also available in: Unified diff