File: | target-unicore32/softmmu.c |
Location: | line 219, column 5 |
Description: | Value stored to 'ret' is never read |
1 | /* |
2 | * Softmmu related functions |
3 | * |
4 | * Copyright (C) 2010-2012 Guan Xuetao |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as |
8 | * published by the Free Software Foundation, or any later version. |
9 | * See the COPYING file in the top-level directory. |
10 | */ |
11 | #ifdef CONFIG_USER_ONLY |
12 | #error This file only exist under softmmu circumstance |
13 | #endif |
14 | |
15 | #include <cpu.h> |
16 | |
17 | #undef DEBUG_UC32 |
18 | |
19 | #ifdef DEBUG_UC32 |
20 | #define DPRINTF(fmt, ...)do {} while (0) printf("%s: " fmt , __func__, ## __VA_ARGS__) |
21 | #else |
22 | #define DPRINTF(fmt, ...)do {} while (0) do {} while (0) |
23 | #endif |
24 | |
25 | #define SUPERPAGE_SIZE(1 << 22) (1 << 22) |
26 | #define UC32_PAGETABLE_READ(1 << 8) (1 << 8) |
27 | #define UC32_PAGETABLE_WRITE(1 << 7) (1 << 7) |
28 | #define UC32_PAGETABLE_EXEC(1 << 6) (1 << 6) |
29 | #define UC32_PAGETABLE_EXIST(1 << 2) (1 << 2) |
30 | #define PAGETABLE_TYPE(x)((x) & 3) ((x) & 3) |
31 | |
32 | |
33 | /* Map CPU modes onto saved register banks. */ |
34 | static inline int bank_number(CPUUniCore32State *env, int mode) |
35 | { |
36 | switch (mode) { |
37 | case ASR_MODE_USER(0x10): |
38 | case ASR_MODE_SUSR(0x1f): |
39 | return 0; |
40 | case ASR_MODE_PRIV(0x13): |
41 | return 1; |
42 | case ASR_MODE_TRAP(0x17): |
43 | return 2; |
44 | case ASR_MODE_EXTN(0x1b): |
45 | return 3; |
46 | case ASR_MODE_INTR(0x12): |
47 | return 4; |
48 | } |
49 | cpu_abort(env, "Bad mode %x\n", mode); |
50 | return -1; |
51 | } |
52 | |
53 | void switch_mode(CPUUniCore32State *env, int mode) |
54 | { |
55 | int old_mode; |
56 | int i; |
57 | |
58 | old_mode = env->uncached_asr & ASR_M(0x1f); |
59 | if (mode == old_mode) { |
60 | return; |
61 | } |
62 | |
63 | i = bank_number(env, old_mode); |
64 | env->banked_r29[i] = env->regs[29]; |
65 | env->banked_r30[i] = env->regs[30]; |
66 | env->banked_bsr[i] = env->bsr; |
67 | |
68 | i = bank_number(env, mode); |
69 | env->regs[29] = env->banked_r29[i]; |
70 | env->regs[30] = env->banked_r30[i]; |
71 | env->bsr = env->banked_bsr[i]; |
72 | } |
73 | |
74 | /* Handle a CPU exception. */ |
75 | void uc32_cpu_do_interrupt(CPUState *cs) |
76 | { |
77 | UniCore32CPU *cpu = UNICORE32_CPU(cs)((UniCore32CPU *)object_dynamic_cast_assert(((Object *)((cs)) ), ("unicore32-cpu"), "/home/stefan/src/qemu/qemu.org/qemu/target-unicore32/softmmu.c" , 77, __func__)); |
78 | CPUUniCore32State *env = &cpu->env; |
79 | uint32_t addr; |
80 | int new_mode; |
81 | |
82 | switch (env->exception_index) { |
83 | case UC32_EXCP_PRIV(1): |
84 | new_mode = ASR_MODE_PRIV(0x13); |
85 | addr = 0x08; |
86 | break; |
87 | case UC32_EXCP_ITRAP(2): |
88 | DPRINTF("itrap happened at %x\n", env->regs[31])do {} while (0); |
89 | new_mode = ASR_MODE_TRAP(0x17); |
90 | addr = 0x0c; |
91 | break; |
92 | case UC32_EXCP_DTRAP(3): |
93 | DPRINTF("dtrap happened at %x\n", env->regs[31])do {} while (0); |
94 | new_mode = ASR_MODE_TRAP(0x17); |
95 | addr = 0x10; |
96 | break; |
97 | case UC32_EXCP_INTR(4): |
98 | new_mode = ASR_MODE_INTR(0x12); |
99 | addr = 0x18; |
100 | break; |
101 | default: |
102 | cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index); |
103 | return; |
104 | } |
105 | /* High vectors. */ |
106 | if (env->cp0.c1_sys & (1 << 13)) { |
107 | addr += 0xffff0000; |
108 | } |
109 | |
110 | switch_mode(env, new_mode); |
111 | env->bsr = cpu_asr_read(env); |
112 | env->uncached_asr = (env->uncached_asr & ~ASR_M(0x1f)) | new_mode; |
113 | env->uncached_asr |= ASR_I(1 << 7); |
114 | /* The PC already points to the proper instruction. */ |
115 | env->regs[30] = env->regs[31]; |
116 | env->regs[31] = addr; |
117 | cs->interrupt_request |= CPU_INTERRUPT_EXITTB0x0004; |
118 | } |
119 | |
120 | static int get_phys_addr_ucv2(CPUUniCore32State *env, uint32_t address, |
121 | int access_type, int is_user, uint32_t *phys_ptr, int *prot, |
122 | target_ulong *page_size) |
123 | { |
124 | int code; |
125 | uint32_t table; |
126 | uint32_t desc; |
127 | uint32_t phys_addr; |
128 | |
129 | /* Pagetable walk. */ |
130 | /* Lookup l1 descriptor. */ |
131 | table = env->cp0.c2_base & 0xfffff000; |
132 | table |= (address >> 20) & 0xffc; |
133 | desc = ldl_phys(table); |
134 | code = 0; |
135 | switch (PAGETABLE_TYPE(desc)((desc) & 3)) { |
136 | case 3: |
137 | /* Superpage */ |
138 | if (!(desc & UC32_PAGETABLE_EXIST(1 << 2))) { |
139 | code = 0x0b; /* superpage miss */ |
140 | goto do_fault; |
141 | } |
142 | phys_addr = (desc & 0xffc00000) | (address & 0x003fffff); |
143 | *page_size = SUPERPAGE_SIZE(1 << 22); |
144 | break; |
145 | case 0: |
146 | /* Lookup l2 entry. */ |
147 | if (is_user) { |
148 | DPRINTF("PGD address %x, desc %x\n", table, desc)do {} while (0); |
149 | } |
150 | if (!(desc & UC32_PAGETABLE_EXIST(1 << 2))) { |
151 | code = 0x05; /* second pagetable miss */ |
152 | goto do_fault; |
153 | } |
154 | table = (desc & 0xfffff000) | ((address >> 10) & 0xffc); |
155 | desc = ldl_phys(table); |
156 | /* 4k page. */ |
157 | if (is_user) { |
158 | DPRINTF("PTE address %x, desc %x\n", table, desc)do {} while (0); |
159 | } |
160 | if (!(desc & UC32_PAGETABLE_EXIST(1 << 2))) { |
161 | code = 0x08; /* page miss */ |
162 | goto do_fault; |
163 | } |
164 | switch (PAGETABLE_TYPE(desc)((desc) & 3)) { |
165 | case 0: |
166 | phys_addr = (desc & 0xfffff000) | (address & 0xfff); |
167 | *page_size = TARGET_PAGE_SIZE(1 << 12); |
168 | break; |
169 | default: |
170 | cpu_abort(env, "wrong page type!"); |
171 | } |
172 | break; |
173 | default: |
174 | cpu_abort(env, "wrong page type!"); |
175 | } |
176 | |
177 | *phys_ptr = phys_addr; |
178 | *prot = 0; |
179 | /* Check access permissions. */ |
180 | if (desc & UC32_PAGETABLE_READ(1 << 8)) { |
181 | *prot |= PAGE_READ0x0001; |
182 | } else { |
183 | if (is_user && (access_type == 0)) { |
184 | code = 0x11; /* access unreadable area */ |
185 | goto do_fault; |
186 | } |
187 | } |
188 | |
189 | if (desc & UC32_PAGETABLE_WRITE(1 << 7)) { |
190 | *prot |= PAGE_WRITE0x0002; |
191 | } else { |
192 | if (is_user && (access_type == 1)) { |
193 | code = 0x12; /* access unwritable area */ |
194 | goto do_fault; |
195 | } |
196 | } |
197 | |
198 | if (desc & UC32_PAGETABLE_EXEC(1 << 6)) { |
199 | *prot |= PAGE_EXEC0x0004; |
200 | } else { |
201 | if (is_user && (access_type == 2)) { |
202 | code = 0x13; /* access unexecutable area */ |
203 | goto do_fault; |
204 | } |
205 | } |
206 | |
207 | do_fault: |
208 | return code; |
209 | } |
210 | |
211 | int uc32_cpu_handle_mmu_fault(CPUUniCore32State *env, target_ulong address, |
212 | int access_type, int mmu_idx) |
213 | { |
214 | uint32_t phys_addr; |
215 | target_ulong page_size; |
216 | int prot; |
217 | int ret, is_user; |
218 | |
219 | ret = 1; |
Value stored to 'ret' is never read | |
220 | is_user = mmu_idx == MMU_USER_IDX1; |
221 | |
222 | if ((env->cp0.c1_sys & 1) == 0) { |
223 | /* MMU disabled. */ |
224 | phys_addr = address; |
225 | prot = PAGE_READ0x0001 | PAGE_WRITE0x0002 | PAGE_EXEC0x0004; |
226 | page_size = TARGET_PAGE_SIZE(1 << 12); |
227 | ret = 0; |
228 | } else { |
229 | if ((address & (1 << 31)) || (is_user)) { |
230 | ret = get_phys_addr_ucv2(env, address, access_type, is_user, |
231 | &phys_addr, &prot, &page_size); |
232 | if (is_user) { |
233 | DPRINTF("user space access: ret %x, address %x, "do {} while (0) |
234 | "access_type %x, phys_addr %x, prot %x\n",do {} while (0) |
235 | ret, address, access_type, phys_addr, prot)do {} while (0); |
236 | } |
237 | } else { |
238 | /*IO memory */ |
239 | phys_addr = address | (1 << 31); |
240 | prot = PAGE_READ0x0001 | PAGE_WRITE0x0002 | PAGE_EXEC0x0004; |
241 | page_size = TARGET_PAGE_SIZE(1 << 12); |
242 | ret = 0; |
243 | } |
244 | } |
245 | |
246 | if (ret == 0) { |
247 | /* Map a single page. */ |
248 | phys_addr &= TARGET_PAGE_MASK~((1 << 12) - 1); |
249 | address &= TARGET_PAGE_MASK~((1 << 12) - 1); |
250 | tlb_set_page(env, address, phys_addr, prot, mmu_idx, page_size); |
251 | return 0; |
252 | } |
253 | |
254 | env->cp0.c3_faultstatus = ret; |
255 | env->cp0.c4_faultaddr = address; |
256 | if (access_type == 2) { |
257 | env->exception_index = UC32_EXCP_ITRAP(2); |
258 | } else { |
259 | env->exception_index = UC32_EXCP_DTRAP(3); |
260 | } |
261 | return ret; |
262 | } |
263 | |
264 | hwaddr uc32_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) |
265 | { |
266 | UniCore32CPU *cpu = UNICORE32_CPU(cs)((UniCore32CPU *)object_dynamic_cast_assert(((Object *)((cs)) ), ("unicore32-cpu"), "/home/stefan/src/qemu/qemu.org/qemu/target-unicore32/softmmu.c" , 266, __func__)); |
267 | |
268 | cpu_abort(&cpu->env, "%s not supported yet\n", __func__); |
269 | return addr; |
270 | } |