]> Git Repo - qemu.git/blob - target-i386/helper.c
d08de8a8b4246dededf485f9841747f57a2f5976
[qemu.git] / target-i386 / helper.c
1 /*
2  *  i386 helpers
3  * 
4  *  Copyright (c) 2003 Fabrice Bellard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include "exec.h"
21
22 //#define DEBUG_PCALL
23
24 #if 0
25 #define raise_exception_err(a, b)\
26 do {\
27     printf("raise_exception line=%d\n", __LINE__);\
28     (raise_exception_err)(a, b);\
29 } while (0)
30 #endif
31
32 const uint8_t parity_table[256] = {
33     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
34     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
35     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
36     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
37     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
38     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
39     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
40     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
41     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
42     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
43     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
44     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
45     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
46     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
47     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
48     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
49     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
50     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
51     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
52     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
53     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
54     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
55     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
56     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
57     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
58     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
59     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
60     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
61     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
62     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
63     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
64     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
65 };
66
67 /* modulo 17 table */
68 const uint8_t rclw_table[32] = {
69     0, 1, 2, 3, 4, 5, 6, 7, 
70     8, 9,10,11,12,13,14,15,
71    16, 0, 1, 2, 3, 4, 5, 6,
72     7, 8, 9,10,11,12,13,14,
73 };
74
75 /* modulo 9 table */
76 const uint8_t rclb_table[32] = {
77     0, 1, 2, 3, 4, 5, 6, 7, 
78     8, 0, 1, 2, 3, 4, 5, 6,
79     7, 8, 0, 1, 2, 3, 4, 5, 
80     6, 7, 8, 0, 1, 2, 3, 4,
81 };
82
83 const CPU86_LDouble f15rk[7] =
84 {
85     0.00000000000000000000L,
86     1.00000000000000000000L,
87     3.14159265358979323851L,  /*pi*/
88     0.30102999566398119523L,  /*lg2*/
89     0.69314718055994530943L,  /*ln2*/
90     1.44269504088896340739L,  /*l2e*/
91     3.32192809488736234781L,  /*l2t*/
92 };
93     
94 /* thread support */
95
96 spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
97
98 void cpu_lock(void)
99 {
100     spin_lock(&global_cpu_lock);
101 }
102
103 void cpu_unlock(void)
104 {
105     spin_unlock(&global_cpu_lock);
106 }
107
108 void cpu_loop_exit(void)
109 {
110     /* NOTE: the register at this point must be saved by hand because
111        longjmp restore them */
112 #ifdef reg_EAX
113     env->regs[R_EAX] = EAX;
114 #endif
115 #ifdef reg_ECX
116     env->regs[R_ECX] = ECX;
117 #endif
118 #ifdef reg_EDX
119     env->regs[R_EDX] = EDX;
120 #endif
121 #ifdef reg_EBX
122     env->regs[R_EBX] = EBX;
123 #endif
124 #ifdef reg_ESP
125     env->regs[R_ESP] = ESP;
126 #endif
127 #ifdef reg_EBP
128     env->regs[R_EBP] = EBP;
129 #endif
130 #ifdef reg_ESI
131     env->regs[R_ESI] = ESI;
132 #endif
133 #ifdef reg_EDI
134     env->regs[R_EDI] = EDI;
135 #endif
136     longjmp(env->jmp_env, 1);
137 }
138
139 /* return non zero if error */
140 static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr,
141                                int selector)
142 {
143     SegmentCache *dt;
144     int index;
145     uint8_t *ptr;
146
147     if (selector & 0x4)
148         dt = &env->ldt;
149     else
150         dt = &env->gdt;
151     index = selector & ~7;
152     if ((index + 7) > dt->limit)
153         return -1;
154     ptr = dt->base + index;
155     *e1_ptr = ldl_kernel(ptr);
156     *e2_ptr = ldl_kernel(ptr + 4);
157     return 0;
158 }
159                                      
160 static inline unsigned int get_seg_limit(uint32_t e1, uint32_t e2)
161 {
162     unsigned int limit;
163     limit = (e1 & 0xffff) | (e2 & 0x000f0000);
164     if (e2 & DESC_G_MASK)
165         limit = (limit << 12) | 0xfff;
166     return limit;
167 }
168
169 static inline uint8_t *get_seg_base(uint32_t e1, uint32_t e2)
170 {
171     return (uint8_t *)((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
172 }
173
174 static inline void load_seg_cache_raw_dt(SegmentCache *sc, uint32_t e1, uint32_t e2)
175 {
176     sc->base = get_seg_base(e1, e2);
177     sc->limit = get_seg_limit(e1, e2);
178     sc->flags = e2;
179 }
180
181 /* init the segment cache in vm86 mode. */
182 static inline void load_seg_vm(int seg, int selector)
183 {
184     selector &= 0xffff;
185     cpu_x86_load_seg_cache(env, seg, selector, 
186                            (uint8_t *)(selector << 4), 0xffff, 0);
187 }
188
189 static inline void get_ss_esp_from_tss(uint32_t *ss_ptr, 
190                                        uint32_t *esp_ptr, int dpl)
191 {
192     int type, index, shift;
193     
194 #if 0
195     {
196         int i;
197         printf("TR: base=%p limit=%x\n", env->tr.base, env->tr.limit);
198         for(i=0;i<env->tr.limit;i++) {
199             printf("%02x ", env->tr.base[i]);
200             if ((i & 7) == 7) printf("\n");
201         }
202         printf("\n");
203     }
204 #endif
205
206     if (!(env->tr.flags & DESC_P_MASK))
207         cpu_abort(env, "invalid tss");
208     type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
209     if ((type & 7) != 1)
210         cpu_abort(env, "invalid tss type");
211     shift = type >> 3;
212     index = (dpl * 4 + 2) << shift;
213     if (index + (4 << shift) - 1 > env->tr.limit)
214         raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
215     if (shift == 0) {
216         *esp_ptr = lduw_kernel(env->tr.base + index);
217         *ss_ptr = lduw_kernel(env->tr.base + index + 2);
218     } else {
219         *esp_ptr = ldl_kernel(env->tr.base + index);
220         *ss_ptr = lduw_kernel(env->tr.base + index + 4);
221     }
222 }
223
224 /* XXX: merge with load_seg() */
225 static void tss_load_seg(int seg_reg, int selector)
226 {
227     uint32_t e1, e2;
228     int rpl, dpl, cpl;
229
230     if ((selector & 0xfffc) != 0) {
231         if (load_segment(&e1, &e2, selector) != 0)
232             raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
233         if (!(e2 & DESC_S_MASK))
234             raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
235         rpl = selector & 3;
236         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
237         cpl = env->hflags & HF_CPL_MASK;
238         if (seg_reg == R_CS) {
239             if (!(e2 & DESC_CS_MASK))
240                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
241             if (dpl != rpl)
242                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
243             if ((e2 & DESC_C_MASK) && dpl > rpl)
244                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
245                 
246         } else if (seg_reg == R_SS) {
247             /* SS must be writable data */
248             if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
249                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
250             if (dpl != cpl || dpl != rpl)
251                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
252         } else {
253             /* not readable code */
254             if ((e2 & DESC_CS_MASK) && !(e2 & DESC_R_MASK))
255                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
256             /* if data or non conforming code, checks the rights */
257             if (((e2 >> DESC_TYPE_SHIFT) & 0xf) < 12) {
258                 if (dpl < cpl || dpl < rpl)
259                     raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
260             }
261         }
262         if (!(e2 & DESC_P_MASK))
263             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
264         cpu_x86_load_seg_cache(env, seg_reg, selector, 
265                        get_seg_base(e1, e2),
266                        get_seg_limit(e1, e2),
267                        e2);
268     } else {
269         if (seg_reg == R_SS || seg_reg == R_CS) 
270             raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
271     }
272 }
273
274 #define SWITCH_TSS_JMP  0
275 #define SWITCH_TSS_IRET 1
276 #define SWITCH_TSS_CALL 2
277
278 /* XXX: restore CPU state in registers (PowerPC case) */
279 static void switch_tss(int tss_selector, 
280                        uint32_t e1, uint32_t e2, int source)
281 {
282     int tss_limit, tss_limit_max, type, old_tss_limit_max, old_type, v1, v2, i;
283     uint8_t *tss_base;
284     uint32_t new_regs[8], new_segs[6];
285     uint32_t new_eflags, new_eip, new_cr3, new_ldt, new_trap;
286     uint32_t old_eflags, eflags_mask;
287     SegmentCache *dt;
288     int index;
289     uint8_t *ptr;
290
291     type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
292 #ifdef DEBUG_PCALL
293     if (loglevel & CPU_LOG_PCALL)
294         fprintf(logfile, "switch_tss: sel=0x%04x type=%d src=%d\n", tss_selector, type, source);
295 #endif
296
297     /* if task gate, we read the TSS segment and we load it */
298     if (type == 5) {
299         if (!(e2 & DESC_P_MASK))
300             raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
301         tss_selector = e1 >> 16;
302         if (tss_selector & 4)
303             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
304         if (load_segment(&e1, &e2, tss_selector) != 0)
305             raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
306         if (e2 & DESC_S_MASK)
307             raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
308         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
309         if ((type & 7) != 1)
310             raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
311     }
312
313     if (!(e2 & DESC_P_MASK))
314         raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
315
316     if (type & 8)
317         tss_limit_max = 103;
318     else
319         tss_limit_max = 43;
320     tss_limit = get_seg_limit(e1, e2);
321     tss_base = get_seg_base(e1, e2);
322     if ((tss_selector & 4) != 0 || 
323         tss_limit < tss_limit_max)
324         raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
325     old_type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
326     if (old_type & 8)
327         old_tss_limit_max = 103;
328     else
329         old_tss_limit_max = 43;
330
331     /* read all the registers from the new TSS */
332     if (type & 8) {
333         /* 32 bit */
334         new_cr3 = ldl_kernel(tss_base + 0x1c);
335         new_eip = ldl_kernel(tss_base + 0x20);
336         new_eflags = ldl_kernel(tss_base + 0x24);
337         for(i = 0; i < 8; i++)
338             new_regs[i] = ldl_kernel(tss_base + (0x28 + i * 4));
339         for(i = 0; i < 6; i++)
340             new_segs[i] = lduw_kernel(tss_base + (0x48 + i * 4));
341         new_ldt = lduw_kernel(tss_base + 0x60);
342         new_trap = ldl_kernel(tss_base + 0x64);
343     } else {
344         /* 16 bit */
345         new_cr3 = 0;
346         new_eip = lduw_kernel(tss_base + 0x0e);
347         new_eflags = lduw_kernel(tss_base + 0x10);
348         for(i = 0; i < 8; i++)
349             new_regs[i] = lduw_kernel(tss_base + (0x12 + i * 2)) | 0xffff0000;
350         for(i = 0; i < 4; i++)
351             new_segs[i] = lduw_kernel(tss_base + (0x22 + i * 4));
352         new_ldt = lduw_kernel(tss_base + 0x2a);
353         new_segs[R_FS] = 0;
354         new_segs[R_GS] = 0;
355         new_trap = 0;
356     }
357     
358     /* NOTE: we must avoid memory exceptions during the task switch,
359        so we make dummy accesses before */
360     /* XXX: it can still fail in some cases, so a bigger hack is
361        necessary to valid the TLB after having done the accesses */
362
363     v1 = ldub_kernel(env->tr.base);
364     v2 = ldub(env->tr.base + old_tss_limit_max);
365     stb_kernel(env->tr.base, v1);
366     stb_kernel(env->tr.base + old_tss_limit_max, v2);
367     
368     /* clear busy bit (it is restartable) */
369     if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_IRET) {
370         uint8_t *ptr;
371         uint32_t e2;
372         ptr = env->gdt.base + (env->tr.selector << 3);
373         e2 = ldl_kernel(ptr + 4);
374         e2 &= ~DESC_TSS_BUSY_MASK;
375         stl_kernel(ptr + 4, e2);
376     }
377     old_eflags = compute_eflags();
378     if (source == SWITCH_TSS_IRET)
379         old_eflags &= ~NT_MASK;
380     
381     /* save the current state in the old TSS */
382     if (type & 8) {
383         /* 32 bit */
384         stl_kernel(env->tr.base + 0x20, env->eip);
385         stl_kernel(env->tr.base + 0x24, old_eflags);
386         for(i = 0; i < 8; i++)
387             stl_kernel(env->tr.base + (0x28 + i * 4), env->regs[i]);
388         for(i = 0; i < 6; i++)
389             stw_kernel(env->tr.base + (0x48 + i * 4), env->segs[i].selector);
390     } else {
391         /* 16 bit */
392         stw_kernel(env->tr.base + 0x0e, new_eip);
393         stw_kernel(env->tr.base + 0x10, old_eflags);
394         for(i = 0; i < 8; i++)
395             stw_kernel(env->tr.base + (0x12 + i * 2), env->regs[i]);
396         for(i = 0; i < 4; i++)
397             stw_kernel(env->tr.base + (0x22 + i * 4), env->segs[i].selector);
398     }
399     
400     /* now if an exception occurs, it will occurs in the next task
401        context */
402
403     if (source == SWITCH_TSS_CALL) {
404         stw_kernel(tss_base, env->tr.selector);
405         new_eflags |= NT_MASK;
406     }
407
408     /* set busy bit */
409     if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_CALL) {
410         uint8_t *ptr;
411         uint32_t e2;
412         ptr = env->gdt.base + (tss_selector << 3);
413         e2 = ldl_kernel(ptr + 4);
414         e2 |= DESC_TSS_BUSY_MASK;
415         stl_kernel(ptr + 4, e2);
416     }
417
418     /* set the new CPU state */
419     /* from this point, any exception which occurs can give problems */
420     env->cr[0] |= CR0_TS_MASK;
421     env->tr.selector = tss_selector;
422     env->tr.base = tss_base;
423     env->tr.limit = tss_limit;
424     env->tr.flags = e2 & ~DESC_TSS_BUSY_MASK;
425     
426     if ((type & 8) && (env->cr[0] & CR0_PG_MASK)) {
427         cpu_x86_update_cr3(env, new_cr3);
428     }
429     
430     /* load all registers without an exception, then reload them with
431        possible exception */
432     env->eip = new_eip;
433     eflags_mask = TF_MASK | AC_MASK | ID_MASK | 
434         IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK;
435     if (!(type & 8))
436         eflags_mask &= 0xffff;
437     load_eflags(new_eflags, eflags_mask);
438     for(i = 0; i < 8; i++)
439         env->regs[i] = new_regs[i];
440     if (new_eflags & VM_MASK) {
441         for(i = 0; i < 6; i++) 
442             load_seg_vm(i, new_segs[i]);
443         /* in vm86, CPL is always 3 */
444         cpu_x86_set_cpl(env, 3);
445     } else {
446         /* CPL is set the RPL of CS */
447         cpu_x86_set_cpl(env, new_segs[R_CS] & 3);
448         /* first just selectors as the rest may trigger exceptions */
449         for(i = 0; i < 6; i++)
450             cpu_x86_load_seg_cache(env, i, new_segs[i], NULL, 0, 0);
451     }
452     
453     env->ldt.selector = new_ldt & ~4;
454     env->ldt.base = NULL;
455     env->ldt.limit = 0;
456     env->ldt.flags = 0;
457
458     /* load the LDT */
459     if (new_ldt & 4)
460         raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
461
462     if ((new_ldt & 0xfffc) != 0) {
463         dt = &env->gdt;
464         index = new_ldt & ~7;
465         if ((index + 7) > dt->limit)
466             raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
467         ptr = dt->base + index;
468         e1 = ldl_kernel(ptr);
469         e2 = ldl_kernel(ptr + 4);
470         if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
471             raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
472         if (!(e2 & DESC_P_MASK))
473             raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
474         load_seg_cache_raw_dt(&env->ldt, e1, e2);
475     }
476     
477     /* load the segments */
478     if (!(new_eflags & VM_MASK)) {
479         tss_load_seg(R_CS, new_segs[R_CS]);
480         tss_load_seg(R_SS, new_segs[R_SS]);
481         tss_load_seg(R_ES, new_segs[R_ES]);
482         tss_load_seg(R_DS, new_segs[R_DS]);
483         tss_load_seg(R_FS, new_segs[R_FS]);
484         tss_load_seg(R_GS, new_segs[R_GS]);
485     }
486     
487     /* check that EIP is in the CS segment limits */
488     if (new_eip > env->segs[R_CS].limit) {
489         raise_exception_err(EXCP0D_GPF, 0);
490     }
491 }
492
493 /* check if Port I/O is allowed in TSS */
494 static inline void check_io(int addr, int size)
495 {
496     int io_offset, val, mask;
497     
498     /* TSS must be a valid 32 bit one */
499     if (!(env->tr.flags & DESC_P_MASK) ||
500         ((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 ||
501         env->tr.limit < 103)
502         goto fail;
503     io_offset = lduw_kernel(env->tr.base + 0x66);
504     io_offset += (addr >> 3);
505     /* Note: the check needs two bytes */
506     if ((io_offset + 1) > env->tr.limit)
507         goto fail;
508     val = lduw_kernel(env->tr.base + io_offset);
509     val >>= (addr & 7);
510     mask = (1 << size) - 1;
511     /* all bits must be zero to allow the I/O */
512     if ((val & mask) != 0) {
513     fail:
514         raise_exception_err(EXCP0D_GPF, 0);
515     }
516 }
517
518 void check_iob_T0(void)
519 {
520     check_io(T0, 1);
521 }
522
523 void check_iow_T0(void)
524 {
525     check_io(T0, 2);
526 }
527
528 void check_iol_T0(void)
529 {
530     check_io(T0, 4);
531 }
532
533 void check_iob_DX(void)
534 {
535     check_io(EDX & 0xffff, 1);
536 }
537
538 void check_iow_DX(void)
539 {
540     check_io(EDX & 0xffff, 2);
541 }
542
543 void check_iol_DX(void)
544 {
545     check_io(EDX & 0xffff, 4);
546 }
547
548 static inline unsigned int get_sp_mask(unsigned int e2)
549 {
550     if (e2 & DESC_B_MASK)
551         return 0xffffffff;
552     else
553         return 0xffff;
554 }
555
556 /* XXX: add a is_user flag to have proper security support */
557 #define PUSHW(ssp, sp, sp_mask, val)\
558 {\
559     sp -= 2;\
560     stw_kernel((ssp) + (sp & (sp_mask)), (val));\
561 }
562
563 #define PUSHL(ssp, sp, sp_mask, val)\
564 {\
565     sp -= 4;\
566     stl_kernel((ssp) + (sp & (sp_mask)), (val));\
567 }
568
569 #define POPW(ssp, sp, sp_mask, val)\
570 {\
571     val = lduw_kernel((ssp) + (sp & (sp_mask)));\
572     sp += 2;\
573 }
574
575 #define POPL(ssp, sp, sp_mask, val)\
576 {\
577     val = ldl_kernel((ssp) + (sp & (sp_mask)));\
578     sp += 4;\
579 }
580
581 /* protected mode interrupt */
582 static void do_interrupt_protected(int intno, int is_int, int error_code,
583                                    unsigned int next_eip, int is_hw)
584 {
585     SegmentCache *dt;
586     uint8_t *ptr, *ssp;
587     int type, dpl, selector, ss_dpl, cpl, sp_mask;
588     int has_error_code, new_stack, shift;
589     uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2;
590     uint32_t old_eip;
591
592     has_error_code = 0;
593     if (!is_int && !is_hw) {
594         switch(intno) {
595         case 8:
596         case 10:
597         case 11:
598         case 12:
599         case 13:
600         case 14:
601         case 17:
602             has_error_code = 1;
603             break;
604         }
605     }
606
607     dt = &env->idt;
608     if (intno * 8 + 7 > dt->limit)
609         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
610     ptr = dt->base + intno * 8;
611     e1 = ldl_kernel(ptr);
612     e2 = ldl_kernel(ptr + 4);
613     /* check gate type */
614     type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
615     switch(type) {
616     case 5: /* task gate */
617         /* must do that check here to return the correct error code */
618         if (!(e2 & DESC_P_MASK))
619             raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
620         switch_tss(intno * 8, e1, e2, SWITCH_TSS_CALL);
621         if (has_error_code) {
622             int mask;
623             /* push the error code */
624             shift = (env->segs[R_CS].flags >> DESC_B_SHIFT) & 1;
625             if (env->segs[R_SS].flags & DESC_B_MASK)
626                 mask = 0xffffffff;
627             else
628                 mask = 0xffff;
629             esp = (env->regs[R_ESP] - (2 << shift)) & mask;
630             ssp = env->segs[R_SS].base + esp;
631             if (shift)
632                 stl_kernel(ssp, error_code);
633             else
634                 stw_kernel(ssp, error_code);
635             env->regs[R_ESP] = (esp & mask) | (env->regs[R_ESP] & ~mask);
636         }
637         return;
638     case 6: /* 286 interrupt gate */
639     case 7: /* 286 trap gate */
640     case 14: /* 386 interrupt gate */
641     case 15: /* 386 trap gate */
642         break;
643     default:
644         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
645         break;
646     }
647     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
648     cpl = env->hflags & HF_CPL_MASK;
649     /* check privledge if software int */
650     if (is_int && dpl < cpl)
651         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
652     /* check valid bit */
653     if (!(e2 & DESC_P_MASK))
654         raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
655     selector = e1 >> 16;
656     offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
657     if ((selector & 0xfffc) == 0)
658         raise_exception_err(EXCP0D_GPF, 0);
659
660     if (load_segment(&e1, &e2, selector) != 0)
661         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
662     if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
663         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
664     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
665     if (dpl > cpl)
666         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
667     if (!(e2 & DESC_P_MASK))
668         raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
669     if (!(e2 & DESC_C_MASK) && dpl < cpl) {
670         /* to inner priviledge */
671         get_ss_esp_from_tss(&ss, &esp, dpl);
672         if ((ss & 0xfffc) == 0)
673             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
674         if ((ss & 3) != dpl)
675             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
676         if (load_segment(&ss_e1, &ss_e2, ss) != 0)
677             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
678         ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
679         if (ss_dpl != dpl)
680             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
681         if (!(ss_e2 & DESC_S_MASK) ||
682             (ss_e2 & DESC_CS_MASK) ||
683             !(ss_e2 & DESC_W_MASK))
684             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
685         if (!(ss_e2 & DESC_P_MASK))
686             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
687         new_stack = 1;
688         sp_mask = get_sp_mask(ss_e2);
689         ssp = get_seg_base(ss_e1, ss_e2);
690     } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
691         /* to same priviledge */
692         if (env->eflags & VM_MASK)
693             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
694         new_stack = 0;
695         sp_mask = get_sp_mask(env->segs[R_SS].flags);
696         ssp = env->segs[R_SS].base;
697         esp = ESP;
698         dpl = cpl;
699     } else {
700         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
701         new_stack = 0; /* avoid warning */
702         sp_mask = 0; /* avoid warning */
703         ssp = NULL; /* avoid warning */
704         esp = 0; /* avoid warning */
705     }
706
707     shift = type >> 3;
708
709 #if 0
710     /* XXX: check that enough room is available */
711     push_size = 6 + (new_stack << 2) + (has_error_code << 1);
712     if (env->eflags & VM_MASK)
713         push_size += 8;
714     push_size <<= shift;
715 #endif
716     if (is_int)
717         old_eip = next_eip;
718     else
719         old_eip = env->eip;
720     if (shift == 1) {
721         if (new_stack) {
722             if (env->eflags & VM_MASK) {
723                 PUSHL(ssp, esp, sp_mask, env->segs[R_GS].selector);
724                 PUSHL(ssp, esp, sp_mask, env->segs[R_FS].selector);
725                 PUSHL(ssp, esp, sp_mask, env->segs[R_DS].selector);
726                 PUSHL(ssp, esp, sp_mask, env->segs[R_ES].selector);
727             }
728             PUSHL(ssp, esp, sp_mask, env->segs[R_SS].selector);
729             PUSHL(ssp, esp, sp_mask, ESP);
730         }
731         PUSHL(ssp, esp, sp_mask, compute_eflags());
732         PUSHL(ssp, esp, sp_mask, env->segs[R_CS].selector);
733         PUSHL(ssp, esp, sp_mask, old_eip);
734         if (has_error_code) {
735             PUSHL(ssp, esp, sp_mask, error_code);
736         }
737     } else {
738         if (new_stack) {
739             if (env->eflags & VM_MASK) {
740                 PUSHW(ssp, esp, sp_mask, env->segs[R_GS].selector);
741                 PUSHW(ssp, esp, sp_mask, env->segs[R_FS].selector);
742                 PUSHW(ssp, esp, sp_mask, env->segs[R_DS].selector);
743                 PUSHW(ssp, esp, sp_mask, env->segs[R_ES].selector);
744             }
745             PUSHW(ssp, esp, sp_mask, env->segs[R_SS].selector);
746             PUSHW(ssp, esp, sp_mask, ESP);
747         }
748         PUSHW(ssp, esp, sp_mask, compute_eflags());
749         PUSHW(ssp, esp, sp_mask, env->segs[R_CS].selector);
750         PUSHW(ssp, esp, sp_mask, old_eip);
751         if (has_error_code) {
752             PUSHW(ssp, esp, sp_mask, error_code);
753         }
754     }
755     
756     if (new_stack) {
757         if (env->eflags & VM_MASK) {
758             /* XXX: explain me why W2K hangs if the whole segment cache is
759                reset ? */
760 #if 1
761             env->segs[R_ES].selector = 0;
762             env->segs[R_ES].flags = 0;
763             env->segs[R_DS].selector = 0;
764             env->segs[R_DS].flags = 0;
765             env->segs[R_FS].selector = 0;
766             env->segs[R_FS].flags = 0;
767             env->segs[R_GS].selector = 0;
768             env->segs[R_GS].flags = 0;
769 #else
770             cpu_x86_load_seg_cache(env, R_ES, 0, NULL, 0, 0);
771             cpu_x86_load_seg_cache(env, R_DS, 0, NULL, 0, 0);
772             cpu_x86_load_seg_cache(env, R_FS, 0, NULL, 0, 0);
773             cpu_x86_load_seg_cache(env, R_GS, 0, NULL, 0, 0);
774 #endif
775         }
776         ss = (ss & ~3) | dpl;
777         cpu_x86_load_seg_cache(env, R_SS, ss, 
778                                ssp, get_seg_limit(ss_e1, ss_e2), ss_e2);
779     }
780     ESP = (ESP & ~sp_mask) | (esp & sp_mask);
781
782     selector = (selector & ~3) | dpl;
783     cpu_x86_load_seg_cache(env, R_CS, selector, 
784                    get_seg_base(e1, e2),
785                    get_seg_limit(e1, e2),
786                    e2);
787     cpu_x86_set_cpl(env, dpl);
788     env->eip = offset;
789
790     /* interrupt gate clear IF mask */
791     if ((type & 1) == 0) {
792         env->eflags &= ~IF_MASK;
793     }
794     env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
795 }
796
797 /* real mode interrupt */
798 static void do_interrupt_real(int intno, int is_int, int error_code,
799                               unsigned int next_eip)
800 {
801     SegmentCache *dt;
802     uint8_t *ptr, *ssp;
803     int selector;
804     uint32_t offset, esp;
805     uint32_t old_cs, old_eip;
806
807     /* real mode (simpler !) */
808     dt = &env->idt;
809     if (intno * 4 + 3 > dt->limit)
810         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
811     ptr = dt->base + intno * 4;
812     offset = lduw_kernel(ptr);
813     selector = lduw_kernel(ptr + 2);
814     esp = ESP;
815     ssp = env->segs[R_SS].base;
816     if (is_int)
817         old_eip = next_eip;
818     else
819         old_eip = env->eip;
820     old_cs = env->segs[R_CS].selector;
821     /* XXX: use SS segment size ? */
822     PUSHW(ssp, esp, 0xffff, compute_eflags());
823     PUSHW(ssp, esp, 0xffff, old_cs);
824     PUSHW(ssp, esp, 0xffff, old_eip);
825     
826     /* update processor state */
827     ESP = (ESP & ~0xffff) | (esp & 0xffff);
828     env->eip = offset;
829     env->segs[R_CS].selector = selector;
830     env->segs[R_CS].base = (uint8_t *)(selector << 4);
831     env->eflags &= ~(IF_MASK | TF_MASK | AC_MASK | RF_MASK);
832 }
833
834 /* fake user mode interrupt */
835 void do_interrupt_user(int intno, int is_int, int error_code, 
836                        unsigned int next_eip)
837 {
838     SegmentCache *dt;
839     uint8_t *ptr;
840     int dpl, cpl;
841     uint32_t e2;
842
843     dt = &env->idt;
844     ptr = dt->base + (intno * 8);
845     e2 = ldl_kernel(ptr + 4);
846     
847     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
848     cpl = env->hflags & HF_CPL_MASK;
849     /* check privledge if software int */
850     if (is_int && dpl < cpl)
851         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
852
853     /* Since we emulate only user space, we cannot do more than
854        exiting the emulation with the suitable exception and error
855        code */
856     if (is_int)
857         EIP = next_eip;
858 }
859
860 /*
861  * Begin execution of an interruption. is_int is TRUE if coming from
862  * the int instruction. next_eip is the EIP value AFTER the interrupt
863  * instruction. It is only relevant if is_int is TRUE.  
864  */
865 void do_interrupt(int intno, int is_int, int error_code, 
866                   unsigned int next_eip, int is_hw)
867 {
868 #ifdef DEBUG_PCALL
869     if (loglevel & (CPU_LOG_PCALL | CPU_LOG_INT)) {
870         if ((env->cr[0] & CR0_PE_MASK)) {
871             static int count;
872             fprintf(logfile, "%6d: v=%02x e=%04x i=%d cpl=%d IP=%04x:%08x SP=%04x:%08x",
873                     count, intno, error_code, is_int,
874                     env->hflags & HF_CPL_MASK,
875                     env->segs[R_CS].selector, EIP,
876                     env->segs[R_SS].selector, ESP);
877             if (intno == 0x0e) {
878                 fprintf(logfile, " CR2=%08x", env->cr[2]);
879             } else {
880                 fprintf(logfile, " EAX=%08x", env->regs[R_EAX]);
881             }
882             fprintf(logfile, "\n");
883 #if 0
884             cpu_x86_dump_state(env, logfile, X86_DUMP_CCOP);
885             {
886                 int i;
887                 uint8_t *ptr;
888                 fprintf(logfile, "       code=");
889                 ptr = env->segs[R_CS].base + env->eip;
890                 for(i = 0; i < 16; i++) {
891                     fprintf(logfile, " %02x", ldub(ptr + i));
892                 }
893                 fprintf(logfile, "\n");
894             }
895 #endif
896             count++;
897         }
898     }
899 #endif
900     if (env->cr[0] & CR0_PE_MASK) {
901         do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);
902     } else {
903         do_interrupt_real(intno, is_int, error_code, next_eip);
904     }
905 }
906
907 /*
908  * Signal an interruption. It is executed in the main CPU loop.
909  * is_int is TRUE if coming from the int instruction. next_eip is the
910  * EIP value AFTER the interrupt instruction. It is only relevant if
911  * is_int is TRUE.  
912  */
913 void raise_interrupt(int intno, int is_int, int error_code, 
914                      unsigned int next_eip)
915 {
916     env->exception_index = intno;
917     env->error_code = error_code;
918     env->exception_is_int = is_int;
919     env->exception_next_eip = next_eip;
920     cpu_loop_exit();
921 }
922
923 /* shortcuts to generate exceptions */
924
925 void (raise_exception_err)(int exception_index, int error_code)
926 {
927     raise_interrupt(exception_index, 0, error_code, 0);
928 }
929
930 void raise_exception(int exception_index)
931 {
932     raise_interrupt(exception_index, 0, 0, 0);
933 }
934
935 #ifdef BUGGY_GCC_DIV64
936 /* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we
937    call it from another function */
938 uint32_t div64(uint32_t *q_ptr, uint64_t num, uint32_t den)
939 {
940     *q_ptr = num / den;
941     return num % den;
942 }
943
944 int32_t idiv64(int32_t *q_ptr, int64_t num, int32_t den)
945 {
946     *q_ptr = num / den;
947     return num % den;
948 }
949 #endif
950
951 void helper_divl_EAX_T0(uint32_t eip)
952 {
953     unsigned int den, q, r;
954     uint64_t num;
955     
956     num = EAX | ((uint64_t)EDX << 32);
957     den = T0;
958     if (den == 0) {
959         EIP = eip;
960         raise_exception(EXCP00_DIVZ);
961     }
962 #ifdef BUGGY_GCC_DIV64
963     r = div64(&q, num, den);
964 #else
965     q = (num / den);
966     r = (num % den);
967 #endif
968     EAX = q;
969     EDX = r;
970 }
971
972 void helper_idivl_EAX_T0(uint32_t eip)
973 {
974     int den, q, r;
975     int64_t num;
976     
977     num = EAX | ((uint64_t)EDX << 32);
978     den = T0;
979     if (den == 0) {
980         EIP = eip;
981         raise_exception(EXCP00_DIVZ);
982     }
983 #ifdef BUGGY_GCC_DIV64
984     r = idiv64(&q, num, den);
985 #else
986     q = (num / den);
987     r = (num % den);
988 #endif
989     EAX = q;
990     EDX = r;
991 }
992
993 void helper_cmpxchg8b(void)
994 {
995     uint64_t d;
996     int eflags;
997
998     eflags = cc_table[CC_OP].compute_all();
999     d = ldq((uint8_t *)A0);
1000     if (d == (((uint64_t)EDX << 32) | EAX)) {
1001         stq((uint8_t *)A0, ((uint64_t)ECX << 32) | EBX);
1002         eflags |= CC_Z;
1003     } else {
1004         EDX = d >> 32;
1005         EAX = d;
1006         eflags &= ~CC_Z;
1007     }
1008     CC_SRC = eflags;
1009 }
1010
1011 #define CPUID_FP87 (1 << 0)
1012 #define CPUID_VME  (1 << 1)
1013 #define CPUID_DE   (1 << 2)
1014 #define CPUID_PSE  (1 << 3)
1015 #define CPUID_TSC  (1 << 4)
1016 #define CPUID_MSR  (1 << 5)
1017 #define CPUID_PAE  (1 << 6)
1018 #define CPUID_MCE  (1 << 7)
1019 #define CPUID_CX8  (1 << 8)
1020 #define CPUID_APIC (1 << 9)
1021 #define CPUID_SEP  (1 << 11) /* sysenter/sysexit */
1022 #define CPUID_MTRR (1 << 12)
1023 #define CPUID_PGE  (1 << 13)
1024 #define CPUID_MCA  (1 << 14)
1025 #define CPUID_CMOV (1 << 15)
1026 /* ... */
1027 #define CPUID_MMX  (1 << 23)
1028 #define CPUID_FXSR (1 << 24)
1029 #define CPUID_SSE  (1 << 25)
1030 #define CPUID_SSE2 (1 << 26)
1031
1032 void helper_cpuid(void)
1033 {
1034     switch(EAX) {
1035     case 0:
1036         EAX = 2; /* max EAX index supported */
1037         EBX = 0x756e6547;
1038         ECX = 0x6c65746e;
1039         EDX = 0x49656e69;
1040         break;
1041     case 1:
1042         {
1043             int family, model, stepping;
1044             /* EAX = 1 info */
1045 #if 0
1046             /* pentium 75-200 */
1047             family = 5;
1048             model = 2;
1049             stepping = 11;
1050 #else
1051             /* pentium pro */
1052             family = 6;
1053             model = 1;
1054             stepping = 3;
1055 #endif
1056             EAX = (family << 8) | (model << 4) | stepping;
1057             EBX = 0;
1058             ECX = 0;
1059             EDX = CPUID_FP87 | CPUID_DE | CPUID_PSE |
1060                 CPUID_TSC | CPUID_MSR | CPUID_MCE |
1061                 CPUID_CX8 | CPUID_PGE | CPUID_CMOV;
1062         }
1063         break;
1064     default:
1065         /* cache info: needed for Pentium Pro compatibility */
1066         EAX = 0x410601;
1067         EBX = 0;
1068         ECX = 0;
1069         EDX = 0;
1070         break;
1071     }
1072 }
1073
1074 void helper_lldt_T0(void)
1075 {
1076     int selector;
1077     SegmentCache *dt;
1078     uint32_t e1, e2;
1079     int index;
1080     uint8_t *ptr;
1081     
1082     selector = T0 & 0xffff;
1083     if ((selector & 0xfffc) == 0) {
1084         /* XXX: NULL selector case: invalid LDT */
1085         env->ldt.base = NULL;
1086         env->ldt.limit = 0;
1087     } else {
1088         if (selector & 0x4)
1089             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1090         dt = &env->gdt;
1091         index = selector & ~7;
1092         if ((index + 7) > dt->limit)
1093             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1094         ptr = dt->base + index;
1095         e1 = ldl_kernel(ptr);
1096         e2 = ldl_kernel(ptr + 4);
1097         if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
1098             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1099         if (!(e2 & DESC_P_MASK))
1100             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
1101         load_seg_cache_raw_dt(&env->ldt, e1, e2);
1102     }
1103     env->ldt.selector = selector;
1104 }
1105
1106 void helper_ltr_T0(void)
1107 {
1108     int selector;
1109     SegmentCache *dt;
1110     uint32_t e1, e2;
1111     int index, type;
1112     uint8_t *ptr;
1113     
1114     selector = T0 & 0xffff;
1115     if ((selector & 0xfffc) == 0) {
1116         /* NULL selector case: invalid LDT */
1117         env->tr.base = NULL;
1118         env->tr.limit = 0;
1119         env->tr.flags = 0;
1120     } else {
1121         if (selector & 0x4)
1122             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1123         dt = &env->gdt;
1124         index = selector & ~7;
1125         if ((index + 7) > dt->limit)
1126             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1127         ptr = dt->base + index;
1128         e1 = ldl_kernel(ptr);
1129         e2 = ldl_kernel(ptr + 4);
1130         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
1131         if ((e2 & DESC_S_MASK) || 
1132             (type != 1 && type != 9))
1133             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1134         if (!(e2 & DESC_P_MASK))
1135             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
1136         load_seg_cache_raw_dt(&env->tr, e1, e2);
1137         e2 |= DESC_TSS_BUSY_MASK;
1138         stl_kernel(ptr + 4, e2);
1139     }
1140     env->tr.selector = selector;
1141 }
1142
1143 /* only works if protected mode and not VM86. seg_reg must be != R_CS */
1144 void load_seg(int seg_reg, int selector)
1145 {
1146     uint32_t e1, e2;
1147     int cpl, dpl, rpl;
1148     SegmentCache *dt;
1149     int index;
1150     uint8_t *ptr;
1151
1152     selector &= 0xffff;
1153     if ((selector & 0xfffc) == 0) {
1154         /* null selector case */
1155         if (seg_reg == R_SS)
1156             raise_exception_err(EXCP0D_GPF, 0);
1157         cpu_x86_load_seg_cache(env, seg_reg, selector, NULL, 0, 0);
1158     } else {
1159         
1160         if (selector & 0x4)
1161             dt = &env->ldt;
1162         else
1163             dt = &env->gdt;
1164         index = selector & ~7;
1165         if ((index + 7) > dt->limit)
1166             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1167         ptr = dt->base + index;
1168         e1 = ldl_kernel(ptr);
1169         e2 = ldl_kernel(ptr + 4);
1170
1171         if (!(e2 & DESC_S_MASK))
1172             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1173         rpl = selector & 3;
1174         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1175         cpl = env->hflags & HF_CPL_MASK;
1176         if (seg_reg == R_SS) {
1177             /* must be writable segment */
1178             if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
1179                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1180             if (rpl != cpl || dpl != cpl)
1181                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1182         } else {
1183             /* must be readable segment */
1184             if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK)
1185                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1186             
1187             if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
1188                 /* if not conforming code, test rights */
1189                 if (dpl < cpl || dpl < rpl)
1190                     raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1191             }
1192         }
1193
1194         if (!(e2 & DESC_P_MASK)) {
1195             if (seg_reg == R_SS)
1196                 raise_exception_err(EXCP0C_STACK, selector & 0xfffc);
1197             else
1198                 raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
1199         }
1200
1201         /* set the access bit if not already set */
1202         if (!(e2 & DESC_A_MASK)) {
1203             e2 |= DESC_A_MASK;
1204             stl_kernel(ptr + 4, e2);
1205         }
1206
1207         cpu_x86_load_seg_cache(env, seg_reg, selector, 
1208                        get_seg_base(e1, e2),
1209                        get_seg_limit(e1, e2),
1210                        e2);
1211 #if 0
1212         fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx flags=%08x\n", 
1213                 selector, (unsigned long)sc->base, sc->limit, sc->flags);
1214 #endif
1215     }
1216 }
1217
1218 /* protected mode jump */
1219 void helper_ljmp_protected_T0_T1(void)
1220 {
1221     int new_cs, new_eip, gate_cs, type;
1222     uint32_t e1, e2, cpl, dpl, rpl, limit;
1223
1224     new_cs = T0;
1225     new_eip = T1;
1226     if ((new_cs & 0xfffc) == 0)
1227         raise_exception_err(EXCP0D_GPF, 0);
1228     if (load_segment(&e1, &e2, new_cs) != 0)
1229         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1230     cpl = env->hflags & HF_CPL_MASK;
1231     if (e2 & DESC_S_MASK) {
1232         if (!(e2 & DESC_CS_MASK))
1233             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1234         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1235         if (e2 & DESC_C_MASK) {
1236             /* conforming code segment */
1237             if (dpl > cpl)
1238                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1239         } else {
1240             /* non conforming code segment */
1241             rpl = new_cs & 3;
1242             if (rpl > cpl)
1243                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1244             if (dpl != cpl)
1245                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1246         }
1247         if (!(e2 & DESC_P_MASK))
1248             raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
1249         limit = get_seg_limit(e1, e2);
1250         if (new_eip > limit)
1251             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1252         cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
1253                        get_seg_base(e1, e2), limit, e2);
1254         EIP = new_eip;
1255     } else {
1256         /* jump to call or task gate */
1257         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1258         rpl = new_cs & 3;
1259         cpl = env->hflags & HF_CPL_MASK;
1260         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
1261         switch(type) {
1262         case 1: /* 286 TSS */
1263         case 9: /* 386 TSS */
1264         case 5: /* task gate */
1265             if (dpl < cpl || dpl < rpl)
1266                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1267             switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP);
1268             break;
1269         case 4: /* 286 call gate */
1270         case 12: /* 386 call gate */
1271             if ((dpl < cpl) || (dpl < rpl))
1272                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1273             if (!(e2 & DESC_P_MASK))
1274                 raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
1275             gate_cs = e1 >> 16;
1276             if (load_segment(&e1, &e2, gate_cs) != 0)
1277                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
1278             dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1279             /* must be code segment */
1280             if (((e2 & (DESC_S_MASK | DESC_CS_MASK)) != 
1281                  (DESC_S_MASK | DESC_CS_MASK)))
1282                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
1283             if (((e2 & DESC_C_MASK) && (dpl > cpl)) ||
1284                 (!(e2 & DESC_C_MASK) && (dpl != cpl)))
1285                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
1286             if (!(e2 & DESC_P_MASK))
1287                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
1288             new_eip = (e1 & 0xffff);
1289             if (type == 12)
1290                 new_eip |= (e2 & 0xffff0000);
1291             limit = get_seg_limit(e1, e2);
1292             if (new_eip > limit)
1293                 raise_exception_err(EXCP0D_GPF, 0);
1294             cpu_x86_load_seg_cache(env, R_CS, (gate_cs & 0xfffc) | cpl,
1295                                    get_seg_base(e1, e2), limit, e2);
1296             EIP = new_eip;
1297             break;
1298         default:
1299             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1300             break;
1301         }
1302     }
1303 }
1304
1305 /* real mode call */
1306 void helper_lcall_real_T0_T1(int shift, int next_eip)
1307 {
1308     int new_cs, new_eip;
1309     uint32_t esp, esp_mask;
1310     uint8_t *ssp;
1311
1312     new_cs = T0;
1313     new_eip = T1;
1314     esp = ESP;
1315     esp_mask = get_sp_mask(env->segs[R_SS].flags);
1316     ssp = env->segs[R_SS].base;
1317     if (shift) {
1318         PUSHL(ssp, esp, esp_mask, env->segs[R_CS].selector);
1319         PUSHL(ssp, esp, esp_mask, next_eip);
1320     } else {
1321         PUSHW(ssp, esp, esp_mask, env->segs[R_CS].selector);
1322         PUSHW(ssp, esp, esp_mask, next_eip);
1323     }
1324
1325     ESP = (ESP & ~esp_mask) | (esp & esp_mask);
1326     env->eip = new_eip;
1327     env->segs[R_CS].selector = new_cs;
1328     env->segs[R_CS].base = (uint8_t *)(new_cs << 4);
1329 }
1330
1331 /* protected mode call */
1332 void helper_lcall_protected_T0_T1(int shift, int next_eip)
1333 {
1334     int new_cs, new_eip, new_stack, i;
1335     uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;
1336     uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask;
1337     uint32_t val, limit, old_sp_mask;
1338     uint8_t *ssp, *old_ssp;
1339     
1340     new_cs = T0;
1341     new_eip = T1;
1342 #ifdef DEBUG_PCALL
1343     if (loglevel & CPU_LOG_PCALL) {
1344         fprintf(logfile, "lcall %04x:%08x s=%d\n",
1345                 new_cs, new_eip, shift);
1346         cpu_x86_dump_state(env, logfile, X86_DUMP_CCOP);
1347     }
1348 #endif
1349     if ((new_cs & 0xfffc) == 0)
1350         raise_exception_err(EXCP0D_GPF, 0);
1351     if (load_segment(&e1, &e2, new_cs) != 0)
1352         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1353     cpl = env->hflags & HF_CPL_MASK;
1354 #ifdef DEBUG_PCALL
1355     if (loglevel & CPU_LOG_PCALL) {
1356         fprintf(logfile, "desc=%08x:%08x\n", e1, e2);
1357     }
1358 #endif
1359     if (e2 & DESC_S_MASK) {
1360         if (!(e2 & DESC_CS_MASK))
1361             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1362         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1363         if (e2 & DESC_C_MASK) {
1364             /* conforming code segment */
1365             if (dpl > cpl)
1366                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1367         } else {
1368             /* non conforming code segment */
1369             rpl = new_cs & 3;
1370             if (rpl > cpl)
1371                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1372             if (dpl != cpl)
1373                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1374         }
1375         if (!(e2 & DESC_P_MASK))
1376             raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
1377
1378         sp = ESP;
1379         sp_mask = get_sp_mask(env->segs[R_SS].flags);
1380         ssp = env->segs[R_SS].base;
1381         if (shift) {
1382             PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
1383             PUSHL(ssp, sp, sp_mask, next_eip);
1384         } else {
1385             PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
1386             PUSHW(ssp, sp, sp_mask, next_eip);
1387         }
1388         
1389         limit = get_seg_limit(e1, e2);
1390         if (new_eip > limit)
1391             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1392         /* from this point, not restartable */
1393         ESP = (ESP & ~sp_mask) | (sp & sp_mask);
1394         cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
1395                        get_seg_base(e1, e2), limit, e2);
1396         EIP = new_eip;
1397     } else {
1398         /* check gate type */
1399         type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
1400         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1401         rpl = new_cs & 3;
1402         switch(type) {
1403         case 1: /* available 286 TSS */
1404         case 9: /* available 386 TSS */
1405         case 5: /* task gate */
1406             if (dpl < cpl || dpl < rpl)
1407                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1408             switch_tss(new_cs, e1, e2, SWITCH_TSS_CALL);
1409             return;
1410         case 4: /* 286 call gate */
1411         case 12: /* 386 call gate */
1412             break;
1413         default:
1414             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1415             break;
1416         }
1417         shift = type >> 3;
1418
1419         if (dpl < cpl || dpl < rpl)
1420             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1421         /* check valid bit */
1422         if (!(e2 & DESC_P_MASK))
1423             raise_exception_err(EXCP0B_NOSEG,  new_cs & 0xfffc);
1424         selector = e1 >> 16;
1425         offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
1426         param_count = e2 & 0x1f;
1427         if ((selector & 0xfffc) == 0)
1428             raise_exception_err(EXCP0D_GPF, 0);
1429
1430         if (load_segment(&e1, &e2, selector) != 0)
1431             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1432         if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
1433             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1434         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1435         if (dpl > cpl)
1436             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1437         if (!(e2 & DESC_P_MASK))
1438             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
1439
1440         if (!(e2 & DESC_C_MASK) && dpl < cpl) {
1441             /* to inner priviledge */
1442             get_ss_esp_from_tss(&ss, &sp, dpl);
1443 #ifdef DEBUG_PCALL
1444             if (loglevel & CPU_LOG_PCALL)
1445                 fprintf(logfile, "new ss:esp=%04x:%08x param_count=%d ESP=%x\n", 
1446                         ss, sp, param_count, ESP);
1447 #endif
1448             if ((ss & 0xfffc) == 0)
1449                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
1450             if ((ss & 3) != dpl)
1451                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
1452             if (load_segment(&ss_e1, &ss_e2, ss) != 0)
1453                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
1454             ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
1455             if (ss_dpl != dpl)
1456                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
1457             if (!(ss_e2 & DESC_S_MASK) ||
1458                 (ss_e2 & DESC_CS_MASK) ||
1459                 !(ss_e2 & DESC_W_MASK))
1460                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
1461             if (!(ss_e2 & DESC_P_MASK))
1462                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
1463             
1464             //            push_size = ((param_count * 2) + 8) << shift;
1465
1466             old_sp_mask = get_sp_mask(env->segs[R_SS].flags);
1467             old_ssp = env->segs[R_SS].base;
1468             
1469             sp_mask = get_sp_mask(ss_e2);
1470             ssp = get_seg_base(ss_e1, ss_e2);
1471             if (shift) {
1472                 PUSHL(ssp, sp, sp_mask, env->segs[R_SS].selector);
1473                 PUSHL(ssp, sp, sp_mask, ESP);
1474                 for(i = param_count - 1; i >= 0; i--) {
1475                     val = ldl_kernel(old_ssp + ((ESP + i * 4) & old_sp_mask));
1476                     PUSHL(ssp, sp, sp_mask, val);
1477                 }
1478             } else {
1479                 PUSHW(ssp, sp, sp_mask, env->segs[R_SS].selector);
1480                 PUSHW(ssp, sp, sp_mask, ESP);
1481                 for(i = param_count - 1; i >= 0; i--) {
1482                     val = lduw_kernel(old_ssp + ((ESP + i * 2) & old_sp_mask));
1483                     PUSHW(ssp, sp, sp_mask, val);
1484                 }
1485             }
1486             new_stack = 1;
1487         } else {
1488             /* to same priviledge */
1489             sp = ESP;
1490             sp_mask = get_sp_mask(env->segs[R_SS].flags);
1491             ssp = env->segs[R_SS].base;
1492             //            push_size = (4 << shift);
1493             new_stack = 0;
1494         }
1495
1496         if (shift) {
1497             PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
1498             PUSHL(ssp, sp, sp_mask, next_eip);
1499         } else {
1500             PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
1501             PUSHW(ssp, sp, sp_mask, next_eip);
1502         }
1503
1504         /* from this point, not restartable */
1505
1506         if (new_stack) {
1507             ss = (ss & ~3) | dpl;
1508             cpu_x86_load_seg_cache(env, R_SS, ss, 
1509                                    ssp,
1510                                    get_seg_limit(ss_e1, ss_e2),
1511                                    ss_e2);
1512         }
1513
1514         selector = (selector & ~3) | dpl;
1515         cpu_x86_load_seg_cache(env, R_CS, selector, 
1516                        get_seg_base(e1, e2),
1517                        get_seg_limit(e1, e2),
1518                        e2);
1519         cpu_x86_set_cpl(env, dpl);
1520         ESP = (ESP & ~sp_mask) | (sp & sp_mask);
1521         EIP = offset;
1522     }
1523 }
1524
1525 /* real and vm86 mode iret */
1526 void helper_iret_real(int shift)
1527 {
1528     uint32_t sp, new_cs, new_eip, new_eflags, sp_mask;
1529     uint8_t *ssp;
1530     int eflags_mask;
1531
1532     sp_mask = 0xffff; /* XXXX: use SS segment size ? */
1533     sp = ESP;
1534     ssp = env->segs[R_SS].base;
1535     if (shift == 1) {
1536         /* 32 bits */
1537         POPL(ssp, sp, sp_mask, new_eip);
1538         POPL(ssp, sp, sp_mask, new_cs);
1539         new_cs &= 0xffff;
1540         POPL(ssp, sp, sp_mask, new_eflags);
1541     } else {
1542         /* 16 bits */
1543         POPW(ssp, sp, sp_mask, new_eip);
1544         POPW(ssp, sp, sp_mask, new_cs);
1545         POPW(ssp, sp, sp_mask, new_eflags);
1546     }
1547     ESP = (ESP & ~sp_mask) | (sp & sp_mask);
1548     load_seg_vm(R_CS, new_cs);
1549     env->eip = new_eip;
1550     if (env->eflags & VM_MASK)
1551         eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK | NT_MASK;
1552     else
1553         eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK | RF_MASK | NT_MASK;
1554     if (shift == 0)
1555         eflags_mask &= 0xffff;
1556     load_eflags(new_eflags, eflags_mask);
1557 }
1558
1559 static inline void validate_seg(int seg_reg, int cpl)
1560 {
1561     int dpl;
1562     uint32_t e2;
1563     
1564     e2 = env->segs[seg_reg].flags;
1565     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1566     if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
1567         /* data or non conforming code segment */
1568         if (dpl < cpl) {
1569             cpu_x86_load_seg_cache(env, seg_reg, 0, NULL, 0, 0);
1570         }
1571     }
1572 }
1573
1574 /* protected mode iret */
1575 static inline void helper_ret_protected(int shift, int is_iret, int addend)
1576 {
1577     uint32_t sp, new_cs, new_eip, new_eflags, new_esp, new_ss, sp_mask;
1578     uint32_t new_es, new_ds, new_fs, new_gs;
1579     uint32_t e1, e2, ss_e1, ss_e2;
1580     int cpl, dpl, rpl, eflags_mask, iopl;
1581     uint8_t *ssp;
1582     
1583     sp_mask = get_sp_mask(env->segs[R_SS].flags);
1584     sp = ESP;
1585     ssp = env->segs[R_SS].base;
1586     if (shift == 1) {
1587         /* 32 bits */
1588         POPL(ssp, sp, sp_mask, new_eip);
1589         POPL(ssp, sp, sp_mask, new_cs);
1590         new_cs &= 0xffff;
1591         if (is_iret) {
1592             POPL(ssp, sp, sp_mask, new_eflags);
1593             if (new_eflags & VM_MASK)
1594                 goto return_to_vm86;
1595         }
1596     } else {
1597         /* 16 bits */
1598         POPW(ssp, sp, sp_mask, new_eip);
1599         POPW(ssp, sp, sp_mask, new_cs);
1600         if (is_iret)
1601             POPW(ssp, sp, sp_mask, new_eflags);
1602     }
1603 #ifdef DEBUG_PCALL
1604     if (loglevel & CPU_LOG_PCALL) {
1605         fprintf(logfile, "lret new %04x:%08x s=%d addend=0x%x\n",
1606                 new_cs, new_eip, shift, addend);
1607         cpu_x86_dump_state(env, logfile, X86_DUMP_CCOP);
1608     }
1609 #endif
1610     if ((new_cs & 0xfffc) == 0)
1611         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1612     if (load_segment(&e1, &e2, new_cs) != 0)
1613         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1614     if (!(e2 & DESC_S_MASK) ||
1615         !(e2 & DESC_CS_MASK))
1616         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1617     cpl = env->hflags & HF_CPL_MASK;
1618     rpl = new_cs & 3; 
1619     if (rpl < cpl)
1620         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1621     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1622     if (e2 & DESC_C_MASK) {
1623         if (dpl > rpl)
1624             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1625     } else {
1626         if (dpl != rpl)
1627             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1628     }
1629     if (!(e2 & DESC_P_MASK))
1630         raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
1631     
1632     sp += addend;
1633     if (rpl == cpl) {
1634         /* return to same priledge level */
1635         cpu_x86_load_seg_cache(env, R_CS, new_cs, 
1636                        get_seg_base(e1, e2),
1637                        get_seg_limit(e1, e2),
1638                        e2);
1639     } else {
1640         /* return to different priviledge level */
1641         if (shift == 1) {
1642             /* 32 bits */
1643             POPL(ssp, sp, sp_mask, new_esp);
1644             POPL(ssp, sp, sp_mask, new_ss);
1645             new_ss &= 0xffff;
1646         } else {
1647             /* 16 bits */
1648             POPW(ssp, sp, sp_mask, new_esp);
1649             POPW(ssp, sp, sp_mask, new_ss);
1650         }
1651 #ifdef DEBUG_PCALL
1652         if (loglevel & CPU_LOG_PCALL) {
1653             fprintf(logfile, "new ss:esp=%04x:%08x\n",
1654                     new_ss, new_esp);
1655         }
1656 #endif
1657         
1658         if ((new_ss & 3) != rpl)
1659             raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
1660         if (load_segment(&ss_e1, &ss_e2, new_ss) != 0)
1661             raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
1662         if (!(ss_e2 & DESC_S_MASK) ||
1663             (ss_e2 & DESC_CS_MASK) ||
1664             !(ss_e2 & DESC_W_MASK))
1665             raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
1666         dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
1667         if (dpl != rpl)
1668             raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
1669         if (!(ss_e2 & DESC_P_MASK))
1670             raise_exception_err(EXCP0B_NOSEG, new_ss & 0xfffc);
1671
1672         cpu_x86_load_seg_cache(env, R_CS, new_cs, 
1673                        get_seg_base(e1, e2),
1674                        get_seg_limit(e1, e2),
1675                        e2);
1676         cpu_x86_load_seg_cache(env, R_SS, new_ss, 
1677                        get_seg_base(ss_e1, ss_e2),
1678                        get_seg_limit(ss_e1, ss_e2),
1679                        ss_e2);
1680         cpu_x86_set_cpl(env, rpl);
1681         sp = new_esp;
1682         /* XXX: change sp_mask according to old segment ? */
1683
1684         /* validate data segments */
1685         validate_seg(R_ES, cpl);
1686         validate_seg(R_DS, cpl);
1687         validate_seg(R_FS, cpl);
1688         validate_seg(R_GS, cpl);
1689
1690         sp += addend;
1691     }
1692     ESP = (ESP & ~sp_mask) | (sp & sp_mask);
1693     env->eip = new_eip;
1694     if (is_iret) {
1695         /* NOTE: 'cpl' is the _old_ CPL */
1696         eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK | NT_MASK;
1697         if (cpl == 0)
1698             eflags_mask |= IOPL_MASK;
1699         iopl = (env->eflags >> IOPL_SHIFT) & 3;
1700         if (cpl <= iopl)
1701             eflags_mask |= IF_MASK;
1702         if (shift == 0)
1703             eflags_mask &= 0xffff;
1704         load_eflags(new_eflags, eflags_mask);
1705     }
1706     return;
1707
1708  return_to_vm86:
1709     POPL(ssp, sp, sp_mask, new_esp);
1710     POPL(ssp, sp, sp_mask, new_ss);
1711     POPL(ssp, sp, sp_mask, new_es);
1712     POPL(ssp, sp, sp_mask, new_ds);
1713     POPL(ssp, sp, sp_mask, new_fs);
1714     POPL(ssp, sp, sp_mask, new_gs);
1715     
1716     /* modify processor state */
1717     load_eflags(new_eflags, TF_MASK | AC_MASK | ID_MASK | 
1718                 IF_MASK | IOPL_MASK | VM_MASK | NT_MASK | VIF_MASK | VIP_MASK);
1719     load_seg_vm(R_CS, new_cs & 0xffff);
1720     cpu_x86_set_cpl(env, 3);
1721     load_seg_vm(R_SS, new_ss & 0xffff);
1722     load_seg_vm(R_ES, new_es & 0xffff);
1723     load_seg_vm(R_DS, new_ds & 0xffff);
1724     load_seg_vm(R_FS, new_fs & 0xffff);
1725     load_seg_vm(R_GS, new_gs & 0xffff);
1726
1727     env->eip = new_eip;
1728     ESP = new_esp;
1729 }
1730
1731 void helper_iret_protected(int shift)
1732 {
1733     int tss_selector, type;
1734     uint32_t e1, e2;
1735     
1736     /* specific case for TSS */
1737     if (env->eflags & NT_MASK) {
1738         tss_selector = lduw_kernel(env->tr.base + 0);
1739         if (tss_selector & 4)
1740             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
1741         if (load_segment(&e1, &e2, tss_selector) != 0)
1742             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
1743         type = (e2 >> DESC_TYPE_SHIFT) & 0x17;
1744         /* NOTE: we check both segment and busy TSS */
1745         if (type != 3)
1746             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
1747         switch_tss(tss_selector, e1, e2, SWITCH_TSS_IRET);
1748     } else {
1749         helper_ret_protected(shift, 1, 0);
1750     }
1751 }
1752
1753 void helper_lret_protected(int shift, int addend)
1754 {
1755     helper_ret_protected(shift, 0, addend);
1756 }
1757
1758 void helper_movl_crN_T0(int reg)
1759 {
1760     switch(reg) {
1761     case 0:
1762         cpu_x86_update_cr0(env, T0);
1763         break;
1764     case 3:
1765         cpu_x86_update_cr3(env, T0);
1766         break;
1767     case 4:
1768         cpu_x86_update_cr4(env, T0);
1769         break;
1770     default:
1771         env->cr[reg] = T0;
1772         break;
1773     }
1774 }
1775
1776 /* XXX: do more */
1777 void helper_movl_drN_T0(int reg)
1778 {
1779     env->dr[reg] = T0;
1780 }
1781
1782 void helper_invlpg(unsigned int addr)
1783 {
1784     cpu_x86_flush_tlb(env, addr);
1785 }
1786
1787 /* rdtsc */
1788 #if !defined(__i386__) && !defined(__x86_64__)
1789 uint64_t emu_time;
1790 #endif
1791
1792 void helper_rdtsc(void)
1793 {
1794     uint64_t val;
1795 #if defined(__i386__) || defined(__x86_64__)
1796     asm("rdtsc" : "=A" (val));
1797 #else
1798     /* better than nothing: the time increases */
1799     val = emu_time++;
1800 #endif
1801     EAX = val;
1802     EDX = val >> 32;
1803 }
1804
1805 void helper_wrmsr(void)
1806 {
1807     switch(ECX) {
1808     case MSR_IA32_SYSENTER_CS:
1809         env->sysenter_cs = EAX & 0xffff;
1810         break;
1811     case MSR_IA32_SYSENTER_ESP:
1812         env->sysenter_esp = EAX;
1813         break;
1814     case MSR_IA32_SYSENTER_EIP:
1815         env->sysenter_eip = EAX;
1816         break;
1817     default:
1818         /* XXX: exception ? */
1819         break; 
1820     }
1821 }
1822
1823 void helper_rdmsr(void)
1824 {
1825     switch(ECX) {
1826     case MSR_IA32_SYSENTER_CS:
1827         EAX = env->sysenter_cs;
1828         EDX = 0;
1829         break;
1830     case MSR_IA32_SYSENTER_ESP:
1831         EAX = env->sysenter_esp;
1832         EDX = 0;
1833         break;
1834     case MSR_IA32_SYSENTER_EIP:
1835         EAX = env->sysenter_eip;
1836         EDX = 0;
1837         break;
1838     default:
1839         /* XXX: exception ? */
1840         break; 
1841     }
1842 }
1843
1844 void helper_lsl(void)
1845 {
1846     unsigned int selector, limit;
1847     uint32_t e1, e2;
1848     int rpl, dpl, cpl, type;
1849
1850     CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z;
1851     selector = T0 & 0xffff;
1852     if (load_segment(&e1, &e2, selector) != 0)
1853         return;
1854     rpl = selector & 3;
1855     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1856     cpl = env->hflags & HF_CPL_MASK;
1857     if (e2 & DESC_S_MASK) {
1858         if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
1859             /* conforming */
1860         } else {
1861             if (dpl < cpl || dpl < rpl)
1862                 return;
1863         }
1864     } else {
1865         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
1866         switch(type) {
1867         case 1:
1868         case 2:
1869         case 3:
1870         case 9:
1871         case 11:
1872             break;
1873         default:
1874             return;
1875         }
1876         if (dpl < cpl || dpl < rpl)
1877             return;
1878     }
1879     limit = get_seg_limit(e1, e2);
1880     T1 = limit;
1881     CC_SRC |= CC_Z;
1882 }
1883
1884 void helper_lar(void)
1885 {
1886     unsigned int selector;
1887     uint32_t e1, e2;
1888     int rpl, dpl, cpl, type;
1889
1890     CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z;
1891     selector = T0 & 0xffff;
1892     if ((selector & 0xfffc) == 0)
1893         return;
1894     if (load_segment(&e1, &e2, selector) != 0)
1895         return;
1896     rpl = selector & 3;
1897     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1898     cpl = env->hflags & HF_CPL_MASK;
1899     if (e2 & DESC_S_MASK) {
1900         if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
1901             /* conforming */
1902         } else {
1903             if (dpl < cpl || dpl < rpl)
1904                 return;
1905         }
1906     } else {
1907         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
1908         switch(type) {
1909         case 1:
1910         case 2:
1911         case 3:
1912         case 4:
1913         case 5:
1914         case 9:
1915         case 11:
1916         case 12:
1917             break;
1918         default:
1919             return;
1920         }
1921         if (dpl < cpl || dpl < rpl)
1922             return;
1923     }
1924     T1 = e2 & 0x00f0ff00;
1925     CC_SRC |= CC_Z;
1926 }
1927
1928 void helper_verr(void)
1929 {
1930     unsigned int selector;
1931     uint32_t e1, e2;
1932     int rpl, dpl, cpl;
1933
1934     CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z;
1935     selector = T0 & 0xffff;
1936     if ((selector & 0xfffc) == 0)
1937         return;
1938     if (load_segment(&e1, &e2, selector) != 0)
1939         return;
1940     if (!(e2 & DESC_S_MASK))
1941         return;
1942     rpl = selector & 3;
1943     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1944     cpl = env->hflags & HF_CPL_MASK;
1945     if (e2 & DESC_CS_MASK) {
1946         if (!(e2 & DESC_R_MASK))
1947             return;
1948         if (!(e2 & DESC_C_MASK)) {
1949             if (dpl < cpl || dpl < rpl)
1950                 return;
1951         }
1952     } else {
1953         if (dpl < cpl || dpl < rpl)
1954             return;
1955     }
1956     CC_SRC |= CC_Z;
1957 }
1958
1959 void helper_verw(void)
1960 {
1961     unsigned int selector;
1962     uint32_t e1, e2;
1963     int rpl, dpl, cpl;
1964
1965     CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z;
1966     selector = T0 & 0xffff;
1967     if ((selector & 0xfffc) == 0)
1968         return;
1969     if (load_segment(&e1, &e2, selector) != 0)
1970         return;
1971     if (!(e2 & DESC_S_MASK))
1972         return;
1973     rpl = selector & 3;
1974     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1975     cpl = env->hflags & HF_CPL_MASK;
1976     if (e2 & DESC_CS_MASK) {
1977         return;
1978     } else {
1979         if (dpl < cpl || dpl < rpl)
1980             return;
1981         if (!(e2 & DESC_W_MASK))
1982             return;
1983     }
1984     CC_SRC |= CC_Z;
1985 }
1986
1987 /* FPU helpers */
1988
1989 void helper_fldt_ST0_A0(void)
1990 {
1991     int new_fpstt;
1992     new_fpstt = (env->fpstt - 1) & 7;
1993     env->fpregs[new_fpstt] = helper_fldt((uint8_t *)A0);
1994     env->fpstt = new_fpstt;
1995     env->fptags[new_fpstt] = 0; /* validate stack entry */
1996 }
1997
1998 void helper_fstt_ST0_A0(void)
1999 {
2000     helper_fstt(ST0, (uint8_t *)A0);
2001 }
2002
2003 /* BCD ops */
2004
2005 #define MUL10(iv) ( iv + iv + (iv << 3) )
2006
2007 void helper_fbld_ST0_A0(void)
2008 {
2009     CPU86_LDouble tmp;
2010     uint64_t val;
2011     unsigned int v;
2012     int i;
2013
2014     val = 0;
2015     for(i = 8; i >= 0; i--) {
2016         v = ldub((uint8_t *)A0 + i);
2017         val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
2018     }
2019     tmp = val;
2020     if (ldub((uint8_t *)A0 + 9) & 0x80)
2021         tmp = -tmp;
2022     fpush();
2023     ST0 = tmp;
2024 }
2025
2026 void helper_fbst_ST0_A0(void)
2027 {
2028     CPU86_LDouble tmp;
2029     int v;
2030     uint8_t *mem_ref, *mem_end;
2031     int64_t val;
2032
2033     tmp = rint(ST0);
2034     val = (int64_t)tmp;
2035     mem_ref = (uint8_t *)A0;
2036     mem_end = mem_ref + 9;
2037     if (val < 0) {
2038         stb(mem_end, 0x80);
2039         val = -val;
2040     } else {
2041         stb(mem_end, 0x00);
2042     }
2043     while (mem_ref < mem_end) {
2044         if (val == 0)
2045             break;
2046         v = val % 100;
2047         val = val / 100;
2048         v = ((v / 10) << 4) | (v % 10);
2049         stb(mem_ref++, v);
2050     }
2051     while (mem_ref < mem_end) {
2052         stb(mem_ref++, 0);
2053     }
2054 }
2055
2056 void helper_f2xm1(void)
2057 {
2058     ST0 = pow(2.0,ST0) - 1.0;
2059 }
2060
2061 void helper_fyl2x(void)
2062 {
2063     CPU86_LDouble fptemp;
2064     
2065     fptemp = ST0;
2066     if (fptemp>0.0){
2067         fptemp = log(fptemp)/log(2.0);   /* log2(ST) */
2068         ST1 *= fptemp;
2069         fpop();
2070     } else { 
2071         env->fpus &= (~0x4700);
2072         env->fpus |= 0x400;
2073     }
2074 }
2075
2076 void helper_fptan(void)
2077 {
2078     CPU86_LDouble fptemp;
2079
2080     fptemp = ST0;
2081     if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2082         env->fpus |= 0x400;
2083     } else {
2084         ST0 = tan(fptemp);
2085         fpush();
2086         ST0 = 1.0;
2087         env->fpus &= (~0x400);  /* C2 <-- 0 */
2088         /* the above code is for  |arg| < 2**52 only */
2089     }
2090 }
2091
2092 void helper_fpatan(void)
2093 {
2094     CPU86_LDouble fptemp, fpsrcop;
2095
2096     fpsrcop = ST1;
2097     fptemp = ST0;
2098     ST1 = atan2(fpsrcop,fptemp);
2099     fpop();
2100 }
2101
2102 void helper_fxtract(void)
2103 {
2104     CPU86_LDoubleU temp;
2105     unsigned int expdif;
2106
2107     temp.d = ST0;
2108     expdif = EXPD(temp) - EXPBIAS;
2109     /*DP exponent bias*/
2110     ST0 = expdif;
2111     fpush();
2112     BIASEXPONENT(temp);
2113     ST0 = temp.d;
2114 }
2115
2116 void helper_fprem1(void)
2117 {
2118     CPU86_LDouble dblq, fpsrcop, fptemp;
2119     CPU86_LDoubleU fpsrcop1, fptemp1;
2120     int expdif;
2121     int q;
2122
2123     fpsrcop = ST0;
2124     fptemp = ST1;
2125     fpsrcop1.d = fpsrcop;
2126     fptemp1.d = fptemp;
2127     expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
2128     if (expdif < 53) {
2129         dblq = fpsrcop / fptemp;
2130         dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
2131         ST0 = fpsrcop - fptemp*dblq;
2132         q = (int)dblq; /* cutting off top bits is assumed here */
2133         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
2134                                 /* (C0,C1,C3) <-- (q2,q1,q0) */
2135         env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
2136         env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
2137         env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
2138     } else {
2139         env->fpus |= 0x400;  /* C2 <-- 1 */
2140         fptemp = pow(2.0, expdif-50);
2141         fpsrcop = (ST0 / ST1) / fptemp;
2142         /* fpsrcop = integer obtained by rounding to the nearest */
2143         fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)?
2144             floor(fpsrcop): ceil(fpsrcop);
2145         ST0 -= (ST1 * fpsrcop * fptemp);
2146     }
2147 }
2148
2149 void helper_fprem(void)
2150 {
2151     CPU86_LDouble dblq, fpsrcop, fptemp;
2152     CPU86_LDoubleU fpsrcop1, fptemp1;
2153     int expdif;
2154     int q;
2155     
2156     fpsrcop = ST0;
2157     fptemp = ST1;
2158     fpsrcop1.d = fpsrcop;
2159     fptemp1.d = fptemp;
2160     expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
2161     if ( expdif < 53 ) {
2162         dblq = fpsrcop / fptemp;
2163         dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
2164         ST0 = fpsrcop - fptemp*dblq;
2165         q = (int)dblq; /* cutting off top bits is assumed here */
2166         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
2167                                 /* (C0,C1,C3) <-- (q2,q1,q0) */
2168         env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
2169         env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
2170         env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
2171     } else {
2172         env->fpus |= 0x400;  /* C2 <-- 1 */
2173         fptemp = pow(2.0, expdif-50);
2174         fpsrcop = (ST0 / ST1) / fptemp;
2175         /* fpsrcop = integer obtained by chopping */
2176         fpsrcop = (fpsrcop < 0.0)?
2177             -(floor(fabs(fpsrcop))): floor(fpsrcop);
2178         ST0 -= (ST1 * fpsrcop * fptemp);
2179     }
2180 }
2181
2182 void helper_fyl2xp1(void)
2183 {
2184     CPU86_LDouble fptemp;
2185
2186     fptemp = ST0;
2187     if ((fptemp+1.0)>0.0) {
2188         fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
2189         ST1 *= fptemp;
2190         fpop();
2191     } else { 
2192         env->fpus &= (~0x4700);
2193         env->fpus |= 0x400;
2194     }
2195 }
2196
2197 void helper_fsqrt(void)
2198 {
2199     CPU86_LDouble fptemp;
2200
2201     fptemp = ST0;
2202     if (fptemp<0.0) { 
2203         env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
2204         env->fpus |= 0x400;
2205     }
2206     ST0 = sqrt(fptemp);
2207 }
2208
2209 void helper_fsincos(void)
2210 {
2211     CPU86_LDouble fptemp;
2212
2213     fptemp = ST0;
2214     if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2215         env->fpus |= 0x400;
2216     } else {
2217         ST0 = sin(fptemp);
2218         fpush();
2219         ST0 = cos(fptemp);
2220         env->fpus &= (~0x400);  /* C2 <-- 0 */
2221         /* the above code is for  |arg| < 2**63 only */
2222     }
2223 }
2224
2225 void helper_frndint(void)
2226 {
2227     CPU86_LDouble a;
2228
2229     a = ST0;
2230 #ifdef __arm__
2231     switch(env->fpuc & RC_MASK) {
2232     default:
2233     case RC_NEAR:
2234         asm("rndd %0, %1" : "=f" (a) : "f"(a));
2235         break;
2236     case RC_DOWN:
2237         asm("rnddm %0, %1" : "=f" (a) : "f"(a));
2238         break;
2239     case RC_UP:
2240         asm("rnddp %0, %1" : "=f" (a) : "f"(a));
2241         break;
2242     case RC_CHOP:
2243         asm("rnddz %0, %1" : "=f" (a) : "f"(a));
2244         break;
2245     }
2246 #else
2247     a = rint(a);
2248 #endif
2249     ST0 = a;
2250 }
2251
2252 void helper_fscale(void)
2253 {
2254     CPU86_LDouble fpsrcop, fptemp;
2255
2256     fpsrcop = 2.0;
2257     fptemp = pow(fpsrcop,ST1);
2258     ST0 *= fptemp;
2259 }
2260
2261 void helper_fsin(void)
2262 {
2263     CPU86_LDouble fptemp;
2264
2265     fptemp = ST0;
2266     if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2267         env->fpus |= 0x400;
2268     } else {
2269         ST0 = sin(fptemp);
2270         env->fpus &= (~0x400);  /* C2 <-- 0 */
2271         /* the above code is for  |arg| < 2**53 only */
2272     }
2273 }
2274
2275 void helper_fcos(void)
2276 {
2277     CPU86_LDouble fptemp;
2278
2279     fptemp = ST0;
2280     if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2281         env->fpus |= 0x400;
2282     } else {
2283         ST0 = cos(fptemp);
2284         env->fpus &= (~0x400);  /* C2 <-- 0 */
2285         /* the above code is for  |arg5 < 2**63 only */
2286     }
2287 }
2288
2289 void helper_fxam_ST0(void)
2290 {
2291     CPU86_LDoubleU temp;
2292     int expdif;
2293
2294     temp.d = ST0;
2295
2296     env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
2297     if (SIGND(temp))
2298         env->fpus |= 0x200; /* C1 <-- 1 */
2299
2300     expdif = EXPD(temp);
2301     if (expdif == MAXEXPD) {
2302         if (MANTD(temp) == 0)
2303             env->fpus |=  0x500 /*Infinity*/;
2304         else
2305             env->fpus |=  0x100 /*NaN*/;
2306     } else if (expdif == 0) {
2307         if (MANTD(temp) == 0)
2308             env->fpus |=  0x4000 /*Zero*/;
2309         else
2310             env->fpus |= 0x4400 /*Denormal*/;
2311     } else {
2312         env->fpus |= 0x400;
2313     }
2314 }
2315
2316 void helper_fstenv(uint8_t *ptr, int data32)
2317 {
2318     int fpus, fptag, exp, i;
2319     uint64_t mant;
2320     CPU86_LDoubleU tmp;
2321
2322     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2323     fptag = 0;
2324     for (i=7; i>=0; i--) {
2325         fptag <<= 2;
2326         if (env->fptags[i]) {
2327             fptag |= 3;
2328         } else {
2329             tmp.d = env->fpregs[i];
2330             exp = EXPD(tmp);
2331             mant = MANTD(tmp);
2332             if (exp == 0 && mant == 0) {
2333                 /* zero */
2334                 fptag |= 1;
2335             } else if (exp == 0 || exp == MAXEXPD
2336 #ifdef USE_X86LDOUBLE
2337                        || (mant & (1LL << 63)) == 0
2338 #endif
2339                        ) {
2340                 /* NaNs, infinity, denormal */
2341                 fptag |= 2;
2342             }
2343         }
2344     }
2345     if (data32) {
2346         /* 32 bit */
2347         stl(ptr, env->fpuc);
2348         stl(ptr + 4, fpus);
2349         stl(ptr + 8, fptag);
2350         stl(ptr + 12, 0); /* fpip */
2351         stl(ptr + 16, 0); /* fpcs */
2352         stl(ptr + 20, 0); /* fpoo */
2353         stl(ptr + 24, 0); /* fpos */
2354     } else {
2355         /* 16 bit */
2356         stw(ptr, env->fpuc);
2357         stw(ptr + 2, fpus);
2358         stw(ptr + 4, fptag);
2359         stw(ptr + 6, 0);
2360         stw(ptr + 8, 0);
2361         stw(ptr + 10, 0);
2362         stw(ptr + 12, 0);
2363     }
2364 }
2365
2366 void helper_fldenv(uint8_t *ptr, int data32)
2367 {
2368     int i, fpus, fptag;
2369
2370     if (data32) {
2371         env->fpuc = lduw(ptr);
2372         fpus = lduw(ptr + 4);
2373         fptag = lduw(ptr + 8);
2374     }
2375     else {
2376         env->fpuc = lduw(ptr);
2377         fpus = lduw(ptr + 2);
2378         fptag = lduw(ptr + 4);
2379     }
2380     env->fpstt = (fpus >> 11) & 7;
2381     env->fpus = fpus & ~0x3800;
2382     for(i = 0;i < 8; i++) {
2383         env->fptags[i] = ((fptag & 3) == 3);
2384         fptag >>= 2;
2385     }
2386 }
2387
2388 void helper_fsave(uint8_t *ptr, int data32)
2389 {
2390     CPU86_LDouble tmp;
2391     int i;
2392
2393     helper_fstenv(ptr, data32);
2394
2395     ptr += (14 << data32);
2396     for(i = 0;i < 8; i++) {
2397         tmp = ST(i);
2398         helper_fstt(tmp, ptr);
2399         ptr += 10;
2400     }
2401
2402     /* fninit */
2403     env->fpus = 0;
2404     env->fpstt = 0;
2405     env->fpuc = 0x37f;
2406     env->fptags[0] = 1;
2407     env->fptags[1] = 1;
2408     env->fptags[2] = 1;
2409     env->fptags[3] = 1;
2410     env->fptags[4] = 1;
2411     env->fptags[5] = 1;
2412     env->fptags[6] = 1;
2413     env->fptags[7] = 1;
2414 }
2415
2416 void helper_frstor(uint8_t *ptr, int data32)
2417 {
2418     CPU86_LDouble tmp;
2419     int i;
2420
2421     helper_fldenv(ptr, data32);
2422     ptr += (14 << data32);
2423
2424     for(i = 0;i < 8; i++) {
2425         tmp = helper_fldt(ptr);
2426         ST(i) = tmp;
2427         ptr += 10;
2428     }
2429 }
2430
2431 #if !defined(CONFIG_USER_ONLY) 
2432
2433 #define MMUSUFFIX _mmu
2434 #define GETPC() (__builtin_return_address(0))
2435
2436 #define SHIFT 0
2437 #include "softmmu_template.h"
2438
2439 #define SHIFT 1
2440 #include "softmmu_template.h"
2441
2442 #define SHIFT 2
2443 #include "softmmu_template.h"
2444
2445 #define SHIFT 3
2446 #include "softmmu_template.h"
2447
2448 #endif
2449
2450 /* try to fill the TLB and return an exception if error. If retaddr is
2451    NULL, it means that the function was called in C code (i.e. not
2452    from generated code or from helper.c) */
2453 /* XXX: fix it to restore all registers */
2454 void tlb_fill(unsigned long addr, int is_write, int is_user, void *retaddr)
2455 {
2456     TranslationBlock *tb;
2457     int ret;
2458     unsigned long pc;
2459     CPUX86State *saved_env;
2460
2461     /* XXX: hack to restore env in all cases, even if not called from
2462        generated code */
2463     saved_env = env;
2464     env = cpu_single_env;
2465
2466     ret = cpu_x86_handle_mmu_fault(env, addr, is_write, is_user, 1);
2467     if (ret) {
2468         if (retaddr) {
2469             /* now we have a real cpu fault */
2470             pc = (unsigned long)retaddr;
2471             tb = tb_find_pc(pc);
2472             if (tb) {
2473                 /* the PC is inside the translated code. It means that we have
2474                    a virtual CPU fault */
2475                 cpu_restore_state(tb, env, pc, NULL);
2476             }
2477         }
2478         raise_exception_err(EXCP0E_PAGE, env->error_code);
2479     }
2480     env = saved_env;
2481 }
This page took 0.158978 seconds and 2 git commands to generate.