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