Revision e62b5b13 target-cris/helper.c
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 |
Also available in: Unified diff