]> Git Repo - qemu.git/blob - target-i386/helper.c
x86_64 fixes (initial patch by Filip Navara)
[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     fprintf(logfile, "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     regs_to_env();
113     longjmp(env->jmp_env, 1);
114 }
115
116 /* return non zero if error */
117 static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr,
118                                int selector)
119 {
120     SegmentCache *dt;
121     int index;
122     target_ulong ptr;
123
124     if (selector & 0x4)
125         dt = &env->ldt;
126     else
127         dt = &env->gdt;
128     index = selector & ~7;
129     if ((index + 7) > dt->limit)
130         return -1;
131     ptr = dt->base + index;
132     *e1_ptr = ldl_kernel(ptr);
133     *e2_ptr = ldl_kernel(ptr + 4);
134     return 0;
135 }
136                                      
137 static inline unsigned int get_seg_limit(uint32_t e1, uint32_t e2)
138 {
139     unsigned int limit;
140     limit = (e1 & 0xffff) | (e2 & 0x000f0000);
141     if (e2 & DESC_G_MASK)
142         limit = (limit << 12) | 0xfff;
143     return limit;
144 }
145
146 static inline uint32_t get_seg_base(uint32_t e1, uint32_t e2)
147 {
148     return ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
149 }
150
151 static inline void load_seg_cache_raw_dt(SegmentCache *sc, uint32_t e1, uint32_t e2)
152 {
153     sc->base = get_seg_base(e1, e2);
154     sc->limit = get_seg_limit(e1, e2);
155     sc->flags = e2;
156 }
157
158 /* init the segment cache in vm86 mode. */
159 static inline void load_seg_vm(int seg, int selector)
160 {
161     selector &= 0xffff;
162     cpu_x86_load_seg_cache(env, seg, selector, 
163                            (selector << 4), 0xffff, 0);
164 }
165
166 static inline void get_ss_esp_from_tss(uint32_t *ss_ptr, 
167                                        uint32_t *esp_ptr, int dpl)
168 {
169     int type, index, shift;
170     
171 #if 0
172     {
173         int i;
174         printf("TR: base=%p limit=%x\n", env->tr.base, env->tr.limit);
175         for(i=0;i<env->tr.limit;i++) {
176             printf("%02x ", env->tr.base[i]);
177             if ((i & 7) == 7) printf("\n");
178         }
179         printf("\n");
180     }
181 #endif
182
183     if (!(env->tr.flags & DESC_P_MASK))
184         cpu_abort(env, "invalid tss");
185     type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
186     if ((type & 7) != 1)
187         cpu_abort(env, "invalid tss type");
188     shift = type >> 3;
189     index = (dpl * 4 + 2) << shift;
190     if (index + (4 << shift) - 1 > env->tr.limit)
191         raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
192     if (shift == 0) {
193         *esp_ptr = lduw_kernel(env->tr.base + index);
194         *ss_ptr = lduw_kernel(env->tr.base + index + 2);
195     } else {
196         *esp_ptr = ldl_kernel(env->tr.base + index);
197         *ss_ptr = lduw_kernel(env->tr.base + index + 4);
198     }
199 }
200
201 /* XXX: merge with load_seg() */
202 static void tss_load_seg(int seg_reg, int selector)
203 {
204     uint32_t e1, e2;
205     int rpl, dpl, cpl;
206
207     if ((selector & 0xfffc) != 0) {
208         if (load_segment(&e1, &e2, selector) != 0)
209             raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
210         if (!(e2 & DESC_S_MASK))
211             raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
212         rpl = selector & 3;
213         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
214         cpl = env->hflags & HF_CPL_MASK;
215         if (seg_reg == R_CS) {
216             if (!(e2 & DESC_CS_MASK))
217                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
218             if (dpl != rpl)
219                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
220             if ((e2 & DESC_C_MASK) && dpl > rpl)
221                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
222                 
223         } else if (seg_reg == R_SS) {
224             /* SS must be writable data */
225             if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
226                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
227             if (dpl != cpl || dpl != rpl)
228                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
229         } else {
230             /* not readable code */
231             if ((e2 & DESC_CS_MASK) && !(e2 & DESC_R_MASK))
232                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
233             /* if data or non conforming code, checks the rights */
234             if (((e2 >> DESC_TYPE_SHIFT) & 0xf) < 12) {
235                 if (dpl < cpl || dpl < rpl)
236                     raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
237             }
238         }
239         if (!(e2 & DESC_P_MASK))
240             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
241         cpu_x86_load_seg_cache(env, seg_reg, selector, 
242                        get_seg_base(e1, e2),
243                        get_seg_limit(e1, e2),
244                        e2);
245     } else {
246         if (seg_reg == R_SS || seg_reg == R_CS) 
247             raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
248     }
249 }
250
251 #define SWITCH_TSS_JMP  0
252 #define SWITCH_TSS_IRET 1
253 #define SWITCH_TSS_CALL 2
254
255 /* XXX: restore CPU state in registers (PowerPC case) */
256 static void switch_tss(int tss_selector, 
257                        uint32_t e1, uint32_t e2, int source,
258                        uint32_t next_eip)
259 {
260     int tss_limit, tss_limit_max, type, old_tss_limit_max, old_type, v1, v2, i;
261     target_ulong tss_base;
262     uint32_t new_regs[8], new_segs[6];
263     uint32_t new_eflags, new_eip, new_cr3, new_ldt, new_trap;
264     uint32_t old_eflags, eflags_mask;
265     SegmentCache *dt;
266     int index;
267     target_ulong ptr;
268
269     type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
270 #ifdef DEBUG_PCALL
271     if (loglevel & CPU_LOG_PCALL)
272         fprintf(logfile, "switch_tss: sel=0x%04x type=%d src=%d\n", tss_selector, type, source);
273 #endif
274
275     /* if task gate, we read the TSS segment and we load it */
276     if (type == 5) {
277         if (!(e2 & DESC_P_MASK))
278             raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
279         tss_selector = e1 >> 16;
280         if (tss_selector & 4)
281             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
282         if (load_segment(&e1, &e2, tss_selector) != 0)
283             raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
284         if (e2 & DESC_S_MASK)
285             raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
286         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
287         if ((type & 7) != 1)
288             raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
289     }
290
291     if (!(e2 & DESC_P_MASK))
292         raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
293
294     if (type & 8)
295         tss_limit_max = 103;
296     else
297         tss_limit_max = 43;
298     tss_limit = get_seg_limit(e1, e2);
299     tss_base = get_seg_base(e1, e2);
300     if ((tss_selector & 4) != 0 || 
301         tss_limit < tss_limit_max)
302         raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
303     old_type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
304     if (old_type & 8)
305         old_tss_limit_max = 103;
306     else
307         old_tss_limit_max = 43;
308
309     /* read all the registers from the new TSS */
310     if (type & 8) {
311         /* 32 bit */
312         new_cr3 = ldl_kernel(tss_base + 0x1c);
313         new_eip = ldl_kernel(tss_base + 0x20);
314         new_eflags = ldl_kernel(tss_base + 0x24);
315         for(i = 0; i < 8; i++)
316             new_regs[i] = ldl_kernel(tss_base + (0x28 + i * 4));
317         for(i = 0; i < 6; i++)
318             new_segs[i] = lduw_kernel(tss_base + (0x48 + i * 4));
319         new_ldt = lduw_kernel(tss_base + 0x60);
320         new_trap = ldl_kernel(tss_base + 0x64);
321     } else {
322         /* 16 bit */
323         new_cr3 = 0;
324         new_eip = lduw_kernel(tss_base + 0x0e);
325         new_eflags = lduw_kernel(tss_base + 0x10);
326         for(i = 0; i < 8; i++)
327             new_regs[i] = lduw_kernel(tss_base + (0x12 + i * 2)) | 0xffff0000;
328         for(i = 0; i < 4; i++)
329             new_segs[i] = lduw_kernel(tss_base + (0x22 + i * 4));
330         new_ldt = lduw_kernel(tss_base + 0x2a);
331         new_segs[R_FS] = 0;
332         new_segs[R_GS] = 0;
333         new_trap = 0;
334     }
335     
336     /* NOTE: we must avoid memory exceptions during the task switch,
337        so we make dummy accesses before */
338     /* XXX: it can still fail in some cases, so a bigger hack is
339        necessary to valid the TLB after having done the accesses */
340
341     v1 = ldub_kernel(env->tr.base);
342     v2 = ldub(env->tr.base + old_tss_limit_max);
343     stb_kernel(env->tr.base, v1);
344     stb_kernel(env->tr.base + old_tss_limit_max, v2);
345     
346     /* clear busy bit (it is restartable) */
347     if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_IRET) {
348         target_ulong ptr;
349         uint32_t e2;
350         ptr = env->gdt.base + (env->tr.selector & ~7);
351         e2 = ldl_kernel(ptr + 4);
352         e2 &= ~DESC_TSS_BUSY_MASK;
353         stl_kernel(ptr + 4, e2);
354     }
355     old_eflags = compute_eflags();
356     if (source == SWITCH_TSS_IRET)
357         old_eflags &= ~NT_MASK;
358     
359     /* save the current state in the old TSS */
360     if (type & 8) {
361         /* 32 bit */
362         stl_kernel(env->tr.base + 0x20, next_eip);
363         stl_kernel(env->tr.base + 0x24, old_eflags);
364         stl_kernel(env->tr.base + (0x28 + 0 * 4), EAX);
365         stl_kernel(env->tr.base + (0x28 + 1 * 4), ECX);
366         stl_kernel(env->tr.base + (0x28 + 2 * 4), EDX);
367         stl_kernel(env->tr.base + (0x28 + 3 * 4), EBX);
368         stl_kernel(env->tr.base + (0x28 + 4 * 4), ESP);
369         stl_kernel(env->tr.base + (0x28 + 5 * 4), EBP);
370         stl_kernel(env->tr.base + (0x28 + 6 * 4), ESI);
371         stl_kernel(env->tr.base + (0x28 + 7 * 4), EDI);
372         for(i = 0; i < 6; i++)
373             stw_kernel(env->tr.base + (0x48 + i * 4), env->segs[i].selector);
374     } else {
375         /* 16 bit */
376         stw_kernel(env->tr.base + 0x0e, next_eip);
377         stw_kernel(env->tr.base + 0x10, old_eflags);
378         stw_kernel(env->tr.base + (0x12 + 0 * 2), EAX);
379         stw_kernel(env->tr.base + (0x12 + 1 * 2), ECX);
380         stw_kernel(env->tr.base + (0x12 + 2 * 2), EDX);
381         stw_kernel(env->tr.base + (0x12 + 3 * 2), EBX);
382         stw_kernel(env->tr.base + (0x12 + 4 * 2), ESP);
383         stw_kernel(env->tr.base + (0x12 + 5 * 2), EBP);
384         stw_kernel(env->tr.base + (0x12 + 6 * 2), ESI);
385         stw_kernel(env->tr.base + (0x12 + 7 * 2), EDI);
386         for(i = 0; i < 4; i++)
387             stw_kernel(env->tr.base + (0x22 + i * 4), env->segs[i].selector);
388     }
389     
390     /* now if an exception occurs, it will occurs in the next task
391        context */
392
393     if (source == SWITCH_TSS_CALL) {
394         stw_kernel(tss_base, env->tr.selector);
395         new_eflags |= NT_MASK;
396     }
397
398     /* set busy bit */
399     if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_CALL) {
400         target_ulong ptr;
401         uint32_t e2;
402         ptr = env->gdt.base + (tss_selector & ~7);
403         e2 = ldl_kernel(ptr + 4);
404         e2 |= DESC_TSS_BUSY_MASK;
405         stl_kernel(ptr + 4, e2);
406     }
407
408     /* set the new CPU state */
409     /* from this point, any exception which occurs can give problems */
410     env->cr[0] |= CR0_TS_MASK;
411     env->hflags |= HF_TS_MASK;
412     env->tr.selector = tss_selector;
413     env->tr.base = tss_base;
414     env->tr.limit = tss_limit;
415     env->tr.flags = e2 & ~DESC_TSS_BUSY_MASK;
416     
417     if ((type & 8) && (env->cr[0] & CR0_PG_MASK)) {
418         cpu_x86_update_cr3(env, new_cr3);
419     }
420     
421     /* load all registers without an exception, then reload them with
422        possible exception */
423     env->eip = new_eip;
424     eflags_mask = TF_MASK | AC_MASK | ID_MASK | 
425         IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK;
426     if (!(type & 8))
427         eflags_mask &= 0xffff;
428     load_eflags(new_eflags, eflags_mask);
429     /* XXX: what to do in 16 bit case ? */
430     EAX = new_regs[0];
431     ECX = new_regs[1];
432     EDX = new_regs[2];
433     EBX = new_regs[3];
434     ESP = new_regs[4];
435     EBP = new_regs[5];
436     ESI = new_regs[6];
437     EDI = new_regs[7];
438     if (new_eflags & VM_MASK) {
439         for(i = 0; i < 6; i++) 
440             load_seg_vm(i, new_segs[i]);
441         /* in vm86, CPL is always 3 */
442         cpu_x86_set_cpl(env, 3);
443     } else {
444         /* CPL is set the RPL of CS */
445         cpu_x86_set_cpl(env, new_segs[R_CS] & 3);
446         /* first just selectors as the rest may trigger exceptions */
447         for(i = 0; i < 6; i++)
448             cpu_x86_load_seg_cache(env, i, new_segs[i], 0, 0, 0);
449     }
450     
451     env->ldt.selector = new_ldt & ~4;
452     env->ldt.base = 0;
453     env->ldt.limit = 0;
454     env->ldt.flags = 0;
455
456     /* load the LDT */
457     if (new_ldt & 4)
458         raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
459
460     if ((new_ldt & 0xfffc) != 0) {
461         dt = &env->gdt;
462         index = new_ldt & ~7;
463         if ((index + 7) > dt->limit)
464             raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
465         ptr = dt->base + index;
466         e1 = ldl_kernel(ptr);
467         e2 = ldl_kernel(ptr + 4);
468         if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
469             raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
470         if (!(e2 & DESC_P_MASK))
471             raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
472         load_seg_cache_raw_dt(&env->ldt, e1, e2);
473     }
474     
475     /* load the segments */
476     if (!(new_eflags & VM_MASK)) {
477         tss_load_seg(R_CS, new_segs[R_CS]);
478         tss_load_seg(R_SS, new_segs[R_SS]);
479         tss_load_seg(R_ES, new_segs[R_ES]);
480         tss_load_seg(R_DS, new_segs[R_DS]);
481         tss_load_seg(R_FS, new_segs[R_FS]);
482         tss_load_seg(R_GS, new_segs[R_GS]);
483     }
484     
485     /* check that EIP is in the CS segment limits */
486     if (new_eip > env->segs[R_CS].limit) {
487         /* XXX: different exception if CALL ? */
488         raise_exception_err(EXCP0D_GPF, 0);
489     }
490 }
491
492 /* check if Port I/O is allowed in TSS */
493 static inline void check_io(int addr, int size)
494 {
495     int io_offset, val, mask;
496     
497     /* TSS must be a valid 32 bit one */
498     if (!(env->tr.flags & DESC_P_MASK) ||
499         ((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 ||
500         env->tr.limit < 103)
501         goto fail;
502     io_offset = lduw_kernel(env->tr.base + 0x66);
503     io_offset += (addr >> 3);
504     /* Note: the check needs two bytes */
505     if ((io_offset + 1) > env->tr.limit)
506         goto fail;
507     val = lduw_kernel(env->tr.base + io_offset);
508     val >>= (addr & 7);
509     mask = (1 << size) - 1;
510     /* all bits must be zero to allow the I/O */
511     if ((val & mask) != 0) {
512     fail:
513         raise_exception_err(EXCP0D_GPF, 0);
514     }
515 }
516
517 void check_iob_T0(void)
518 {
519     check_io(T0, 1);
520 }
521
522 void check_iow_T0(void)
523 {
524     check_io(T0, 2);
525 }
526
527 void check_iol_T0(void)
528 {
529     check_io(T0, 4);
530 }
531
532 void check_iob_DX(void)
533 {
534     check_io(EDX & 0xffff, 1);
535 }
536
537 void check_iow_DX(void)
538 {
539     check_io(EDX & 0xffff, 2);
540 }
541
542 void check_iol_DX(void)
543 {
544     check_io(EDX & 0xffff, 4);
545 }
546
547 static inline unsigned int get_sp_mask(unsigned int e2)
548 {
549     if (e2 & DESC_B_MASK)
550         return 0xffffffff;
551     else
552         return 0xffff;
553 }
554
555 /* XXX: add a is_user flag to have proper security support */
556 #define PUSHW(ssp, sp, sp_mask, val)\
557 {\
558     sp -= 2;\
559     stw_kernel((ssp) + (sp & (sp_mask)), (val));\
560 }
561
562 #define PUSHL(ssp, sp, sp_mask, val)\
563 {\
564     sp -= 4;\
565     stl_kernel((ssp) + (sp & (sp_mask)), (val));\
566 }
567
568 #define POPW(ssp, sp, sp_mask, val)\
569 {\
570     val = lduw_kernel((ssp) + (sp & (sp_mask)));\
571     sp += 2;\
572 }
573
574 #define POPL(ssp, sp, sp_mask, val)\
575 {\
576     val = (uint32_t)ldl_kernel((ssp) + (sp & (sp_mask)));\
577     sp += 4;\
578 }
579
580 /* protected mode interrupt */
581 static void do_interrupt_protected(int intno, int is_int, int error_code,
582                                    unsigned int next_eip, int is_hw)
583 {
584     SegmentCache *dt;
585     target_ulong ptr, ssp;
586     int type, dpl, selector, ss_dpl, cpl, sp_mask;
587     int has_error_code, new_stack, shift;
588     uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2;
589     uint32_t old_eip;
590
591     has_error_code = 0;
592     if (!is_int && !is_hw) {
593         switch(intno) {
594         case 8:
595         case 10:
596         case 11:
597         case 12:
598         case 13:
599         case 14:
600         case 17:
601             has_error_code = 1;
602             break;
603         }
604     }
605     if (is_int)
606         old_eip = next_eip;
607     else
608         old_eip = env->eip;
609
610     dt = &env->idt;
611     if (intno * 8 + 7 > dt->limit)
612         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
613     ptr = dt->base + intno * 8;
614     e1 = ldl_kernel(ptr);
615     e2 = ldl_kernel(ptr + 4);
616     /* check gate type */
617     type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
618     switch(type) {
619     case 5: /* task gate */
620         /* must do that check here to return the correct error code */
621         if (!(e2 & DESC_P_MASK))
622             raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
623         switch_tss(intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip);
624         if (has_error_code) {
625             int mask;
626             /* push the error code */
627             shift = (env->segs[R_CS].flags >> DESC_B_SHIFT) & 1;
628             if (env->segs[R_SS].flags & DESC_B_MASK)
629                 mask = 0xffffffff;
630             else
631                 mask = 0xffff;
632             esp = (ESP - (2 << shift)) & mask;
633             ssp = env->segs[R_SS].base + esp;
634             if (shift)
635                 stl_kernel(ssp, error_code);
636             else
637                 stw_kernel(ssp, error_code);
638             ESP = (esp & mask) | (ESP & ~mask);
639         }
640         return;
641     case 6: /* 286 interrupt gate */
642     case 7: /* 286 trap gate */
643     case 14: /* 386 interrupt gate */
644     case 15: /* 386 trap gate */
645         break;
646     default:
647         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
648         break;
649     }
650     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
651     cpl = env->hflags & HF_CPL_MASK;
652     /* check privledge if software int */
653     if (is_int && dpl < cpl)
654         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
655     /* check valid bit */
656     if (!(e2 & DESC_P_MASK))
657         raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
658     selector = e1 >> 16;
659     offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
660     if ((selector & 0xfffc) == 0)
661         raise_exception_err(EXCP0D_GPF, 0);
662
663     if (load_segment(&e1, &e2, selector) != 0)
664         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
665     if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
666         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
667     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
668     if (dpl > cpl)
669         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
670     if (!(e2 & DESC_P_MASK))
671         raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
672     if (!(e2 & DESC_C_MASK) && dpl < cpl) {
673         /* to inner priviledge */
674         get_ss_esp_from_tss(&ss, &esp, dpl);
675         if ((ss & 0xfffc) == 0)
676             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
677         if ((ss & 3) != dpl)
678             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
679         if (load_segment(&ss_e1, &ss_e2, ss) != 0)
680             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
681         ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
682         if (ss_dpl != dpl)
683             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
684         if (!(ss_e2 & DESC_S_MASK) ||
685             (ss_e2 & DESC_CS_MASK) ||
686             !(ss_e2 & DESC_W_MASK))
687             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
688         if (!(ss_e2 & DESC_P_MASK))
689             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
690         new_stack = 1;
691         sp_mask = get_sp_mask(ss_e2);
692         ssp = get_seg_base(ss_e1, ss_e2);
693     } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
694         /* to same priviledge */
695         if (env->eflags & VM_MASK)
696             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
697         new_stack = 0;
698         sp_mask = get_sp_mask(env->segs[R_SS].flags);
699         ssp = env->segs[R_SS].base;
700         esp = ESP;
701         dpl = cpl;
702     } else {
703         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
704         new_stack = 0; /* avoid warning */
705         sp_mask = 0; /* avoid warning */
706         ssp = 0; /* avoid warning */
707         esp = 0; /* avoid warning */
708     }
709
710     shift = type >> 3;
711
712 #if 0
713     /* XXX: check that enough room is available */
714     push_size = 6 + (new_stack << 2) + (has_error_code << 1);
715     if (env->eflags & VM_MASK)
716         push_size += 8;
717     push_size <<= shift;
718 #endif
719     if (shift == 1) {
720         if (new_stack) {
721             if (env->eflags & VM_MASK) {
722                 PUSHL(ssp, esp, sp_mask, env->segs[R_GS].selector);
723                 PUSHL(ssp, esp, sp_mask, env->segs[R_FS].selector);
724                 PUSHL(ssp, esp, sp_mask, env->segs[R_DS].selector);
725                 PUSHL(ssp, esp, sp_mask, env->segs[R_ES].selector);
726             }
727             PUSHL(ssp, esp, sp_mask, env->segs[R_SS].selector);
728             PUSHL(ssp, esp, sp_mask, ESP);
729         }
730         PUSHL(ssp, esp, sp_mask, compute_eflags());
731         PUSHL(ssp, esp, sp_mask, env->segs[R_CS].selector);
732         PUSHL(ssp, esp, sp_mask, old_eip);
733         if (has_error_code) {
734             PUSHL(ssp, esp, sp_mask, error_code);
735         }
736     } else {
737         if (new_stack) {
738             if (env->eflags & VM_MASK) {
739                 PUSHW(ssp, esp, sp_mask, env->segs[R_GS].selector);
740                 PUSHW(ssp, esp, sp_mask, env->segs[R_FS].selector);
741                 PUSHW(ssp, esp, sp_mask, env->segs[R_DS].selector);
742                 PUSHW(ssp, esp, sp_mask, env->segs[R_ES].selector);
743             }
744             PUSHW(ssp, esp, sp_mask, env->segs[R_SS].selector);
745             PUSHW(ssp, esp, sp_mask, ESP);
746         }
747         PUSHW(ssp, esp, sp_mask, compute_eflags());
748         PUSHW(ssp, esp, sp_mask, env->segs[R_CS].selector);
749         PUSHW(ssp, esp, sp_mask, old_eip);
750         if (has_error_code) {
751             PUSHW(ssp, esp, sp_mask, error_code);
752         }
753     }
754     
755     if (new_stack) {
756         if (env->eflags & VM_MASK) {
757             cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0, 0);
758             cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0, 0);
759             cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0, 0);
760             cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0, 0);
761         }
762         ss = (ss & ~3) | dpl;
763         cpu_x86_load_seg_cache(env, R_SS, ss, 
764                                ssp, get_seg_limit(ss_e1, ss_e2), ss_e2);
765     }
766     ESP = (ESP & ~sp_mask) | (esp & sp_mask);
767
768     selector = (selector & ~3) | dpl;
769     cpu_x86_load_seg_cache(env, R_CS, selector, 
770                    get_seg_base(e1, e2),
771                    get_seg_limit(e1, e2),
772                    e2);
773     cpu_x86_set_cpl(env, dpl);
774     env->eip = offset;
775
776     /* interrupt gate clear IF mask */
777     if ((type & 1) == 0) {
778         env->eflags &= ~IF_MASK;
779     }
780     env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
781 }
782
783 #ifdef TARGET_X86_64
784
785 #define PUSHQ(sp, val)\
786 {\
787     sp -= 8;\
788     stq_kernel(sp, (val));\
789 }
790
791 #define POPQ(sp, val)\
792 {\
793     val = ldq_kernel(sp);\
794     sp += 8;\
795 }
796
797 static inline target_ulong get_rsp_from_tss(int level)
798 {
799     int index;
800     
801 #if 0
802     printf("TR: base=" TARGET_FMT_lx " limit=%x\n", 
803            env->tr.base, env->tr.limit);
804 #endif
805
806     if (!(env->tr.flags & DESC_P_MASK))
807         cpu_abort(env, "invalid tss");
808     index = 8 * level + 4;
809     if ((index + 7) > env->tr.limit)
810         raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
811     return ldq_kernel(env->tr.base + index);
812 }
813
814 /* 64 bit interrupt */
815 static void do_interrupt64(int intno, int is_int, int error_code,
816                            target_ulong next_eip, int is_hw)
817 {
818     SegmentCache *dt;
819     target_ulong ptr;
820     int type, dpl, selector, cpl, ist;
821     int has_error_code, new_stack;
822     uint32_t e1, e2, e3, ss;
823     target_ulong old_eip, esp, offset;
824
825     has_error_code = 0;
826     if (!is_int && !is_hw) {
827         switch(intno) {
828         case 8:
829         case 10:
830         case 11:
831         case 12:
832         case 13:
833         case 14:
834         case 17:
835             has_error_code = 1;
836             break;
837         }
838     }
839     if (is_int)
840         old_eip = next_eip;
841     else
842         old_eip = env->eip;
843
844     dt = &env->idt;
845     if (intno * 16 + 15 > dt->limit)
846         raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
847     ptr = dt->base + intno * 16;
848     e1 = ldl_kernel(ptr);
849     e2 = ldl_kernel(ptr + 4);
850     e3 = ldl_kernel(ptr + 8);
851     /* check gate type */
852     type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
853     switch(type) {
854     case 14: /* 386 interrupt gate */
855     case 15: /* 386 trap gate */
856         break;
857     default:
858         raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
859         break;
860     }
861     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
862     cpl = env->hflags & HF_CPL_MASK;
863     /* check privledge if software int */
864     if (is_int && dpl < cpl)
865         raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
866     /* check valid bit */
867     if (!(e2 & DESC_P_MASK))
868         raise_exception_err(EXCP0B_NOSEG, intno * 16 + 2);
869     selector = e1 >> 16;
870     offset = ((target_ulong)e3 << 32) | (e2 & 0xffff0000) | (e1 & 0x0000ffff);
871     ist = e2 & 7;
872     if ((selector & 0xfffc) == 0)
873         raise_exception_err(EXCP0D_GPF, 0);
874
875     if (load_segment(&e1, &e2, selector) != 0)
876         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
877     if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
878         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
879     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
880     if (dpl > cpl)
881         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
882     if (!(e2 & DESC_P_MASK))
883         raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
884     if (!(e2 & DESC_L_MASK) || (e2 & DESC_B_MASK))
885         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
886     if ((!(e2 & DESC_C_MASK) && dpl < cpl) || ist != 0) {
887         /* to inner priviledge */
888         if (ist != 0)
889             esp = get_rsp_from_tss(ist + 3);
890         else
891             esp = get_rsp_from_tss(dpl);
892         ss = 0;
893         new_stack = 1;
894     } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
895         /* to same priviledge */
896         if (env->eflags & VM_MASK)
897             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
898         new_stack = 0;
899         esp = ESP & ~0xf; /* align stack */
900         dpl = cpl;
901     } else {
902         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
903         new_stack = 0; /* avoid warning */
904         esp = 0; /* avoid warning */
905     }
906
907     PUSHQ(esp, env->segs[R_SS].selector);
908     PUSHQ(esp, ESP);
909     PUSHQ(esp, compute_eflags());
910     PUSHQ(esp, env->segs[R_CS].selector);
911     PUSHQ(esp, old_eip);
912     if (has_error_code) {
913         PUSHQ(esp, error_code);
914     }
915     
916     if (new_stack) {
917         ss = 0 | dpl;
918         cpu_x86_load_seg_cache(env, R_SS, ss, 0, 0, 0);
919     }
920     ESP = esp;
921
922     selector = (selector & ~3) | dpl;
923     cpu_x86_load_seg_cache(env, R_CS, selector, 
924                    get_seg_base(e1, e2),
925                    get_seg_limit(e1, e2),
926                    e2);
927     cpu_x86_set_cpl(env, dpl);
928     env->eip = offset;
929
930     /* interrupt gate clear IF mask */
931     if ((type & 1) == 0) {
932         env->eflags &= ~IF_MASK;
933     }
934     env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
935 }
936 #endif
937
938 void helper_syscall(int next_eip_addend)
939 {
940     int selector;
941
942     if (!(env->efer & MSR_EFER_SCE)) {
943         raise_exception_err(EXCP06_ILLOP, 0);
944     }
945     selector = (env->star >> 32) & 0xffff;
946 #ifdef TARGET_X86_64
947     if (env->hflags & HF_LMA_MASK) {
948         ECX = env->eip + next_eip_addend;
949         env->regs[11] = compute_eflags();
950
951         cpu_x86_set_cpl(env, 0);
952         cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, 
953                            0, 0xffffffff, 
954                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
955                                DESC_S_MASK |
956                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
957         cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc, 
958                                0, 0xffffffff,
959                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
960                                DESC_S_MASK |
961                                DESC_W_MASK | DESC_A_MASK);
962         env->eflags &= ~env->fmask;
963         if (env->hflags & HF_CS64_MASK)
964             env->eip = env->lstar;
965         else
966             env->eip = env->cstar;
967     } else 
968 #endif
969     {
970         ECX = (uint32_t)(env->eip + next_eip_addend);
971         
972         cpu_x86_set_cpl(env, 0);
973         cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, 
974                            0, 0xffffffff, 
975                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
976                                DESC_S_MASK |
977                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
978         cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc, 
979                                0, 0xffffffff,
980                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
981                                DESC_S_MASK |
982                                DESC_W_MASK | DESC_A_MASK);
983         env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
984         env->eip = (uint32_t)env->star;
985     }
986 }
987
988 void helper_sysret(int dflag)
989 {
990     int cpl, selector;
991
992     if (!(env->efer & MSR_EFER_SCE)) {
993         raise_exception_err(EXCP06_ILLOP, 0);
994     }
995     cpl = env->hflags & HF_CPL_MASK;
996     if (!(env->cr[0] & CR0_PE_MASK) || cpl != 0) {
997         raise_exception_err(EXCP0D_GPF, 0);
998     }
999     selector = (env->star >> 48) & 0xffff;
1000 #ifdef TARGET_X86_64
1001     if (env->hflags & HF_LMA_MASK) {
1002         if (dflag == 2) {
1003             cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3, 
1004                                    0, 0xffffffff, 
1005                                    DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1006                                    DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1007                                    DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | 
1008                                    DESC_L_MASK);
1009             env->eip = ECX;
1010         } else {
1011             cpu_x86_load_seg_cache(env, R_CS, selector | 3, 
1012                                    0, 0xffffffff, 
1013                                    DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1014                                    DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1015                                    DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1016             env->eip = (uint32_t)ECX;
1017         }
1018         cpu_x86_load_seg_cache(env, R_SS, selector + 8, 
1019                                0, 0xffffffff,
1020                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1021                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1022                                DESC_W_MASK | DESC_A_MASK);
1023         load_eflags((uint32_t)(env->regs[11]), TF_MASK | AC_MASK | ID_MASK | 
1024                     IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK);
1025         cpu_x86_set_cpl(env, 3);
1026     } else 
1027 #endif
1028     {
1029         cpu_x86_load_seg_cache(env, R_CS, selector | 3, 
1030                                0, 0xffffffff, 
1031                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1032                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1033                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1034         env->eip = (uint32_t)ECX;
1035         cpu_x86_load_seg_cache(env, R_SS, selector + 8, 
1036                                0, 0xffffffff,
1037                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1038                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1039                                DESC_W_MASK | DESC_A_MASK);
1040         env->eflags |= IF_MASK;
1041         cpu_x86_set_cpl(env, 3);
1042     }
1043 #ifdef USE_KQEMU
1044     if (kqemu_is_ok(env)) {
1045         if (env->hflags & HF_LMA_MASK)
1046             CC_OP = CC_OP_EFLAGS;
1047         env->exception_index = -1;
1048         cpu_loop_exit();
1049     }
1050 #endif
1051 }
1052
1053 /* real mode interrupt */
1054 static void do_interrupt_real(int intno, int is_int, int error_code,
1055                               unsigned int next_eip)
1056 {
1057     SegmentCache *dt;
1058     target_ulong ptr, ssp;
1059     int selector;
1060     uint32_t offset, esp;
1061     uint32_t old_cs, old_eip;
1062
1063     /* real mode (simpler !) */
1064     dt = &env->idt;
1065     if (intno * 4 + 3 > dt->limit)
1066         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
1067     ptr = dt->base + intno * 4;
1068     offset = lduw_kernel(ptr);
1069     selector = lduw_kernel(ptr + 2);
1070     esp = ESP;
1071     ssp = env->segs[R_SS].base;
1072     if (is_int)
1073         old_eip = next_eip;
1074     else
1075         old_eip = env->eip;
1076     old_cs = env->segs[R_CS].selector;
1077     /* XXX: use SS segment size ? */
1078     PUSHW(ssp, esp, 0xffff, compute_eflags());
1079     PUSHW(ssp, esp, 0xffff, old_cs);
1080     PUSHW(ssp, esp, 0xffff, old_eip);
1081     
1082     /* update processor state */
1083     ESP = (ESP & ~0xffff) | (esp & 0xffff);
1084     env->eip = offset;
1085     env->segs[R_CS].selector = selector;
1086     env->segs[R_CS].base = (selector << 4);
1087     env->eflags &= ~(IF_MASK | TF_MASK | AC_MASK | RF_MASK);
1088 }
1089
1090 /* fake user mode interrupt */
1091 void do_interrupt_user(int intno, int is_int, int error_code, 
1092                        target_ulong next_eip)
1093 {
1094     SegmentCache *dt;
1095     target_ulong ptr;
1096     int dpl, cpl;
1097     uint32_t e2;
1098
1099     dt = &env->idt;
1100     ptr = dt->base + (intno * 8);
1101     e2 = ldl_kernel(ptr + 4);
1102     
1103     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1104     cpl = env->hflags & HF_CPL_MASK;
1105     /* check privledge if software int */
1106     if (is_int && dpl < cpl)
1107         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
1108
1109     /* Since we emulate only user space, we cannot do more than
1110        exiting the emulation with the suitable exception and error
1111        code */
1112     if (is_int)
1113         EIP = next_eip;
1114 }
1115
1116 /*
1117  * Begin execution of an interruption. is_int is TRUE if coming from
1118  * the int instruction. next_eip is the EIP value AFTER the interrupt
1119  * instruction. It is only relevant if is_int is TRUE.  
1120  */
1121 void do_interrupt(int intno, int is_int, int error_code, 
1122                   target_ulong next_eip, int is_hw)
1123 {
1124 #ifdef DEBUG_PCALL
1125     if (loglevel & (CPU_LOG_PCALL | CPU_LOG_INT)) {
1126         if ((env->cr[0] & CR0_PE_MASK)) {
1127             static int count;
1128             fprintf(logfile, "%6d: v=%02x e=%04x i=%d cpl=%d IP=%04x:" TARGET_FMT_lx " pc=" TARGET_FMT_lx " SP=%04x:" TARGET_FMT_lx,
1129                     count, intno, error_code, is_int,
1130                     env->hflags & HF_CPL_MASK,
1131                     env->segs[R_CS].selector, EIP,
1132                     (int)env->segs[R_CS].base + EIP,
1133                     env->segs[R_SS].selector, ESP);
1134             if (intno == 0x0e) {
1135                 fprintf(logfile, " CR2=" TARGET_FMT_lx, env->cr[2]);
1136             } else {
1137                 fprintf(logfile, " EAX=" TARGET_FMT_lx, EAX);
1138             }
1139             fprintf(logfile, "\n");
1140 #if 0
1141             cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1142             {
1143                 int i;
1144                 uint8_t *ptr;
1145                 fprintf(logfile, "       code=");
1146                 ptr = env->segs[R_CS].base + env->eip;
1147                 for(i = 0; i < 16; i++) {
1148                     fprintf(logfile, " %02x", ldub(ptr + i));
1149                 }
1150                 fprintf(logfile, "\n");
1151             }
1152 #endif
1153             count++;
1154         }
1155     }
1156 #endif
1157     if (env->cr[0] & CR0_PE_MASK) {
1158 #if TARGET_X86_64
1159         if (env->hflags & HF_LMA_MASK) {
1160             do_interrupt64(intno, is_int, error_code, next_eip, is_hw);
1161         } else
1162 #endif
1163         {
1164             do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);
1165         }
1166     } else {
1167         do_interrupt_real(intno, is_int, error_code, next_eip);
1168     }
1169 }
1170
1171 /*
1172  * Signal an interruption. It is executed in the main CPU loop.
1173  * is_int is TRUE if coming from the int instruction. next_eip is the
1174  * EIP value AFTER the interrupt instruction. It is only relevant if
1175  * is_int is TRUE.  
1176  */
1177 void raise_interrupt(int intno, int is_int, int error_code, 
1178                      int next_eip_addend)
1179 {
1180     env->exception_index = intno;
1181     env->error_code = error_code;
1182     env->exception_is_int = is_int;
1183     env->exception_next_eip = env->eip + next_eip_addend;
1184     cpu_loop_exit();
1185 }
1186
1187 /* same as raise_exception_err, but do not restore global registers */
1188 static void raise_exception_err_norestore(int exception_index, int error_code)
1189 {
1190     env->exception_index = exception_index;
1191     env->error_code = error_code;
1192     env->exception_is_int = 0;
1193     env->exception_next_eip = 0;
1194     longjmp(env->jmp_env, 1);
1195 }
1196
1197 /* shortcuts to generate exceptions */
1198
1199 void (raise_exception_err)(int exception_index, int error_code)
1200 {
1201     raise_interrupt(exception_index, 0, error_code, 0);
1202 }
1203
1204 void raise_exception(int exception_index)
1205 {
1206     raise_interrupt(exception_index, 0, 0, 0);
1207 }
1208
1209 #ifdef BUGGY_GCC_DIV64
1210 /* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we
1211    call it from another function */
1212 uint32_t div32(uint32_t *q_ptr, uint64_t num, uint32_t den)
1213 {
1214     *q_ptr = num / den;
1215     return num % den;
1216 }
1217
1218 int32_t idiv32(int32_t *q_ptr, int64_t num, int32_t den)
1219 {
1220     *q_ptr = num / den;
1221     return num % den;
1222 }
1223 #endif
1224
1225 void helper_divl_EAX_T0(void)
1226 {
1227     unsigned int den, q, r;
1228     uint64_t num;
1229     
1230     num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1231     den = T0;
1232     if (den == 0) {
1233         raise_exception(EXCP00_DIVZ);
1234     }
1235 #ifdef BUGGY_GCC_DIV64
1236     r = div32(&q, num, den);
1237 #else
1238     q = (num / den);
1239     r = (num % den);
1240 #endif
1241     EAX = (uint32_t)q;
1242     EDX = (uint32_t)r;
1243 }
1244
1245 void helper_idivl_EAX_T0(void)
1246 {
1247     int den, q, r;
1248     int64_t num;
1249     
1250     num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1251     den = T0;
1252     if (den == 0) {
1253         raise_exception(EXCP00_DIVZ);
1254     }
1255 #ifdef BUGGY_GCC_DIV64
1256     r = idiv32(&q, num, den);
1257 #else
1258     q = (num / den);
1259     r = (num % den);
1260 #endif
1261     EAX = (uint32_t)q;
1262     EDX = (uint32_t)r;
1263 }
1264
1265 void helper_cmpxchg8b(void)
1266 {
1267     uint64_t d;
1268     int eflags;
1269
1270     eflags = cc_table[CC_OP].compute_all();
1271     d = ldq(A0);
1272     if (d == (((uint64_t)EDX << 32) | EAX)) {
1273         stq(A0, ((uint64_t)ECX << 32) | EBX);
1274         eflags |= CC_Z;
1275     } else {
1276         EDX = d >> 32;
1277         EAX = d;
1278         eflags &= ~CC_Z;
1279     }
1280     CC_SRC = eflags;
1281 }
1282
1283 void helper_cpuid(void)
1284 {
1285     uint32_t index;
1286     index = (uint32_t)EAX;
1287     
1288     /* test if maximum index reached */
1289     if (index & 0x80000000) {
1290         if (index > env->cpuid_xlevel) 
1291             index = env->cpuid_level;
1292     } else {
1293         if (index > env->cpuid_level) 
1294             index = env->cpuid_level;
1295     }
1296         
1297     switch(index) {
1298     case 0:
1299         EAX = env->cpuid_level;
1300         EBX = env->cpuid_vendor1;
1301         EDX = env->cpuid_vendor2;
1302         ECX = env->cpuid_vendor3;
1303         break;
1304     case 1:
1305         EAX = env->cpuid_version;
1306         EBX = 0;
1307         ECX = env->cpuid_ext_features;
1308         EDX = env->cpuid_features;
1309         break;
1310     case 2:
1311         /* cache info: needed for Pentium Pro compatibility */
1312         EAX = 0x410601;
1313         EBX = 0;
1314         ECX = 0;
1315         EDX = 0;
1316         break;
1317     case 0x80000000:
1318         EAX = env->cpuid_xlevel;
1319         EBX = env->cpuid_vendor1;
1320         EDX = env->cpuid_vendor2;
1321         ECX = env->cpuid_vendor3;
1322         break;
1323     case 0x80000001:
1324         EAX = env->cpuid_features;
1325         EBX = 0;
1326         ECX = 0;
1327         EDX = env->cpuid_ext2_features;
1328         break;
1329     case 0x80000002:
1330     case 0x80000003:
1331     case 0x80000004:
1332         EAX = env->cpuid_model[(index - 0x80000002) * 4 + 0];
1333         EBX = env->cpuid_model[(index - 0x80000002) * 4 + 1];
1334         ECX = env->cpuid_model[(index - 0x80000002) * 4 + 2];
1335         EDX = env->cpuid_model[(index - 0x80000002) * 4 + 3];
1336         break;
1337     case 0x80000005:
1338         /* cache info (L1 cache) */
1339         EAX = 0x01ff01ff;
1340         EBX = 0x01ff01ff;
1341         ECX = 0x40020140;
1342         EDX = 0x40020140;
1343         break;
1344     case 0x80000006:
1345         /* cache info (L2 cache) */
1346         EAX = 0;
1347         EBX = 0x42004200;
1348         ECX = 0x02008140;
1349         EDX = 0;
1350         break;
1351     case 0x80000008:
1352         /* virtual & phys address size in low 2 bytes. */
1353         EAX = 0x00003028;
1354         EBX = 0;
1355         ECX = 0;
1356         EDX = 0;
1357         break;
1358     default:
1359         /* reserved values: zero */
1360         EAX = 0;
1361         EBX = 0;
1362         ECX = 0;
1363         EDX = 0;
1364         break;
1365     }
1366 }
1367
1368 void helper_enter_level(int level, int data32)
1369 {
1370     target_ulong ssp;
1371     uint32_t esp_mask, esp, ebp;
1372
1373     esp_mask = get_sp_mask(env->segs[R_SS].flags);
1374     ssp = env->segs[R_SS].base;
1375     ebp = EBP;
1376     esp = ESP;
1377     if (data32) {
1378         /* 32 bit */
1379         esp -= 4;
1380         while (--level) {
1381             esp -= 4;
1382             ebp -= 4;
1383             stl(ssp + (esp & esp_mask), ldl(ssp + (ebp & esp_mask)));
1384         }
1385         esp -= 4;
1386         stl(ssp + (esp & esp_mask), T1);
1387     } else {
1388         /* 16 bit */
1389         esp -= 2;
1390         while (--level) {
1391             esp -= 2;
1392             ebp -= 2;
1393             stw(ssp + (esp & esp_mask), lduw(ssp + (ebp & esp_mask)));
1394         }
1395         esp -= 2;
1396         stw(ssp + (esp & esp_mask), T1);
1397     }
1398 }
1399
1400 #ifdef TARGET_X86_64
1401 void helper_enter64_level(int level, int data64)
1402 {
1403     target_ulong esp, ebp;
1404     ebp = EBP;
1405     esp = ESP;
1406
1407     if (data64) {
1408         /* 64 bit */
1409         esp -= 8;
1410         while (--level) {
1411             esp -= 8;
1412             ebp -= 8;
1413             stq(esp, ldq(ebp));
1414         }
1415         esp -= 8;
1416         stq(esp, T1);
1417     } else {
1418         /* 16 bit */
1419         esp -= 2;
1420         while (--level) {
1421             esp -= 2;
1422             ebp -= 2;
1423             stw(esp, lduw(ebp));
1424         }
1425         esp -= 2;
1426         stw(esp, T1);
1427     }
1428 }
1429 #endif
1430
1431 void helper_lldt_T0(void)
1432 {
1433     int selector;
1434     SegmentCache *dt;
1435     uint32_t e1, e2;
1436     int index, entry_limit;
1437     target_ulong ptr;
1438     
1439     selector = T0 & 0xffff;
1440     if ((selector & 0xfffc) == 0) {
1441         /* XXX: NULL selector case: invalid LDT */
1442         env->ldt.base = 0;
1443         env->ldt.limit = 0;
1444     } else {
1445         if (selector & 0x4)
1446             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1447         dt = &env->gdt;
1448         index = selector & ~7;
1449 #ifdef TARGET_X86_64
1450         if (env->hflags & HF_LMA_MASK)
1451             entry_limit = 15;
1452         else
1453 #endif            
1454             entry_limit = 7;
1455         if ((index + entry_limit) > dt->limit)
1456             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1457         ptr = dt->base + index;
1458         e1 = ldl_kernel(ptr);
1459         e2 = ldl_kernel(ptr + 4);
1460         if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
1461             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1462         if (!(e2 & DESC_P_MASK))
1463             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
1464 #ifdef TARGET_X86_64
1465         if (env->hflags & HF_LMA_MASK) {
1466             uint32_t e3;
1467             e3 = ldl_kernel(ptr + 8);
1468             load_seg_cache_raw_dt(&env->ldt, e1, e2);
1469             env->ldt.base |= (target_ulong)e3 << 32;
1470         } else
1471 #endif
1472         {
1473             load_seg_cache_raw_dt(&env->ldt, e1, e2);
1474         }
1475     }
1476     env->ldt.selector = selector;
1477 }
1478
1479 void helper_ltr_T0(void)
1480 {
1481     int selector;
1482     SegmentCache *dt;
1483     uint32_t e1, e2;
1484     int index, type, entry_limit;
1485     target_ulong ptr;
1486     
1487     selector = T0 & 0xffff;
1488     if ((selector & 0xfffc) == 0) {
1489         /* NULL selector case: invalid TR */
1490         env->tr.base = 0;
1491         env->tr.limit = 0;
1492         env->tr.flags = 0;
1493     } else {
1494         if (selector & 0x4)
1495             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1496         dt = &env->gdt;
1497         index = selector & ~7;
1498 #ifdef TARGET_X86_64
1499         if (env->hflags & HF_LMA_MASK)
1500             entry_limit = 15;
1501         else
1502 #endif            
1503             entry_limit = 7;
1504         if ((index + entry_limit) > dt->limit)
1505             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1506         ptr = dt->base + index;
1507         e1 = ldl_kernel(ptr);
1508         e2 = ldl_kernel(ptr + 4);
1509         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
1510         if ((e2 & DESC_S_MASK) || 
1511             (type != 1 && type != 9))
1512             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1513         if (!(e2 & DESC_P_MASK))
1514             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
1515 #ifdef TARGET_X86_64
1516         if (env->hflags & HF_LMA_MASK) {
1517             uint32_t e3;
1518             e3 = ldl_kernel(ptr + 8);
1519             load_seg_cache_raw_dt(&env->tr, e1, e2);
1520             env->tr.base |= (target_ulong)e3 << 32;
1521         } else 
1522 #endif
1523         {
1524             load_seg_cache_raw_dt(&env->tr, e1, e2);
1525         }
1526         e2 |= DESC_TSS_BUSY_MASK;
1527         stl_kernel(ptr + 4, e2);
1528     }
1529     env->tr.selector = selector;
1530 }
1531
1532 /* only works if protected mode and not VM86. seg_reg must be != R_CS */
1533 void load_seg(int seg_reg, int selector)
1534 {
1535     uint32_t e1, e2;
1536     int cpl, dpl, rpl;
1537     SegmentCache *dt;
1538     int index;
1539     target_ulong ptr;
1540
1541     selector &= 0xffff;
1542     cpl = env->hflags & HF_CPL_MASK;
1543     if ((selector & 0xfffc) == 0) {
1544         /* null selector case */
1545         if (seg_reg == R_SS
1546 #ifdef TARGET_X86_64
1547             && (!(env->hflags & HF_CS64_MASK) || cpl == 3)
1548 #endif
1549             )
1550             raise_exception_err(EXCP0D_GPF, 0);
1551         cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0);
1552     } else {
1553         
1554         if (selector & 0x4)
1555             dt = &env->ldt;
1556         else
1557             dt = &env->gdt;
1558         index = selector & ~7;
1559         if ((index + 7) > dt->limit)
1560             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1561         ptr = dt->base + index;
1562         e1 = ldl_kernel(ptr);
1563         e2 = ldl_kernel(ptr + 4);
1564         
1565         if (!(e2 & DESC_S_MASK))
1566             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1567         rpl = selector & 3;
1568         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1569         if (seg_reg == R_SS) {
1570             /* must be writable segment */
1571             if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
1572                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1573             if (rpl != cpl || dpl != cpl)
1574                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1575         } else {
1576             /* must be readable segment */
1577             if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK)
1578                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1579             
1580             if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
1581                 /* if not conforming code, test rights */
1582                 if (dpl < cpl || dpl < rpl)
1583                     raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1584             }
1585         }
1586
1587         if (!(e2 & DESC_P_MASK)) {
1588             if (seg_reg == R_SS)
1589                 raise_exception_err(EXCP0C_STACK, selector & 0xfffc);
1590             else
1591                 raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
1592         }
1593
1594         /* set the access bit if not already set */
1595         if (!(e2 & DESC_A_MASK)) {
1596             e2 |= DESC_A_MASK;
1597             stl_kernel(ptr + 4, e2);
1598         }
1599
1600         cpu_x86_load_seg_cache(env, seg_reg, selector, 
1601                        get_seg_base(e1, e2),
1602                        get_seg_limit(e1, e2),
1603                        e2);
1604 #if 0
1605         fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx flags=%08x\n", 
1606                 selector, (unsigned long)sc->base, sc->limit, sc->flags);
1607 #endif
1608     }
1609 }
1610
1611 /* protected mode jump */
1612 void helper_ljmp_protected_T0_T1(int next_eip_addend)
1613 {
1614     int new_cs, gate_cs, type;
1615     uint32_t e1, e2, cpl, dpl, rpl, limit;
1616     target_ulong new_eip, next_eip;
1617     
1618     new_cs = T0;
1619     new_eip = T1;
1620     if ((new_cs & 0xfffc) == 0)
1621         raise_exception_err(EXCP0D_GPF, 0);
1622     if (load_segment(&e1, &e2, new_cs) != 0)
1623         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1624     cpl = env->hflags & HF_CPL_MASK;
1625     if (e2 & DESC_S_MASK) {
1626         if (!(e2 & DESC_CS_MASK))
1627             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1628         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1629         if (e2 & DESC_C_MASK) {
1630             /* conforming code segment */
1631             if (dpl > cpl)
1632                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1633         } else {
1634             /* non conforming code segment */
1635             rpl = new_cs & 3;
1636             if (rpl > cpl)
1637                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1638             if (dpl != cpl)
1639                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1640         }
1641         if (!(e2 & DESC_P_MASK))
1642             raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
1643         limit = get_seg_limit(e1, e2);
1644         if (new_eip > limit && 
1645             !(env->hflags & HF_LMA_MASK) && !(e2 & DESC_L_MASK))
1646             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1647         cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
1648                        get_seg_base(e1, e2), limit, e2);
1649         EIP = new_eip;
1650     } else {
1651         /* jump to call or task gate */
1652         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1653         rpl = new_cs & 3;
1654         cpl = env->hflags & HF_CPL_MASK;
1655         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
1656         switch(type) {
1657         case 1: /* 286 TSS */
1658         case 9: /* 386 TSS */
1659         case 5: /* task gate */
1660             if (dpl < cpl || dpl < rpl)
1661                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1662             next_eip = env->eip + next_eip_addend;
1663             switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip);
1664             break;
1665         case 4: /* 286 call gate */
1666         case 12: /* 386 call gate */
1667             if ((dpl < cpl) || (dpl < rpl))
1668                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1669             if (!(e2 & DESC_P_MASK))
1670                 raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
1671             gate_cs = e1 >> 16;
1672             new_eip = (e1 & 0xffff);
1673             if (type == 12)
1674                 new_eip |= (e2 & 0xffff0000);
1675             if (load_segment(&e1, &e2, gate_cs) != 0)
1676                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
1677             dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1678             /* must be code segment */
1679             if (((e2 & (DESC_S_MASK | DESC_CS_MASK)) != 
1680                  (DESC_S_MASK | DESC_CS_MASK)))
1681                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
1682             if (((e2 & DESC_C_MASK) && (dpl > cpl)) || 
1683                 (!(e2 & DESC_C_MASK) && (dpl != cpl)))
1684                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
1685             if (!(e2 & DESC_P_MASK))
1686                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
1687             limit = get_seg_limit(e1, e2);
1688             if (new_eip > limit)
1689                 raise_exception_err(EXCP0D_GPF, 0);
1690             cpu_x86_load_seg_cache(env, R_CS, (gate_cs & 0xfffc) | cpl,
1691                                    get_seg_base(e1, e2), limit, e2);
1692             EIP = new_eip;
1693             break;
1694         default:
1695             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1696             break;
1697         }
1698     }
1699 }
1700
1701 /* real mode call */
1702 void helper_lcall_real_T0_T1(int shift, int next_eip)
1703 {
1704     int new_cs, new_eip;
1705     uint32_t esp, esp_mask;
1706     target_ulong ssp;
1707
1708     new_cs = T0;
1709     new_eip = T1;
1710     esp = ESP;
1711     esp_mask = get_sp_mask(env->segs[R_SS].flags);
1712     ssp = env->segs[R_SS].base;
1713     if (shift) {
1714         PUSHL(ssp, esp, esp_mask, env->segs[R_CS].selector);
1715         PUSHL(ssp, esp, esp_mask, next_eip);
1716     } else {
1717         PUSHW(ssp, esp, esp_mask, env->segs[R_CS].selector);
1718         PUSHW(ssp, esp, esp_mask, next_eip);
1719     }
1720
1721     ESP = (ESP & ~esp_mask) | (esp & esp_mask);
1722     env->eip = new_eip;
1723     env->segs[R_CS].selector = new_cs;
1724     env->segs[R_CS].base = (new_cs << 4);
1725 }
1726
1727 /* protected mode call */
1728 void helper_lcall_protected_T0_T1(int shift, int next_eip_addend)
1729 {
1730     int new_cs, new_eip, new_stack, i;
1731     uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;
1732     uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask;
1733     uint32_t val, limit, old_sp_mask;
1734     target_ulong ssp, old_ssp, next_eip;
1735     
1736     new_cs = T0;
1737     new_eip = T1;
1738     next_eip = env->eip + next_eip_addend;
1739 #ifdef DEBUG_PCALL
1740     if (loglevel & CPU_LOG_PCALL) {
1741         fprintf(logfile, "lcall %04x:%08x s=%d\n",
1742                 new_cs, new_eip, shift);
1743         cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1744     }
1745 #endif
1746     if ((new_cs & 0xfffc) == 0)
1747         raise_exception_err(EXCP0D_GPF, 0);
1748     if (load_segment(&e1, &e2, new_cs) != 0)
1749         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1750     cpl = env->hflags & HF_CPL_MASK;
1751 #ifdef DEBUG_PCALL
1752     if (loglevel & CPU_LOG_PCALL) {
1753         fprintf(logfile, "desc=%08x:%08x\n", e1, e2);
1754     }
1755 #endif
1756     if (e2 & DESC_S_MASK) {
1757         if (!(e2 & DESC_CS_MASK))
1758             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1759         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1760         if (e2 & DESC_C_MASK) {
1761             /* conforming code segment */
1762             if (dpl > cpl)
1763                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1764         } else {
1765             /* non conforming code segment */
1766             rpl = new_cs & 3;
1767             if (rpl > cpl)
1768                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1769             if (dpl != cpl)
1770                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1771         }
1772         if (!(e2 & DESC_P_MASK))
1773             raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
1774
1775 #ifdef TARGET_X86_64
1776         /* XXX: check 16/32 bit cases in long mode */
1777         if (shift == 2) {
1778             target_ulong rsp;
1779             /* 64 bit case */
1780             rsp = ESP;
1781             PUSHQ(rsp, env->segs[R_CS].selector);
1782             PUSHQ(rsp, next_eip);
1783             /* from this point, not restartable */
1784             ESP = rsp;
1785             cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
1786                                    get_seg_base(e1, e2), 
1787                                    get_seg_limit(e1, e2), e2);
1788             EIP = new_eip;
1789         } else 
1790 #endif
1791         {
1792             sp = ESP;
1793             sp_mask = get_sp_mask(env->segs[R_SS].flags);
1794             ssp = env->segs[R_SS].base;
1795             if (shift) {
1796                 PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
1797                 PUSHL(ssp, sp, sp_mask, next_eip);
1798             } else {
1799                 PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
1800                 PUSHW(ssp, sp, sp_mask, next_eip);
1801             }
1802             
1803             limit = get_seg_limit(e1, e2);
1804             if (new_eip > limit)
1805                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1806             /* from this point, not restartable */
1807             ESP = (ESP & ~sp_mask) | (sp & sp_mask);
1808             cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
1809                                    get_seg_base(e1, e2), limit, e2);
1810             EIP = new_eip;
1811         }
1812     } else {
1813         /* check gate type */
1814         type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
1815         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1816         rpl = new_cs & 3;
1817         switch(type) {
1818         case 1: /* available 286 TSS */
1819         case 9: /* available 386 TSS */
1820         case 5: /* task gate */
1821             if (dpl < cpl || dpl < rpl)
1822                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1823             switch_tss(new_cs, e1, e2, SWITCH_TSS_CALL, next_eip);
1824             return;
1825         case 4: /* 286 call gate */
1826         case 12: /* 386 call gate */
1827             break;
1828         default:
1829             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1830             break;
1831         }
1832         shift = type >> 3;
1833
1834         if (dpl < cpl || dpl < rpl)
1835             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1836         /* check valid bit */
1837         if (!(e2 & DESC_P_MASK))
1838             raise_exception_err(EXCP0B_NOSEG,  new_cs & 0xfffc);
1839         selector = e1 >> 16;
1840         offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
1841         param_count = e2 & 0x1f;
1842         if ((selector & 0xfffc) == 0)
1843             raise_exception_err(EXCP0D_GPF, 0);
1844
1845         if (load_segment(&e1, &e2, selector) != 0)
1846             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1847         if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
1848             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1849         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1850         if (dpl > cpl)
1851             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1852         if (!(e2 & DESC_P_MASK))
1853             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
1854
1855         if (!(e2 & DESC_C_MASK) && dpl < cpl) {
1856             /* to inner priviledge */
1857             get_ss_esp_from_tss(&ss, &sp, dpl);
1858 #ifdef DEBUG_PCALL
1859             if (loglevel & CPU_LOG_PCALL)
1860                 fprintf(logfile, "new ss:esp=%04x:%08x param_count=%d ESP=" TARGET_FMT_lx "\n", 
1861                         ss, sp, param_count, ESP);
1862 #endif
1863             if ((ss & 0xfffc) == 0)
1864                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
1865             if ((ss & 3) != dpl)
1866                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
1867             if (load_segment(&ss_e1, &ss_e2, ss) != 0)
1868                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
1869             ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
1870             if (ss_dpl != dpl)
1871                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
1872             if (!(ss_e2 & DESC_S_MASK) ||
1873                 (ss_e2 & DESC_CS_MASK) ||
1874                 !(ss_e2 & DESC_W_MASK))
1875                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
1876             if (!(ss_e2 & DESC_P_MASK))
1877                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
1878             
1879             //            push_size = ((param_count * 2) + 8) << shift;
1880
1881             old_sp_mask = get_sp_mask(env->segs[R_SS].flags);
1882             old_ssp = env->segs[R_SS].base;
1883             
1884             sp_mask = get_sp_mask(ss_e2);
1885             ssp = get_seg_base(ss_e1, ss_e2);
1886             if (shift) {
1887                 PUSHL(ssp, sp, sp_mask, env->segs[R_SS].selector);
1888                 PUSHL(ssp, sp, sp_mask, ESP);
1889                 for(i = param_count - 1; i >= 0; i--) {
1890                     val = ldl_kernel(old_ssp + ((ESP + i * 4) & old_sp_mask));
1891                     PUSHL(ssp, sp, sp_mask, val);
1892                 }
1893             } else {
1894                 PUSHW(ssp, sp, sp_mask, env->segs[R_SS].selector);
1895                 PUSHW(ssp, sp, sp_mask, ESP);
1896                 for(i = param_count - 1; i >= 0; i--) {
1897                     val = lduw_kernel(old_ssp + ((ESP + i * 2) & old_sp_mask));
1898                     PUSHW(ssp, sp, sp_mask, val);
1899                 }
1900             }
1901             new_stack = 1;
1902         } else {
1903             /* to same priviledge */
1904             sp = ESP;
1905             sp_mask = get_sp_mask(env->segs[R_SS].flags);
1906             ssp = env->segs[R_SS].base;
1907             //            push_size = (4 << shift);
1908             new_stack = 0;
1909         }
1910
1911         if (shift) {
1912             PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
1913             PUSHL(ssp, sp, sp_mask, next_eip);
1914         } else {
1915             PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
1916             PUSHW(ssp, sp, sp_mask, next_eip);
1917         }
1918
1919         /* from this point, not restartable */
1920
1921         if (new_stack) {
1922             ss = (ss & ~3) | dpl;
1923             cpu_x86_load_seg_cache(env, R_SS, ss, 
1924                                    ssp,
1925                                    get_seg_limit(ss_e1, ss_e2),
1926                                    ss_e2);
1927         }
1928
1929         selector = (selector & ~3) | dpl;
1930         cpu_x86_load_seg_cache(env, R_CS, selector, 
1931                        get_seg_base(e1, e2),
1932                        get_seg_limit(e1, e2),
1933                        e2);
1934         cpu_x86_set_cpl(env, dpl);
1935         ESP = (ESP & ~sp_mask) | (sp & sp_mask);
1936         EIP = offset;
1937     }
1938 #ifdef USE_KQEMU
1939     if (kqemu_is_ok(env)) {
1940         env->exception_index = -1;
1941         cpu_loop_exit();
1942     }
1943 #endif
1944 }
1945
1946 /* real and vm86 mode iret */
1947 void helper_iret_real(int shift)
1948 {
1949     uint32_t sp, new_cs, new_eip, new_eflags, sp_mask;
1950     target_ulong ssp;
1951     int eflags_mask;
1952
1953     sp_mask = 0xffff; /* XXXX: use SS segment size ? */
1954     sp = ESP;
1955     ssp = env->segs[R_SS].base;
1956     if (shift == 1) {
1957         /* 32 bits */
1958         POPL(ssp, sp, sp_mask, new_eip);
1959         POPL(ssp, sp, sp_mask, new_cs);
1960         new_cs &= 0xffff;
1961         POPL(ssp, sp, sp_mask, new_eflags);
1962     } else {
1963         /* 16 bits */
1964         POPW(ssp, sp, sp_mask, new_eip);
1965         POPW(ssp, sp, sp_mask, new_cs);
1966         POPW(ssp, sp, sp_mask, new_eflags);
1967     }
1968     ESP = (ESP & ~sp_mask) | (sp & sp_mask);
1969     load_seg_vm(R_CS, new_cs);
1970     env->eip = new_eip;
1971     if (env->eflags & VM_MASK)
1972         eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK | NT_MASK;
1973     else
1974         eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK | RF_MASK | NT_MASK;
1975     if (shift == 0)
1976         eflags_mask &= 0xffff;
1977     load_eflags(new_eflags, eflags_mask);
1978 }
1979
1980 static inline void validate_seg(int seg_reg, int cpl)
1981 {
1982     int dpl;
1983     uint32_t e2;
1984     
1985     e2 = env->segs[seg_reg].flags;
1986     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1987     if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
1988         /* data or non conforming code segment */
1989         if (dpl < cpl) {
1990             cpu_x86_load_seg_cache(env, seg_reg, 0, 0, 0, 0);
1991         }
1992     }
1993 }
1994
1995 /* protected mode iret */
1996 static inline void helper_ret_protected(int shift, int is_iret, int addend)
1997 {
1998     uint32_t new_cs, new_eflags, new_ss;
1999     uint32_t new_es, new_ds, new_fs, new_gs;
2000     uint32_t e1, e2, ss_e1, ss_e2;
2001     int cpl, dpl, rpl, eflags_mask, iopl;
2002     target_ulong ssp, sp, new_eip, new_esp, sp_mask;
2003     
2004 #ifdef TARGET_X86_64
2005     if (shift == 2)
2006         sp_mask = -1;
2007     else
2008 #endif
2009         sp_mask = get_sp_mask(env->segs[R_SS].flags);
2010     sp = ESP;
2011     /* XXX: ssp is zero in 64 bit ? */
2012     ssp = env->segs[R_SS].base;
2013     new_eflags = 0; /* avoid warning */
2014 #ifdef TARGET_X86_64
2015     if (shift == 2) {
2016         POPQ(sp, new_eip);
2017         POPQ(sp, new_cs);
2018         new_cs &= 0xffff;
2019         if (is_iret) {
2020             POPQ(sp, new_eflags);
2021         }
2022     } else
2023 #endif
2024     if (shift == 1) {
2025         /* 32 bits */
2026         POPL(ssp, sp, sp_mask, new_eip);
2027         POPL(ssp, sp, sp_mask, new_cs);
2028         new_cs &= 0xffff;
2029         if (is_iret) {
2030             POPL(ssp, sp, sp_mask, new_eflags);
2031             if (new_eflags & VM_MASK)
2032                 goto return_to_vm86;
2033         }
2034     } else {
2035         /* 16 bits */
2036         POPW(ssp, sp, sp_mask, new_eip);
2037         POPW(ssp, sp, sp_mask, new_cs);
2038         if (is_iret)
2039             POPW(ssp, sp, sp_mask, new_eflags);
2040     }
2041 #ifdef DEBUG_PCALL
2042     if (loglevel & CPU_LOG_PCALL) {
2043         fprintf(logfile, "lret new %04x:" TARGET_FMT_lx " s=%d addend=0x%x\n",
2044                 new_cs, new_eip, shift, addend);
2045         cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
2046     }
2047 #endif
2048     if ((new_cs & 0xfffc) == 0)
2049         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2050     if (load_segment(&e1, &e2, new_cs) != 0)
2051         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2052     if (!(e2 & DESC_S_MASK) ||
2053         !(e2 & DESC_CS_MASK))
2054         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2055     cpl = env->hflags & HF_CPL_MASK;
2056     rpl = new_cs & 3; 
2057     if (rpl < cpl)
2058         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2059     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2060     if (e2 & DESC_C_MASK) {
2061         if (dpl > rpl)
2062             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2063     } else {
2064         if (dpl != rpl)
2065             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2066     }
2067     if (!(e2 & DESC_P_MASK))
2068         raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2069     
2070     sp += addend;
2071     if (rpl == cpl && (!(env->hflags & HF_CS64_MASK) || 
2072                        ((env->hflags & HF_CS64_MASK) && !is_iret))) {
2073         /* return to same priledge level */
2074         cpu_x86_load_seg_cache(env, R_CS, new_cs, 
2075                        get_seg_base(e1, e2),
2076                        get_seg_limit(e1, e2),
2077                        e2);
2078     } else {
2079         /* return to different priviledge level */
2080 #ifdef TARGET_X86_64
2081         if (shift == 2) {
2082             POPQ(sp, new_esp);
2083             POPQ(sp, new_ss);
2084             new_ss &= 0xffff;
2085         } else
2086 #endif
2087         if (shift == 1) {
2088             /* 32 bits */
2089             POPL(ssp, sp, sp_mask, new_esp);
2090             POPL(ssp, sp, sp_mask, new_ss);
2091             new_ss &= 0xffff;
2092         } else {
2093             /* 16 bits */
2094             POPW(ssp, sp, sp_mask, new_esp);
2095             POPW(ssp, sp, sp_mask, new_ss);
2096         }
2097 #ifdef DEBUG_PCALL
2098         if (loglevel & CPU_LOG_PCALL) {
2099             fprintf(logfile, "new ss:esp=%04x:" TARGET_FMT_lx "\n",
2100                     new_ss, new_esp);
2101         }
2102 #endif
2103         if ((new_ss & 0xfffc) == 0) {
2104 #ifdef TARGET_X86_64
2105             /* NULL ss is allowed in long mode if cpl != 3*/
2106             if ((env->hflags & HF_LMA_MASK) && rpl != 3) {
2107                 cpu_x86_load_seg_cache(env, R_SS, new_ss, 
2108                                        0, 0xffffffff,
2109                                        DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2110                                        DESC_S_MASK | (rpl << DESC_DPL_SHIFT) |
2111                                        DESC_W_MASK | DESC_A_MASK);
2112             } else 
2113 #endif
2114             {
2115                 raise_exception_err(EXCP0D_GPF, 0);
2116             }
2117         } else {
2118             if ((new_ss & 3) != rpl)
2119                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2120             if (load_segment(&ss_e1, &ss_e2, new_ss) != 0)
2121                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2122             if (!(ss_e2 & DESC_S_MASK) ||
2123                 (ss_e2 & DESC_CS_MASK) ||
2124                 !(ss_e2 & DESC_W_MASK))
2125                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2126             dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
2127             if (dpl != rpl)
2128                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2129             if (!(ss_e2 & DESC_P_MASK))
2130                 raise_exception_err(EXCP0B_NOSEG, new_ss & 0xfffc);
2131             cpu_x86_load_seg_cache(env, R_SS, new_ss, 
2132                                    get_seg_base(ss_e1, ss_e2),
2133                                    get_seg_limit(ss_e1, ss_e2),
2134                                    ss_e2);
2135         }
2136
2137         cpu_x86_load_seg_cache(env, R_CS, new_cs, 
2138                        get_seg_base(e1, e2),
2139                        get_seg_limit(e1, e2),
2140                        e2);
2141         cpu_x86_set_cpl(env, rpl);
2142         sp = new_esp;
2143 #ifdef TARGET_X86_64
2144         if (shift == 2)
2145             sp_mask = -1;
2146         else
2147 #endif
2148             sp_mask = get_sp_mask(ss_e2);
2149
2150         /* validate data segments */
2151         validate_seg(R_ES, cpl);
2152         validate_seg(R_DS, cpl);
2153         validate_seg(R_FS, cpl);
2154         validate_seg(R_GS, cpl);
2155
2156         sp += addend;
2157     }
2158     ESP = (ESP & ~sp_mask) | (sp & sp_mask);
2159     env->eip = new_eip;
2160     if (is_iret) {
2161         /* NOTE: 'cpl' is the _old_ CPL */
2162         eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK | NT_MASK;
2163         if (cpl == 0)
2164             eflags_mask |= IOPL_MASK;
2165         iopl = (env->eflags >> IOPL_SHIFT) & 3;
2166         if (cpl <= iopl)
2167             eflags_mask |= IF_MASK;
2168         if (shift == 0)
2169             eflags_mask &= 0xffff;
2170         load_eflags(new_eflags, eflags_mask);
2171     }
2172     return;
2173
2174  return_to_vm86:
2175     POPL(ssp, sp, sp_mask, new_esp);
2176     POPL(ssp, sp, sp_mask, new_ss);
2177     POPL(ssp, sp, sp_mask, new_es);
2178     POPL(ssp, sp, sp_mask, new_ds);
2179     POPL(ssp, sp, sp_mask, new_fs);
2180     POPL(ssp, sp, sp_mask, new_gs);
2181     
2182     /* modify processor state */
2183     load_eflags(new_eflags, TF_MASK | AC_MASK | ID_MASK | 
2184                 IF_MASK | IOPL_MASK | VM_MASK | NT_MASK | VIF_MASK | VIP_MASK);
2185     load_seg_vm(R_CS, new_cs & 0xffff);
2186     cpu_x86_set_cpl(env, 3);
2187     load_seg_vm(R_SS, new_ss & 0xffff);
2188     load_seg_vm(R_ES, new_es & 0xffff);
2189     load_seg_vm(R_DS, new_ds & 0xffff);
2190     load_seg_vm(R_FS, new_fs & 0xffff);
2191     load_seg_vm(R_GS, new_gs & 0xffff);
2192
2193     env->eip = new_eip & 0xffff;
2194     ESP = new_esp;
2195 }
2196
2197 void helper_iret_protected(int shift, int next_eip)
2198 {
2199     int tss_selector, type;
2200     uint32_t e1, e2;
2201     
2202     /* specific case for TSS */
2203     if (env->eflags & NT_MASK) {
2204 #ifdef TARGET_X86_64
2205         if (env->hflags & HF_LMA_MASK)
2206             raise_exception_err(EXCP0D_GPF, 0);
2207 #endif
2208         tss_selector = lduw_kernel(env->tr.base + 0);
2209         if (tss_selector & 4)
2210             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2211         if (load_segment(&e1, &e2, tss_selector) != 0)
2212             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2213         type = (e2 >> DESC_TYPE_SHIFT) & 0x17;
2214         /* NOTE: we check both segment and busy TSS */
2215         if (type != 3)
2216             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2217         switch_tss(tss_selector, e1, e2, SWITCH_TSS_IRET, next_eip);
2218     } else {
2219         helper_ret_protected(shift, 1, 0);
2220     }
2221 #ifdef USE_KQEMU
2222     if (kqemu_is_ok(env)) {
2223         CC_OP = CC_OP_EFLAGS;
2224         env->exception_index = -1;
2225         cpu_loop_exit();
2226     }
2227 #endif
2228 }
2229
2230 void helper_lret_protected(int shift, int addend)
2231 {
2232     helper_ret_protected(shift, 0, addend);
2233 #ifdef USE_KQEMU
2234     if (kqemu_is_ok(env)) {
2235         env->exception_index = -1;
2236         cpu_loop_exit();
2237     }
2238 #endif
2239 }
2240
2241 void helper_sysenter(void)
2242 {
2243     if (env->sysenter_cs == 0) {
2244         raise_exception_err(EXCP0D_GPF, 0);
2245     }
2246     env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK);
2247     cpu_x86_set_cpl(env, 0);
2248     cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc, 
2249                            0, 0xffffffff, 
2250                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2251                            DESC_S_MASK |
2252                            DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2253     cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc, 
2254                            0, 0xffffffff,
2255                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2256                            DESC_S_MASK |
2257                            DESC_W_MASK | DESC_A_MASK);
2258     ESP = env->sysenter_esp;
2259     EIP = env->sysenter_eip;
2260 }
2261
2262 void helper_sysexit(void)
2263 {
2264     int cpl;
2265
2266     cpl = env->hflags & HF_CPL_MASK;
2267     if (env->sysenter_cs == 0 || cpl != 0) {
2268         raise_exception_err(EXCP0D_GPF, 0);
2269     }
2270     cpu_x86_set_cpl(env, 3);
2271     cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3, 
2272                            0, 0xffffffff, 
2273                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2274                            DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2275                            DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2276     cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3, 
2277                            0, 0xffffffff,
2278                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2279                            DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2280                            DESC_W_MASK | DESC_A_MASK);
2281     ESP = ECX;
2282     EIP = EDX;
2283 #ifdef USE_KQEMU
2284     if (kqemu_is_ok(env)) {
2285         env->exception_index = -1;
2286         cpu_loop_exit();
2287     }
2288 #endif
2289 }
2290
2291 void helper_movl_crN_T0(int reg)
2292 {
2293 #if !defined(CONFIG_USER_ONLY) 
2294     switch(reg) {
2295     case 0:
2296         cpu_x86_update_cr0(env, T0);
2297         break;
2298     case 3:
2299         cpu_x86_update_cr3(env, T0);
2300         break;
2301     case 4:
2302         cpu_x86_update_cr4(env, T0);
2303         break;
2304     case 8:
2305         cpu_set_apic_tpr(env, T0);
2306         break;
2307     default:
2308         env->cr[reg] = T0;
2309         break;
2310     }
2311 #endif
2312 }
2313
2314 /* XXX: do more */
2315 void helper_movl_drN_T0(int reg)
2316 {
2317     env->dr[reg] = T0;
2318 }
2319
2320 void helper_invlpg(target_ulong addr)
2321 {
2322     cpu_x86_flush_tlb(env, addr);
2323 }
2324
2325 void helper_rdtsc(void)
2326 {
2327     uint64_t val;
2328     
2329     val = cpu_get_tsc(env);
2330     EAX = (uint32_t)(val);
2331     EDX = (uint32_t)(val >> 32);
2332 }
2333
2334 #if defined(CONFIG_USER_ONLY) 
2335 void helper_wrmsr(void)
2336 {
2337 }
2338
2339 void helper_rdmsr(void)
2340 {
2341 }
2342 #else
2343 void helper_wrmsr(void)
2344 {
2345     uint64_t val;
2346
2347     val = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
2348
2349     switch((uint32_t)ECX) {
2350     case MSR_IA32_SYSENTER_CS:
2351         env->sysenter_cs = val & 0xffff;
2352         break;
2353     case MSR_IA32_SYSENTER_ESP:
2354         env->sysenter_esp = val;
2355         break;
2356     case MSR_IA32_SYSENTER_EIP:
2357         env->sysenter_eip = val;
2358         break;
2359     case MSR_IA32_APICBASE:
2360         cpu_set_apic_base(env, val);
2361         break;
2362     case MSR_EFER:
2363         {
2364             uint64_t update_mask;
2365             update_mask = 0;
2366             if (env->cpuid_ext2_features & CPUID_EXT2_SYSCALL)
2367                 update_mask |= MSR_EFER_SCE;
2368             if (env->cpuid_ext2_features & CPUID_EXT2_LM)
2369                 update_mask |= MSR_EFER_LME;
2370             if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR)
2371                 update_mask |= MSR_EFER_FFXSR;
2372             if (env->cpuid_ext2_features & CPUID_EXT2_NX)
2373                 update_mask |= MSR_EFER_NXE;
2374             env->efer = (env->efer & ~update_mask) | 
2375             (val & update_mask);
2376         }
2377         break;
2378     case MSR_STAR:
2379         env->star = val;
2380         break;
2381     case MSR_PAT:
2382         env->pat = val;
2383         break;
2384 #ifdef TARGET_X86_64
2385     case MSR_LSTAR:
2386         env->lstar = val;
2387         break;
2388     case MSR_CSTAR:
2389         env->cstar = val;
2390         break;
2391     case MSR_FMASK:
2392         env->fmask = val;
2393         break;
2394     case MSR_FSBASE:
2395         env->segs[R_FS].base = val;
2396         break;
2397     case MSR_GSBASE:
2398         env->segs[R_GS].base = val;
2399         break;
2400     case MSR_KERNELGSBASE:
2401         env->kernelgsbase = val;
2402         break;
2403 #endif
2404     default:
2405         /* XXX: exception ? */
2406         break; 
2407     }
2408 }
2409
2410 void helper_rdmsr(void)
2411 {
2412     uint64_t val;
2413     switch((uint32_t)ECX) {
2414     case MSR_IA32_SYSENTER_CS:
2415         val = env->sysenter_cs;
2416         break;
2417     case MSR_IA32_SYSENTER_ESP:
2418         val = env->sysenter_esp;
2419         break;
2420     case MSR_IA32_SYSENTER_EIP:
2421         val = env->sysenter_eip;
2422         break;
2423     case MSR_IA32_APICBASE:
2424         val = cpu_get_apic_base(env);
2425         break;
2426     case MSR_EFER:
2427         val = env->efer;
2428         break;
2429     case MSR_STAR:
2430         val = env->star;
2431         break;
2432     case MSR_PAT:
2433         val = env->pat;
2434         break;
2435 #ifdef TARGET_X86_64
2436     case MSR_LSTAR:
2437         val = env->lstar;
2438         break;
2439     case MSR_CSTAR:
2440         val = env->cstar;
2441         break;
2442     case MSR_FMASK:
2443         val = env->fmask;
2444         break;
2445     case MSR_FSBASE:
2446         val = env->segs[R_FS].base;
2447         break;
2448     case MSR_GSBASE:
2449         val = env->segs[R_GS].base;
2450         break;
2451     case MSR_KERNELGSBASE:
2452         val = env->kernelgsbase;
2453         break;
2454 #endif
2455     default:
2456         /* XXX: exception ? */
2457         val = 0;
2458         break; 
2459     }
2460     EAX = (uint32_t)(val);
2461     EDX = (uint32_t)(val >> 32);
2462 }
2463 #endif
2464
2465 void helper_lsl(void)
2466 {
2467     unsigned int selector, limit;
2468     uint32_t e1, e2, eflags;
2469     int rpl, dpl, cpl, type;
2470
2471     eflags = cc_table[CC_OP].compute_all();
2472     selector = T0 & 0xffff;
2473     if (load_segment(&e1, &e2, selector) != 0)
2474         goto fail;
2475     rpl = selector & 3;
2476     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2477     cpl = env->hflags & HF_CPL_MASK;
2478     if (e2 & DESC_S_MASK) {
2479         if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
2480             /* conforming */
2481         } else {
2482             if (dpl < cpl || dpl < rpl)
2483                 goto fail;
2484         }
2485     } else {
2486         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2487         switch(type) {
2488         case 1:
2489         case 2:
2490         case 3:
2491         case 9:
2492         case 11:
2493             break;
2494         default:
2495             goto fail;
2496         }
2497         if (dpl < cpl || dpl < rpl) {
2498         fail:
2499             CC_SRC = eflags & ~CC_Z;
2500             return;
2501         }
2502     }
2503     limit = get_seg_limit(e1, e2);
2504     T1 = limit;
2505     CC_SRC = eflags | CC_Z;
2506 }
2507
2508 void helper_lar(void)
2509 {
2510     unsigned int selector;
2511     uint32_t e1, e2, eflags;
2512     int rpl, dpl, cpl, type;
2513
2514     eflags = cc_table[CC_OP].compute_all();
2515     selector = T0 & 0xffff;
2516     if ((selector & 0xfffc) == 0)
2517         goto fail;
2518     if (load_segment(&e1, &e2, selector) != 0)
2519         goto fail;
2520     rpl = selector & 3;
2521     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2522     cpl = env->hflags & HF_CPL_MASK;
2523     if (e2 & DESC_S_MASK) {
2524         if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
2525             /* conforming */
2526         } else {
2527             if (dpl < cpl || dpl < rpl)
2528                 goto fail;
2529         }
2530     } else {
2531         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2532         switch(type) {
2533         case 1:
2534         case 2:
2535         case 3:
2536         case 4:
2537         case 5:
2538         case 9:
2539         case 11:
2540         case 12:
2541             break;
2542         default:
2543             goto fail;
2544         }
2545         if (dpl < cpl || dpl < rpl) {
2546         fail:
2547             CC_SRC = eflags & ~CC_Z;
2548             return;
2549         }
2550     }
2551     T1 = e2 & 0x00f0ff00;
2552     CC_SRC = eflags | CC_Z;
2553 }
2554
2555 void helper_verr(void)
2556 {
2557     unsigned int selector;
2558     uint32_t e1, e2, eflags;
2559     int rpl, dpl, cpl;
2560
2561     eflags = cc_table[CC_OP].compute_all();
2562     selector = T0 & 0xffff;
2563     if ((selector & 0xfffc) == 0)
2564         goto fail;
2565     if (load_segment(&e1, &e2, selector) != 0)
2566         goto fail;
2567     if (!(e2 & DESC_S_MASK))
2568         goto fail;
2569     rpl = selector & 3;
2570     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2571     cpl = env->hflags & HF_CPL_MASK;
2572     if (e2 & DESC_CS_MASK) {
2573         if (!(e2 & DESC_R_MASK))
2574             goto fail;
2575         if (!(e2 & DESC_C_MASK)) {
2576             if (dpl < cpl || dpl < rpl)
2577                 goto fail;
2578         }
2579     } else {
2580         if (dpl < cpl || dpl < rpl) {
2581         fail:
2582             CC_SRC = eflags & ~CC_Z;
2583             return;
2584         }
2585     }
2586     CC_SRC = eflags | CC_Z;
2587 }
2588
2589 void helper_verw(void)
2590 {
2591     unsigned int selector;
2592     uint32_t e1, e2, eflags;
2593     int rpl, dpl, cpl;
2594
2595     eflags = cc_table[CC_OP].compute_all();
2596     selector = T0 & 0xffff;
2597     if ((selector & 0xfffc) == 0)
2598         goto fail;
2599     if (load_segment(&e1, &e2, selector) != 0)
2600         goto fail;
2601     if (!(e2 & DESC_S_MASK))
2602         goto fail;
2603     rpl = selector & 3;
2604     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2605     cpl = env->hflags & HF_CPL_MASK;
2606     if (e2 & DESC_CS_MASK) {
2607         goto fail;
2608     } else {
2609         if (dpl < cpl || dpl < rpl)
2610             goto fail;
2611         if (!(e2 & DESC_W_MASK)) {
2612         fail:
2613             CC_SRC = eflags & ~CC_Z;
2614             return;
2615         }
2616     }
2617     CC_SRC = eflags | CC_Z;
2618 }
2619
2620 /* FPU helpers */
2621
2622 void helper_fldt_ST0_A0(void)
2623 {
2624     int new_fpstt;
2625     new_fpstt = (env->fpstt - 1) & 7;
2626     env->fpregs[new_fpstt].d = helper_fldt(A0);
2627     env->fpstt = new_fpstt;
2628     env->fptags[new_fpstt] = 0; /* validate stack entry */
2629 }
2630
2631 void helper_fstt_ST0_A0(void)
2632 {
2633     helper_fstt(ST0, A0);
2634 }
2635
2636 void fpu_set_exception(int mask)
2637 {
2638     env->fpus |= mask;
2639     if (env->fpus & (~env->fpuc & FPUC_EM))
2640         env->fpus |= FPUS_SE | FPUS_B;
2641 }
2642
2643 CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b)
2644 {
2645     if (b == 0.0) 
2646         fpu_set_exception(FPUS_ZE);
2647     return a / b;
2648 }
2649
2650 void fpu_raise_exception(void)
2651 {
2652     if (env->cr[0] & CR0_NE_MASK) {
2653         raise_exception(EXCP10_COPR);
2654     } 
2655 #if !defined(CONFIG_USER_ONLY) 
2656     else {
2657         cpu_set_ferr(env);
2658     }
2659 #endif
2660 }
2661
2662 /* BCD ops */
2663
2664 void helper_fbld_ST0_A0(void)
2665 {
2666     CPU86_LDouble tmp;
2667     uint64_t val;
2668     unsigned int v;
2669     int i;
2670
2671     val = 0;
2672     for(i = 8; i >= 0; i--) {
2673         v = ldub(A0 + i);
2674         val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
2675     }
2676     tmp = val;
2677     if (ldub(A0 + 9) & 0x80)
2678         tmp = -tmp;
2679     fpush();
2680     ST0 = tmp;
2681 }
2682
2683 void helper_fbst_ST0_A0(void)
2684 {
2685     int v;
2686     target_ulong mem_ref, mem_end;
2687     int64_t val;
2688
2689     val = floatx_to_int64(ST0, &env->fp_status);
2690     mem_ref = A0;
2691     mem_end = mem_ref + 9;
2692     if (val < 0) {
2693         stb(mem_end, 0x80);
2694         val = -val;
2695     } else {
2696         stb(mem_end, 0x00);
2697     }
2698     while (mem_ref < mem_end) {
2699         if (val == 0)
2700             break;
2701         v = val % 100;
2702         val = val / 100;
2703         v = ((v / 10) << 4) | (v % 10);
2704         stb(mem_ref++, v);
2705     }
2706     while (mem_ref < mem_end) {
2707         stb(mem_ref++, 0);
2708     }
2709 }
2710
2711 void helper_f2xm1(void)
2712 {
2713     ST0 = pow(2.0,ST0) - 1.0;
2714 }
2715
2716 void helper_fyl2x(void)
2717 {
2718     CPU86_LDouble fptemp;
2719     
2720     fptemp = ST0;
2721     if (fptemp>0.0){
2722         fptemp = log(fptemp)/log(2.0);   /* log2(ST) */
2723         ST1 *= fptemp;
2724         fpop();
2725     } else { 
2726         env->fpus &= (~0x4700);
2727         env->fpus |= 0x400;
2728     }
2729 }
2730
2731 void helper_fptan(void)
2732 {
2733     CPU86_LDouble fptemp;
2734
2735     fptemp = ST0;
2736     if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2737         env->fpus |= 0x400;
2738     } else {
2739         ST0 = tan(fptemp);
2740         fpush();
2741         ST0 = 1.0;
2742         env->fpus &= (~0x400);  /* C2 <-- 0 */
2743         /* the above code is for  |arg| < 2**52 only */
2744     }
2745 }
2746
2747 void helper_fpatan(void)
2748 {
2749     CPU86_LDouble fptemp, fpsrcop;
2750
2751     fpsrcop = ST1;
2752     fptemp = ST0;
2753     ST1 = atan2(fpsrcop,fptemp);
2754     fpop();
2755 }
2756
2757 void helper_fxtract(void)
2758 {
2759     CPU86_LDoubleU temp;
2760     unsigned int expdif;
2761
2762     temp.d = ST0;
2763     expdif = EXPD(temp) - EXPBIAS;
2764     /*DP exponent bias*/
2765     ST0 = expdif;
2766     fpush();
2767     BIASEXPONENT(temp);
2768     ST0 = temp.d;
2769 }
2770
2771 void helper_fprem1(void)
2772 {
2773     CPU86_LDouble dblq, fpsrcop, fptemp;
2774     CPU86_LDoubleU fpsrcop1, fptemp1;
2775     int expdif;
2776     int q;
2777
2778     fpsrcop = ST0;
2779     fptemp = ST1;
2780     fpsrcop1.d = fpsrcop;
2781     fptemp1.d = fptemp;
2782     expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
2783     if (expdif < 53) {
2784         dblq = fpsrcop / fptemp;
2785         dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
2786         ST0 = fpsrcop - fptemp*dblq;
2787         q = (int)dblq; /* cutting off top bits is assumed here */
2788         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
2789                                 /* (C0,C1,C3) <-- (q2,q1,q0) */
2790         env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
2791         env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
2792         env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
2793     } else {
2794         env->fpus |= 0x400;  /* C2 <-- 1 */
2795         fptemp = pow(2.0, expdif-50);
2796         fpsrcop = (ST0 / ST1) / fptemp;
2797         /* fpsrcop = integer obtained by rounding to the nearest */
2798         fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)?
2799             floor(fpsrcop): ceil(fpsrcop);
2800         ST0 -= (ST1 * fpsrcop * fptemp);
2801     }
2802 }
2803
2804 void helper_fprem(void)
2805 {
2806     CPU86_LDouble dblq, fpsrcop, fptemp;
2807     CPU86_LDoubleU fpsrcop1, fptemp1;
2808     int expdif;
2809     int q;
2810     
2811     fpsrcop = ST0;
2812     fptemp = ST1;
2813     fpsrcop1.d = fpsrcop;
2814     fptemp1.d = fptemp;
2815     expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
2816     if ( expdif < 53 ) {
2817         dblq = fpsrcop / fptemp;
2818         dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
2819         ST0 = fpsrcop - fptemp*dblq;
2820         q = (int)dblq; /* cutting off top bits is assumed here */
2821         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
2822                                 /* (C0,C1,C3) <-- (q2,q1,q0) */
2823         env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
2824         env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
2825         env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
2826     } else {
2827         env->fpus |= 0x400;  /* C2 <-- 1 */
2828         fptemp = pow(2.0, expdif-50);
2829         fpsrcop = (ST0 / ST1) / fptemp;
2830         /* fpsrcop = integer obtained by chopping */
2831         fpsrcop = (fpsrcop < 0.0)?
2832             -(floor(fabs(fpsrcop))): floor(fpsrcop);
2833         ST0 -= (ST1 * fpsrcop * fptemp);
2834     }
2835 }
2836
2837 void helper_fyl2xp1(void)
2838 {
2839     CPU86_LDouble fptemp;
2840
2841     fptemp = ST0;
2842     if ((fptemp+1.0)>0.0) {
2843         fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
2844         ST1 *= fptemp;
2845         fpop();
2846     } else { 
2847         env->fpus &= (~0x4700);
2848         env->fpus |= 0x400;
2849     }
2850 }
2851
2852 void helper_fsqrt(void)
2853 {
2854     CPU86_LDouble fptemp;
2855
2856     fptemp = ST0;
2857     if (fptemp<0.0) { 
2858         env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
2859         env->fpus |= 0x400;
2860     }
2861     ST0 = sqrt(fptemp);
2862 }
2863
2864 void helper_fsincos(void)
2865 {
2866     CPU86_LDouble fptemp;
2867
2868     fptemp = ST0;
2869     if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2870         env->fpus |= 0x400;
2871     } else {
2872         ST0 = sin(fptemp);
2873         fpush();
2874         ST0 = cos(fptemp);
2875         env->fpus &= (~0x400);  /* C2 <-- 0 */
2876         /* the above code is for  |arg| < 2**63 only */
2877     }
2878 }
2879
2880 void helper_frndint(void)
2881 {
2882     ST0 = floatx_round_to_int(ST0, &env->fp_status);
2883 }
2884
2885 void helper_fscale(void)
2886 {
2887     CPU86_LDouble fpsrcop, fptemp;
2888
2889     fpsrcop = 2.0;
2890     fptemp = pow(fpsrcop,ST1);
2891     ST0 *= fptemp;
2892 }
2893
2894 void helper_fsin(void)
2895 {
2896     CPU86_LDouble fptemp;
2897
2898     fptemp = ST0;
2899     if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2900         env->fpus |= 0x400;
2901     } else {
2902         ST0 = sin(fptemp);
2903         env->fpus &= (~0x400);  /* C2 <-- 0 */
2904         /* the above code is for  |arg| < 2**53 only */
2905     }
2906 }
2907
2908 void helper_fcos(void)
2909 {
2910     CPU86_LDouble fptemp;
2911
2912     fptemp = ST0;
2913     if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2914         env->fpus |= 0x400;
2915     } else {
2916         ST0 = cos(fptemp);
2917         env->fpus &= (~0x400);  /* C2 <-- 0 */
2918         /* the above code is for  |arg5 < 2**63 only */
2919     }
2920 }
2921
2922 void helper_fxam_ST0(void)
2923 {
2924     CPU86_LDoubleU temp;
2925     int expdif;
2926
2927     temp.d = ST0;
2928
2929     env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
2930     if (SIGND(temp))
2931         env->fpus |= 0x200; /* C1 <-- 1 */
2932
2933     expdif = EXPD(temp);
2934     if (expdif == MAXEXPD) {
2935         if (MANTD(temp) == 0)
2936             env->fpus |=  0x500 /*Infinity*/;
2937         else
2938             env->fpus |=  0x100 /*NaN*/;
2939     } else if (expdif == 0) {
2940         if (MANTD(temp) == 0)
2941             env->fpus |=  0x4000 /*Zero*/;
2942         else
2943             env->fpus |= 0x4400 /*Denormal*/;
2944     } else {
2945         env->fpus |= 0x400;
2946     }
2947 }
2948
2949 void helper_fstenv(target_ulong ptr, int data32)
2950 {
2951     int fpus, fptag, exp, i;
2952     uint64_t mant;
2953     CPU86_LDoubleU tmp;
2954
2955     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2956     fptag = 0;
2957     for (i=7; i>=0; i--) {
2958         fptag <<= 2;
2959         if (env->fptags[i]) {
2960             fptag |= 3;
2961         } else {
2962             tmp.d = env->fpregs[i].d;
2963             exp = EXPD(tmp);
2964             mant = MANTD(tmp);
2965             if (exp == 0 && mant == 0) {
2966                 /* zero */
2967                 fptag |= 1;
2968             } else if (exp == 0 || exp == MAXEXPD
2969 #ifdef USE_X86LDOUBLE
2970                        || (mant & (1LL << 63)) == 0
2971 #endif
2972                        ) {
2973                 /* NaNs, infinity, denormal */
2974                 fptag |= 2;
2975             }
2976         }
2977     }
2978     if (data32) {
2979         /* 32 bit */
2980         stl(ptr, env->fpuc);
2981         stl(ptr + 4, fpus);
2982         stl(ptr + 8, fptag);
2983         stl(ptr + 12, 0); /* fpip */
2984         stl(ptr + 16, 0); /* fpcs */
2985         stl(ptr + 20, 0); /* fpoo */
2986         stl(ptr + 24, 0); /* fpos */
2987     } else {
2988         /* 16 bit */
2989         stw(ptr, env->fpuc);
2990         stw(ptr + 2, fpus);
2991         stw(ptr + 4, fptag);
2992         stw(ptr + 6, 0);
2993         stw(ptr + 8, 0);
2994         stw(ptr + 10, 0);
2995         stw(ptr + 12, 0);
2996     }
2997 }
2998
2999 void helper_fldenv(target_ulong ptr, int data32)
3000 {
3001     int i, fpus, fptag;
3002
3003     if (data32) {
3004         env->fpuc = lduw(ptr);
3005         fpus = lduw(ptr + 4);
3006         fptag = lduw(ptr + 8);
3007     }
3008     else {
3009         env->fpuc = lduw(ptr);
3010         fpus = lduw(ptr + 2);
3011         fptag = lduw(ptr + 4);
3012     }
3013     env->fpstt = (fpus >> 11) & 7;
3014     env->fpus = fpus & ~0x3800;
3015     for(i = 0;i < 8; i++) {
3016         env->fptags[i] = ((fptag & 3) == 3);
3017         fptag >>= 2;
3018     }
3019 }
3020
3021 void helper_fsave(target_ulong ptr, int data32)
3022 {
3023     CPU86_LDouble tmp;
3024     int i;
3025
3026     helper_fstenv(ptr, data32);
3027
3028     ptr += (14 << data32);
3029     for(i = 0;i < 8; i++) {
3030         tmp = ST(i);
3031         helper_fstt(tmp, ptr);
3032         ptr += 10;
3033     }
3034
3035     /* fninit */
3036     env->fpus = 0;
3037     env->fpstt = 0;
3038     env->fpuc = 0x37f;
3039     env->fptags[0] = 1;
3040     env->fptags[1] = 1;
3041     env->fptags[2] = 1;
3042     env->fptags[3] = 1;
3043     env->fptags[4] = 1;
3044     env->fptags[5] = 1;
3045     env->fptags[6] = 1;
3046     env->fptags[7] = 1;
3047 }
3048
3049 void helper_frstor(target_ulong ptr, int data32)
3050 {
3051     CPU86_LDouble tmp;
3052     int i;
3053
3054     helper_fldenv(ptr, data32);
3055     ptr += (14 << data32);
3056
3057     for(i = 0;i < 8; i++) {
3058         tmp = helper_fldt(ptr);
3059         ST(i) = tmp;
3060         ptr += 10;
3061     }
3062 }
3063
3064 void helper_fxsave(target_ulong ptr, int data64)
3065 {
3066     int fpus, fptag, i, nb_xmm_regs;
3067     CPU86_LDouble tmp;
3068     target_ulong addr;
3069
3070     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
3071     fptag = 0;
3072     for(i = 0; i < 8; i++) {
3073         fptag |= (env->fptags[i] << i);
3074     }
3075     stw(ptr, env->fpuc);
3076     stw(ptr + 2, fpus);
3077     stw(ptr + 4, fptag ^ 0xff);
3078
3079     addr = ptr + 0x20;
3080     for(i = 0;i < 8; i++) {
3081         tmp = ST(i);
3082         helper_fstt(tmp, addr);
3083         addr += 16;
3084     }
3085     
3086     if (env->cr[4] & CR4_OSFXSR_MASK) {
3087         /* XXX: finish it */
3088         stl(ptr + 0x18, env->mxcsr); /* mxcsr */
3089         stl(ptr + 0x1c, 0x0000ffff); /* mxcsr_mask */
3090         nb_xmm_regs = 8 << data64;
3091         addr = ptr + 0xa0;
3092         for(i = 0; i < nb_xmm_regs; i++) {
3093             stq(addr, env->xmm_regs[i].XMM_Q(0));
3094             stq(addr + 8, env->xmm_regs[i].XMM_Q(1));
3095             addr += 16;
3096         }
3097     }
3098 }
3099
3100 void helper_fxrstor(target_ulong ptr, int data64)
3101 {
3102     int i, fpus, fptag, nb_xmm_regs;
3103     CPU86_LDouble tmp;
3104     target_ulong addr;
3105
3106     env->fpuc = lduw(ptr);
3107     fpus = lduw(ptr + 2);
3108     fptag = lduw(ptr + 4);
3109     env->fpstt = (fpus >> 11) & 7;
3110     env->fpus = fpus & ~0x3800;
3111     fptag ^= 0xff;
3112     for(i = 0;i < 8; i++) {
3113         env->fptags[i] = ((fptag >> i) & 1);
3114     }
3115
3116     addr = ptr + 0x20;
3117     for(i = 0;i < 8; i++) {
3118         tmp = helper_fldt(addr);
3119         ST(i) = tmp;
3120         addr += 16;
3121     }
3122
3123     if (env->cr[4] & CR4_OSFXSR_MASK) {
3124         /* XXX: finish it */
3125         env->mxcsr = ldl(ptr + 0x18);
3126         //ldl(ptr + 0x1c);
3127         nb_xmm_regs = 8 << data64;
3128         addr = ptr + 0xa0;
3129         for(i = 0; i < nb_xmm_regs; i++) {
3130             env->xmm_regs[i].XMM_Q(0) = ldq(addr);
3131             env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
3132             addr += 16;
3133         }
3134     }
3135 }
3136
3137 #ifndef USE_X86LDOUBLE
3138
3139 void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
3140 {
3141     CPU86_LDoubleU temp;
3142     int e;
3143
3144     temp.d = f;
3145     /* mantissa */
3146     *pmant = (MANTD(temp) << 11) | (1LL << 63);
3147     /* exponent + sign */
3148     e = EXPD(temp) - EXPBIAS + 16383;
3149     e |= SIGND(temp) >> 16;
3150     *pexp = e;
3151 }
3152
3153 CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
3154 {
3155     CPU86_LDoubleU temp;
3156     int e;
3157     uint64_t ll;
3158
3159     /* XXX: handle overflow ? */
3160     e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
3161     e |= (upper >> 4) & 0x800; /* sign */
3162     ll = (mant >> 11) & ((1LL << 52) - 1);
3163 #ifdef __arm__
3164     temp.l.upper = (e << 20) | (ll >> 32);
3165     temp.l.lower = ll;
3166 #else
3167     temp.ll = ll | ((uint64_t)e << 52);
3168 #endif
3169     return temp.d;
3170 }
3171
3172 #else
3173
3174 void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
3175 {
3176     CPU86_LDoubleU temp;
3177
3178     temp.d = f;
3179     *pmant = temp.l.lower;
3180     *pexp = temp.l.upper;
3181 }
3182
3183 CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
3184 {
3185     CPU86_LDoubleU temp;
3186
3187     temp.l.upper = upper;
3188     temp.l.lower = mant;
3189     return temp.d;
3190 }
3191 #endif
3192
3193 #ifdef TARGET_X86_64
3194
3195 //#define DEBUG_MULDIV
3196
3197 static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
3198 {
3199     *plow += a;
3200     /* carry test */
3201     if (*plow < a)
3202         (*phigh)++;
3203     *phigh += b;
3204 }
3205
3206 static void neg128(uint64_t *plow, uint64_t *phigh)
3207 {
3208     *plow = ~ *plow;
3209     *phigh = ~ *phigh;
3210     add128(plow, phigh, 1, 0);
3211 }
3212
3213 static void mul64(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
3214 {
3215     uint32_t a0, a1, b0, b1;
3216     uint64_t v;
3217
3218     a0 = a;
3219     a1 = a >> 32;
3220
3221     b0 = b;
3222     b1 = b >> 32;
3223     
3224     v = (uint64_t)a0 * (uint64_t)b0;
3225     *plow = v;
3226     *phigh = 0;
3227
3228     v = (uint64_t)a0 * (uint64_t)b1;
3229     add128(plow, phigh, v << 32, v >> 32);
3230     
3231     v = (uint64_t)a1 * (uint64_t)b0;
3232     add128(plow, phigh, v << 32, v >> 32);
3233     
3234     v = (uint64_t)a1 * (uint64_t)b1;
3235     *phigh += v;
3236 #ifdef DEBUG_MULDIV
3237     printf("mul: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n",
3238            a, b, *phigh, *plow);
3239 #endif
3240 }
3241
3242 static void imul64(uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b)
3243 {
3244     int sa, sb;
3245     sa = (a < 0);
3246     if (sa)
3247         a = -a;
3248     sb = (b < 0);
3249     if (sb)
3250         b = -b;
3251     mul64(plow, phigh, a, b);
3252     if (sa ^ sb) {
3253         neg128(plow, phigh);
3254     }
3255 }
3256
3257 /* XXX: overflow support */
3258 static void div64(uint64_t *plow, uint64_t *phigh, uint64_t b)
3259 {
3260     uint64_t q, r, a1, a0;
3261     int i, qb;
3262
3263     a0 = *plow;
3264     a1 = *phigh;
3265     if (a1 == 0) {
3266         q = a0 / b;
3267         r = a0 % b;
3268         *plow = q;
3269         *phigh = r;
3270     } else {
3271         /* XXX: use a better algorithm */
3272         for(i = 0; i < 64; i++) {
3273             a1 = (a1 << 1) | (a0 >> 63);
3274             if (a1 >= b) {
3275                 a1 -= b;
3276                 qb = 1;
3277             } else {
3278                 qb = 0;
3279             }
3280             a0 = (a0 << 1) | qb;
3281         }
3282 #if defined(DEBUG_MULDIV)
3283         printf("div: 0x%016llx%016llx / 0x%016llx: q=0x%016llx r=0x%016llx\n",
3284                *phigh, *plow, b, a0, a1);
3285 #endif
3286         *plow = a0;
3287         *phigh = a1;
3288     }
3289 }
3290
3291 static void idiv64(uint64_t *plow, uint64_t *phigh, int64_t b)
3292 {
3293     int sa, sb;
3294     sa = ((int64_t)*phigh < 0);
3295     if (sa)
3296         neg128(plow, phigh);
3297     sb = (b < 0);
3298     if (sb)
3299         b = -b;
3300     div64(plow, phigh, b);
3301     if (sa ^ sb)
3302         *plow = - *plow;
3303     if (sa)
3304         *phigh = - *phigh;
3305 }
3306
3307 void helper_mulq_EAX_T0(void)
3308 {
3309     uint64_t r0, r1;
3310
3311     mul64(&r0, &r1, EAX, T0);
3312     EAX = r0;
3313     EDX = r1;
3314     CC_DST = r0;
3315     CC_SRC = r1;
3316 }
3317
3318 void helper_imulq_EAX_T0(void)
3319 {
3320     uint64_t r0, r1;
3321
3322     imul64(&r0, &r1, EAX, T0);
3323     EAX = r0;
3324     EDX = r1;
3325     CC_DST = r0;
3326     CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
3327 }
3328
3329 void helper_imulq_T0_T1(void)
3330 {
3331     uint64_t r0, r1;
3332
3333     imul64(&r0, &r1, T0, T1);
3334     T0 = r0;
3335     CC_DST = r0;
3336     CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
3337 }
3338
3339 void helper_divq_EAX_T0(void)
3340 {
3341     uint64_t r0, r1;
3342     if (T0 == 0) {
3343         raise_exception(EXCP00_DIVZ);
3344     }
3345     r0 = EAX;
3346     r1 = EDX;
3347     div64(&r0, &r1, T0);
3348     EAX = r0;
3349     EDX = r1;
3350 }
3351
3352 void helper_idivq_EAX_T0(void)
3353 {
3354     uint64_t r0, r1;
3355     if (T0 == 0) {
3356         raise_exception(EXCP00_DIVZ);
3357     }
3358     r0 = EAX;
3359     r1 = EDX;
3360     idiv64(&r0, &r1, T0);
3361     EAX = r0;
3362     EDX = r1;
3363 }
3364
3365 #endif
3366
3367 float approx_rsqrt(float a)
3368 {
3369     return 1.0 / sqrt(a);
3370 }
3371
3372 float approx_rcp(float a)
3373 {
3374     return 1.0 / a;
3375 }
3376
3377 void update_fp_status(void)
3378 {
3379     int rnd_type;
3380
3381     /* set rounding mode */
3382     switch(env->fpuc & RC_MASK) {
3383     default:
3384     case RC_NEAR:
3385         rnd_type = float_round_nearest_even;
3386         break;
3387     case RC_DOWN:
3388         rnd_type = float_round_down;
3389         break;
3390     case RC_UP:
3391         rnd_type = float_round_up;
3392         break;
3393     case RC_CHOP:
3394         rnd_type = float_round_to_zero;
3395         break;
3396     }
3397     set_float_rounding_mode(rnd_type, &env->fp_status);
3398 #ifdef FLOATX80
3399     switch((env->fpuc >> 8) & 3) {
3400     case 0:
3401         rnd_type = 32;
3402         break;
3403     case 2:
3404         rnd_type = 64;
3405         break;
3406     case 3:
3407     default:
3408         rnd_type = 80;
3409         break;
3410     }
3411     set_floatx80_rounding_precision(rnd_type, &env->fp_status);
3412 #endif
3413 }
3414
3415 #if !defined(CONFIG_USER_ONLY) 
3416
3417 #define MMUSUFFIX _mmu
3418 #define GETPC() (__builtin_return_address(0))
3419
3420 #define SHIFT 0
3421 #include "softmmu_template.h"
3422
3423 #define SHIFT 1
3424 #include "softmmu_template.h"
3425
3426 #define SHIFT 2
3427 #include "softmmu_template.h"
3428
3429 #define SHIFT 3
3430 #include "softmmu_template.h"
3431
3432 #endif
3433
3434 /* try to fill the TLB and return an exception if error. If retaddr is
3435    NULL, it means that the function was called in C code (i.e. not
3436    from generated code or from helper.c) */
3437 /* XXX: fix it to restore all registers */
3438 void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
3439 {
3440     TranslationBlock *tb;
3441     int ret;
3442     unsigned long pc;
3443     CPUX86State *saved_env;
3444
3445     /* XXX: hack to restore env in all cases, even if not called from
3446        generated code */
3447     saved_env = env;
3448     env = cpu_single_env;
3449
3450     ret = cpu_x86_handle_mmu_fault(env, addr, is_write, is_user, 1);
3451     if (ret) {
3452         if (retaddr) {
3453             /* now we have a real cpu fault */
3454             pc = (unsigned long)retaddr;
3455             tb = tb_find_pc(pc);
3456             if (tb) {
3457                 /* the PC is inside the translated code. It means that we have
3458                    a virtual CPU fault */
3459                 cpu_restore_state(tb, env, pc, NULL);
3460             }
3461         }
3462         if (retaddr)
3463             raise_exception_err(EXCP0E_PAGE, env->error_code);
3464         else
3465             raise_exception_err_norestore(EXCP0E_PAGE, env->error_code);
3466     }
3467     env = saved_env;
3468 }
This page took 0.215952 seconds and 4 git commands to generate.