Commit 61382a500a9e54ef96ca28e0f221151f569cbb6e
1 parent
3a51dee6
full softmmu support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@410 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
10 changed files
with
594 additions
and
339 deletions
cpu-all.h
... | ... | @@ -20,18 +20,19 @@ |
20 | 20 | #ifndef CPU_ALL_H |
21 | 21 | #define CPU_ALL_H |
22 | 22 | |
23 | -/* all CPU memory access use these macros */ | |
24 | -static inline int ldub(void *ptr) | |
23 | +/* CPU memory access without any memory or io remapping */ | |
24 | + | |
25 | +static inline int ldub_raw(void *ptr) | |
25 | 26 | { |
26 | 27 | return *(uint8_t *)ptr; |
27 | 28 | } |
28 | 29 | |
29 | -static inline int ldsb(void *ptr) | |
30 | +static inline int ldsb_raw(void *ptr) | |
30 | 31 | { |
31 | 32 | return *(int8_t *)ptr; |
32 | 33 | } |
33 | 34 | |
34 | -static inline void stb(void *ptr, int v) | |
35 | +static inline void stb_raw(void *ptr, int v) | |
35 | 36 | { |
36 | 37 | *(uint8_t *)ptr = v; |
37 | 38 | } |
... | ... | @@ -42,7 +43,7 @@ static inline void stb(void *ptr, int v) |
42 | 43 | #if defined(WORDS_BIGENDIAN) || defined(__arm__) |
43 | 44 | |
44 | 45 | /* conservative code for little endian unaligned accesses */ |
45 | -static inline int lduw(void *ptr) | |
46 | +static inline int lduw_raw(void *ptr) | |
46 | 47 | { |
47 | 48 | #ifdef __powerpc__ |
48 | 49 | int val; |
... | ... | @@ -54,7 +55,7 @@ static inline int lduw(void *ptr) |
54 | 55 | #endif |
55 | 56 | } |
56 | 57 | |
57 | -static inline int ldsw(void *ptr) | |
58 | +static inline int ldsw_raw(void *ptr) | |
58 | 59 | { |
59 | 60 | #ifdef __powerpc__ |
60 | 61 | int val; |
... | ... | @@ -66,7 +67,7 @@ static inline int ldsw(void *ptr) |
66 | 67 | #endif |
67 | 68 | } |
68 | 69 | |
69 | -static inline int ldl(void *ptr) | |
70 | +static inline int ldl_raw(void *ptr) | |
70 | 71 | { |
71 | 72 | #ifdef __powerpc__ |
72 | 73 | int val; |
... | ... | @@ -78,16 +79,16 @@ static inline int ldl(void *ptr) |
78 | 79 | #endif |
79 | 80 | } |
80 | 81 | |
81 | -static inline uint64_t ldq(void *ptr) | |
82 | +static inline uint64_t ldq_raw(void *ptr) | |
82 | 83 | { |
83 | 84 | uint8_t *p = ptr; |
84 | 85 | uint32_t v1, v2; |
85 | - v1 = ldl(p); | |
86 | - v2 = ldl(p + 4); | |
86 | + v1 = ldl_raw(p); | |
87 | + v2 = ldl_raw(p + 4); | |
87 | 88 | return v1 | ((uint64_t)v2 << 32); |
88 | 89 | } |
89 | 90 | |
90 | -static inline void stw(void *ptr, int v) | |
91 | +static inline void stw_raw(void *ptr, int v) | |
91 | 92 | { |
92 | 93 | #ifdef __powerpc__ |
93 | 94 | __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr)); |
... | ... | @@ -98,7 +99,7 @@ static inline void stw(void *ptr, int v) |
98 | 99 | #endif |
99 | 100 | } |
100 | 101 | |
101 | -static inline void stl(void *ptr, int v) | |
102 | +static inline void stl_raw(void *ptr, int v) | |
102 | 103 | { |
103 | 104 | #ifdef __powerpc__ |
104 | 105 | __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr)); |
... | ... | @@ -111,104 +112,104 @@ static inline void stl(void *ptr, int v) |
111 | 112 | #endif |
112 | 113 | } |
113 | 114 | |
114 | -static inline void stq(void *ptr, uint64_t v) | |
115 | +static inline void stq_raw(void *ptr, uint64_t v) | |
115 | 116 | { |
116 | 117 | uint8_t *p = ptr; |
117 | - stl(p, (uint32_t)v); | |
118 | - stl(p + 4, v >> 32); | |
118 | + stl_raw(p, (uint32_t)v); | |
119 | + stl_raw(p + 4, v >> 32); | |
119 | 120 | } |
120 | 121 | |
121 | 122 | /* float access */ |
122 | 123 | |
123 | -static inline float ldfl(void *ptr) | |
124 | +static inline float ldfl_raw(void *ptr) | |
124 | 125 | { |
125 | 126 | union { |
126 | 127 | float f; |
127 | 128 | uint32_t i; |
128 | 129 | } u; |
129 | - u.i = ldl(ptr); | |
130 | + u.i = ldl_raw(ptr); | |
130 | 131 | return u.f; |
131 | 132 | } |
132 | 133 | |
133 | -static inline void stfl(void *ptr, float v) | |
134 | +static inline void stfl_raw(void *ptr, float v) | |
134 | 135 | { |
135 | 136 | union { |
136 | 137 | float f; |
137 | 138 | uint32_t i; |
138 | 139 | } u; |
139 | 140 | u.f = v; |
140 | - stl(ptr, u.i); | |
141 | + stl_raw(ptr, u.i); | |
141 | 142 | } |
142 | 143 | |
143 | 144 | |
144 | 145 | #if defined(__arm__) && !defined(WORDS_BIGENDIAN) |
145 | 146 | |
146 | 147 | /* NOTE: arm is horrible as double 32 bit words are stored in big endian ! */ |
147 | -static inline double ldfq(void *ptr) | |
148 | +static inline double ldfq_raw(void *ptr) | |
148 | 149 | { |
149 | 150 | union { |
150 | 151 | double d; |
151 | 152 | uint32_t tab[2]; |
152 | 153 | } u; |
153 | - u.tab[1] = ldl(ptr); | |
154 | - u.tab[0] = ldl(ptr + 4); | |
154 | + u.tab[1] = ldl_raw(ptr); | |
155 | + u.tab[0] = ldl_raw(ptr + 4); | |
155 | 156 | return u.d; |
156 | 157 | } |
157 | 158 | |
158 | -static inline void stfq(void *ptr, double v) | |
159 | +static inline void stfq_raw(void *ptr, double v) | |
159 | 160 | { |
160 | 161 | union { |
161 | 162 | double d; |
162 | 163 | uint32_t tab[2]; |
163 | 164 | } u; |
164 | 165 | u.d = v; |
165 | - stl(ptr, u.tab[1]); | |
166 | - stl(ptr + 4, u.tab[0]); | |
166 | + stl_raw(ptr, u.tab[1]); | |
167 | + stl_raw(ptr + 4, u.tab[0]); | |
167 | 168 | } |
168 | 169 | |
169 | 170 | #else |
170 | -static inline double ldfq(void *ptr) | |
171 | +static inline double ldfq_raw(void *ptr) | |
171 | 172 | { |
172 | 173 | union { |
173 | 174 | double d; |
174 | 175 | uint64_t i; |
175 | 176 | } u; |
176 | - u.i = ldq(ptr); | |
177 | + u.i = ldq_raw(ptr); | |
177 | 178 | return u.d; |
178 | 179 | } |
179 | 180 | |
180 | -static inline void stfq(void *ptr, double v) | |
181 | +static inline void stfq_raw(void *ptr, double v) | |
181 | 182 | { |
182 | 183 | union { |
183 | 184 | double d; |
184 | 185 | uint64_t i; |
185 | 186 | } u; |
186 | 187 | u.d = v; |
187 | - stq(ptr, u.i); | |
188 | + stq_raw(ptr, u.i); | |
188 | 189 | } |
189 | 190 | #endif |
190 | 191 | |
191 | 192 | #elif defined(TARGET_WORDS_BIGENDIAN) && !defined(WORDS_BIGENDIAN) |
192 | 193 | |
193 | -static inline int lduw(void *ptr) | |
194 | +static inline int lduw_raw(void *ptr) | |
194 | 195 | { |
195 | 196 | uint8_t *b = (uint8_t *) ptr; |
196 | 197 | return (b[0]<<8|b[1]); |
197 | 198 | } |
198 | 199 | |
199 | -static inline int ldsw(void *ptr) | |
200 | +static inline int ldsw_raw(void *ptr) | |
200 | 201 | { |
201 | 202 | int8_t *b = (int8_t *) ptr; |
202 | 203 | return (b[0]<<8|b[1]); |
203 | 204 | } |
204 | 205 | |
205 | -static inline int ldl(void *ptr) | |
206 | +static inline int ldl_raw(void *ptr) | |
206 | 207 | { |
207 | 208 | uint8_t *b = (uint8_t *) ptr; |
208 | 209 | return (b[0]<<24|b[1]<<16|b[2]<<8|b[3]); |
209 | 210 | } |
210 | 211 | |
211 | -static inline uint64_t ldq(void *ptr) | |
212 | +static inline uint64_t ldq_raw(void *ptr) | |
212 | 213 | { |
213 | 214 | uint32_t a,b; |
214 | 215 | a = ldl (ptr); |
... | ... | @@ -216,14 +217,14 @@ static inline uint64_t ldq(void *ptr) |
216 | 217 | return (((uint64_t)a<<32)|b); |
217 | 218 | } |
218 | 219 | |
219 | -static inline void stw(void *ptr, int v) | |
220 | +static inline void stw_raw(void *ptr, int v) | |
220 | 221 | { |
221 | 222 | uint8_t *d = (uint8_t *) ptr; |
222 | 223 | d[0] = v >> 8; |
223 | 224 | d[1] = v; |
224 | 225 | } |
225 | 226 | |
226 | -static inline void stl(void *ptr, int v) | |
227 | +static inline void stl_raw(void *ptr, int v) | |
227 | 228 | { |
228 | 229 | uint8_t *d = (uint8_t *) ptr; |
229 | 230 | d[0] = v >> 24; |
... | ... | @@ -232,7 +233,7 @@ static inline void stl(void *ptr, int v) |
232 | 233 | d[3] = v; |
233 | 234 | } |
234 | 235 | |
235 | -static inline void stq(void *ptr, uint64_t v) | |
236 | +static inline void stq_raw(void *ptr, uint64_t v) | |
236 | 237 | { |
237 | 238 | stl (ptr, v); |
238 | 239 | stl (ptr+4, v >> 32); |
... | ... | @@ -240,64 +241,102 @@ static inline void stq(void *ptr, uint64_t v) |
240 | 241 | |
241 | 242 | #else |
242 | 243 | |
243 | -static inline int lduw(void *ptr) | |
244 | +static inline int lduw_raw(void *ptr) | |
244 | 245 | { |
245 | 246 | return *(uint16_t *)ptr; |
246 | 247 | } |
247 | 248 | |
248 | -static inline int ldsw(void *ptr) | |
249 | +static inline int ldsw_raw(void *ptr) | |
249 | 250 | { |
250 | 251 | return *(int16_t *)ptr; |
251 | 252 | } |
252 | 253 | |
253 | -static inline int ldl(void *ptr) | |
254 | +static inline int ldl_raw(void *ptr) | |
254 | 255 | { |
255 | 256 | return *(uint32_t *)ptr; |
256 | 257 | } |
257 | 258 | |
258 | -static inline uint64_t ldq(void *ptr) | |
259 | +static inline uint64_t ldq_raw(void *ptr) | |
259 | 260 | { |
260 | 261 | return *(uint64_t *)ptr; |
261 | 262 | } |
262 | 263 | |
263 | -static inline void stw(void *ptr, int v) | |
264 | +static inline void stw_raw(void *ptr, int v) | |
264 | 265 | { |
265 | 266 | *(uint16_t *)ptr = v; |
266 | 267 | } |
267 | 268 | |
268 | -static inline void stl(void *ptr, int v) | |
269 | +static inline void stl_raw(void *ptr, int v) | |
269 | 270 | { |
270 | 271 | *(uint32_t *)ptr = v; |
271 | 272 | } |
272 | 273 | |
273 | -static inline void stq(void *ptr, uint64_t v) | |
274 | +static inline void stq_raw(void *ptr, uint64_t v) | |
274 | 275 | { |
275 | 276 | *(uint64_t *)ptr = v; |
276 | 277 | } |
277 | 278 | |
278 | 279 | /* float access */ |
279 | 280 | |
280 | -static inline float ldfl(void *ptr) | |
281 | +static inline float ldfl_raw(void *ptr) | |
281 | 282 | { |
282 | 283 | return *(float *)ptr; |
283 | 284 | } |
284 | 285 | |
285 | -static inline double ldfq(void *ptr) | |
286 | +static inline double ldfq_raw(void *ptr) | |
286 | 287 | { |
287 | 288 | return *(double *)ptr; |
288 | 289 | } |
289 | 290 | |
290 | -static inline void stfl(void *ptr, float v) | |
291 | +static inline void stfl_raw(void *ptr, float v) | |
291 | 292 | { |
292 | 293 | *(float *)ptr = v; |
293 | 294 | } |
294 | 295 | |
295 | -static inline void stfq(void *ptr, double v) | |
296 | +static inline void stfq_raw(void *ptr, double v) | |
296 | 297 | { |
297 | 298 | *(double *)ptr = v; |
298 | 299 | } |
299 | 300 | #endif |
300 | 301 | |
302 | +/* MMU memory access macros */ | |
303 | + | |
304 | +#if defined(CONFIG_USER_ONLY) | |
305 | + | |
306 | +/* if user mode, no other memory access functions */ | |
307 | +#define ldub(p) ldub_raw(p) | |
308 | +#define ldsb(p) ldsb_raw(p) | |
309 | +#define lduw(p) lduw_raw(p) | |
310 | +#define ldsw(p) ldsw_raw(p) | |
311 | +#define ldl(p) ldl_raw(p) | |
312 | +#define ldq(p) ldq_raw(p) | |
313 | +#define ldfl(p) ldfl_raw(p) | |
314 | +#define ldfq(p) ldfq_raw(p) | |
315 | +#define stb(p, v) stb_raw(p, v) | |
316 | +#define stw(p, v) stw_raw(p, v) | |
317 | +#define stl(p, v) stl_raw(p, v) | |
318 | +#define stq(p, v) stq_raw(p, v) | |
319 | +#define stfl(p, v) stfl_raw(p, v) | |
320 | +#define stfq(p, v) stfq_raw(p, v) | |
321 | + | |
322 | +#define ldub_code(p) ldub_raw(p) | |
323 | +#define ldsb_code(p) ldsb_raw(p) | |
324 | +#define lduw_code(p) lduw_raw(p) | |
325 | +#define ldsw_code(p) ldsw_raw(p) | |
326 | +#define ldl_code(p) ldl_raw(p) | |
327 | + | |
328 | +#define ldub_kernel(p) ldub_raw(p) | |
329 | +#define ldsb_kernel(p) ldsb_raw(p) | |
330 | +#define lduw_kernel(p) lduw_raw(p) | |
331 | +#define ldsw_kernel(p) ldsw_raw(p) | |
332 | +#define ldl_kernel(p) ldl_raw(p) | |
333 | +#define stb_kernel(p, v) stb_raw(p, v) | |
334 | +#define stw_kernel(p, v) stw_raw(p, v) | |
335 | +#define stl_kernel(p, v) stl_raw(p, v) | |
336 | +#define stq_kernel(p, v) stq_raw(p, v) | |
337 | + | |
338 | +#endif /* defined(CONFIG_USER_ONLY) */ | |
339 | + | |
301 | 340 | /* page related stuff */ |
302 | 341 | |
303 | 342 | #define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS) | ... | ... |
exec.c
... | ... | @@ -444,16 +444,20 @@ static inline void tb_alloc_page(TranslationBlock *tb, unsigned int page_index) |
444 | 444 | prot = 0; |
445 | 445 | for(addr = host_start; addr < host_end; addr += TARGET_PAGE_SIZE) |
446 | 446 | prot |= page_get_flags(addr); |
447 | +#if !defined(CONFIG_SOFTMMU) | |
447 | 448 | mprotect((void *)host_start, host_page_size, |
448 | 449 | (prot & PAGE_BITS) & ~PAGE_WRITE); |
450 | +#endif | |
451 | +#if !defined(CONFIG_USER_ONLY) | |
452 | + /* suppress soft TLB */ | |
453 | + /* XXX: must flush on all processor with same address space */ | |
454 | + tlb_flush_page_write(cpu_single_env, host_start); | |
455 | +#endif | |
449 | 456 | #ifdef DEBUG_TB_INVALIDATE |
450 | 457 | printf("protecting code page: 0x%08lx\n", |
451 | 458 | host_start); |
452 | 459 | #endif |
453 | 460 | p->flags &= ~PAGE_WRITE; |
454 | -#ifdef DEBUG_TB_CHECK | |
455 | - tb_page_check(); | |
456 | -#endif | |
457 | 461 | } |
458 | 462 | } |
459 | 463 | |
... | ... | @@ -483,6 +487,9 @@ void tb_link(TranslationBlock *tb) |
483 | 487 | if (page_index2 != page_index1) { |
484 | 488 | tb_alloc_page(tb, page_index2); |
485 | 489 | } |
490 | +#ifdef DEBUG_TB_CHECK | |
491 | + tb_page_check(); | |
492 | +#endif | |
486 | 493 | tb->jmp_first = (TranslationBlock *)((long)tb | 2); |
487 | 494 | tb->jmp_next[0] = NULL; |
488 | 495 | tb->jmp_next[1] = NULL; |
... | ... | @@ -517,20 +524,23 @@ int page_unprotect(unsigned long address) |
517 | 524 | /* if the page was really writable, then we change its |
518 | 525 | protection back to writable */ |
519 | 526 | if (prot & PAGE_WRITE_ORG) { |
520 | - mprotect((void *)host_start, host_page_size, | |
521 | - (prot & PAGE_BITS) | PAGE_WRITE); | |
522 | 527 | pindex = (address - host_start) >> TARGET_PAGE_BITS; |
523 | - p1[pindex].flags |= PAGE_WRITE; | |
524 | - /* and since the content will be modified, we must invalidate | |
525 | - the corresponding translated code. */ | |
526 | - tb_invalidate_page(address); | |
528 | + if (!(p1[pindex].flags & PAGE_WRITE)) { | |
529 | +#if !defined(CONFIG_SOFTMMU) | |
530 | + mprotect((void *)host_start, host_page_size, | |
531 | + (prot & PAGE_BITS) | PAGE_WRITE); | |
532 | +#endif | |
533 | + p1[pindex].flags |= PAGE_WRITE; | |
534 | + /* and since the content will be modified, we must invalidate | |
535 | + the corresponding translated code. */ | |
536 | + tb_invalidate_page(address); | |
527 | 537 | #ifdef DEBUG_TB_CHECK |
528 | - tb_invalidate_check(address); | |
538 | + tb_invalidate_check(address); | |
529 | 539 | #endif |
530 | - return 1; | |
531 | - } else { | |
532 | - return 0; | |
540 | + return 1; | |
541 | + } | |
533 | 542 | } |
543 | + return 0; | |
534 | 544 | } |
535 | 545 | |
536 | 546 | /* call this function when system calls directly modify a memory area */ |
... | ... | @@ -734,13 +744,17 @@ void cpu_abort(CPUState *env, const char *fmt, ...) |
734 | 744 | /* unmap all maped pages and flush all associated code */ |
735 | 745 | void page_unmap(void) |
736 | 746 | { |
737 | - PageDesc *p, *pmap; | |
738 | - unsigned long addr; | |
739 | - int i, j, ret, j1; | |
747 | + PageDesc *pmap; | |
748 | + int i; | |
740 | 749 | |
741 | 750 | for(i = 0; i < L1_SIZE; i++) { |
742 | 751 | pmap = l1_map[i]; |
743 | 752 | if (pmap) { |
753 | +#if !defined(CONFIG_SOFTMMU) | |
754 | + PageDesc *p; | |
755 | + unsigned long addr; | |
756 | + int j, ret, j1; | |
757 | + | |
744 | 758 | p = pmap; |
745 | 759 | for(j = 0;j < L2_SIZE;) { |
746 | 760 | if (p->flags & PAGE_VALID) { |
... | ... | @@ -763,6 +777,7 @@ void page_unmap(void) |
763 | 777 | j++; |
764 | 778 | } |
765 | 779 | } |
780 | +#endif | |
766 | 781 | free(pmap); |
767 | 782 | l1_map[i] = NULL; |
768 | 783 | } |
... | ... | @@ -773,7 +788,7 @@ void page_unmap(void) |
773 | 788 | |
774 | 789 | void tlb_flush(CPUState *env) |
775 | 790 | { |
776 | -#if defined(TARGET_I386) | |
791 | +#if !defined(CONFIG_USER_ONLY) | |
777 | 792 | int i; |
778 | 793 | for(i = 0; i < CPU_TLB_SIZE; i++) { |
779 | 794 | env->tlb_read[0][i].address = -1; |
... | ... | @@ -784,16 +799,38 @@ void tlb_flush(CPUState *env) |
784 | 799 | #endif |
785 | 800 | } |
786 | 801 | |
802 | +static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, uint32_t addr) | |
803 | +{ | |
804 | + if (addr == (tlb_entry->address & | |
805 | + (TARGET_PAGE_MASK | TLB_INVALID_MASK))) | |
806 | + tlb_entry->address = -1; | |
807 | +} | |
808 | + | |
787 | 809 | void tlb_flush_page(CPUState *env, uint32_t addr) |
788 | 810 | { |
789 | -#if defined(TARGET_I386) | |
811 | +#if !defined(CONFIG_USER_ONLY) | |
812 | + int i; | |
813 | + | |
814 | + addr &= TARGET_PAGE_MASK; | |
815 | + i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); | |
816 | + tlb_flush_entry(&env->tlb_read[0][i], addr); | |
817 | + tlb_flush_entry(&env->tlb_write[0][i], addr); | |
818 | + tlb_flush_entry(&env->tlb_read[1][i], addr); | |
819 | + tlb_flush_entry(&env->tlb_write[1][i], addr); | |
820 | +#endif | |
821 | +} | |
822 | + | |
823 | +/* make all write to page 'addr' trigger a TLB exception to detect | |
824 | + self modifying code */ | |
825 | +void tlb_flush_page_write(CPUState *env, uint32_t addr) | |
826 | +{ | |
827 | +#if !defined(CONFIG_USER_ONLY) | |
790 | 828 | int i; |
791 | 829 | |
830 | + addr &= TARGET_PAGE_MASK; | |
792 | 831 | i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
793 | - env->tlb_read[0][i].address = -1; | |
794 | - env->tlb_write[0][i].address = -1; | |
795 | - env->tlb_read[1][i].address = -1; | |
796 | - env->tlb_write[1][i].address = -1; | |
832 | + tlb_flush_entry(&env->tlb_write[0][i], addr); | |
833 | + tlb_flush_entry(&env->tlb_write[1][i], addr); | |
797 | 834 | #endif |
798 | 835 | } |
799 | 836 | |
... | ... | @@ -900,3 +937,25 @@ int cpu_register_io_memory(int io_index, |
900 | 937 | } |
901 | 938 | return io_index << IO_MEM_SHIFT; |
902 | 939 | } |
940 | + | |
941 | +#if !defined(CONFIG_USER_ONLY) | |
942 | + | |
943 | +#define MMUSUFFIX _cmmu | |
944 | +#define GETPC() NULL | |
945 | +#define env cpu_single_env | |
946 | + | |
947 | +#define SHIFT 0 | |
948 | +#include "softmmu_template.h" | |
949 | + | |
950 | +#define SHIFT 1 | |
951 | +#include "softmmu_template.h" | |
952 | + | |
953 | +#define SHIFT 2 | |
954 | +#include "softmmu_template.h" | |
955 | + | |
956 | +#define SHIFT 3 | |
957 | +#include "softmmu_template.h" | |
958 | + | |
959 | +#undef env | |
960 | + | |
961 | +#endif | ... | ... |
hw/vga_template.h
... | ... | @@ -354,7 +354,7 @@ static void glue(vga_draw_line15_, DEPTH)(VGAState *s1, uint8_t *d, |
354 | 354 | |
355 | 355 | w = width; |
356 | 356 | do { |
357 | - v = lduw((void *)s); | |
357 | + v = lduw_raw((void *)s); | |
358 | 358 | r = (v >> 7) & 0xf8; |
359 | 359 | g = (v >> 2) & 0xf8; |
360 | 360 | b = (v << 3) & 0xf8; |
... | ... | @@ -379,7 +379,7 @@ static void glue(vga_draw_line16_, DEPTH)(VGAState *s1, uint8_t *d, |
379 | 379 | |
380 | 380 | w = width; |
381 | 381 | do { |
382 | - v = lduw((void *)s); | |
382 | + v = lduw_raw((void *)s); | |
383 | 383 | r = (v >> 8) & 0xf8; |
384 | 384 | g = (v >> 3) & 0xfc; |
385 | 385 | b = (v << 3) & 0xf8; | ... | ... |
softmmu_header.h
... | ... | @@ -19,26 +19,48 @@ |
19 | 19 | */ |
20 | 20 | #if DATA_SIZE == 8 |
21 | 21 | #define SUFFIX q |
22 | +#define USUFFIX q | |
22 | 23 | #define DATA_TYPE uint64_t |
23 | 24 | #elif DATA_SIZE == 4 |
24 | 25 | #define SUFFIX l |
26 | +#define USUFFIX l | |
25 | 27 | #define DATA_TYPE uint32_t |
26 | 28 | #elif DATA_SIZE == 2 |
27 | 29 | #define SUFFIX w |
30 | +#define USUFFIX uw | |
28 | 31 | #define DATA_TYPE uint16_t |
29 | 32 | #define DATA_STYPE int16_t |
30 | 33 | #elif DATA_SIZE == 1 |
31 | 34 | #define SUFFIX b |
35 | +#define USUFFIX ub | |
32 | 36 | #define DATA_TYPE uint8_t |
33 | 37 | #define DATA_STYPE int8_t |
34 | 38 | #else |
35 | 39 | #error unsupported data size |
36 | 40 | #endif |
37 | 41 | |
38 | -#if MEMUSER == 0 | |
39 | -#define MEMSUFFIX _kernel | |
42 | +#if ACCESS_TYPE == 0 | |
43 | + | |
44 | +#define CPU_MEM_INDEX 0 | |
45 | +#define MMUSUFFIX _mmu | |
46 | + | |
47 | +#elif ACCESS_TYPE == 1 | |
48 | + | |
49 | +#define CPU_MEM_INDEX 1 | |
50 | +#define MMUSUFFIX _mmu | |
51 | + | |
52 | +#elif ACCESS_TYPE == 2 | |
53 | + | |
54 | +#define CPU_MEM_INDEX ((env->hflags & HF_CPL_MASK) == 3) | |
55 | +#define MMUSUFFIX _mmu | |
56 | + | |
57 | +#elif ACCESS_TYPE == 3 | |
58 | + | |
59 | +#define CPU_MEM_INDEX ((env->hflags & HF_CPL_MASK) == 3) | |
60 | +#define MMUSUFFIX _cmmu | |
61 | + | |
40 | 62 | #else |
41 | -#define MEMSUFFIX _user | |
63 | +#error invalid ACCESS_TYPE | |
42 | 64 | #endif |
43 | 65 | |
44 | 66 | #if DATA_SIZE == 8 |
... | ... | @@ -48,24 +70,26 @@ |
48 | 70 | #endif |
49 | 71 | |
50 | 72 | |
51 | -#if MEMUSER == 0 | |
52 | -DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), _mmu)(unsigned long addr); | |
53 | -void REGPARM(2) glue(glue(__st, SUFFIX), _mmu)(unsigned long addr, DATA_TYPE v); | |
54 | -#endif | |
73 | +DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(unsigned long addr, | |
74 | + int is_user); | |
75 | +void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(unsigned long addr, DATA_TYPE v, int is_user); | |
55 | 76 | |
56 | -static inline int glue(glue(ldu, SUFFIX), MEMSUFFIX)(void *ptr) | |
77 | +static inline int glue(glue(ld, USUFFIX), MEMSUFFIX)(void *ptr) | |
57 | 78 | { |
58 | 79 | int index; |
59 | 80 | RES_TYPE res; |
60 | 81 | unsigned long addr, physaddr; |
82 | + int is_user; | |
83 | + | |
61 | 84 | addr = (unsigned long)ptr; |
62 | 85 | index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
63 | - if (__builtin_expect(env->tlb_read[MEMUSER][index].address != | |
86 | + is_user = CPU_MEM_INDEX; | |
87 | + if (__builtin_expect(env->tlb_read[is_user][index].address != | |
64 | 88 | (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) { |
65 | - res = glue(glue(__ld, SUFFIX), _mmu)(addr); | |
89 | + res = glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, is_user); | |
66 | 90 | } else { |
67 | - physaddr = addr + env->tlb_read[MEMUSER][index].addend; | |
68 | - res = glue(glue(ldu, SUFFIX), _raw)((uint8_t *)physaddr); | |
91 | + physaddr = addr + env->tlb_read[is_user][index].addend; | |
92 | + res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr); | |
69 | 93 | } |
70 | 94 | return res; |
71 | 95 | } |
... | ... | @@ -75,13 +99,16 @@ static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(void *ptr) |
75 | 99 | { |
76 | 100 | int res, index; |
77 | 101 | unsigned long addr, physaddr; |
102 | + int is_user; | |
103 | + | |
78 | 104 | addr = (unsigned long)ptr; |
79 | 105 | index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
80 | - if (__builtin_expect(env->tlb_read[MEMUSER][index].address != | |
106 | + is_user = CPU_MEM_INDEX; | |
107 | + if (__builtin_expect(env->tlb_read[is_user][index].address != | |
81 | 108 | (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) { |
82 | - res = (DATA_STYPE)glue(glue(__ld, SUFFIX), _mmu)(addr); | |
109 | + res = (DATA_STYPE)glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, is_user); | |
83 | 110 | } else { |
84 | - physaddr = addr + env->tlb_read[MEMUSER][index].addend; | |
111 | + physaddr = addr + env->tlb_read[is_user][index].addend; | |
85 | 112 | res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)physaddr); |
86 | 113 | } |
87 | 114 | return res; |
... | ... | @@ -92,13 +119,16 @@ static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(void *ptr, RES_TYPE v) |
92 | 119 | { |
93 | 120 | int index; |
94 | 121 | unsigned long addr, physaddr; |
122 | + int is_user; | |
123 | + | |
95 | 124 | addr = (unsigned long)ptr; |
96 | 125 | index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
97 | - if (__builtin_expect(env->tlb_write[MEMUSER][index].address != | |
126 | + is_user = CPU_MEM_INDEX; | |
127 | + if (__builtin_expect(env->tlb_write[is_user][index].address != | |
98 | 128 | (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) { |
99 | - glue(glue(__st, SUFFIX), _mmu)(addr, v); | |
129 | + glue(glue(__st, SUFFIX), MMUSUFFIX)(addr, v, is_user); | |
100 | 130 | } else { |
101 | - physaddr = addr + env->tlb_write[MEMUSER][index].addend; | |
131 | + physaddr = addr + env->tlb_write[is_user][index].addend; | |
102 | 132 | glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, v); |
103 | 133 | } |
104 | 134 | } |
... | ... | @@ -107,5 +137,7 @@ static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(void *ptr, RES_TYPE v) |
107 | 137 | #undef DATA_TYPE |
108 | 138 | #undef DATA_STYPE |
109 | 139 | #undef SUFFIX |
140 | +#undef USUFFIX | |
110 | 141 | #undef DATA_SIZE |
111 | -#undef MEMSUFFIX | |
142 | +#undef CPU_MEM_INDEX | |
143 | +#undef MMUSUFFIX | ... | ... |
softmmu_template.h
... | ... | @@ -21,23 +21,31 @@ |
21 | 21 | |
22 | 22 | #if DATA_SIZE == 8 |
23 | 23 | #define SUFFIX q |
24 | +#define USUFFIX q | |
24 | 25 | #define DATA_TYPE uint64_t |
25 | 26 | #elif DATA_SIZE == 4 |
26 | 27 | #define SUFFIX l |
28 | +#define USUFFIX l | |
27 | 29 | #define DATA_TYPE uint32_t |
28 | 30 | #elif DATA_SIZE == 2 |
29 | 31 | #define SUFFIX w |
32 | +#define USUFFIX uw | |
30 | 33 | #define DATA_TYPE uint16_t |
31 | 34 | #elif DATA_SIZE == 1 |
32 | 35 | #define SUFFIX b |
36 | +#define USUFFIX ub | |
33 | 37 | #define DATA_TYPE uint8_t |
34 | 38 | #else |
35 | 39 | #error unsupported data size |
36 | 40 | #endif |
37 | 41 | |
38 | -static DATA_TYPE glue(slow_ld, SUFFIX)(unsigned long addr, void *retaddr); | |
39 | -static void glue(slow_st, SUFFIX)(unsigned long addr, DATA_TYPE val, | |
40 | - void *retaddr); | |
42 | +static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(unsigned long addr, | |
43 | + int is_user, | |
44 | + void *retaddr); | |
45 | +static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(unsigned long addr, | |
46 | + DATA_TYPE val, | |
47 | + int is_user, | |
48 | + void *retaddr); | |
41 | 49 | |
42 | 50 | static inline DATA_TYPE glue(io_read, SUFFIX)(unsigned long physaddr, |
43 | 51 | unsigned long tlb_addr) |
... | ... | @@ -81,16 +89,16 @@ static inline void glue(io_write, SUFFIX)(unsigned long physaddr, |
81 | 89 | } |
82 | 90 | |
83 | 91 | /* handle all cases except unaligned access which span two pages */ |
84 | -DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), _mmu)(unsigned long addr) | |
92 | +DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(unsigned long addr, | |
93 | + int is_user) | |
85 | 94 | { |
86 | 95 | DATA_TYPE res; |
87 | - int is_user, index; | |
96 | + int index; | |
88 | 97 | unsigned long physaddr, tlb_addr; |
89 | 98 | void *retaddr; |
90 | 99 | |
91 | 100 | /* test if there is match for unaligned or IO access */ |
92 | 101 | /* XXX: could done more in memory macro in a non portable way */ |
93 | - is_user = ((env->hflags & HF_CPL_MASK) == 3); | |
94 | 102 | index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
95 | 103 | redo: |
96 | 104 | tlb_addr = env->tlb_read[is_user][index].address; |
... | ... | @@ -104,29 +112,31 @@ DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), _mmu)(unsigned long addr) |
104 | 112 | } else if (((addr & 0xfff) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { |
105 | 113 | /* slow unaligned access (it spans two pages or IO) */ |
106 | 114 | do_unaligned_access: |
107 | - retaddr = __builtin_return_address(0); | |
108 | - res = glue(slow_ld, SUFFIX)(addr, retaddr); | |
115 | + retaddr = GETPC(); | |
116 | + res = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr, | |
117 | + is_user, retaddr); | |
109 | 118 | } else { |
110 | 119 | /* unaligned access in the same page */ |
111 | - res = glue(glue(ldu, SUFFIX), _raw)((uint8_t *)physaddr); | |
120 | + res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr); | |
112 | 121 | } |
113 | 122 | } else { |
114 | 123 | /* the page is not in the TLB : fill it */ |
115 | - retaddr = __builtin_return_address(0); | |
116 | - tlb_fill(addr, 0, retaddr); | |
124 | + retaddr = GETPC(); | |
125 | + tlb_fill(addr, 0, is_user, retaddr); | |
117 | 126 | goto redo; |
118 | 127 | } |
119 | 128 | return res; |
120 | 129 | } |
121 | 130 | |
122 | 131 | /* handle all unaligned cases */ |
123 | -static DATA_TYPE glue(slow_ld, SUFFIX)(unsigned long addr, void *retaddr) | |
132 | +static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(unsigned long addr, | |
133 | + int is_user, | |
134 | + void *retaddr) | |
124 | 135 | { |
125 | 136 | DATA_TYPE res, res1, res2; |
126 | - int is_user, index, shift; | |
137 | + int index, shift; | |
127 | 138 | unsigned long physaddr, tlb_addr, addr1, addr2; |
128 | 139 | |
129 | - is_user = ((env->hflags & HF_CPL_MASK) == 3); | |
130 | 140 | index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
131 | 141 | redo: |
132 | 142 | tlb_addr = env->tlb_read[is_user][index].address; |
... | ... | @@ -142,8 +152,10 @@ static DATA_TYPE glue(slow_ld, SUFFIX)(unsigned long addr, void *retaddr) |
142 | 152 | /* slow unaligned access (it spans two pages) */ |
143 | 153 | addr1 = addr & ~(DATA_SIZE - 1); |
144 | 154 | addr2 = addr1 + DATA_SIZE; |
145 | - res1 = glue(slow_ld, SUFFIX)(addr1, retaddr); | |
146 | - res2 = glue(slow_ld, SUFFIX)(addr2, retaddr); | |
155 | + res1 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr1, | |
156 | + is_user, retaddr); | |
157 | + res2 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(addr2, | |
158 | + is_user, retaddr); | |
147 | 159 | shift = (addr & (DATA_SIZE - 1)) * 8; |
148 | 160 | #ifdef TARGET_WORDS_BIGENDIAN |
149 | 161 | res = (res1 << shift) | (res2 >> ((DATA_SIZE * 8) - shift)); |
... | ... | @@ -152,24 +164,25 @@ static DATA_TYPE glue(slow_ld, SUFFIX)(unsigned long addr, void *retaddr) |
152 | 164 | #endif |
153 | 165 | } else { |
154 | 166 | /* unaligned/aligned access in the same page */ |
155 | - res = glue(glue(ldu, SUFFIX), _raw)((uint8_t *)physaddr); | |
167 | + res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr); | |
156 | 168 | } |
157 | 169 | } else { |
158 | 170 | /* the page is not in the TLB : fill it */ |
159 | - tlb_fill(addr, 0, retaddr); | |
171 | + tlb_fill(addr, 0, is_user, retaddr); | |
160 | 172 | goto redo; |
161 | 173 | } |
162 | 174 | return res; |
163 | 175 | } |
164 | 176 | |
165 | 177 | |
166 | -void REGPARM(2) glue(glue(__st, SUFFIX), _mmu)(unsigned long addr, DATA_TYPE val) | |
178 | +void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(unsigned long addr, | |
179 | + DATA_TYPE val, | |
180 | + int is_user) | |
167 | 181 | { |
168 | 182 | unsigned long physaddr, tlb_addr; |
169 | 183 | void *retaddr; |
170 | - int is_user, index; | |
184 | + int index; | |
171 | 185 | |
172 | - is_user = ((env->hflags & HF_CPL_MASK) == 3); | |
173 | 186 | index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
174 | 187 | redo: |
175 | 188 | tlb_addr = env->tlb_write[is_user][index].address; |
... | ... | @@ -182,28 +195,30 @@ void REGPARM(2) glue(glue(__st, SUFFIX), _mmu)(unsigned long addr, DATA_TYPE val |
182 | 195 | glue(io_write, SUFFIX)(physaddr, val, tlb_addr); |
183 | 196 | } else if (((addr & 0xfff) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { |
184 | 197 | do_unaligned_access: |
185 | - retaddr = __builtin_return_address(0); | |
186 | - glue(slow_st, SUFFIX)(addr, val, retaddr); | |
198 | + retaddr = GETPC(); | |
199 | + glue(glue(slow_st, SUFFIX), MMUSUFFIX)(addr, val, | |
200 | + is_user, retaddr); | |
187 | 201 | } else { |
188 | 202 | /* aligned/unaligned access in the same page */ |
189 | 203 | glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, val); |
190 | 204 | } |
191 | 205 | } else { |
192 | 206 | /* the page is not in the TLB : fill it */ |
193 | - retaddr = __builtin_return_address(0); | |
194 | - tlb_fill(addr, 1, retaddr); | |
207 | + retaddr = GETPC(); | |
208 | + tlb_fill(addr, 1, is_user, retaddr); | |
195 | 209 | goto redo; |
196 | 210 | } |
197 | 211 | } |
198 | 212 | |
199 | 213 | /* handles all unaligned cases */ |
200 | -static void glue(slow_st, SUFFIX)(unsigned long addr, DATA_TYPE val, | |
201 | - void *retaddr) | |
214 | +static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(unsigned long addr, | |
215 | + DATA_TYPE val, | |
216 | + int is_user, | |
217 | + void *retaddr) | |
202 | 218 | { |
203 | 219 | unsigned long physaddr, tlb_addr; |
204 | - int is_user, index, i; | |
220 | + int index, i; | |
205 | 221 | |
206 | - is_user = ((env->hflags & HF_CPL_MASK) == 3); | |
207 | 222 | index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
208 | 223 | redo: |
209 | 224 | tlb_addr = env->tlb_write[is_user][index].address; |
... | ... | @@ -219,9 +234,11 @@ static void glue(slow_st, SUFFIX)(unsigned long addr, DATA_TYPE val, |
219 | 234 | /* XXX: not efficient, but simple */ |
220 | 235 | for(i = 0;i < DATA_SIZE; i++) { |
221 | 236 | #ifdef TARGET_WORDS_BIGENDIAN |
222 | - slow_stb(addr + i, val >> (((DATA_SIZE - 1) * 8) - (i * 8)), retaddr); | |
237 | + glue(slow_stb, MMUSUFFIX)(addr + i, val >> (((DATA_SIZE - 1) * 8) - (i * 8)), | |
238 | + is_user, retaddr); | |
223 | 239 | #else |
224 | - slow_stb(addr + i, val >> (i * 8), retaddr); | |
240 | + glue(slow_stb, MMUSUFFIX)(addr + i, val >> (i * 8), | |
241 | + is_user, retaddr); | |
225 | 242 | #endif |
226 | 243 | } |
227 | 244 | } else { |
... | ... | @@ -230,7 +247,7 @@ static void glue(slow_st, SUFFIX)(unsigned long addr, DATA_TYPE val, |
230 | 247 | } |
231 | 248 | } else { |
232 | 249 | /* the page is not in the TLB : fill it */ |
233 | - tlb_fill(addr, 1, retaddr); | |
250 | + tlb_fill(addr, 1, is_user, retaddr); | |
234 | 251 | goto redo; |
235 | 252 | } |
236 | 253 | } |
... | ... | @@ -238,4 +255,5 @@ static void glue(slow_st, SUFFIX)(unsigned long addr, DATA_TYPE val, |
238 | 255 | #undef SHIFT |
239 | 256 | #undef DATA_TYPE |
240 | 257 | #undef SUFFIX |
258 | +#undef USUFFIX | |
241 | 259 | #undef DATA_SIZE | ... | ... |
target-i386/exec.h
... | ... | @@ -137,8 +137,10 @@ void helper_invlpg(unsigned int addr); |
137 | 137 | void cpu_x86_update_cr0(CPUX86State *env); |
138 | 138 | void cpu_x86_update_cr3(CPUX86State *env); |
139 | 139 | void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr); |
140 | -int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write); | |
141 | -void tlb_fill(unsigned long addr, int is_write, void *retaddr); | |
140 | +int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, | |
141 | + int is_write, int is_user, int is_softmmu); | |
142 | +void tlb_fill(unsigned long addr, int is_write, int is_user, | |
143 | + void *retaddr); | |
142 | 144 | void __hidden cpu_lock(void); |
143 | 145 | void __hidden cpu_unlock(void); |
144 | 146 | void do_interrupt(int intno, int is_int, int error_code, |
... | ... | @@ -366,26 +368,30 @@ static inline void load_eflags(int eflags, int update_mask) |
366 | 368 | (eflags & update_mask); |
367 | 369 | } |
368 | 370 | |
369 | -/* memory access macros */ | |
371 | +/* XXX: move that to a generic header */ | |
372 | +#if !defined(CONFIG_USER_ONLY) | |
370 | 373 | |
371 | -#define ldul ldl | |
372 | -#define lduq ldq | |
373 | 374 | #define ldul_user ldl_user |
374 | 375 | #define ldul_kernel ldl_kernel |
375 | 376 | |
376 | -#define ldub_raw ldub | |
377 | -#define ldsb_raw ldsb | |
378 | -#define lduw_raw lduw | |
379 | -#define ldsw_raw ldsw | |
380 | -#define ldl_raw ldl | |
381 | -#define ldq_raw ldq | |
377 | +#define ACCESS_TYPE 0 | |
378 | +#define MEMSUFFIX _kernel | |
379 | +#define DATA_SIZE 1 | |
380 | +#include "softmmu_header.h" | |
381 | + | |
382 | +#define DATA_SIZE 2 | |
383 | +#include "softmmu_header.h" | |
382 | 384 | |
383 | -#define stb_raw stb | |
384 | -#define stw_raw stw | |
385 | -#define stl_raw stl | |
386 | -#define stq_raw stq | |
385 | +#define DATA_SIZE 4 | |
386 | +#include "softmmu_header.h" | |
387 | + | |
388 | +#define DATA_SIZE 8 | |
389 | +#include "softmmu_header.h" | |
390 | +#undef ACCESS_TYPE | |
391 | +#undef MEMSUFFIX | |
387 | 392 | |
388 | -#define MEMUSER 0 | |
393 | +#define ACCESS_TYPE 1 | |
394 | +#define MEMSUFFIX _user | |
389 | 395 | #define DATA_SIZE 1 |
390 | 396 | #include "softmmu_header.h" |
391 | 397 | |
... | ... | @@ -397,9 +403,12 @@ static inline void load_eflags(int eflags, int update_mask) |
397 | 403 | |
398 | 404 | #define DATA_SIZE 8 |
399 | 405 | #include "softmmu_header.h" |
406 | +#undef ACCESS_TYPE | |
407 | +#undef MEMSUFFIX | |
400 | 408 | |
401 | -#undef MEMUSER | |
402 | -#define MEMUSER 1 | |
409 | +/* these access are slower, they must be as rare as possible */ | |
410 | +#define ACCESS_TYPE 2 | |
411 | +#define MEMSUFFIX _data | |
403 | 412 | #define DATA_SIZE 1 |
404 | 413 | #include "softmmu_header.h" |
405 | 414 | |
... | ... | @@ -411,6 +420,59 @@ static inline void load_eflags(int eflags, int update_mask) |
411 | 420 | |
412 | 421 | #define DATA_SIZE 8 |
413 | 422 | #include "softmmu_header.h" |
423 | +#undef ACCESS_TYPE | |
424 | +#undef MEMSUFFIX | |
425 | + | |
426 | +#define ldub(p) ldub_data(p) | |
427 | +#define ldsb(p) ldsb_data(p) | |
428 | +#define lduw(p) lduw_data(p) | |
429 | +#define ldsw(p) ldsw_data(p) | |
430 | +#define ldl(p) ldl_data(p) | |
431 | +#define ldq(p) ldq_data(p) | |
432 | + | |
433 | +#define stb(p, v) stb_data(p, v) | |
434 | +#define stw(p, v) stw_data(p, v) | |
435 | +#define stl(p, v) stl_data(p, v) | |
436 | +#define stq(p, v) stq_data(p, v) | |
437 | + | |
438 | +static inline double ldfq(void *ptr) | |
439 | +{ | |
440 | + union { | |
441 | + double d; | |
442 | + uint64_t i; | |
443 | + } u; | |
444 | + u.i = ldq(ptr); | |
445 | + return u.d; | |
446 | +} | |
447 | + | |
448 | +static inline void stfq(void *ptr, double v) | |
449 | +{ | |
450 | + union { | |
451 | + double d; | |
452 | + uint64_t i; | |
453 | + } u; | |
454 | + u.d = v; | |
455 | + stq(ptr, u.i); | |
456 | +} | |
414 | 457 | |
415 | -#undef MEMUSER | |
458 | +static inline float ldfl(void *ptr) | |
459 | +{ | |
460 | + union { | |
461 | + float f; | |
462 | + uint32_t i; | |
463 | + } u; | |
464 | + u.i = ldl(ptr); | |
465 | + return u.f; | |
466 | +} | |
467 | + | |
468 | +static inline void stfl(void *ptr, float v) | |
469 | +{ | |
470 | + union { | |
471 | + float f; | |
472 | + uint32_t i; | |
473 | + } u; | |
474 | + u.f = v; | |
475 | + stl(ptr, u.i); | |
476 | +} | |
416 | 477 | |
478 | +#endif /* !defined(CONFIG_USER_ONLY) */ | ... | ... |
target-i386/helper.c
... | ... | @@ -153,11 +153,11 @@ static inline void get_ss_esp_from_tss(uint32_t *ss_ptr, |
153 | 153 | if (index + (4 << shift) - 1 > env->tr.limit) |
154 | 154 | raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc); |
155 | 155 | if (shift == 0) { |
156 | - *esp_ptr = lduw(env->tr.base + index); | |
157 | - *ss_ptr = lduw(env->tr.base + index + 2); | |
156 | + *esp_ptr = lduw_kernel(env->tr.base + index); | |
157 | + *ss_ptr = lduw_kernel(env->tr.base + index + 2); | |
158 | 158 | } else { |
159 | - *esp_ptr = ldl(env->tr.base + index); | |
160 | - *ss_ptr = lduw(env->tr.base + index + 4); | |
159 | + *esp_ptr = ldl_kernel(env->tr.base + index); | |
160 | + *ss_ptr = lduw_kernel(env->tr.base + index + 4); | |
161 | 161 | } |
162 | 162 | } |
163 | 163 | |
... | ... | @@ -177,8 +177,8 @@ static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr, |
177 | 177 | if ((index + 7) > dt->limit) |
178 | 178 | return -1; |
179 | 179 | ptr = dt->base + index; |
180 | - *e1_ptr = ldl(ptr); | |
181 | - *e2_ptr = ldl(ptr + 4); | |
180 | + *e1_ptr = ldl_kernel(ptr); | |
181 | + *e2_ptr = ldl_kernel(ptr + 4); | |
182 | 182 | return 0; |
183 | 183 | } |
184 | 184 | |
... | ... | @@ -226,8 +226,8 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, |
226 | 226 | if (intno * 8 + 7 > dt->limit) |
227 | 227 | raise_exception_err(EXCP0D_GPF, intno * 8 + 2); |
228 | 228 | ptr = dt->base + intno * 8; |
229 | - e1 = ldl(ptr); | |
230 | - e2 = ldl(ptr + 4); | |
229 | + e1 = ldl_kernel(ptr); | |
230 | + e2 = ldl_kernel(ptr + 4); | |
231 | 231 | /* check gate type */ |
232 | 232 | type = (e2 >> DESC_TYPE_SHIFT) & 0x1f; |
233 | 233 | switch(type) { |
... | ... | @@ -344,47 +344,47 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, |
344 | 344 | int old_eflags; |
345 | 345 | if (env->eflags & VM_MASK) { |
346 | 346 | ssp -= 4; |
347 | - stl(ssp, env->segs[R_GS].selector); | |
347 | + stl_kernel(ssp, env->segs[R_GS].selector); | |
348 | 348 | ssp -= 4; |
349 | - stl(ssp, env->segs[R_FS].selector); | |
349 | + stl_kernel(ssp, env->segs[R_FS].selector); | |
350 | 350 | ssp -= 4; |
351 | - stl(ssp, env->segs[R_DS].selector); | |
351 | + stl_kernel(ssp, env->segs[R_DS].selector); | |
352 | 352 | ssp -= 4; |
353 | - stl(ssp, env->segs[R_ES].selector); | |
353 | + stl_kernel(ssp, env->segs[R_ES].selector); | |
354 | 354 | } |
355 | 355 | if (new_stack) { |
356 | 356 | ssp -= 4; |
357 | - stl(ssp, old_ss); | |
357 | + stl_kernel(ssp, old_ss); | |
358 | 358 | ssp -= 4; |
359 | - stl(ssp, old_esp); | |
359 | + stl_kernel(ssp, old_esp); | |
360 | 360 | } |
361 | 361 | ssp -= 4; |
362 | 362 | old_eflags = compute_eflags(); |
363 | - stl(ssp, old_eflags); | |
363 | + stl_kernel(ssp, old_eflags); | |
364 | 364 | ssp -= 4; |
365 | - stl(ssp, old_cs); | |
365 | + stl_kernel(ssp, old_cs); | |
366 | 366 | ssp -= 4; |
367 | - stl(ssp, old_eip); | |
367 | + stl_kernel(ssp, old_eip); | |
368 | 368 | if (has_error_code) { |
369 | 369 | ssp -= 4; |
370 | - stl(ssp, error_code); | |
370 | + stl_kernel(ssp, error_code); | |
371 | 371 | } |
372 | 372 | } else { |
373 | 373 | if (new_stack) { |
374 | 374 | ssp -= 2; |
375 | - stw(ssp, old_ss); | |
375 | + stw_kernel(ssp, old_ss); | |
376 | 376 | ssp -= 2; |
377 | - stw(ssp, old_esp); | |
377 | + stw_kernel(ssp, old_esp); | |
378 | 378 | } |
379 | 379 | ssp -= 2; |
380 | - stw(ssp, compute_eflags()); | |
380 | + stw_kernel(ssp, compute_eflags()); | |
381 | 381 | ssp -= 2; |
382 | - stw(ssp, old_cs); | |
382 | + stw_kernel(ssp, old_cs); | |
383 | 383 | ssp -= 2; |
384 | - stw(ssp, old_eip); | |
384 | + stw_kernel(ssp, old_eip); | |
385 | 385 | if (has_error_code) { |
386 | 386 | ssp -= 2; |
387 | - stw(ssp, error_code); | |
387 | + stw_kernel(ssp, error_code); | |
388 | 388 | } |
389 | 389 | } |
390 | 390 | |
... | ... | @@ -410,8 +410,8 @@ static void do_interrupt_real(int intno, int is_int, int error_code, |
410 | 410 | if (intno * 4 + 3 > dt->limit) |
411 | 411 | raise_exception_err(EXCP0D_GPF, intno * 8 + 2); |
412 | 412 | ptr = dt->base + intno * 4; |
413 | - offset = lduw(ptr); | |
414 | - selector = lduw(ptr + 2); | |
413 | + offset = lduw_kernel(ptr); | |
414 | + selector = lduw_kernel(ptr + 2); | |
415 | 415 | esp = ESP; |
416 | 416 | ssp = env->segs[R_SS].base; |
417 | 417 | if (is_int) |
... | ... | @@ -420,11 +420,11 @@ static void do_interrupt_real(int intno, int is_int, int error_code, |
420 | 420 | old_eip = env->eip; |
421 | 421 | old_cs = env->segs[R_CS].selector; |
422 | 422 | esp -= 2; |
423 | - stw(ssp + (esp & 0xffff), compute_eflags()); | |
423 | + stw_kernel(ssp + (esp & 0xffff), compute_eflags()); | |
424 | 424 | esp -= 2; |
425 | - stw(ssp + (esp & 0xffff), old_cs); | |
425 | + stw_kernel(ssp + (esp & 0xffff), old_cs); | |
426 | 426 | esp -= 2; |
427 | - stw(ssp + (esp & 0xffff), old_eip); | |
427 | + stw_kernel(ssp + (esp & 0xffff), old_eip); | |
428 | 428 | |
429 | 429 | /* update processor state */ |
430 | 430 | ESP = (ESP & ~0xffff) | (esp & 0xffff); |
... | ... | @@ -445,7 +445,7 @@ void do_interrupt_user(int intno, int is_int, int error_code, |
445 | 445 | |
446 | 446 | dt = &env->idt; |
447 | 447 | ptr = dt->base + (intno * 8); |
448 | - e2 = ldl(ptr + 4); | |
448 | + e2 = ldl_kernel(ptr + 4); | |
449 | 449 | |
450 | 450 | dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
451 | 451 | cpl = env->hflags & HF_CPL_MASK; |
... | ... | @@ -651,8 +651,8 @@ void helper_lldt_T0(void) |
651 | 651 | if ((index + 7) > dt->limit) |
652 | 652 | raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
653 | 653 | ptr = dt->base + index; |
654 | - e1 = ldl(ptr); | |
655 | - e2 = ldl(ptr + 4); | |
654 | + e1 = ldl_kernel(ptr); | |
655 | + e2 = ldl_kernel(ptr + 4); | |
656 | 656 | if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2) |
657 | 657 | raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
658 | 658 | if (!(e2 & DESC_P_MASK)) |
... | ... | @@ -684,8 +684,8 @@ void helper_ltr_T0(void) |
684 | 684 | if ((index + 7) > dt->limit) |
685 | 685 | raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
686 | 686 | ptr = dt->base + index; |
687 | - e1 = ldl(ptr); | |
688 | - e2 = ldl(ptr + 4); | |
687 | + e1 = ldl_kernel(ptr); | |
688 | + e2 = ldl_kernel(ptr + 4); | |
689 | 689 | type = (e2 >> DESC_TYPE_SHIFT) & 0xf; |
690 | 690 | if ((e2 & DESC_S_MASK) || |
691 | 691 | (type != 2 && type != 9)) |
... | ... | @@ -694,7 +694,7 @@ void helper_ltr_T0(void) |
694 | 694 | raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); |
695 | 695 | load_seg_cache_raw_dt(&env->tr, e1, e2); |
696 | 696 | e2 |= 0x00000200; /* set the busy bit */ |
697 | - stl(ptr + 4, e2); | |
697 | + stl_kernel(ptr + 4, e2); | |
698 | 698 | } |
699 | 699 | env->tr.selector = selector; |
700 | 700 | } |
... | ... | @@ -813,14 +813,14 @@ void helper_lcall_real_T0_T1(int shift, int next_eip) |
813 | 813 | ssp = env->segs[R_SS].base; |
814 | 814 | if (shift) { |
815 | 815 | esp -= 4; |
816 | - stl(ssp + (esp & esp_mask), env->segs[R_CS].selector); | |
816 | + stl_kernel(ssp + (esp & esp_mask), env->segs[R_CS].selector); | |
817 | 817 | esp -= 4; |
818 | - stl(ssp + (esp & esp_mask), next_eip); | |
818 | + stl_kernel(ssp + (esp & esp_mask), next_eip); | |
819 | 819 | } else { |
820 | 820 | esp -= 2; |
821 | - stw(ssp + (esp & esp_mask), env->segs[R_CS].selector); | |
821 | + stw_kernel(ssp + (esp & esp_mask), env->segs[R_CS].selector); | |
822 | 822 | esp -= 2; |
823 | - stw(ssp + (esp & esp_mask), next_eip); | |
823 | + stw_kernel(ssp + (esp & esp_mask), next_eip); | |
824 | 824 | } |
825 | 825 | |
826 | 826 | if (!(env->segs[R_SS].flags & DESC_B_MASK)) |
... | ... | @@ -873,14 +873,14 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip) |
873 | 873 | ssp = env->segs[R_SS].base + sp; |
874 | 874 | if (shift) { |
875 | 875 | ssp -= 4; |
876 | - stl(ssp, env->segs[R_CS].selector); | |
876 | + stl_kernel(ssp, env->segs[R_CS].selector); | |
877 | 877 | ssp -= 4; |
878 | - stl(ssp, next_eip); | |
878 | + stl_kernel(ssp, next_eip); | |
879 | 879 | } else { |
880 | 880 | ssp -= 2; |
881 | - stw(ssp, env->segs[R_CS].selector); | |
881 | + stw_kernel(ssp, env->segs[R_CS].selector); | |
882 | 882 | ssp -= 2; |
883 | - stw(ssp, next_eip); | |
883 | + stw_kernel(ssp, next_eip); | |
884 | 884 | } |
885 | 885 | sp -= (4 << shift); |
886 | 886 | |
... | ... | @@ -975,23 +975,23 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip) |
975 | 975 | ssp = env->segs[R_SS].base + sp; |
976 | 976 | if (shift) { |
977 | 977 | ssp -= 4; |
978 | - stl(ssp, old_ss); | |
978 | + stl_kernel(ssp, old_ss); | |
979 | 979 | ssp -= 4; |
980 | - stl(ssp, old_esp); | |
980 | + stl_kernel(ssp, old_esp); | |
981 | 981 | ssp -= 4 * param_count; |
982 | 982 | for(i = 0; i < param_count; i++) { |
983 | - val = ldl(old_ssp + i * 4); | |
984 | - stl(ssp + i * 4, val); | |
983 | + val = ldl_kernel(old_ssp + i * 4); | |
984 | + stl_kernel(ssp + i * 4, val); | |
985 | 985 | } |
986 | 986 | } else { |
987 | 987 | ssp -= 2; |
988 | - stw(ssp, old_ss); | |
988 | + stw_kernel(ssp, old_ss); | |
989 | 989 | ssp -= 2; |
990 | - stw(ssp, old_esp); | |
990 | + stw_kernel(ssp, old_esp); | |
991 | 991 | ssp -= 2 * param_count; |
992 | 992 | for(i = 0; i < param_count; i++) { |
993 | - val = lduw(old_ssp + i * 2); | |
994 | - stw(ssp + i * 2, val); | |
993 | + val = lduw_kernel(old_ssp + i * 2); | |
994 | + stw_kernel(ssp + i * 2, val); | |
995 | 995 | } |
996 | 996 | } |
997 | 997 | } else { |
... | ... | @@ -1004,14 +1004,14 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip) |
1004 | 1004 | |
1005 | 1005 | if (shift) { |
1006 | 1006 | ssp -= 4; |
1007 | - stl(ssp, env->segs[R_CS].selector); | |
1007 | + stl_kernel(ssp, env->segs[R_CS].selector); | |
1008 | 1008 | ssp -= 4; |
1009 | - stl(ssp, next_eip); | |
1009 | + stl_kernel(ssp, next_eip); | |
1010 | 1010 | } else { |
1011 | 1011 | ssp -= 2; |
1012 | - stw(ssp, env->segs[R_CS].selector); | |
1012 | + stw_kernel(ssp, env->segs[R_CS].selector); | |
1013 | 1013 | ssp -= 2; |
1014 | - stw(ssp, next_eip); | |
1014 | + stw_kernel(ssp, next_eip); | |
1015 | 1015 | } |
1016 | 1016 | |
1017 | 1017 | sp -= push_size; |
... | ... | @@ -1042,14 +1042,14 @@ void helper_iret_real(int shift) |
1042 | 1042 | ssp = env->segs[R_SS].base + sp; |
1043 | 1043 | if (shift == 1) { |
1044 | 1044 | /* 32 bits */ |
1045 | - new_eflags = ldl(ssp + 8); | |
1046 | - new_cs = ldl(ssp + 4) & 0xffff; | |
1047 | - new_eip = ldl(ssp) & 0xffff; | |
1045 | + new_eflags = ldl_kernel(ssp + 8); | |
1046 | + new_cs = ldl_kernel(ssp + 4) & 0xffff; | |
1047 | + new_eip = ldl_kernel(ssp) & 0xffff; | |
1048 | 1048 | } else { |
1049 | 1049 | /* 16 bits */ |
1050 | - new_eflags = lduw(ssp + 4); | |
1051 | - new_cs = lduw(ssp + 2); | |
1052 | - new_eip = lduw(ssp); | |
1050 | + new_eflags = lduw_kernel(ssp + 4); | |
1051 | + new_cs = lduw_kernel(ssp + 2); | |
1052 | + new_eip = lduw_kernel(ssp); | |
1053 | 1053 | } |
1054 | 1054 | new_esp = sp + (6 << shift); |
1055 | 1055 | ESP = (ESP & 0xffff0000) | |
... | ... | @@ -1078,17 +1078,17 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) |
1078 | 1078 | if (shift == 1) { |
1079 | 1079 | /* 32 bits */ |
1080 | 1080 | if (is_iret) |
1081 | - new_eflags = ldl(ssp + 8); | |
1082 | - new_cs = ldl(ssp + 4) & 0xffff; | |
1083 | - new_eip = ldl(ssp); | |
1081 | + new_eflags = ldl_kernel(ssp + 8); | |
1082 | + new_cs = ldl_kernel(ssp + 4) & 0xffff; | |
1083 | + new_eip = ldl_kernel(ssp); | |
1084 | 1084 | if (is_iret && (new_eflags & VM_MASK)) |
1085 | 1085 | goto return_to_vm86; |
1086 | 1086 | } else { |
1087 | 1087 | /* 16 bits */ |
1088 | 1088 | if (is_iret) |
1089 | - new_eflags = lduw(ssp + 4); | |
1090 | - new_cs = lduw(ssp + 2); | |
1091 | - new_eip = lduw(ssp); | |
1089 | + new_eflags = lduw_kernel(ssp + 4); | |
1090 | + new_cs = lduw_kernel(ssp + 2); | |
1091 | + new_eip = lduw_kernel(ssp); | |
1092 | 1092 | } |
1093 | 1093 | if ((new_cs & 0xfffc) == 0) |
1094 | 1094 | raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
... | ... | @@ -1124,12 +1124,12 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) |
1124 | 1124 | ssp += (4 << shift) + ((2 * is_iret) << shift) + addend; |
1125 | 1125 | if (shift == 1) { |
1126 | 1126 | /* 32 bits */ |
1127 | - new_esp = ldl(ssp); | |
1128 | - new_ss = ldl(ssp + 4) & 0xffff; | |
1127 | + new_esp = ldl_kernel(ssp); | |
1128 | + new_ss = ldl_kernel(ssp + 4) & 0xffff; | |
1129 | 1129 | } else { |
1130 | 1130 | /* 16 bits */ |
1131 | - new_esp = lduw(ssp); | |
1132 | - new_ss = lduw(ssp + 2); | |
1131 | + new_esp = lduw_kernel(ssp); | |
1132 | + new_ss = lduw_kernel(ssp + 2); | |
1133 | 1133 | } |
1134 | 1134 | |
1135 | 1135 | if ((new_ss & 3) != rpl) |
... | ... | @@ -1175,12 +1175,12 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) |
1175 | 1175 | return; |
1176 | 1176 | |
1177 | 1177 | return_to_vm86: |
1178 | - new_esp = ldl(ssp + 12); | |
1179 | - new_ss = ldl(ssp + 16); | |
1180 | - new_es = ldl(ssp + 20); | |
1181 | - new_ds = ldl(ssp + 24); | |
1182 | - new_fs = ldl(ssp + 28); | |
1183 | - new_gs = ldl(ssp + 32); | |
1178 | + new_esp = ldl_kernel(ssp + 12); | |
1179 | + new_ss = ldl_kernel(ssp + 16); | |
1180 | + new_es = ldl_kernel(ssp + 20); | |
1181 | + new_ds = ldl_kernel(ssp + 24); | |
1182 | + new_fs = ldl_kernel(ssp + 28); | |
1183 | + new_gs = ldl_kernel(ssp + 32); | |
1184 | 1184 | |
1185 | 1185 | /* modify processor state */ |
1186 | 1186 | load_eflags(new_eflags, FL_UPDATE_CPL0_MASK | VM_MASK | VIF_MASK | VIP_MASK); |
... | ... | @@ -1770,6 +1770,11 @@ void helper_frstor(uint8_t *ptr, int data32) |
1770 | 1770 | } |
1771 | 1771 | } |
1772 | 1772 | |
1773 | +#if !defined(CONFIG_USER_ONLY) | |
1774 | + | |
1775 | +#define MMUSUFFIX _mmu | |
1776 | +#define GETPC() (__builtin_return_address(0)) | |
1777 | + | |
1773 | 1778 | #define SHIFT 0 |
1774 | 1779 | #include "softmmu_template.h" |
1775 | 1780 | |
... | ... | @@ -1782,22 +1787,41 @@ void helper_frstor(uint8_t *ptr, int data32) |
1782 | 1787 | #define SHIFT 3 |
1783 | 1788 | #include "softmmu_template.h" |
1784 | 1789 | |
1785 | -/* try to fill the TLB and return an exception if error */ | |
1786 | -void tlb_fill(unsigned long addr, int is_write, void *retaddr) | |
1790 | +#endif | |
1791 | + | |
1792 | +/* try to fill the TLB and return an exception if error. If retaddr is | |
1793 | + NULL, it means that the function was called in C code (i.e. not | |
1794 | + from generated code or from helper.c) */ | |
1795 | +/* XXX: fix it to restore all registers */ | |
1796 | +void tlb_fill(unsigned long addr, int is_write, int is_user, void *retaddr) | |
1787 | 1797 | { |
1788 | 1798 | TranslationBlock *tb; |
1789 | 1799 | int ret; |
1790 | 1800 | unsigned long pc; |
1791 | - ret = cpu_x86_handle_mmu_fault(env, addr, is_write); | |
1801 | + CPUX86State *saved_env; | |
1802 | + | |
1803 | + /* XXX: hack to restore env in all cases, even if not called from | |
1804 | + generated code */ | |
1805 | + saved_env = env; | |
1806 | + env = cpu_single_env; | |
1807 | + if (is_write && page_unprotect(addr)) { | |
1808 | + /* nothing more to do: the page was write protected because | |
1809 | + there was code in it. page_unprotect() flushed the code. */ | |
1810 | + } | |
1811 | + | |
1812 | + ret = cpu_x86_handle_mmu_fault(env, addr, is_write, is_user, 1); | |
1792 | 1813 | if (ret) { |
1793 | - /* now we have a real cpu fault */ | |
1794 | - pc = (unsigned long)retaddr; | |
1795 | - tb = tb_find_pc(pc); | |
1796 | - if (tb) { | |
1797 | - /* the PC is inside the translated code. It means that we have | |
1798 | - a virtual CPU fault */ | |
1799 | - cpu_restore_state(tb, env, pc); | |
1814 | + if (retaddr) { | |
1815 | + /* now we have a real cpu fault */ | |
1816 | + pc = (unsigned long)retaddr; | |
1817 | + tb = tb_find_pc(pc); | |
1818 | + if (tb) { | |
1819 | + /* the PC is inside the translated code. It means that we have | |
1820 | + a virtual CPU fault */ | |
1821 | + cpu_restore_state(tb, env, pc); | |
1822 | + } | |
1800 | 1823 | } |
1801 | 1824 | raise_exception_err(EXCP0E_PAGE, env->error_code); |
1802 | 1825 | } |
1826 | + env = saved_env; | |
1803 | 1827 | } | ... | ... |
target-i386/helper2.c
... | ... | @@ -210,7 +210,9 @@ void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr) |
210 | 210 | flags = page_get_flags(addr); |
211 | 211 | if (flags & PAGE_VALID) { |
212 | 212 | virt_addr = addr & ~0xfff; |
213 | +#if !defined(CONFIG_SOFTMMU) | |
213 | 214 | munmap((void *)virt_addr, 4096); |
215 | +#endif | |
214 | 216 | page_set_flags(virt_addr, virt_addr + 4096, 0); |
215 | 217 | } |
216 | 218 | } |
... | ... | @@ -221,16 +223,14 @@ void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr) |
221 | 223 | 1 = generate PF fault |
222 | 224 | 2 = soft MMU activation required for this block |
223 | 225 | */ |
224 | -int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write) | |
226 | +int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, | |
227 | + int is_write, int is_user, int is_softmmu) | |
225 | 228 | { |
226 | 229 | uint8_t *pde_ptr, *pte_ptr; |
227 | 230 | uint32_t pde, pte, virt_addr; |
228 | - int cpl, error_code, is_dirty, is_user, prot, page_size, ret; | |
231 | + int error_code, is_dirty, prot, page_size, ret; | |
229 | 232 | unsigned long pd; |
230 | 233 | |
231 | - cpl = env->hflags & HF_CPL_MASK; | |
232 | - is_user = (cpl == 3); | |
233 | - | |
234 | 234 | #ifdef DEBUG_MMU |
235 | 235 | printf("MMU fault: addr=0x%08x w=%d u=%d eip=%08x\n", |
236 | 236 | addr, is_write, is_user, env->eip); |
... | ... | @@ -252,7 +252,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write) |
252 | 252 | |
253 | 253 | /* page directory entry */ |
254 | 254 | pde_ptr = phys_ram_base + ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)); |
255 | - pde = ldl(pde_ptr); | |
255 | + pde = ldl_raw(pde_ptr); | |
256 | 256 | if (!(pde & PG_PRESENT_MASK)) { |
257 | 257 | error_code = 0; |
258 | 258 | goto do_fault; |
... | ... | @@ -274,7 +274,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write) |
274 | 274 | pde |= PG_ACCESSED_MASK; |
275 | 275 | if (is_dirty) |
276 | 276 | pde |= PG_DIRTY_MASK; |
277 | - stl(pde_ptr, pde); | |
277 | + stl_raw(pde_ptr, pde); | |
278 | 278 | } |
279 | 279 | |
280 | 280 | pte = pde & ~0x003ff000; /* align to 4MB */ |
... | ... | @@ -283,12 +283,12 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write) |
283 | 283 | } else { |
284 | 284 | if (!(pde & PG_ACCESSED_MASK)) { |
285 | 285 | pde |= PG_ACCESSED_MASK; |
286 | - stl(pde_ptr, pde); | |
286 | + stl_raw(pde_ptr, pde); | |
287 | 287 | } |
288 | 288 | |
289 | 289 | /* page directory entry */ |
290 | 290 | pte_ptr = phys_ram_base + ((pde & ~0xfff) + ((addr >> 10) & 0xffc)); |
291 | - pte = ldl(pte_ptr); | |
291 | + pte = ldl_raw(pte_ptr); | |
292 | 292 | if (!(pte & PG_PRESENT_MASK)) { |
293 | 293 | error_code = 0; |
294 | 294 | goto do_fault; |
... | ... | @@ -308,7 +308,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write) |
308 | 308 | pte |= PG_ACCESSED_MASK; |
309 | 309 | if (is_dirty) |
310 | 310 | pte |= PG_DIRTY_MASK; |
311 | - stl(pte_ptr, pte); | |
311 | + stl_raw(pte_ptr, pte); | |
312 | 312 | } |
313 | 313 | page_size = 4096; |
314 | 314 | virt_addr = addr & ~0xfff; |
... | ... | @@ -325,7 +325,10 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write) |
325 | 325 | } |
326 | 326 | |
327 | 327 | do_mapping: |
328 | - if (env->hflags & HF_SOFTMMU_MASK) { | |
328 | +#if !defined(CONFIG_SOFTMMU) | |
329 | + if (is_softmmu) | |
330 | +#endif | |
331 | + { | |
329 | 332 | unsigned long paddr, vaddr, address, addend, page_offset; |
330 | 333 | int index; |
331 | 334 | |
... | ... | @@ -352,32 +355,39 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write) |
352 | 355 | env->tlb_write[is_user][index].address = address; |
353 | 356 | env->tlb_write[is_user][index].addend = addend; |
354 | 357 | } |
358 | + page_set_flags(vaddr, vaddr + TARGET_PAGE_SIZE, | |
359 | + PAGE_VALID | PAGE_EXEC | prot); | |
360 | + ret = 0; | |
355 | 361 | } |
356 | - ret = 0; | |
357 | - /* XXX: incorrect for 4MB pages */ | |
358 | - pd = physpage_find(pte & ~0xfff); | |
359 | - if ((pd & 0xfff) != 0) { | |
360 | - /* IO access: no mapping is done as it will be handled by the | |
361 | - soft MMU */ | |
362 | - if (!(env->hflags & HF_SOFTMMU_MASK)) | |
363 | - ret = 2; | |
364 | - } else { | |
365 | - void *map_addr; | |
366 | - map_addr = mmap((void *)virt_addr, page_size, prot, | |
367 | - MAP_SHARED | MAP_FIXED, phys_ram_fd, pd); | |
368 | - if (map_addr == MAP_FAILED) { | |
369 | - fprintf(stderr, | |
370 | - "mmap failed when mapped physical address 0x%08x to virtual address 0x%08x\n", | |
371 | - pte & ~0xfff, virt_addr); | |
372 | - exit(1); | |
373 | - } | |
362 | +#if !defined(CONFIG_SOFTMMU) | |
363 | + else { | |
364 | + ret = 0; | |
365 | + /* XXX: incorrect for 4MB pages */ | |
366 | + pd = physpage_find(pte & ~0xfff); | |
367 | + if ((pd & 0xfff) != 0) { | |
368 | + /* IO access: no mapping is done as it will be handled by the | |
369 | + soft MMU */ | |
370 | + if (!(env->hflags & HF_SOFTMMU_MASK)) | |
371 | + ret = 2; | |
372 | + } else { | |
373 | + void *map_addr; | |
374 | + map_addr = mmap((void *)virt_addr, page_size, prot, | |
375 | + MAP_SHARED | MAP_FIXED, phys_ram_fd, pd); | |
376 | + if (map_addr == MAP_FAILED) { | |
377 | + fprintf(stderr, | |
378 | + "mmap failed when mapped physical address 0x%08x to virtual address 0x%08x\n", | |
379 | + pte & ~0xfff, virt_addr); | |
380 | + exit(1); | |
381 | + } | |
374 | 382 | #ifdef DEBUG_MMU |
375 | - printf("mmaping 0x%08x to virt 0x%08x pse=%d\n", | |
376 | - pte & ~0xfff, virt_addr, (page_size != 4096)); | |
383 | + printf("mmaping 0x%08x to virt 0x%08x pse=%d\n", | |
384 | + pte & ~0xfff, virt_addr, (page_size != 4096)); | |
377 | 385 | #endif |
378 | - page_set_flags(virt_addr, virt_addr + page_size, | |
379 | - PAGE_VALID | PAGE_EXEC | prot); | |
386 | + page_set_flags(virt_addr, virt_addr + page_size, | |
387 | + PAGE_VALID | PAGE_EXEC | prot); | |
388 | + } | |
380 | 389 | } |
390 | +#endif | |
381 | 391 | return ret; |
382 | 392 | do_fault_protect: |
383 | 393 | error_code = PG_ERROR_P_MASK; | ... | ... |
target-i386/op.c
... | ... | @@ -376,14 +376,16 @@ void OPPROTO op_andl_A0_ffff(void) |
376 | 376 | |
377 | 377 | /* memory access */ |
378 | 378 | |
379 | -#define MEMSUFFIX | |
379 | +#define MEMSUFFIX _raw | |
380 | 380 | #include "ops_mem.h" |
381 | 381 | |
382 | +#if !defined(CONFIG_USER_ONLY) | |
382 | 383 | #define MEMSUFFIX _user |
383 | 384 | #include "ops_mem.h" |
384 | 385 | |
385 | 386 | #define MEMSUFFIX _kernel |
386 | 387 | #include "ops_mem.h" |
388 | +#endif | |
387 | 389 | |
388 | 390 | /* used for bit operations */ |
389 | 391 | ... | ... |
target-i386/translate.c
... | ... | @@ -570,10 +570,10 @@ static GenOpFunc *gen_op_bsx_T0_cc[2][2] = { |
570 | 570 | }; |
571 | 571 | |
572 | 572 | static GenOpFunc *gen_op_lds_T0_A0[3 * 3] = { |
573 | - gen_op_ldsb_T0_A0, | |
574 | - gen_op_ldsw_T0_A0, | |
573 | + gen_op_ldsb_raw_T0_A0, | |
574 | + gen_op_ldsw_raw_T0_A0, | |
575 | 575 | NULL, |
576 | - | |
576 | +#ifndef CONFIG_USER_ONLY | |
577 | 577 | gen_op_ldsb_kernel_T0_A0, |
578 | 578 | gen_op_ldsw_kernel_T0_A0, |
579 | 579 | NULL, |
... | ... | @@ -581,13 +581,15 @@ static GenOpFunc *gen_op_lds_T0_A0[3 * 3] = { |
581 | 581 | gen_op_ldsb_user_T0_A0, |
582 | 582 | gen_op_ldsw_user_T0_A0, |
583 | 583 | NULL, |
584 | +#endif | |
584 | 585 | }; |
585 | 586 | |
586 | 587 | static GenOpFunc *gen_op_ldu_T0_A0[3 * 3] = { |
587 | - gen_op_ldub_T0_A0, | |
588 | - gen_op_lduw_T0_A0, | |
588 | + gen_op_ldub_raw_T0_A0, | |
589 | + gen_op_lduw_raw_T0_A0, | |
589 | 590 | NULL, |
590 | 591 | |
592 | +#ifndef CONFIG_USER_ONLY | |
591 | 593 | gen_op_ldub_kernel_T0_A0, |
592 | 594 | gen_op_lduw_kernel_T0_A0, |
593 | 595 | NULL, |
... | ... | @@ -595,14 +597,16 @@ static GenOpFunc *gen_op_ldu_T0_A0[3 * 3] = { |
595 | 597 | gen_op_ldub_user_T0_A0, |
596 | 598 | gen_op_lduw_user_T0_A0, |
597 | 599 | NULL, |
600 | +#endif | |
598 | 601 | }; |
599 | 602 | |
600 | 603 | /* sign does not matter, except for lidt/lgdt call (TODO: fix it) */ |
601 | 604 | static GenOpFunc *gen_op_ld_T0_A0[3 * 3] = { |
602 | - gen_op_ldub_T0_A0, | |
603 | - gen_op_lduw_T0_A0, | |
604 | - gen_op_ldl_T0_A0, | |
605 | + gen_op_ldub_raw_T0_A0, | |
606 | + gen_op_lduw_raw_T0_A0, | |
607 | + gen_op_ldl_raw_T0_A0, | |
605 | 608 | |
609 | +#ifndef CONFIG_USER_ONLY | |
606 | 610 | gen_op_ldub_kernel_T0_A0, |
607 | 611 | gen_op_lduw_kernel_T0_A0, |
608 | 612 | gen_op_ldl_kernel_T0_A0, |
... | ... | @@ -610,13 +614,15 @@ static GenOpFunc *gen_op_ld_T0_A0[3 * 3] = { |
610 | 614 | gen_op_ldub_user_T0_A0, |
611 | 615 | gen_op_lduw_user_T0_A0, |
612 | 616 | gen_op_ldl_user_T0_A0, |
617 | +#endif | |
613 | 618 | }; |
614 | 619 | |
615 | 620 | static GenOpFunc *gen_op_ld_T1_A0[3 * 3] = { |
616 | - gen_op_ldub_T1_A0, | |
617 | - gen_op_lduw_T1_A0, | |
618 | - gen_op_ldl_T1_A0, | |
621 | + gen_op_ldub_raw_T1_A0, | |
622 | + gen_op_lduw_raw_T1_A0, | |
623 | + gen_op_ldl_raw_T1_A0, | |
619 | 624 | |
625 | +#ifndef CONFIG_USER_ONLY | |
620 | 626 | gen_op_ldub_kernel_T1_A0, |
621 | 627 | gen_op_lduw_kernel_T1_A0, |
622 | 628 | gen_op_ldl_kernel_T1_A0, |
... | ... | @@ -624,13 +630,15 @@ static GenOpFunc *gen_op_ld_T1_A0[3 * 3] = { |
624 | 630 | gen_op_ldub_user_T1_A0, |
625 | 631 | gen_op_lduw_user_T1_A0, |
626 | 632 | gen_op_ldl_user_T1_A0, |
633 | +#endif | |
627 | 634 | }; |
628 | 635 | |
629 | 636 | static GenOpFunc *gen_op_st_T0_A0[3 * 3] = { |
630 | - gen_op_stb_T0_A0, | |
631 | - gen_op_stw_T0_A0, | |
632 | - gen_op_stl_T0_A0, | |
637 | + gen_op_stb_raw_T0_A0, | |
638 | + gen_op_stw_raw_T0_A0, | |
639 | + gen_op_stl_raw_T0_A0, | |
633 | 640 | |
641 | +#ifndef CONFIG_USER_ONLY | |
634 | 642 | gen_op_stb_kernel_T0_A0, |
635 | 643 | gen_op_stw_kernel_T0_A0, |
636 | 644 | gen_op_stl_kernel_T0_A0, |
... | ... | @@ -638,6 +646,7 @@ static GenOpFunc *gen_op_st_T0_A0[3 * 3] = { |
638 | 646 | gen_op_stb_user_T0_A0, |
639 | 647 | gen_op_stw_user_T0_A0, |
640 | 648 | gen_op_stl_user_T0_A0, |
649 | +#endif | |
641 | 650 | }; |
642 | 651 | |
643 | 652 | static inline void gen_string_movl_A0_ESI(DisasContext *s) |
... | ... | @@ -1176,7 +1185,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ |
1176 | 1185 | |
1177 | 1186 | if (base == 4) { |
1178 | 1187 | havesib = 1; |
1179 | - code = ldub(s->pc++); | |
1188 | + code = ldub_code(s->pc++); | |
1180 | 1189 | scale = (code >> 6) & 3; |
1181 | 1190 | index = (code >> 3) & 7; |
1182 | 1191 | base = code & 7; |
... | ... | @@ -1186,18 +1195,18 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ |
1186 | 1195 | case 0: |
1187 | 1196 | if (base == 5) { |
1188 | 1197 | base = -1; |
1189 | - disp = ldl(s->pc); | |
1198 | + disp = ldl_code(s->pc); | |
1190 | 1199 | s->pc += 4; |
1191 | 1200 | } else { |
1192 | 1201 | disp = 0; |
1193 | 1202 | } |
1194 | 1203 | break; |
1195 | 1204 | case 1: |
1196 | - disp = (int8_t)ldub(s->pc++); | |
1205 | + disp = (int8_t)ldub_code(s->pc++); | |
1197 | 1206 | break; |
1198 | 1207 | default: |
1199 | 1208 | case 2: |
1200 | - disp = ldl(s->pc); | |
1209 | + disp = ldl_code(s->pc); | |
1201 | 1210 | s->pc += 4; |
1202 | 1211 | break; |
1203 | 1212 | } |
... | ... | @@ -1229,7 +1238,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ |
1229 | 1238 | switch (mod) { |
1230 | 1239 | case 0: |
1231 | 1240 | if (rm == 6) { |
1232 | - disp = lduw(s->pc); | |
1241 | + disp = lduw_code(s->pc); | |
1233 | 1242 | s->pc += 2; |
1234 | 1243 | gen_op_movl_A0_im(disp); |
1235 | 1244 | rm = 0; /* avoid SS override */ |
... | ... | @@ -1239,11 +1248,11 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ |
1239 | 1248 | } |
1240 | 1249 | break; |
1241 | 1250 | case 1: |
1242 | - disp = (int8_t)ldub(s->pc++); | |
1251 | + disp = (int8_t)ldub_code(s->pc++); | |
1243 | 1252 | break; |
1244 | 1253 | default: |
1245 | 1254 | case 2: |
1246 | - disp = lduw(s->pc); | |
1255 | + disp = lduw_code(s->pc); | |
1247 | 1256 | s->pc += 2; |
1248 | 1257 | break; |
1249 | 1258 | } |
... | ... | @@ -1337,16 +1346,16 @@ static inline uint32_t insn_get(DisasContext *s, int ot) |
1337 | 1346 | |
1338 | 1347 | switch(ot) { |
1339 | 1348 | case OT_BYTE: |
1340 | - ret = ldub(s->pc); | |
1349 | + ret = ldub_code(s->pc); | |
1341 | 1350 | s->pc++; |
1342 | 1351 | break; |
1343 | 1352 | case OT_WORD: |
1344 | - ret = lduw(s->pc); | |
1353 | + ret = lduw_code(s->pc); | |
1345 | 1354 | s->pc += 2; |
1346 | 1355 | break; |
1347 | 1356 | default: |
1348 | 1357 | case OT_LONG: |
1349 | - ret = ldl(s->pc); | |
1358 | + ret = ldl_code(s->pc); | |
1350 | 1359 | s->pc += 4; |
1351 | 1360 | break; |
1352 | 1361 | } |
... | ... | @@ -1756,7 +1765,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
1756 | 1765 | dflag = s->code32; |
1757 | 1766 | s->override = -1; |
1758 | 1767 | next_byte: |
1759 | - b = ldub(s->pc); | |
1768 | + b = ldub_code(s->pc); | |
1760 | 1769 | s->pc++; |
1761 | 1770 | /* check prefixes */ |
1762 | 1771 | switch (b) { |
... | ... | @@ -1814,7 +1823,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
1814 | 1823 | case 0x0f: |
1815 | 1824 | /**************************/ |
1816 | 1825 | /* extended op code */ |
1817 | - b = ldub(s->pc++) | 0x100; | |
1826 | + b = ldub_code(s->pc++) | 0x100; | |
1818 | 1827 | goto reswitch; |
1819 | 1828 | |
1820 | 1829 | /**************************/ |
... | ... | @@ -1839,7 +1848,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
1839 | 1848 | |
1840 | 1849 | switch(f) { |
1841 | 1850 | case 0: /* OP Ev, Gv */ |
1842 | - modrm = ldub(s->pc++); | |
1851 | + modrm = ldub_code(s->pc++); | |
1843 | 1852 | reg = ((modrm >> 3) & 7); |
1844 | 1853 | mod = (modrm >> 6) & 3; |
1845 | 1854 | rm = modrm & 7; |
... | ... | @@ -1861,7 +1870,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
1861 | 1870 | gen_op(s, op, ot, opreg); |
1862 | 1871 | break; |
1863 | 1872 | case 1: /* OP Gv, Ev */ |
1864 | - modrm = ldub(s->pc++); | |
1873 | + modrm = ldub_code(s->pc++); | |
1865 | 1874 | mod = (modrm >> 6) & 3; |
1866 | 1875 | reg = ((modrm >> 3) & 7); |
1867 | 1876 | rm = modrm & 7; |
... | ... | @@ -1895,7 +1904,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
1895 | 1904 | else |
1896 | 1905 | ot = dflag ? OT_LONG : OT_WORD; |
1897 | 1906 | |
1898 | - modrm = ldub(s->pc++); | |
1907 | + modrm = ldub_code(s->pc++); | |
1899 | 1908 | mod = (modrm >> 6) & 3; |
1900 | 1909 | rm = modrm & 7; |
1901 | 1910 | op = (modrm >> 3) & 7; |
... | ... | @@ -1939,7 +1948,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
1939 | 1948 | else |
1940 | 1949 | ot = dflag ? OT_LONG : OT_WORD; |
1941 | 1950 | |
1942 | - modrm = ldub(s->pc++); | |
1951 | + modrm = ldub_code(s->pc++); | |
1943 | 1952 | mod = (modrm >> 6) & 3; |
1944 | 1953 | rm = modrm & 7; |
1945 | 1954 | op = (modrm >> 3) & 7; |
... | ... | @@ -2045,7 +2054,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2045 | 2054 | else |
2046 | 2055 | ot = dflag ? OT_LONG : OT_WORD; |
2047 | 2056 | |
2048 | - modrm = ldub(s->pc++); | |
2057 | + modrm = ldub_code(s->pc++); | |
2049 | 2058 | mod = (modrm >> 6) & 3; |
2050 | 2059 | rm = modrm & 7; |
2051 | 2060 | op = (modrm >> 3) & 7; |
... | ... | @@ -2085,10 +2094,10 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2085 | 2094 | gen_push_T0(s); |
2086 | 2095 | gen_eob(s); |
2087 | 2096 | break; |
2088 | - case 3: /*< lcall Ev */ | |
2097 | + case 3: /* lcall Ev */ | |
2089 | 2098 | gen_op_ld_T1_A0[ot + s->mem_index](); |
2090 | 2099 | gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); |
2091 | - gen_op_ld_T0_A0[OT_WORD + s->mem_index](); | |
2100 | + gen_op_ldu_T0_A0[OT_WORD + s->mem_index](); | |
2092 | 2101 | do_lcall: |
2093 | 2102 | if (s->pe && !s->vm86) { |
2094 | 2103 | if (s->cc_op != CC_OP_DYNAMIC) |
... | ... | @@ -2109,7 +2118,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2109 | 2118 | case 5: /* ljmp Ev */ |
2110 | 2119 | gen_op_ld_T1_A0[ot + s->mem_index](); |
2111 | 2120 | gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); |
2112 | - gen_op_lduw_T0_A0(); | |
2121 | + gen_op_ldu_T0_A0[OT_WORD + s->mem_index](); | |
2113 | 2122 | do_ljmp: |
2114 | 2123 | if (s->pe && !s->vm86) { |
2115 | 2124 | if (s->cc_op != CC_OP_DYNAMIC) |
... | ... | @@ -2138,7 +2147,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2138 | 2147 | else |
2139 | 2148 | ot = dflag ? OT_LONG : OT_WORD; |
2140 | 2149 | |
2141 | - modrm = ldub(s->pc++); | |
2150 | + modrm = ldub_code(s->pc++); | |
2142 | 2151 | mod = (modrm >> 6) & 3; |
2143 | 2152 | rm = modrm & 7; |
2144 | 2153 | reg = (modrm >> 3) & 7; |
... | ... | @@ -2179,7 +2188,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2179 | 2188 | case 0x69: /* imul Gv, Ev, I */ |
2180 | 2189 | case 0x6b: |
2181 | 2190 | ot = dflag ? OT_LONG : OT_WORD; |
2182 | - modrm = ldub(s->pc++); | |
2191 | + modrm = ldub_code(s->pc++); | |
2183 | 2192 | reg = ((modrm >> 3) & 7) + OR_EAX; |
2184 | 2193 | gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
2185 | 2194 | if (b == 0x69) { |
... | ... | @@ -2206,7 +2215,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2206 | 2215 | ot = OT_BYTE; |
2207 | 2216 | else |
2208 | 2217 | ot = dflag ? OT_LONG : OT_WORD; |
2209 | - modrm = ldub(s->pc++); | |
2218 | + modrm = ldub_code(s->pc++); | |
2210 | 2219 | reg = (modrm >> 3) & 7; |
2211 | 2220 | mod = (modrm >> 6) & 3; |
2212 | 2221 | if (mod == 3) { |
... | ... | @@ -2233,7 +2242,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2233 | 2242 | ot = OT_BYTE; |
2234 | 2243 | else |
2235 | 2244 | ot = dflag ? OT_LONG : OT_WORD; |
2236 | - modrm = ldub(s->pc++); | |
2245 | + modrm = ldub_code(s->pc++); | |
2237 | 2246 | reg = (modrm >> 3) & 7; |
2238 | 2247 | mod = (modrm >> 6) & 3; |
2239 | 2248 | gen_op_mov_TN_reg[ot][1][reg](); |
... | ... | @@ -2250,7 +2259,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2250 | 2259 | s->cc_op = CC_OP_SUBB + ot; |
2251 | 2260 | break; |
2252 | 2261 | case 0x1c7: /* cmpxchg8b */ |
2253 | - modrm = ldub(s->pc++); | |
2262 | + modrm = ldub_code(s->pc++); | |
2254 | 2263 | mod = (modrm >> 6) & 3; |
2255 | 2264 | if (mod == 3) |
2256 | 2265 | goto illegal_op; |
... | ... | @@ -2291,7 +2300,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2291 | 2300 | break; |
2292 | 2301 | case 0x8f: /* pop Ev */ |
2293 | 2302 | ot = dflag ? OT_LONG : OT_WORD; |
2294 | - modrm = ldub(s->pc++); | |
2303 | + modrm = ldub_code(s->pc++); | |
2295 | 2304 | gen_pop_T0(s); |
2296 | 2305 | s->popl_esp_hack = 2 << dflag; |
2297 | 2306 | gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); |
... | ... | @@ -2301,9 +2310,9 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2301 | 2310 | case 0xc8: /* enter */ |
2302 | 2311 | { |
2303 | 2312 | int level; |
2304 | - val = lduw(s->pc); | |
2313 | + val = lduw_code(s->pc); | |
2305 | 2314 | s->pc += 2; |
2306 | - level = ldub(s->pc++); | |
2315 | + level = ldub_code(s->pc++); | |
2307 | 2316 | gen_enter(s, val, level); |
2308 | 2317 | } |
2309 | 2318 | break; |
... | ... | @@ -2369,7 +2378,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2369 | 2378 | ot = OT_BYTE; |
2370 | 2379 | else |
2371 | 2380 | ot = dflag ? OT_LONG : OT_WORD; |
2372 | - modrm = ldub(s->pc++); | |
2381 | + modrm = ldub_code(s->pc++); | |
2373 | 2382 | reg = (modrm >> 3) & 7; |
2374 | 2383 | |
2375 | 2384 | /* generate a generic store */ |
... | ... | @@ -2381,7 +2390,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2381 | 2390 | ot = OT_BYTE; |
2382 | 2391 | else |
2383 | 2392 | ot = dflag ? OT_LONG : OT_WORD; |
2384 | - modrm = ldub(s->pc++); | |
2393 | + modrm = ldub_code(s->pc++); | |
2385 | 2394 | mod = (modrm >> 6) & 3; |
2386 | 2395 | if (mod != 3) |
2387 | 2396 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
... | ... | @@ -2398,14 +2407,14 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2398 | 2407 | ot = OT_BYTE; |
2399 | 2408 | else |
2400 | 2409 | ot = dflag ? OT_LONG : OT_WORD; |
2401 | - modrm = ldub(s->pc++); | |
2410 | + modrm = ldub_code(s->pc++); | |
2402 | 2411 | reg = (modrm >> 3) & 7; |
2403 | 2412 | |
2404 | 2413 | gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
2405 | 2414 | gen_op_mov_reg_T0[ot][reg](); |
2406 | 2415 | break; |
2407 | 2416 | case 0x8e: /* mov seg, Gv */ |
2408 | - modrm = ldub(s->pc++); | |
2417 | + modrm = ldub_code(s->pc++); | |
2409 | 2418 | reg = (modrm >> 3) & 7; |
2410 | 2419 | if (reg >= 6 || reg == R_CS) |
2411 | 2420 | goto illegal_op; |
... | ... | @@ -2422,7 +2431,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2422 | 2431 | } |
2423 | 2432 | break; |
2424 | 2433 | case 0x8c: /* mov Gv, seg */ |
2425 | - modrm = ldub(s->pc++); | |
2434 | + modrm = ldub_code(s->pc++); | |
2426 | 2435 | reg = (modrm >> 3) & 7; |
2427 | 2436 | mod = (modrm >> 6) & 3; |
2428 | 2437 | if (reg >= 6) |
... | ... | @@ -2444,7 +2453,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2444 | 2453 | d_ot = dflag + OT_WORD; |
2445 | 2454 | /* ot is the size of source */ |
2446 | 2455 | ot = (b & 1) + OT_BYTE; |
2447 | - modrm = ldub(s->pc++); | |
2456 | + modrm = ldub_code(s->pc++); | |
2448 | 2457 | reg = ((modrm >> 3) & 7) + OR_EAX; |
2449 | 2458 | mod = (modrm >> 6) & 3; |
2450 | 2459 | rm = modrm & 7; |
... | ... | @@ -2481,7 +2490,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2481 | 2490 | |
2482 | 2491 | case 0x8d: /* lea */ |
2483 | 2492 | ot = dflag ? OT_LONG : OT_WORD; |
2484 | - modrm = ldub(s->pc++); | |
2493 | + modrm = ldub_code(s->pc++); | |
2485 | 2494 | reg = (modrm >> 3) & 7; |
2486 | 2495 | /* we must ensure that no segment is added */ |
2487 | 2496 | s->override = -1; |
... | ... | @@ -2574,7 +2583,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2574 | 2583 | ot = OT_BYTE; |
2575 | 2584 | else |
2576 | 2585 | ot = dflag ? OT_LONG : OT_WORD; |
2577 | - modrm = ldub(s->pc++); | |
2586 | + modrm = ldub_code(s->pc++); | |
2578 | 2587 | reg = (modrm >> 3) & 7; |
2579 | 2588 | mod = (modrm >> 6) & 3; |
2580 | 2589 | if (mod == 3) { |
... | ... | @@ -2613,7 +2622,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2613 | 2622 | op = R_GS; |
2614 | 2623 | do_lxx: |
2615 | 2624 | ot = dflag ? OT_LONG : OT_WORD; |
2616 | - modrm = ldub(s->pc++); | |
2625 | + modrm = ldub_code(s->pc++); | |
2617 | 2626 | reg = (modrm >> 3) & 7; |
2618 | 2627 | mod = (modrm >> 6) & 3; |
2619 | 2628 | if (mod == 3) |
... | ... | @@ -2622,7 +2631,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2622 | 2631 | gen_op_ld_T1_A0[ot + s->mem_index](); |
2623 | 2632 | gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); |
2624 | 2633 | /* load the segment first to handle exceptions properly */ |
2625 | - gen_op_lduw_T0_A0(); | |
2634 | + gen_op_ldu_T0_A0[OT_WORD + s->mem_index](); | |
2626 | 2635 | gen_movl_seg_T0(s, op, pc_start - s->cs_base); |
2627 | 2636 | /* then put the data */ |
2628 | 2637 | gen_op_mov_reg_T1[ot][reg](); |
... | ... | @@ -2645,7 +2654,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2645 | 2654 | else |
2646 | 2655 | ot = dflag ? OT_LONG : OT_WORD; |
2647 | 2656 | |
2648 | - modrm = ldub(s->pc++); | |
2657 | + modrm = ldub_code(s->pc++); | |
2649 | 2658 | mod = (modrm >> 6) & 3; |
2650 | 2659 | rm = modrm & 7; |
2651 | 2660 | op = (modrm >> 3) & 7; |
... | ... | @@ -2662,7 +2671,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2662 | 2671 | gen_shift(s, op, ot, opreg, OR_ECX); |
2663 | 2672 | } else { |
2664 | 2673 | if (shift == 2) { |
2665 | - shift = ldub(s->pc++); | |
2674 | + shift = ldub_code(s->pc++); | |
2666 | 2675 | } |
2667 | 2676 | gen_shifti(s, op, ot, opreg, shift); |
2668 | 2677 | } |
... | ... | @@ -2696,7 +2705,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2696 | 2705 | shift = 0; |
2697 | 2706 | do_shiftd: |
2698 | 2707 | ot = dflag ? OT_LONG : OT_WORD; |
2699 | - modrm = ldub(s->pc++); | |
2708 | + modrm = ldub_code(s->pc++); | |
2700 | 2709 | mod = (modrm >> 6) & 3; |
2701 | 2710 | rm = modrm & 7; |
2702 | 2711 | reg = (modrm >> 3) & 7; |
... | ... | @@ -2710,7 +2719,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2710 | 2719 | gen_op_mov_TN_reg[ot][1][reg](); |
2711 | 2720 | |
2712 | 2721 | if (shift) { |
2713 | - val = ldub(s->pc++); | |
2722 | + val = ldub_code(s->pc++); | |
2714 | 2723 | val &= 0x1f; |
2715 | 2724 | if (val) { |
2716 | 2725 | if (mod == 3) |
... | ... | @@ -2739,7 +2748,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2739 | 2748 | /************************/ |
2740 | 2749 | /* floats */ |
2741 | 2750 | case 0xd8 ... 0xdf: |
2742 | - modrm = ldub(s->pc++); | |
2751 | + modrm = ldub_code(s->pc++); | |
2743 | 2752 | mod = (modrm >> 6) & 3; |
2744 | 2753 | rm = modrm & 7; |
2745 | 2754 | op = ((b & 7) << 3) | ((modrm >> 3) & 7); |
... | ... | @@ -3256,7 +3265,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
3256 | 3265 | ot = OT_BYTE; |
3257 | 3266 | else |
3258 | 3267 | ot = dflag ? OT_LONG : OT_WORD; |
3259 | - val = ldub(s->pc++); | |
3268 | + val = ldub_code(s->pc++); | |
3260 | 3269 | gen_op_movl_T0_im(val); |
3261 | 3270 | gen_op_in[ot](); |
3262 | 3271 | gen_op_mov_reg_T1[ot][R_EAX](); |
... | ... | @@ -3271,7 +3280,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
3271 | 3280 | ot = OT_BYTE; |
3272 | 3281 | else |
3273 | 3282 | ot = dflag ? OT_LONG : OT_WORD; |
3274 | - val = ldub(s->pc++); | |
3283 | + val = ldub_code(s->pc++); | |
3275 | 3284 | gen_op_movl_T0_im(val); |
3276 | 3285 | gen_op_mov_TN_reg[ot][1][R_EAX](); |
3277 | 3286 | gen_op_out[ot](); |
... | ... | @@ -3309,7 +3318,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
3309 | 3318 | /************************/ |
3310 | 3319 | /* control */ |
3311 | 3320 | case 0xc2: /* ret im */ |
3312 | - val = ldsw(s->pc); | |
3321 | + val = ldsw_code(s->pc); | |
3313 | 3322 | s->pc += 2; |
3314 | 3323 | gen_pop_T0(s); |
3315 | 3324 | gen_stack_update(s, val + (2 << s->dflag)); |
... | ... | @@ -3327,7 +3336,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
3327 | 3336 | gen_eob(s); |
3328 | 3337 | break; |
3329 | 3338 | case 0xca: /* lret im */ |
3330 | - val = ldsw(s->pc); | |
3339 | + val = ldsw_code(s->pc); | |
3331 | 3340 | s->pc += 2; |
3332 | 3341 | do_lret: |
3333 | 3342 | if (s->pe && !s->vm86) { |
... | ... | @@ -3443,13 +3452,13 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
3443 | 3452 | break; |
3444 | 3453 | |
3445 | 3454 | case 0x190 ... 0x19f: /* setcc Gv */ |
3446 | - modrm = ldub(s->pc++); | |
3455 | + modrm = ldub_code(s->pc++); | |
3447 | 3456 | gen_setcc(s, b); |
3448 | 3457 | gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1); |
3449 | 3458 | break; |
3450 | 3459 | case 0x140 ... 0x14f: /* cmov Gv, Ev */ |
3451 | 3460 | ot = dflag ? OT_LONG : OT_WORD; |
3452 | - modrm = ldub(s->pc++); | |
3461 | + modrm = ldub_code(s->pc++); | |
3453 | 3462 | reg = (modrm >> 3) & 7; |
3454 | 3463 | mod = (modrm >> 6) & 3; |
3455 | 3464 | gen_setcc(s, b); |
... | ... | @@ -3542,7 +3551,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
3542 | 3551 | /* bit operations */ |
3543 | 3552 | case 0x1ba: /* bt/bts/btr/btc Gv, im */ |
3544 | 3553 | ot = dflag ? OT_LONG : OT_WORD; |
3545 | - modrm = ldub(s->pc++); | |
3554 | + modrm = ldub_code(s->pc++); | |
3546 | 3555 | op = (modrm >> 3) & 7; |
3547 | 3556 | mod = (modrm >> 6) & 3; |
3548 | 3557 | rm = modrm & 7; |
... | ... | @@ -3553,7 +3562,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
3553 | 3562 | gen_op_mov_TN_reg[ot][0][rm](); |
3554 | 3563 | } |
3555 | 3564 | /* load shift */ |
3556 | - val = ldub(s->pc++); | |
3565 | + val = ldub_code(s->pc++); | |
3557 | 3566 | gen_op_movl_T1_im(val); |
3558 | 3567 | if (op < 4) |
3559 | 3568 | goto illegal_op; |
... | ... | @@ -3581,7 +3590,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
3581 | 3590 | op = 3; |
3582 | 3591 | do_btx: |
3583 | 3592 | ot = dflag ? OT_LONG : OT_WORD; |
3584 | - modrm = ldub(s->pc++); | |
3593 | + modrm = ldub_code(s->pc++); | |
3585 | 3594 | reg = (modrm >> 3) & 7; |
3586 | 3595 | mod = (modrm >> 6) & 3; |
3587 | 3596 | rm = modrm & 7; |
... | ... | @@ -3610,7 +3619,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
3610 | 3619 | case 0x1bc: /* bsf */ |
3611 | 3620 | case 0x1bd: /* bsr */ |
3612 | 3621 | ot = dflag ? OT_LONG : OT_WORD; |
3613 | - modrm = ldub(s->pc++); | |
3622 | + modrm = ldub_code(s->pc++); | |
3614 | 3623 | reg = (modrm >> 3) & 7; |
3615 | 3624 | gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
3616 | 3625 | gen_op_bsx_T0_cc[ot - OT_WORD][b & 1](); |
... | ... | @@ -3646,12 +3655,12 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
3646 | 3655 | s->cc_op = CC_OP_EFLAGS; |
3647 | 3656 | break; |
3648 | 3657 | case 0xd4: /* aam */ |
3649 | - val = ldub(s->pc++); | |
3658 | + val = ldub_code(s->pc++); | |
3650 | 3659 | gen_op_aam(val); |
3651 | 3660 | s->cc_op = CC_OP_LOGICB; |
3652 | 3661 | break; |
3653 | 3662 | case 0xd5: /* aad */ |
3654 | - val = ldub(s->pc++); | |
3663 | + val = ldub_code(s->pc++); | |
3655 | 3664 | gen_op_aad(val); |
3656 | 3665 | s->cc_op = CC_OP_LOGICB; |
3657 | 3666 | break; |
... | ... | @@ -3665,7 +3674,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
3665 | 3674 | gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base); |
3666 | 3675 | break; |
3667 | 3676 | case 0xcd: /* int N */ |
3668 | - val = ldub(s->pc++); | |
3677 | + val = ldub_code(s->pc++); | |
3669 | 3678 | /* XXX: add error code for vm86 GPF */ |
3670 | 3679 | if (!s->vm86) |
3671 | 3680 | gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base); |
... | ... | @@ -3718,7 +3727,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
3718 | 3727 | break; |
3719 | 3728 | case 0x62: /* bound */ |
3720 | 3729 | ot = dflag ? OT_LONG : OT_WORD; |
3721 | - modrm = ldub(s->pc++); | |
3730 | + modrm = ldub_code(s->pc++); | |
3722 | 3731 | reg = (modrm >> 3) & 7; |
3723 | 3732 | mod = (modrm >> 6) & 3; |
3724 | 3733 | if (mod == 3) |
... | ... | @@ -3785,7 +3794,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
3785 | 3794 | } |
3786 | 3795 | break; |
3787 | 3796 | case 0x100: |
3788 | - modrm = ldub(s->pc++); | |
3797 | + modrm = ldub_code(s->pc++); | |
3789 | 3798 | mod = (modrm >> 6) & 3; |
3790 | 3799 | op = (modrm >> 3) & 7; |
3791 | 3800 | switch(op) { |
... | ... | @@ -3828,7 +3837,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
3828 | 3837 | } |
3829 | 3838 | break; |
3830 | 3839 | case 0x101: |
3831 | - modrm = ldub(s->pc++); | |
3840 | + modrm = ldub_code(s->pc++); | |
3832 | 3841 | mod = (modrm >> 6) & 3; |
3833 | 3842 | op = (modrm >> 3) & 7; |
3834 | 3843 | switch(op) { |
... | ... | @@ -3904,7 +3913,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
3904 | 3913 | if (!s->pe || s->vm86) |
3905 | 3914 | goto illegal_op; |
3906 | 3915 | ot = dflag ? OT_LONG : OT_WORD; |
3907 | - modrm = ldub(s->pc++); | |
3916 | + modrm = ldub_code(s->pc++); | |
3908 | 3917 | reg = (modrm >> 3) & 7; |
3909 | 3918 | gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
3910 | 3919 | gen_op_mov_TN_reg[ot][1][reg](); |
... | ... | @@ -3918,7 +3927,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
3918 | 3927 | gen_op_mov_reg_T1[ot][reg](); |
3919 | 3928 | break; |
3920 | 3929 | case 0x118: |
3921 | - modrm = ldub(s->pc++); | |
3930 | + modrm = ldub_code(s->pc++); | |
3922 | 3931 | mod = (modrm >> 6) & 3; |
3923 | 3932 | op = (modrm >> 3) & 7; |
3924 | 3933 | switch(op) { |
... | ... | @@ -3940,7 +3949,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
3940 | 3949 | if (s->cpl != 0) { |
3941 | 3950 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3942 | 3951 | } else { |
3943 | - modrm = ldub(s->pc++); | |
3952 | + modrm = ldub_code(s->pc++); | |
3944 | 3953 | if ((modrm & 0xc0) != 0xc0) |
3945 | 3954 | goto illegal_op; |
3946 | 3955 | rm = modrm & 7; |
... | ... | @@ -3970,7 +3979,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
3970 | 3979 | if (s->cpl != 0) { |
3971 | 3980 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3972 | 3981 | } else { |
3973 | - modrm = ldub(s->pc++); | |
3982 | + modrm = ldub_code(s->pc++); | |
3974 | 3983 | if ((modrm & 0xc0) != 0xc0) |
3975 | 3984 | goto illegal_op; |
3976 | 3985 | rm = modrm & 7; | ... | ... |