Fix off-by-one unwinding error.
[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 #define CPU_NO_GLOBAL_REGS
21 #include "exec.h"
22 #include "host-utils.h"
23
24 //#define DEBUG_PCALL
25
26 #if 0
27 #define raise_exception_err(a, b)\
28 do {\
29     if (logfile)\
30         fprintf(logfile, "raise_exception line=%d\n", __LINE__);\
31     (raise_exception_err)(a, b);\
32 } while (0)
33 #endif
34
35 const uint8_t parity_table[256] = {
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     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
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     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
42     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
43     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
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     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
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     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
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     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
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     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
58     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
59     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
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     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
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     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
66     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
67     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
68 };
69
70 /* modulo 17 table */
71 const uint8_t rclw_table[32] = {
72     0, 1, 2, 3, 4, 5, 6, 7,
73     8, 9,10,11,12,13,14,15,
74    16, 0, 1, 2, 3, 4, 5, 6,
75     7, 8, 9,10,11,12,13,14,
76 };
77
78 /* modulo 9 table */
79 const uint8_t rclb_table[32] = {
80     0, 1, 2, 3, 4, 5, 6, 7,
81     8, 0, 1, 2, 3, 4, 5, 6,
82     7, 8, 0, 1, 2, 3, 4, 5,
83     6, 7, 8, 0, 1, 2, 3, 4,
84 };
85
86 const CPU86_LDouble f15rk[7] =
87 {
88     0.00000000000000000000L,
89     1.00000000000000000000L,
90     3.14159265358979323851L,  /*pi*/
91     0.30102999566398119523L,  /*lg2*/
92     0.69314718055994530943L,  /*ln2*/
93     1.44269504088896340739L,  /*l2e*/
94     3.32192809488736234781L,  /*l2t*/
95 };
96
97 /* broken thread support */
98
99 spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
100
101 void helper_lock(void)
102 {
103     spin_lock(&global_cpu_lock);
104 }
105
106 void helper_unlock(void)
107 {
108     spin_unlock(&global_cpu_lock);
109 }
110
111 void helper_write_eflags(target_ulong t0, uint32_t update_mask)
112 {
113     load_eflags(t0, update_mask);
114 }
115
116 target_ulong helper_read_eflags(void)
117 {
118     uint32_t eflags;
119     eflags = cc_table[CC_OP].compute_all();
120     eflags |= (DF & DF_MASK);
121     eflags |= env->eflags & ~(VM_MASK | RF_MASK);
122     return eflags;
123 }
124
125 /* return non zero if error */
126 static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr,
127                                int selector)
128 {
129     SegmentCache *dt;
130     int index;
131     target_ulong ptr;
132
133     if (selector & 0x4)
134         dt = &env->ldt;
135     else
136         dt = &env->gdt;
137     index = selector & ~7;
138     if ((index + 7) > dt->limit)
139         return -1;
140     ptr = dt->base + index;
141     *e1_ptr = ldl_kernel(ptr);
142     *e2_ptr = ldl_kernel(ptr + 4);
143     return 0;
144 }
145
146 static inline unsigned int get_seg_limit(uint32_t e1, uint32_t e2)
147 {
148     unsigned int limit;
149     limit = (e1 & 0xffff) | (e2 & 0x000f0000);
150     if (e2 & DESC_G_MASK)
151         limit = (limit << 12) | 0xfff;
152     return limit;
153 }
154
155 static inline uint32_t get_seg_base(uint32_t e1, uint32_t e2)
156 {
157     return ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
158 }
159
160 static inline void load_seg_cache_raw_dt(SegmentCache *sc, uint32_t e1, uint32_t e2)
161 {
162     sc->base = get_seg_base(e1, e2);
163     sc->limit = get_seg_limit(e1, e2);
164     sc->flags = e2;
165 }
166
167 /* init the segment cache in vm86 mode. */
168 static inline void load_seg_vm(int seg, int selector)
169 {
170     selector &= 0xffff;
171     cpu_x86_load_seg_cache(env, seg, selector,
172                            (selector << 4), 0xffff, 0);
173 }
174
175 static inline void get_ss_esp_from_tss(uint32_t *ss_ptr,
176                                        uint32_t *esp_ptr, int dpl)
177 {
178     int type, index, shift;
179
180 #if 0
181     {
182         int i;
183         printf("TR: base=%p limit=%x\n", env->tr.base, env->tr.limit);
184         for(i=0;i<env->tr.limit;i++) {
185             printf("%02x ", env->tr.base[i]);
186             if ((i & 7) == 7) printf("\n");
187         }
188         printf("\n");
189     }
190 #endif
191
192     if (!(env->tr.flags & DESC_P_MASK))
193         cpu_abort(env, "invalid tss");
194     type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
195     if ((type & 7) != 1)
196         cpu_abort(env, "invalid tss type");
197     shift = type >> 3;
198     index = (dpl * 4 + 2) << shift;
199     if (index + (4 << shift) - 1 > env->tr.limit)
200         raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
201     if (shift == 0) {
202         *esp_ptr = lduw_kernel(env->tr.base + index);
203         *ss_ptr = lduw_kernel(env->tr.base + index + 2);
204     } else {
205         *esp_ptr = ldl_kernel(env->tr.base + index);
206         *ss_ptr = lduw_kernel(env->tr.base + index + 4);
207     }
208 }
209
210 /* XXX: merge with load_seg() */
211 static void tss_load_seg(int seg_reg, int selector)
212 {
213     uint32_t e1, e2;
214     int rpl, dpl, cpl;
215
216     if ((selector & 0xfffc) != 0) {
217         if (load_segment(&e1, &e2, selector) != 0)
218             raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
219         if (!(e2 & DESC_S_MASK))
220             raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
221         rpl = selector & 3;
222         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
223         cpl = env->hflags & HF_CPL_MASK;
224         if (seg_reg == R_CS) {
225             if (!(e2 & DESC_CS_MASK))
226                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
227             /* XXX: is it correct ? */
228             if (dpl != rpl)
229                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
230             if ((e2 & DESC_C_MASK) && dpl > rpl)
231                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
232         } else if (seg_reg == R_SS) {
233             /* SS must be writable data */
234             if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
235                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
236             if (dpl != cpl || dpl != rpl)
237                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
238         } else {
239             /* not readable code */
240             if ((e2 & DESC_CS_MASK) && !(e2 & DESC_R_MASK))
241                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
242             /* if data or non conforming code, checks the rights */
243             if (((e2 >> DESC_TYPE_SHIFT) & 0xf) < 12) {
244                 if (dpl < cpl || dpl < rpl)
245                     raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
246             }
247         }
248         if (!(e2 & DESC_P_MASK))
249             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
250         cpu_x86_load_seg_cache(env, seg_reg, selector,
251                        get_seg_base(e1, e2),
252                        get_seg_limit(e1, e2),
253                        e2);
254     } else {
255         if (seg_reg == R_SS || seg_reg == R_CS)
256             raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
257     }
258 }
259
260 #define SWITCH_TSS_JMP  0
261 #define SWITCH_TSS_IRET 1
262 #define SWITCH_TSS_CALL 2
263
264 /* XXX: restore CPU state in registers (PowerPC case) */
265 static void switch_tss(int tss_selector,
266                        uint32_t e1, uint32_t e2, int source,
267                        uint32_t next_eip)
268 {
269     int tss_limit, tss_limit_max, type, old_tss_limit_max, old_type, v1, v2, i;
270     target_ulong tss_base;
271     uint32_t new_regs[8], new_segs[6];
272     uint32_t new_eflags, new_eip, new_cr3, new_ldt, new_trap;
273     uint32_t old_eflags, eflags_mask;
274     SegmentCache *dt;
275     int index;
276     target_ulong ptr;
277
278     type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
279 #ifdef DEBUG_PCALL
280     if (loglevel & CPU_LOG_PCALL)
281         fprintf(logfile, "switch_tss: sel=0x%04x type=%d src=%d\n", tss_selector, type, source);
282 #endif
283
284     /* if task gate, we read the TSS segment and we load it */
285     if (type == 5) {
286         if (!(e2 & DESC_P_MASK))
287             raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
288         tss_selector = e1 >> 16;
289         if (tss_selector & 4)
290             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
291         if (load_segment(&e1, &e2, tss_selector) != 0)
292             raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
293         if (e2 & DESC_S_MASK)
294             raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
295         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
296         if ((type & 7) != 1)
297             raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
298     }
299
300     if (!(e2 & DESC_P_MASK))
301         raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
302
303     if (type & 8)
304         tss_limit_max = 103;
305     else
306         tss_limit_max = 43;
307     tss_limit = get_seg_limit(e1, e2);
308     tss_base = get_seg_base(e1, e2);
309     if ((tss_selector & 4) != 0 ||
310         tss_limit < tss_limit_max)
311         raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
312     old_type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
313     if (old_type & 8)
314         old_tss_limit_max = 103;
315     else
316         old_tss_limit_max = 43;
317
318     /* read all the registers from the new TSS */
319     if (type & 8) {
320         /* 32 bit */
321         new_cr3 = ldl_kernel(tss_base + 0x1c);
322         new_eip = ldl_kernel(tss_base + 0x20);
323         new_eflags = ldl_kernel(tss_base + 0x24);
324         for(i = 0; i < 8; i++)
325             new_regs[i] = ldl_kernel(tss_base + (0x28 + i * 4));
326         for(i = 0; i < 6; i++)
327             new_segs[i] = lduw_kernel(tss_base + (0x48 + i * 4));
328         new_ldt = lduw_kernel(tss_base + 0x60);
329         new_trap = ldl_kernel(tss_base + 0x64);
330     } else {
331         /* 16 bit */
332         new_cr3 = 0;
333         new_eip = lduw_kernel(tss_base + 0x0e);
334         new_eflags = lduw_kernel(tss_base + 0x10);
335         for(i = 0; i < 8; i++)
336             new_regs[i] = lduw_kernel(tss_base + (0x12 + i * 2)) | 0xffff0000;
337         for(i = 0; i < 4; i++)
338             new_segs[i] = lduw_kernel(tss_base + (0x22 + i * 4));
339         new_ldt = lduw_kernel(tss_base + 0x2a);
340         new_segs[R_FS] = 0;
341         new_segs[R_GS] = 0;
342         new_trap = 0;
343     }
344
345     /* NOTE: we must avoid memory exceptions during the task switch,
346        so we make dummy accesses before */
347     /* XXX: it can still fail in some cases, so a bigger hack is
348        necessary to valid the TLB after having done the accesses */
349
350     v1 = ldub_kernel(env->tr.base);
351     v2 = ldub_kernel(env->tr.base + old_tss_limit_max);
352     stb_kernel(env->tr.base, v1);
353     stb_kernel(env->tr.base + old_tss_limit_max, v2);
354
355     /* clear busy bit (it is restartable) */
356     if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_IRET) {
357         target_ulong ptr;
358         uint32_t e2;
359         ptr = env->gdt.base + (env->tr.selector & ~7);
360         e2 = ldl_kernel(ptr + 4);
361         e2 &= ~DESC_TSS_BUSY_MASK;
362         stl_kernel(ptr + 4, e2);
363     }
364     old_eflags = compute_eflags();
365     if (source == SWITCH_TSS_IRET)
366         old_eflags &= ~NT_MASK;
367
368     /* save the current state in the old TSS */
369     if (type & 8) {
370         /* 32 bit */
371         stl_kernel(env->tr.base + 0x20, next_eip);
372         stl_kernel(env->tr.base + 0x24, old_eflags);
373         stl_kernel(env->tr.base + (0x28 + 0 * 4), EAX);
374         stl_kernel(env->tr.base + (0x28 + 1 * 4), ECX);
375         stl_kernel(env->tr.base + (0x28 + 2 * 4), EDX);
376         stl_kernel(env->tr.base + (0x28 + 3 * 4), EBX);
377         stl_kernel(env->tr.base + (0x28 + 4 * 4), ESP);
378         stl_kernel(env->tr.base + (0x28 + 5 * 4), EBP);
379         stl_kernel(env->tr.base + (0x28 + 6 * 4), ESI);
380         stl_kernel(env->tr.base + (0x28 + 7 * 4), EDI);
381         for(i = 0; i < 6; i++)
382             stw_kernel(env->tr.base + (0x48 + i * 4), env->segs[i].selector);
383     } else {
384         /* 16 bit */
385         stw_kernel(env->tr.base + 0x0e, next_eip);
386         stw_kernel(env->tr.base + 0x10, old_eflags);
387         stw_kernel(env->tr.base + (0x12 + 0 * 2), EAX);
388         stw_kernel(env->tr.base + (0x12 + 1 * 2), ECX);
389         stw_kernel(env->tr.base + (0x12 + 2 * 2), EDX);
390         stw_kernel(env->tr.base + (0x12 + 3 * 2), EBX);
391         stw_kernel(env->tr.base + (0x12 + 4 * 2), ESP);
392         stw_kernel(env->tr.base + (0x12 + 5 * 2), EBP);
393         stw_kernel(env->tr.base + (0x12 + 6 * 2), ESI);
394         stw_kernel(env->tr.base + (0x12 + 7 * 2), EDI);
395         for(i = 0; i < 4; i++)
396             stw_kernel(env->tr.base + (0x22 + i * 4), env->segs[i].selector);
397     }
398
399     /* now if an exception occurs, it will occurs in the next task
400        context */
401
402     if (source == SWITCH_TSS_CALL) {
403         stw_kernel(tss_base, env->tr.selector);
404         new_eflags |= NT_MASK;
405     }
406
407     /* set busy bit */
408     if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_CALL) {
409         target_ulong ptr;
410         uint32_t e2;
411         ptr = env->gdt.base + (tss_selector & ~7);
412         e2 = ldl_kernel(ptr + 4);
413         e2 |= DESC_TSS_BUSY_MASK;
414         stl_kernel(ptr + 4, e2);
415     }
416
417     /* set the new CPU state */
418     /* from this point, any exception which occurs can give problems */
419     env->cr[0] |= CR0_TS_MASK;
420     env->hflags |= HF_TS_MASK;
421     env->tr.selector = tss_selector;
422     env->tr.base = tss_base;
423     env->tr.limit = tss_limit;
424     env->tr.flags = e2 & ~DESC_TSS_BUSY_MASK;
425
426     if ((type & 8) && (env->cr[0] & CR0_PG_MASK)) {
427         cpu_x86_update_cr3(env, new_cr3);
428     }
429
430     /* load all registers without an exception, then reload them with
431        possible exception */
432     env->eip = new_eip;
433     eflags_mask = TF_MASK | AC_MASK | ID_MASK |
434         IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK;
435     if (!(type & 8))
436         eflags_mask &= 0xffff;
437     load_eflags(new_eflags, eflags_mask);
438     /* XXX: what to do in 16 bit case ? */
439     EAX = new_regs[0];
440     ECX = new_regs[1];
441     EDX = new_regs[2];
442     EBX = new_regs[3];
443     ESP = new_regs[4];
444     EBP = new_regs[5];
445     ESI = new_regs[6];
446     EDI = new_regs[7];
447     if (new_eflags & VM_MASK) {
448         for(i = 0; i < 6; i++)
449             load_seg_vm(i, new_segs[i]);
450         /* in vm86, CPL is always 3 */
451         cpu_x86_set_cpl(env, 3);
452     } else {
453         /* CPL is set the RPL of CS */
454         cpu_x86_set_cpl(env, new_segs[R_CS] & 3);
455         /* first just selectors as the rest may trigger exceptions */
456         for(i = 0; i < 6; i++)
457             cpu_x86_load_seg_cache(env, i, new_segs[i], 0, 0, 0);
458     }
459
460     env->ldt.selector = new_ldt & ~4;
461     env->ldt.base = 0;
462     env->ldt.limit = 0;
463     env->ldt.flags = 0;
464
465     /* load the LDT */
466     if (new_ldt & 4)
467         raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
468
469     if ((new_ldt & 0xfffc) != 0) {
470         dt = &env->gdt;
471         index = new_ldt & ~7;
472         if ((index + 7) > dt->limit)
473             raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
474         ptr = dt->base + index;
475         e1 = ldl_kernel(ptr);
476         e2 = ldl_kernel(ptr + 4);
477         if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
478             raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
479         if (!(e2 & DESC_P_MASK))
480             raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
481         load_seg_cache_raw_dt(&env->ldt, e1, e2);
482     }
483
484     /* load the segments */
485     if (!(new_eflags & VM_MASK)) {
486         tss_load_seg(R_CS, new_segs[R_CS]);
487         tss_load_seg(R_SS, new_segs[R_SS]);
488         tss_load_seg(R_ES, new_segs[R_ES]);
489         tss_load_seg(R_DS, new_segs[R_DS]);
490         tss_load_seg(R_FS, new_segs[R_FS]);
491         tss_load_seg(R_GS, new_segs[R_GS]);
492     }
493
494     /* check that EIP is in the CS segment limits */
495     if (new_eip > env->segs[R_CS].limit) {
496         /* XXX: different exception if CALL ? */
497         raise_exception_err(EXCP0D_GPF, 0);
498     }
499 }
500
501 /* check if Port I/O is allowed in TSS */
502 static inline void check_io(int addr, int size)
503 {
504     int io_offset, val, mask;
505
506     /* TSS must be a valid 32 bit one */
507     if (!(env->tr.flags & DESC_P_MASK) ||
508         ((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 ||
509         env->tr.limit < 103)
510         goto fail;
511     io_offset = lduw_kernel(env->tr.base + 0x66);
512     io_offset += (addr >> 3);
513     /* Note: the check needs two bytes */
514     if ((io_offset + 1) > env->tr.limit)
515         goto fail;
516     val = lduw_kernel(env->tr.base + io_offset);
517     val >>= (addr & 7);
518     mask = (1 << size) - 1;
519     /* all bits must be zero to allow the I/O */
520     if ((val & mask) != 0) {
521     fail:
522         raise_exception_err(EXCP0D_GPF, 0);
523     }
524 }
525
526 void helper_check_iob(uint32_t t0)
527 {
528     check_io(t0, 1);
529 }
530
531 void helper_check_iow(uint32_t t0)
532 {
533     check_io(t0, 2);
534 }
535
536 void helper_check_iol(uint32_t t0)
537 {
538     check_io(t0, 4);
539 }
540
541 void helper_outb(uint32_t port, uint32_t data)
542 {
543     cpu_outb(env, port, data & 0xff);
544 }
545
546 target_ulong helper_inb(uint32_t port)
547 {
548     return cpu_inb(env, port);
549 }
550
551 void helper_outw(uint32_t port, uint32_t data)
552 {
553     cpu_outw(env, port, data & 0xffff);
554 }
555
556 target_ulong helper_inw(uint32_t port)
557 {
558     return cpu_inw(env, port);
559 }
560
561 void helper_outl(uint32_t port, uint32_t data)
562 {
563     cpu_outl(env, port, data);
564 }
565
566 target_ulong helper_inl(uint32_t port)
567 {
568     return cpu_inl(env, port);
569 }
570
571 static inline unsigned int get_sp_mask(unsigned int e2)
572 {
573     if (e2 & DESC_B_MASK)
574         return 0xffffffff;
575     else
576         return 0xffff;
577 }
578
579 #ifdef TARGET_X86_64
580 #define SET_ESP(val, sp_mask)\
581 do {\
582     if ((sp_mask) == 0xffff)\
583         ESP = (ESP & ~0xffff) | ((val) & 0xffff);\
584     else if ((sp_mask) == 0xffffffffLL)\
585         ESP = (uint32_t)(val);\
586     else\
587         ESP = (val);\
588 } while (0)
589 #else
590 #define SET_ESP(val, sp_mask) ESP = (ESP & ~(sp_mask)) | ((val) & (sp_mask))
591 #endif
592
593 /* XXX: add a is_user flag to have proper security support */
594 #define PUSHW(ssp, sp, sp_mask, val)\
595 {\
596     sp -= 2;\
597     stw_kernel((ssp) + (sp & (sp_mask)), (val));\
598 }
599
600 #define PUSHL(ssp, sp, sp_mask, val)\
601 {\
602     sp -= 4;\
603     stl_kernel((ssp) + (sp & (sp_mask)), (val));\
604 }
605
606 #define POPW(ssp, sp, sp_mask, val)\
607 {\
608     val = lduw_kernel((ssp) + (sp & (sp_mask)));\
609     sp += 2;\
610 }
611
612 #define POPL(ssp, sp, sp_mask, val)\
613 {\
614     val = (uint32_t)ldl_kernel((ssp) + (sp & (sp_mask)));\
615     sp += 4;\
616 }
617
618 /* protected mode interrupt */
619 static void do_interrupt_protected(int intno, int is_int, int error_code,
620                                    unsigned int next_eip, int is_hw)
621 {
622     SegmentCache *dt;
623     target_ulong ptr, ssp;
624     int type, dpl, selector, ss_dpl, cpl;
625     int has_error_code, new_stack, shift;
626     uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2;
627     uint32_t old_eip, sp_mask;
628     int svm_should_check = 1;
629
630     if ((env->intercept & INTERCEPT_SVM_MASK) && !is_int && next_eip==-1) {
631         next_eip = EIP;
632         svm_should_check = 0;
633     }
634
635     if (svm_should_check
636         && (INTERCEPTEDl(_exceptions, 1 << intno)
637         && !is_int)) {
638         raise_interrupt(intno, is_int, error_code, 0);
639     }
640     has_error_code = 0;
641     if (!is_int && !is_hw) {
642         switch(intno) {
643         case 8:
644         case 10:
645         case 11:
646         case 12:
647         case 13:
648         case 14:
649         case 17:
650             has_error_code = 1;
651             break;
652         }
653     }
654     if (is_int)
655         old_eip = next_eip;
656     else
657         old_eip = env->eip;
658
659     dt = &env->idt;
660     if (intno * 8 + 7 > dt->limit)
661         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
662     ptr = dt->base + intno * 8;
663     e1 = ldl_kernel(ptr);
664     e2 = ldl_kernel(ptr + 4);
665     /* check gate type */
666     type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
667     switch(type) {
668     case 5: /* task gate */
669         /* must do that check here to return the correct error code */
670         if (!(e2 & DESC_P_MASK))
671             raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
672         switch_tss(intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip);
673         if (has_error_code) {
674             int type;
675             uint32_t mask;
676             /* push the error code */
677             type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
678             shift = type >> 3;
679             if (env->segs[R_SS].flags & DESC_B_MASK)
680                 mask = 0xffffffff;
681             else
682                 mask = 0xffff;
683             esp = (ESP - (2 << shift)) & mask;
684             ssp = env->segs[R_SS].base + esp;
685             if (shift)
686                 stl_kernel(ssp, error_code);
687             else
688                 stw_kernel(ssp, error_code);
689             SET_ESP(esp, mask);
690         }
691         return;
692     case 6: /* 286 interrupt gate */
693     case 7: /* 286 trap gate */
694     case 14: /* 386 interrupt gate */
695     case 15: /* 386 trap gate */
696         break;
697     default:
698         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
699         break;
700     }
701     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
702     cpl = env->hflags & HF_CPL_MASK;
703     /* check privledge if software int */
704     if (is_int && dpl < cpl)
705         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
706     /* check valid bit */
707     if (!(e2 & DESC_P_MASK))
708         raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
709     selector = e1 >> 16;
710     offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
711     if ((selector & 0xfffc) == 0)
712         raise_exception_err(EXCP0D_GPF, 0);
713
714     if (load_segment(&e1, &e2, selector) != 0)
715         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
716     if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
717         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
718     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
719     if (dpl > cpl)
720         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
721     if (!(e2 & DESC_P_MASK))
722         raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
723     if (!(e2 & DESC_C_MASK) && dpl < cpl) {
724         /* to inner privilege */
725         get_ss_esp_from_tss(&ss, &esp, dpl);
726         if ((ss & 0xfffc) == 0)
727             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
728         if ((ss & 3) != dpl)
729             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
730         if (load_segment(&ss_e1, &ss_e2, ss) != 0)
731             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
732         ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
733         if (ss_dpl != dpl)
734             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
735         if (!(ss_e2 & DESC_S_MASK) ||
736             (ss_e2 & DESC_CS_MASK) ||
737             !(ss_e2 & DESC_W_MASK))
738             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
739         if (!(ss_e2 & DESC_P_MASK))
740             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
741         new_stack = 1;
742         sp_mask = get_sp_mask(ss_e2);
743         ssp = get_seg_base(ss_e1, ss_e2);
744     } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
745         /* to same privilege */
746         if (env->eflags & VM_MASK)
747             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
748         new_stack = 0;
749         sp_mask = get_sp_mask(env->segs[R_SS].flags);
750         ssp = env->segs[R_SS].base;
751         esp = ESP;
752         dpl = cpl;
753     } else {
754         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
755         new_stack = 0; /* avoid warning */
756         sp_mask = 0; /* avoid warning */
757         ssp = 0; /* avoid warning */
758         esp = 0; /* avoid warning */
759     }
760
761     shift = type >> 3;
762
763 #if 0
764     /* XXX: check that enough room is available */
765     push_size = 6 + (new_stack << 2) + (has_error_code << 1);
766     if (env->eflags & VM_MASK)
767         push_size += 8;
768     push_size <<= shift;
769 #endif
770     if (shift == 1) {
771         if (new_stack) {
772             if (env->eflags & VM_MASK) {
773                 PUSHL(ssp, esp, sp_mask, env->segs[R_GS].selector);
774                 PUSHL(ssp, esp, sp_mask, env->segs[R_FS].selector);
775                 PUSHL(ssp, esp, sp_mask, env->segs[R_DS].selector);
776                 PUSHL(ssp, esp, sp_mask, env->segs[R_ES].selector);
777             }
778             PUSHL(ssp, esp, sp_mask, env->segs[R_SS].selector);
779             PUSHL(ssp, esp, sp_mask, ESP);
780         }
781         PUSHL(ssp, esp, sp_mask, compute_eflags());
782         PUSHL(ssp, esp, sp_mask, env->segs[R_CS].selector);
783         PUSHL(ssp, esp, sp_mask, old_eip);
784         if (has_error_code) {
785             PUSHL(ssp, esp, sp_mask, error_code);
786         }
787     } else {
788         if (new_stack) {
789             if (env->eflags & VM_MASK) {
790                 PUSHW(ssp, esp, sp_mask, env->segs[R_GS].selector);
791                 PUSHW(ssp, esp, sp_mask, env->segs[R_FS].selector);
792                 PUSHW(ssp, esp, sp_mask, env->segs[R_DS].selector);
793                 PUSHW(ssp, esp, sp_mask, env->segs[R_ES].selector);
794             }
795             PUSHW(ssp, esp, sp_mask, env->segs[R_SS].selector);
796             PUSHW(ssp, esp, sp_mask, ESP);
797         }
798         PUSHW(ssp, esp, sp_mask, compute_eflags());
799         PUSHW(ssp, esp, sp_mask, env->segs[R_CS].selector);
800         PUSHW(ssp, esp, sp_mask, old_eip);
801         if (has_error_code) {
802             PUSHW(ssp, esp, sp_mask, error_code);
803         }
804     }
805
806     if (new_stack) {
807         if (env->eflags & VM_MASK) {
808             cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0, 0);
809             cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0, 0);
810             cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0, 0);
811             cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0, 0);
812         }
813         ss = (ss & ~3) | dpl;
814         cpu_x86_load_seg_cache(env, R_SS, ss,
815                                ssp, get_seg_limit(ss_e1, ss_e2), ss_e2);
816     }
817     SET_ESP(esp, sp_mask);
818
819     selector = (selector & ~3) | dpl;
820     cpu_x86_load_seg_cache(env, R_CS, selector,
821                    get_seg_base(e1, e2),
822                    get_seg_limit(e1, e2),
823                    e2);
824     cpu_x86_set_cpl(env, dpl);
825     env->eip = offset;
826
827     /* interrupt gate clear IF mask */
828     if ((type & 1) == 0) {
829         env->eflags &= ~IF_MASK;
830     }
831     env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
832 }
833
834 #ifdef TARGET_X86_64
835
836 #define PUSHQ(sp, val)\
837 {\
838     sp -= 8;\
839     stq_kernel(sp, (val));\
840 }
841
842 #define POPQ(sp, val)\
843 {\
844     val = ldq_kernel(sp);\
845     sp += 8;\
846 }
847
848 static inline target_ulong get_rsp_from_tss(int level)
849 {
850     int index;
851
852 #if 0
853     printf("TR: base=" TARGET_FMT_lx " limit=%x\n",
854            env->tr.base, env->tr.limit);
855 #endif
856
857     if (!(env->tr.flags & DESC_P_MASK))
858         cpu_abort(env, "invalid tss");
859     index = 8 * level + 4;
860     if ((index + 7) > env->tr.limit)
861         raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
862     return ldq_kernel(env->tr.base + index);
863 }
864
865 /* 64 bit interrupt */
866 static void do_interrupt64(int intno, int is_int, int error_code,
867                            target_ulong next_eip, int is_hw)
868 {
869     SegmentCache *dt;
870     target_ulong ptr;
871     int type, dpl, selector, cpl, ist;
872     int has_error_code, new_stack;
873     uint32_t e1, e2, e3, ss;
874     target_ulong old_eip, esp, offset;
875     int svm_should_check = 1;
876
877     if ((env->intercept & INTERCEPT_SVM_MASK) && !is_int && next_eip==-1) {
878         next_eip = EIP;
879         svm_should_check = 0;
880     }
881     if (svm_should_check
882         && INTERCEPTEDl(_exceptions, 1 << intno)
883         && !is_int) {
884         raise_interrupt(intno, is_int, error_code, 0);
885     }
886     has_error_code = 0;
887     if (!is_int && !is_hw) {
888         switch(intno) {
889         case 8:
890         case 10:
891         case 11:
892         case 12:
893         case 13:
894         case 14:
895         case 17:
896             has_error_code = 1;
897             break;
898         }
899     }
900     if (is_int)
901         old_eip = next_eip;
902     else
903         old_eip = env->eip;
904
905     dt = &env->idt;
906     if (intno * 16 + 15 > dt->limit)
907         raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
908     ptr = dt->base + intno * 16;
909     e1 = ldl_kernel(ptr);
910     e2 = ldl_kernel(ptr + 4);
911     e3 = ldl_kernel(ptr + 8);
912     /* check gate type */
913     type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
914     switch(type) {
915     case 14: /* 386 interrupt gate */
916     case 15: /* 386 trap gate */
917         break;
918     default:
919         raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
920         break;
921     }
922     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
923     cpl = env->hflags & HF_CPL_MASK;
924     /* check privledge if software int */
925     if (is_int && dpl < cpl)
926         raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
927     /* check valid bit */
928     if (!(e2 & DESC_P_MASK))
929         raise_exception_err(EXCP0B_NOSEG, intno * 16 + 2);
930     selector = e1 >> 16;
931     offset = ((target_ulong)e3 << 32) | (e2 & 0xffff0000) | (e1 & 0x0000ffff);
932     ist = e2 & 7;
933     if ((selector & 0xfffc) == 0)
934         raise_exception_err(EXCP0D_GPF, 0);
935
936     if (load_segment(&e1, &e2, selector) != 0)
937         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
938     if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
939         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
940     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
941     if (dpl > cpl)
942         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
943     if (!(e2 & DESC_P_MASK))
944         raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
945     if (!(e2 & DESC_L_MASK) || (e2 & DESC_B_MASK))
946         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
947     if ((!(e2 & DESC_C_MASK) && dpl < cpl) || ist != 0) {
948         /* to inner privilege */
949         if (ist != 0)
950             esp = get_rsp_from_tss(ist + 3);
951         else
952             esp = get_rsp_from_tss(dpl);
953         esp &= ~0xfLL; /* align stack */
954         ss = 0;
955         new_stack = 1;
956     } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
957         /* to same privilege */
958         if (env->eflags & VM_MASK)
959             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
960         new_stack = 0;
961         if (ist != 0)
962             esp = get_rsp_from_tss(ist + 3);
963         else
964             esp = ESP;
965         esp &= ~0xfLL; /* align stack */
966         dpl = cpl;
967     } else {
968         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
969         new_stack = 0; /* avoid warning */
970         esp = 0; /* avoid warning */
971     }
972
973     PUSHQ(esp, env->segs[R_SS].selector);
974     PUSHQ(esp, ESP);
975     PUSHQ(esp, compute_eflags());
976     PUSHQ(esp, env->segs[R_CS].selector);
977     PUSHQ(esp, old_eip);
978     if (has_error_code) {
979         PUSHQ(esp, error_code);
980     }
981
982     if (new_stack) {
983         ss = 0 | dpl;
984         cpu_x86_load_seg_cache(env, R_SS, ss, 0, 0, 0);
985     }
986     ESP = esp;
987
988     selector = (selector & ~3) | dpl;
989     cpu_x86_load_seg_cache(env, R_CS, selector,
990                    get_seg_base(e1, e2),
991                    get_seg_limit(e1, e2),
992                    e2);
993     cpu_x86_set_cpl(env, dpl);
994     env->eip = offset;
995
996     /* interrupt gate clear IF mask */
997     if ((type & 1) == 0) {
998         env->eflags &= ~IF_MASK;
999     }
1000     env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
1001 }
1002 #endif
1003
1004 #if defined(CONFIG_USER_ONLY)
1005 void helper_syscall(int next_eip_addend)
1006 {
1007     env->exception_index = EXCP_SYSCALL;
1008     env->exception_next_eip = env->eip + next_eip_addend;
1009     cpu_loop_exit();
1010 }
1011 #else
1012 void helper_syscall(int next_eip_addend)
1013 {
1014     int selector;
1015
1016     if (!(env->efer & MSR_EFER_SCE)) {
1017         raise_exception_err(EXCP06_ILLOP, 0);
1018     }
1019     selector = (env->star >> 32) & 0xffff;
1020 #ifdef TARGET_X86_64
1021     if (env->hflags & HF_LMA_MASK) {
1022         int code64;
1023
1024         ECX = env->eip + next_eip_addend;
1025         env->regs[11] = compute_eflags();
1026
1027         code64 = env->hflags & HF_CS64_MASK;
1028
1029         cpu_x86_set_cpl(env, 0);
1030         cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
1031                            0, 0xffffffff,
1032                                DESC_G_MASK | DESC_P_MASK |
1033                                DESC_S_MASK |
1034                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
1035         cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
1036                                0, 0xffffffff,
1037                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1038                                DESC_S_MASK |
1039                                DESC_W_MASK | DESC_A_MASK);
1040         env->eflags &= ~env->fmask;
1041         load_eflags(env->eflags, 0);
1042         if (code64)
1043             env->eip = env->lstar;
1044         else
1045             env->eip = env->cstar;
1046     } else
1047 #endif
1048     {
1049         ECX = (uint32_t)(env->eip + next_eip_addend);
1050
1051         cpu_x86_set_cpl(env, 0);
1052         cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
1053                            0, 0xffffffff,
1054                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1055                                DESC_S_MASK |
1056                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1057         cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
1058                                0, 0xffffffff,
1059                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1060                                DESC_S_MASK |
1061                                DESC_W_MASK | DESC_A_MASK);
1062         env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
1063         env->eip = (uint32_t)env->star;
1064     }
1065 }
1066 #endif
1067
1068 void helper_sysret(int dflag)
1069 {
1070     int cpl, selector;
1071
1072     if (!(env->efer & MSR_EFER_SCE)) {
1073         raise_exception_err(EXCP06_ILLOP, 0);
1074     }
1075     cpl = env->hflags & HF_CPL_MASK;
1076     if (!(env->cr[0] & CR0_PE_MASK) || cpl != 0) {
1077         raise_exception_err(EXCP0D_GPF, 0);
1078     }
1079     selector = (env->star >> 48) & 0xffff;
1080 #ifdef TARGET_X86_64
1081     if (env->hflags & HF_LMA_MASK) {
1082         if (dflag == 2) {
1083             cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3,
1084                                    0, 0xffffffff,
1085                                    DESC_G_MASK | DESC_P_MASK |
1086                                    DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1087                                    DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK |
1088                                    DESC_L_MASK);
1089             env->eip = ECX;
1090         } else {
1091             cpu_x86_load_seg_cache(env, R_CS, selector | 3,
1092                                    0, 0xffffffff,
1093                                    DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1094                                    DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1095                                    DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1096             env->eip = (uint32_t)ECX;
1097         }
1098         cpu_x86_load_seg_cache(env, R_SS, selector + 8,
1099                                0, 0xffffffff,
1100                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1101                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1102                                DESC_W_MASK | DESC_A_MASK);
1103         load_eflags((uint32_t)(env->regs[11]), TF_MASK | AC_MASK | ID_MASK |
1104                     IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK);
1105         cpu_x86_set_cpl(env, 3);
1106     } else
1107 #endif
1108     {
1109         cpu_x86_load_seg_cache(env, R_CS, selector | 3,
1110                                0, 0xffffffff,
1111                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1112                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1113                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1114         env->eip = (uint32_t)ECX;
1115         cpu_x86_load_seg_cache(env, R_SS, selector + 8,
1116                                0, 0xffffffff,
1117                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1118                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1119                                DESC_W_MASK | DESC_A_MASK);
1120         env->eflags |= IF_MASK;
1121         cpu_x86_set_cpl(env, 3);
1122     }
1123 #ifdef USE_KQEMU
1124     if (kqemu_is_ok(env)) {
1125         if (env->hflags & HF_LMA_MASK)
1126             CC_OP = CC_OP_EFLAGS;
1127         env->exception_index = -1;
1128         cpu_loop_exit();
1129     }
1130 #endif
1131 }
1132
1133 /* real mode interrupt */
1134 static void do_interrupt_real(int intno, int is_int, int error_code,
1135                               unsigned int next_eip)
1136 {
1137     SegmentCache *dt;
1138     target_ulong ptr, ssp;
1139     int selector;
1140     uint32_t offset, esp;
1141     uint32_t old_cs, old_eip;
1142     int svm_should_check = 1;
1143
1144     if ((env->intercept & INTERCEPT_SVM_MASK) && !is_int && next_eip==-1) {
1145         next_eip = EIP;
1146         svm_should_check = 0;
1147     }
1148     if (svm_should_check
1149         && INTERCEPTEDl(_exceptions, 1 << intno)
1150         && !is_int) {
1151         raise_interrupt(intno, is_int, error_code, 0);
1152     }
1153     /* real mode (simpler !) */
1154     dt = &env->idt;
1155     if (intno * 4 + 3 > dt->limit)
1156         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
1157     ptr = dt->base + intno * 4;
1158     offset = lduw_kernel(ptr);
1159     selector = lduw_kernel(ptr + 2);
1160     esp = ESP;
1161     ssp = env->segs[R_SS].base;
1162     if (is_int)
1163         old_eip = next_eip;
1164     else
1165         old_eip = env->eip;
1166     old_cs = env->segs[R_CS].selector;
1167     /* XXX: use SS segment size ? */
1168     PUSHW(ssp, esp, 0xffff, compute_eflags());
1169     PUSHW(ssp, esp, 0xffff, old_cs);
1170     PUSHW(ssp, esp, 0xffff, old_eip);
1171
1172     /* update processor state */
1173     ESP = (ESP & ~0xffff) | (esp & 0xffff);
1174     env->eip = offset;
1175     env->segs[R_CS].selector = selector;
1176     env->segs[R_CS].base = (selector << 4);
1177     env->eflags &= ~(IF_MASK | TF_MASK | AC_MASK | RF_MASK);
1178 }
1179
1180 /* fake user mode interrupt */
1181 void do_interrupt_user(int intno, int is_int, int error_code,
1182                        target_ulong next_eip)
1183 {
1184     SegmentCache *dt;
1185     target_ulong ptr;
1186     int dpl, cpl, shift;
1187     uint32_t e2;
1188
1189     dt = &env->idt;
1190     if (env->hflags & HF_LMA_MASK) {
1191         shift = 4;
1192     } else {
1193         shift = 3;
1194     }
1195     ptr = dt->base + (intno << shift);
1196     e2 = ldl_kernel(ptr + 4);
1197
1198     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1199     cpl = env->hflags & HF_CPL_MASK;
1200     /* check privledge if software int */
1201     if (is_int && dpl < cpl)
1202         raise_exception_err(EXCP0D_GPF, (intno << shift) + 2);
1203
1204     /* Since we emulate only user space, we cannot do more than
1205        exiting the emulation with the suitable exception and error
1206        code */
1207     if (is_int)
1208         EIP = next_eip;
1209 }
1210
1211 /*
1212  * Begin execution of an interruption. is_int is TRUE if coming from
1213  * the int instruction. next_eip is the EIP value AFTER the interrupt
1214  * instruction. It is only relevant if is_int is TRUE.
1215  */
1216 void do_interrupt(int intno, int is_int, int error_code,
1217                   target_ulong next_eip, int is_hw)
1218 {
1219     if (loglevel & CPU_LOG_INT) {
1220         if ((env->cr[0] & CR0_PE_MASK)) {
1221             static int count;
1222             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,
1223                     count, intno, error_code, is_int,
1224                     env->hflags & HF_CPL_MASK,
1225                     env->segs[R_CS].selector, EIP,
1226                     (int)env->segs[R_CS].base + EIP,
1227                     env->segs[R_SS].selector, ESP);
1228             if (intno == 0x0e) {
1229                 fprintf(logfile, " CR2=" TARGET_FMT_lx, env->cr[2]);
1230             } else {
1231                 fprintf(logfile, " EAX=" TARGET_FMT_lx, EAX);
1232             }
1233             fprintf(logfile, "\n");
1234             cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1235 #if 0
1236             {
1237                 int i;
1238                 uint8_t *ptr;
1239                 fprintf(logfile, "       code=");
1240                 ptr = env->segs[R_CS].base + env->eip;
1241                 for(i = 0; i < 16; i++) {
1242                     fprintf(logfile, " %02x", ldub(ptr + i));
1243                 }
1244                 fprintf(logfile, "\n");
1245             }
1246 #endif
1247             count++;
1248         }
1249     }
1250     if (env->cr[0] & CR0_PE_MASK) {
1251 #if TARGET_X86_64
1252         if (env->hflags & HF_LMA_MASK) {
1253             do_interrupt64(intno, is_int, error_code, next_eip, is_hw);
1254         } else
1255 #endif
1256         {
1257             do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);
1258         }
1259     } else {
1260         do_interrupt_real(intno, is_int, error_code, next_eip);
1261     }
1262 }
1263
1264 /*
1265  * Check nested exceptions and change to double or triple fault if
1266  * needed. It should only be called, if this is not an interrupt.
1267  * Returns the new exception number.
1268  */
1269 static int check_exception(int intno, int *error_code)
1270 {
1271     int first_contributory = env->old_exception == 0 ||
1272                               (env->old_exception >= 10 &&
1273                                env->old_exception <= 13);
1274     int second_contributory = intno == 0 ||
1275                                (intno >= 10 && intno <= 13);
1276
1277     if (loglevel & CPU_LOG_INT)
1278         fprintf(logfile, "check_exception old: 0x%x new 0x%x\n",
1279                 env->old_exception, intno);
1280
1281     if (env->old_exception == EXCP08_DBLE)
1282         cpu_abort(env, "triple fault");
1283
1284     if ((first_contributory && second_contributory)
1285         || (env->old_exception == EXCP0E_PAGE &&
1286             (second_contributory || (intno == EXCP0E_PAGE)))) {
1287         intno = EXCP08_DBLE;
1288         *error_code = 0;
1289     }
1290
1291     if (second_contributory || (intno == EXCP0E_PAGE) ||
1292         (intno == EXCP08_DBLE))
1293         env->old_exception = intno;
1294
1295     return intno;
1296 }
1297
1298 /*
1299  * Signal an interruption. It is executed in the main CPU loop.
1300  * is_int is TRUE if coming from the int instruction. next_eip is the
1301  * EIP value AFTER the interrupt instruction. It is only relevant if
1302  * is_int is TRUE.
1303  */
1304 void raise_interrupt(int intno, int is_int, int error_code,
1305                      int next_eip_addend)
1306 {
1307     if (!is_int) {
1308         helper_svm_check_intercept_param(SVM_EXIT_EXCP_BASE + intno, error_code);
1309         intno = check_exception(intno, &error_code);
1310     }
1311
1312     env->exception_index = intno;
1313     env->error_code = error_code;
1314     env->exception_is_int = is_int;
1315     env->exception_next_eip = env->eip + next_eip_addend;
1316     cpu_loop_exit();
1317 }
1318
1319 /* same as raise_exception_err, but do not restore global registers */
1320 static void raise_exception_err_norestore(int exception_index, int error_code)
1321 {
1322     exception_index = check_exception(exception_index, &error_code);
1323
1324     env->exception_index = exception_index;
1325     env->error_code = error_code;
1326     env->exception_is_int = 0;
1327     env->exception_next_eip = 0;
1328     longjmp(env->jmp_env, 1);
1329 }
1330
1331 /* shortcuts to generate exceptions */
1332
1333 void (raise_exception_err)(int exception_index, int error_code)
1334 {
1335     raise_interrupt(exception_index, 0, error_code, 0);
1336 }
1337
1338 void raise_exception(int exception_index)
1339 {
1340     raise_interrupt(exception_index, 0, 0, 0);
1341 }
1342
1343 /* SMM support */
1344
1345 #if defined(CONFIG_USER_ONLY)
1346
1347 void do_smm_enter(void)
1348 {
1349 }
1350
1351 void helper_rsm(void)
1352 {
1353 }
1354
1355 #else
1356
1357 #ifdef TARGET_X86_64
1358 #define SMM_REVISION_ID 0x00020064
1359 #else
1360 #define SMM_REVISION_ID 0x00020000
1361 #endif
1362
1363 void do_smm_enter(void)
1364 {
1365     target_ulong sm_state;
1366     SegmentCache *dt;
1367     int i, offset;
1368
1369     if (loglevel & CPU_LOG_INT) {
1370         fprintf(logfile, "SMM: enter\n");
1371         cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1372     }
1373
1374     env->hflags |= HF_SMM_MASK;
1375     cpu_smm_update(env);
1376
1377     sm_state = env->smbase + 0x8000;
1378
1379 #ifdef TARGET_X86_64
1380     for(i = 0; i < 6; i++) {
1381         dt = &env->segs[i];
1382         offset = 0x7e00 + i * 16;
1383         stw_phys(sm_state + offset, dt->selector);
1384         stw_phys(sm_state + offset + 2, (dt->flags >> 8) & 0xf0ff);
1385         stl_phys(sm_state + offset + 4, dt->limit);
1386         stq_phys(sm_state + offset + 8, dt->base);
1387     }
1388
1389     stq_phys(sm_state + 0x7e68, env->gdt.base);
1390     stl_phys(sm_state + 0x7e64, env->gdt.limit);
1391
1392     stw_phys(sm_state + 0x7e70, env->ldt.selector);
1393     stq_phys(sm_state + 0x7e78, env->ldt.base);
1394     stl_phys(sm_state + 0x7e74, env->ldt.limit);
1395     stw_phys(sm_state + 0x7e72, (env->ldt.flags >> 8) & 0xf0ff);
1396
1397     stq_phys(sm_state + 0x7e88, env->idt.base);
1398     stl_phys(sm_state + 0x7e84, env->idt.limit);
1399
1400     stw_phys(sm_state + 0x7e90, env->tr.selector);
1401     stq_phys(sm_state + 0x7e98, env->tr.base);
1402     stl_phys(sm_state + 0x7e94, env->tr.limit);
1403     stw_phys(sm_state + 0x7e92, (env->tr.flags >> 8) & 0xf0ff);
1404
1405     stq_phys(sm_state + 0x7ed0, env->efer);
1406
1407     stq_phys(sm_state + 0x7ff8, EAX);
1408     stq_phys(sm_state + 0x7ff0, ECX);
1409     stq_phys(sm_state + 0x7fe8, EDX);
1410     stq_phys(sm_state + 0x7fe0, EBX);
1411     stq_phys(sm_state + 0x7fd8, ESP);
1412     stq_phys(sm_state + 0x7fd0, EBP);
1413     stq_phys(sm_state + 0x7fc8, ESI);
1414     stq_phys(sm_state + 0x7fc0, EDI);
1415     for(i = 8; i < 16; i++)
1416         stq_phys(sm_state + 0x7ff8 - i * 8, env->regs[i]);
1417     stq_phys(sm_state + 0x7f78, env->eip);
1418     stl_phys(sm_state + 0x7f70, compute_eflags());
1419     stl_phys(sm_state + 0x7f68, env->dr[6]);
1420     stl_phys(sm_state + 0x7f60, env->dr[7]);
1421
1422     stl_phys(sm_state + 0x7f48, env->cr[4]);
1423     stl_phys(sm_state + 0x7f50, env->cr[3]);
1424     stl_phys(sm_state + 0x7f58, env->cr[0]);
1425
1426     stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
1427     stl_phys(sm_state + 0x7f00, env->smbase);
1428 #else
1429     stl_phys(sm_state + 0x7ffc, env->cr[0]);
1430     stl_phys(sm_state + 0x7ff8, env->cr[3]);
1431     stl_phys(sm_state + 0x7ff4, compute_eflags());
1432     stl_phys(sm_state + 0x7ff0, env->eip);
1433     stl_phys(sm_state + 0x7fec, EDI);
1434     stl_phys(sm_state + 0x7fe8, ESI);
1435     stl_phys(sm_state + 0x7fe4, EBP);
1436     stl_phys(sm_state + 0x7fe0, ESP);
1437     stl_phys(sm_state + 0x7fdc, EBX);
1438     stl_phys(sm_state + 0x7fd8, EDX);
1439     stl_phys(sm_state + 0x7fd4, ECX);
1440     stl_phys(sm_state + 0x7fd0, EAX);
1441     stl_phys(sm_state + 0x7fcc, env->dr[6]);
1442     stl_phys(sm_state + 0x7fc8, env->dr[7]);
1443
1444     stl_phys(sm_state + 0x7fc4, env->tr.selector);
1445     stl_phys(sm_state + 0x7f64, env->tr.base);
1446     stl_phys(sm_state + 0x7f60, env->tr.limit);
1447     stl_phys(sm_state + 0x7f5c, (env->tr.flags >> 8) & 0xf0ff);
1448
1449     stl_phys(sm_state + 0x7fc0, env->ldt.selector);
1450     stl_phys(sm_state + 0x7f80, env->ldt.base);
1451     stl_phys(sm_state + 0x7f7c, env->ldt.limit);
1452     stl_phys(sm_state + 0x7f78, (env->ldt.flags >> 8) & 0xf0ff);
1453
1454     stl_phys(sm_state + 0x7f74, env->gdt.base);
1455     stl_phys(sm_state + 0x7f70, env->gdt.limit);
1456
1457     stl_phys(sm_state + 0x7f58, env->idt.base);
1458     stl_phys(sm_state + 0x7f54, env->idt.limit);
1459
1460     for(i = 0; i < 6; i++) {
1461         dt = &env->segs[i];
1462         if (i < 3)
1463             offset = 0x7f84 + i * 12;
1464         else
1465             offset = 0x7f2c + (i - 3) * 12;
1466         stl_phys(sm_state + 0x7fa8 + i * 4, dt->selector);
1467         stl_phys(sm_state + offset + 8, dt->base);
1468         stl_phys(sm_state + offset + 4, dt->limit);
1469         stl_phys(sm_state + offset, (dt->flags >> 8) & 0xf0ff);
1470     }
1471     stl_phys(sm_state + 0x7f14, env->cr[4]);
1472
1473     stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
1474     stl_phys(sm_state + 0x7ef8, env->smbase);
1475 #endif
1476     /* init SMM cpu state */
1477
1478 #ifdef TARGET_X86_64
1479     env->efer = 0;
1480     env->hflags &= ~HF_LMA_MASK;
1481 #endif
1482     load_eflags(0, ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1483     env->eip = 0x00008000;
1484     cpu_x86_load_seg_cache(env, R_CS, (env->smbase >> 4) & 0xffff, env->smbase,
1485                            0xffffffff, 0);
1486     cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffffffff, 0);
1487     cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffffffff, 0);
1488     cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffffffff, 0);
1489     cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffffffff, 0);
1490     cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffffffff, 0);
1491
1492     cpu_x86_update_cr0(env,
1493                        env->cr[0] & ~(CR0_PE_MASK | CR0_EM_MASK | CR0_TS_MASK | CR0_PG_MASK));
1494     cpu_x86_update_cr4(env, 0);
1495     env->dr[7] = 0x00000400;
1496     CC_OP = CC_OP_EFLAGS;
1497 }
1498
1499 void helper_rsm(void)
1500 {
1501     target_ulong sm_state;
1502     int i, offset;
1503     uint32_t val;
1504
1505     sm_state = env->smbase + 0x8000;
1506 #ifdef TARGET_X86_64
1507     env->efer = ldq_phys(sm_state + 0x7ed0);
1508     if (env->efer & MSR_EFER_LMA)
1509         env->hflags |= HF_LMA_MASK;
1510     else
1511         env->hflags &= ~HF_LMA_MASK;
1512
1513     for(i = 0; i < 6; i++) {
1514         offset = 0x7e00 + i * 16;
1515         cpu_x86_load_seg_cache(env, i,
1516                                lduw_phys(sm_state + offset),
1517                                ldq_phys(sm_state + offset + 8),
1518                                ldl_phys(sm_state + offset + 4),
1519                                (lduw_phys(sm_state + offset + 2) & 0xf0ff) << 8);
1520     }
1521
1522     env->gdt.base = ldq_phys(sm_state + 0x7e68);
1523     env->gdt.limit = ldl_phys(sm_state + 0x7e64);
1524
1525     env->ldt.selector = lduw_phys(sm_state + 0x7e70);
1526     env->ldt.base = ldq_phys(sm_state + 0x7e78);
1527     env->ldt.limit = ldl_phys(sm_state + 0x7e74);
1528     env->ldt.flags = (lduw_phys(sm_state + 0x7e72) & 0xf0ff) << 8;
1529
1530     env->idt.base = ldq_phys(sm_state + 0x7e88);
1531     env->idt.limit = ldl_phys(sm_state + 0x7e84);
1532
1533     env->tr.selector = lduw_phys(sm_state + 0x7e90);
1534     env->tr.base = ldq_phys(sm_state + 0x7e98);
1535     env->tr.limit = ldl_phys(sm_state + 0x7e94);
1536     env->tr.flags = (lduw_phys(sm_state + 0x7e92) & 0xf0ff) << 8;
1537
1538     EAX = ldq_phys(sm_state + 0x7ff8);
1539     ECX = ldq_phys(sm_state + 0x7ff0);
1540     EDX = ldq_phys(sm_state + 0x7fe8);
1541     EBX = ldq_phys(sm_state + 0x7fe0);
1542     ESP = ldq_phys(sm_state + 0x7fd8);
1543     EBP = ldq_phys(sm_state + 0x7fd0);
1544     ESI = ldq_phys(sm_state + 0x7fc8);
1545     EDI = ldq_phys(sm_state + 0x7fc0);
1546     for(i = 8; i < 16; i++)
1547         env->regs[i] = ldq_phys(sm_state + 0x7ff8 - i * 8);
1548     env->eip = ldq_phys(sm_state + 0x7f78);
1549     load_eflags(ldl_phys(sm_state + 0x7f70),
1550                 ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1551     env->dr[6] = ldl_phys(sm_state + 0x7f68);
1552     env->dr[7] = ldl_phys(sm_state + 0x7f60);
1553
1554     cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f48));
1555     cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7f50));
1556     cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7f58));
1557
1558     val = ldl_phys(sm_state + 0x7efc); /* revision ID */
1559     if (val & 0x20000) {
1560         env->smbase = ldl_phys(sm_state + 0x7f00) & ~0x7fff;
1561     }
1562 #else
1563     cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7ffc));
1564     cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7ff8));
1565     load_eflags(ldl_phys(sm_state + 0x7ff4),
1566                 ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1567     env->eip = ldl_phys(sm_state + 0x7ff0);
1568     EDI = ldl_phys(sm_state + 0x7fec);
1569     ESI = ldl_phys(sm_state + 0x7fe8);
1570     EBP = ldl_phys(sm_state + 0x7fe4);
1571     ESP = ldl_phys(sm_state + 0x7fe0);
1572     EBX = ldl_phys(sm_state + 0x7fdc);
1573     EDX = ldl_phys(sm_state + 0x7fd8);
1574     ECX = ldl_phys(sm_state + 0x7fd4);
1575     EAX = ldl_phys(sm_state + 0x7fd0);
1576     env->dr[6] = ldl_phys(sm_state + 0x7fcc);
1577     env->dr[7] = ldl_phys(sm_state + 0x7fc8);
1578
1579     env->tr.selector = ldl_phys(sm_state + 0x7fc4) & 0xffff;
1580     env->tr.base = ldl_phys(sm_state + 0x7f64);
1581     env->tr.limit = ldl_phys(sm_state + 0x7f60);
1582     env->tr.flags = (ldl_phys(sm_state + 0x7f5c) & 0xf0ff) << 8;
1583
1584     env->ldt.selector = ldl_phys(sm_state + 0x7fc0) & 0xffff;
1585     env->ldt.base = ldl_phys(sm_state + 0x7f80);
1586     env->ldt.limit = ldl_phys(sm_state + 0x7f7c);
1587     env->ldt.flags = (ldl_phys(sm_state + 0x7f78) & 0xf0ff) << 8;
1588
1589     env->gdt.base = ldl_phys(sm_state + 0x7f74);
1590     env->gdt.limit = ldl_phys(sm_state + 0x7f70);
1591
1592     env->idt.base = ldl_phys(sm_state + 0x7f58);
1593     env->idt.limit = ldl_phys(sm_state + 0x7f54);
1594
1595     for(i = 0; i < 6; i++) {
1596         if (i < 3)
1597             offset = 0x7f84 + i * 12;
1598         else
1599             offset = 0x7f2c + (i - 3) * 12;
1600         cpu_x86_load_seg_cache(env, i,
1601                                ldl_phys(sm_state + 0x7fa8 + i * 4) & 0xffff,
1602                                ldl_phys(sm_state + offset + 8),
1603                                ldl_phys(sm_state + offset + 4),
1604                                (ldl_phys(sm_state + offset) & 0xf0ff) << 8);
1605     }
1606     cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f14));
1607
1608     val = ldl_phys(sm_state + 0x7efc); /* revision ID */
1609     if (val & 0x20000) {
1610         env->smbase = ldl_phys(sm_state + 0x7ef8) & ~0x7fff;
1611     }
1612 #endif
1613     CC_OP = CC_OP_EFLAGS;
1614     env->hflags &= ~HF_SMM_MASK;
1615     cpu_smm_update(env);
1616
1617     if (loglevel & CPU_LOG_INT) {
1618         fprintf(logfile, "SMM: after RSM\n");
1619         cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1620     }
1621 }
1622
1623 #endif /* !CONFIG_USER_ONLY */
1624
1625
1626 /* division, flags are undefined */
1627
1628 void helper_divb_AL(target_ulong t0)
1629 {
1630     unsigned int num, den, q, r;
1631
1632     num = (EAX & 0xffff);
1633     den = (t0 & 0xff);
1634     if (den == 0) {
1635         raise_exception(EXCP00_DIVZ);
1636     }
1637     q = (num / den);
1638     if (q > 0xff)
1639         raise_exception(EXCP00_DIVZ);
1640     q &= 0xff;
1641     r = (num % den) & 0xff;
1642     EAX = (EAX & ~0xffff) | (r << 8) | q;
1643 }
1644
1645 void helper_idivb_AL(target_ulong t0)
1646 {
1647     int num, den, q, r;
1648
1649     num = (int16_t)EAX;
1650     den = (int8_t)t0;
1651     if (den == 0) {
1652         raise_exception(EXCP00_DIVZ);
1653     }
1654     q = (num / den);
1655     if (q != (int8_t)q)
1656         raise_exception(EXCP00_DIVZ);
1657     q &= 0xff;
1658     r = (num % den) & 0xff;
1659     EAX = (EAX & ~0xffff) | (r << 8) | q;
1660 }
1661
1662 void helper_divw_AX(target_ulong t0)
1663 {
1664     unsigned int num, den, q, r;
1665
1666     num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
1667     den = (t0 & 0xffff);
1668     if (den == 0) {
1669         raise_exception(EXCP00_DIVZ);
1670     }
1671     q = (num / den);
1672     if (q > 0xffff)
1673         raise_exception(EXCP00_DIVZ);
1674     q &= 0xffff;
1675     r = (num % den) & 0xffff;
1676     EAX = (EAX & ~0xffff) | q;
1677     EDX = (EDX & ~0xffff) | r;
1678 }
1679
1680 void helper_idivw_AX(target_ulong t0)
1681 {
1682     int num, den, q, r;
1683
1684     num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
1685     den = (int16_t)t0;
1686     if (den == 0) {
1687         raise_exception(EXCP00_DIVZ);
1688     }
1689     q = (num / den);
1690     if (q != (int16_t)q)
1691         raise_exception(EXCP00_DIVZ);
1692     q &= 0xffff;
1693     r = (num % den) & 0xffff;
1694     EAX = (EAX & ~0xffff) | q;
1695     EDX = (EDX & ~0xffff) | r;
1696 }
1697
1698 void helper_divl_EAX(target_ulong t0)
1699 {
1700     unsigned int den, r;
1701     uint64_t num, q;
1702
1703     num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1704     den = t0;
1705     if (den == 0) {
1706         raise_exception(EXCP00_DIVZ);
1707     }
1708     q = (num / den);
1709     r = (num % den);
1710     if (q > 0xffffffff)
1711         raise_exception(EXCP00_DIVZ);
1712     EAX = (uint32_t)q;
1713     EDX = (uint32_t)r;
1714 }
1715
1716 void helper_idivl_EAX(target_ulong t0)
1717 {
1718     int den, r;
1719     int64_t num, q;
1720
1721     num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1722     den = t0;
1723     if (den == 0) {
1724         raise_exception(EXCP00_DIVZ);
1725     }
1726     q = (num / den);
1727     r = (num % den);
1728     if (q != (int32_t)q)
1729         raise_exception(EXCP00_DIVZ);
1730     EAX = (uint32_t)q;
1731     EDX = (uint32_t)r;
1732 }
1733
1734 /* bcd */
1735
1736 /* XXX: exception */
1737 void helper_aam(int base)
1738 {
1739     int al, ah;
1740     al = EAX & 0xff;
1741     ah = al / base;
1742     al = al % base;
1743     EAX = (EAX & ~0xffff) | al | (ah << 8);
1744     CC_DST = al;
1745 }
1746
1747 void helper_aad(int base)
1748 {
1749     int al, ah;
1750     al = EAX & 0xff;
1751     ah = (EAX >> 8) & 0xff;
1752     al = ((ah * base) + al) & 0xff;
1753     EAX = (EAX & ~0xffff) | al;
1754     CC_DST = al;
1755 }
1756
1757 void helper_aaa(void)
1758 {
1759     int icarry;
1760     int al, ah, af;
1761     int eflags;
1762
1763     eflags = cc_table[CC_OP].compute_all();
1764     af = eflags & CC_A;
1765     al = EAX & 0xff;
1766     ah = (EAX >> 8) & 0xff;
1767
1768     icarry = (al > 0xf9);
1769     if (((al & 0x0f) > 9 ) || af) {
1770         al = (al + 6) & 0x0f;
1771         ah = (ah + 1 + icarry) & 0xff;
1772         eflags |= CC_C | CC_A;
1773     } else {
1774         eflags &= ~(CC_C | CC_A);
1775         al &= 0x0f;
1776     }
1777     EAX = (EAX & ~0xffff) | al | (ah << 8);
1778     CC_SRC = eflags;
1779     FORCE_RET();
1780 }
1781
1782 void helper_aas(void)
1783 {
1784     int icarry;
1785     int al, ah, af;
1786     int eflags;
1787
1788     eflags = cc_table[CC_OP].compute_all();
1789     af = eflags & CC_A;
1790     al = EAX & 0xff;
1791     ah = (EAX >> 8) & 0xff;
1792
1793     icarry = (al < 6);
1794     if (((al & 0x0f) > 9 ) || af) {
1795         al = (al - 6) & 0x0f;
1796         ah = (ah - 1 - icarry) & 0xff;
1797         eflags |= CC_C | CC_A;
1798     } else {
1799         eflags &= ~(CC_C | CC_A);
1800         al &= 0x0f;
1801     }
1802     EAX = (EAX & ~0xffff) | al | (ah << 8);
1803     CC_SRC = eflags;
1804     FORCE_RET();
1805 }
1806
1807 void helper_daa(void)
1808 {
1809     int al, af, cf;
1810     int eflags;
1811
1812     eflags = cc_table[CC_OP].compute_all();
1813     cf = eflags & CC_C;
1814     af = eflags & CC_A;
1815     al = EAX & 0xff;
1816
1817     eflags = 0;
1818     if (((al & 0x0f) > 9 ) || af) {
1819         al = (al + 6) & 0xff;
1820         eflags |= CC_A;
1821     }
1822     if ((al > 0x9f) || cf) {
1823         al = (al + 0x60) & 0xff;
1824         eflags |= CC_C;
1825     }
1826     EAX = (EAX & ~0xff) | al;
1827     /* well, speed is not an issue here, so we compute the flags by hand */
1828     eflags |= (al == 0) << 6; /* zf */
1829     eflags |= parity_table[al]; /* pf */
1830     eflags |= (al & 0x80); /* sf */
1831     CC_SRC = eflags;
1832     FORCE_RET();
1833 }
1834
1835 void helper_das(void)
1836 {
1837     int al, al1, af, cf;
1838     int eflags;
1839
1840     eflags = cc_table[CC_OP].compute_all();
1841     cf = eflags & CC_C;
1842     af = eflags & CC_A;
1843     al = EAX & 0xff;
1844
1845     eflags = 0;
1846     al1 = al;
1847     if (((al & 0x0f) > 9 ) || af) {
1848         eflags |= CC_A;
1849         if (al < 6 || cf)
1850             eflags |= CC_C;
1851         al = (al - 6) & 0xff;
1852     }
1853     if ((al1 > 0x99) || cf) {
1854         al = (al - 0x60) & 0xff;
1855         eflags |= CC_C;
1856     }
1857     EAX = (EAX & ~0xff) | al;
1858     /* well, speed is not an issue here, so we compute the flags by hand */
1859     eflags |= (al == 0) << 6; /* zf */
1860     eflags |= parity_table[al]; /* pf */
1861     eflags |= (al & 0x80); /* sf */
1862     CC_SRC = eflags;
1863     FORCE_RET();
1864 }
1865
1866 void helper_into(int next_eip_addend)
1867 {
1868     int eflags;
1869     eflags = cc_table[CC_OP].compute_all();
1870     if (eflags & CC_O) {
1871         raise_interrupt(EXCP04_INTO, 1, 0, next_eip_addend);
1872     }
1873 }
1874
1875 void helper_cmpxchg8b(target_ulong a0)
1876 {
1877     uint64_t d;
1878     int eflags;
1879
1880     eflags = cc_table[CC_OP].compute_all();
1881     d = ldq(a0);
1882     if (d == (((uint64_t)EDX << 32) | (uint32_t)EAX)) {
1883         stq(a0, ((uint64_t)ECX << 32) | (uint32_t)EBX);
1884         eflags |= CC_Z;
1885     } else {
1886         EDX = (uint32_t)(d >> 32);
1887         EAX = (uint32_t)d;
1888         eflags &= ~CC_Z;
1889     }
1890     CC_SRC = eflags;
1891 }
1892
1893 #ifdef TARGET_X86_64
1894 void helper_cmpxchg16b(target_ulong a0)
1895 {
1896     uint64_t d0, d1;
1897     int eflags;
1898
1899     eflags = cc_table[CC_OP].compute_all();
1900     d0 = ldq(a0);
1901     d1 = ldq(a0 + 8);
1902     if (d0 == EAX && d1 == EDX) {
1903         stq(a0, EBX);
1904         stq(a0 + 8, ECX);
1905         eflags |= CC_Z;
1906     } else {
1907         EDX = d1;
1908         EAX = d0;
1909         eflags &= ~CC_Z;
1910     }
1911     CC_SRC = eflags;
1912 }
1913 #endif
1914
1915 void helper_single_step(void)
1916 {
1917     env->dr[6] |= 0x4000;
1918     raise_exception(EXCP01_SSTP);
1919 }
1920
1921 void helper_cpuid(void)
1922 {
1923     uint32_t index;
1924     index = (uint32_t)EAX;
1925
1926     /* test if maximum index reached */
1927     if (index & 0x80000000) {
1928         if (index > env->cpuid_xlevel)
1929             index = env->cpuid_level;
1930     } else {
1931         if (index > env->cpuid_level)
1932             index = env->cpuid_level;
1933     }
1934
1935     switch(index) {
1936     case 0:
1937         EAX = env->cpuid_level;
1938         EBX = env->cpuid_vendor1;
1939         EDX = env->cpuid_vendor2;
1940         ECX = env->cpuid_vendor3;
1941         break;
1942     case 1:
1943         EAX = env->cpuid_version;
1944         EBX = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
1945         ECX = env->cpuid_ext_features;
1946         EDX = env->cpuid_features;
1947         break;
1948     case 2:
1949         /* cache info: needed for Pentium Pro compatibility */
1950         EAX = 1;
1951         EBX = 0;
1952         ECX = 0;
1953         EDX = 0x2c307d;
1954         break;
1955     case 0x80000000:
1956         EAX = env->cpuid_xlevel;
1957         EBX = env->cpuid_vendor1;
1958         EDX = env->cpuid_vendor2;
1959         ECX = env->cpuid_vendor3;
1960         break;
1961     case 0x80000001:
1962         EAX = env->cpuid_features;
1963         EBX = 0;
1964         ECX = env->cpuid_ext3_features;
1965         EDX = env->cpuid_ext2_features;
1966         break;
1967     case 0x80000002:
1968     case 0x80000003:
1969     case 0x80000004:
1970         EAX = env->cpuid_model[(index - 0x80000002) * 4 + 0];
1971         EBX = env->cpuid_model[(index - 0x80000002) * 4 + 1];
1972         ECX = env->cpuid_model[(index - 0x80000002) * 4 + 2];
1973         EDX = env->cpuid_model[(index - 0x80000002) * 4 + 3];
1974         break;
1975     case 0x80000005:
1976         /* cache info (L1 cache) */
1977         EAX = 0x01ff01ff;
1978         EBX = 0x01ff01ff;
1979         ECX = 0x40020140;
1980         EDX = 0x40020140;
1981         break;
1982     case 0x80000006:
1983         /* cache info (L2 cache) */
1984         EAX = 0;
1985         EBX = 0x42004200;
1986         ECX = 0x02008140;
1987         EDX = 0;
1988         break;
1989     case 0x80000008:
1990         /* virtual & phys address size in low 2 bytes. */
1991 /* XXX: This value must match the one used in the MMU code. */ 
1992 #if defined(TARGET_X86_64)
1993 #  if defined(USE_KQEMU)
1994         EAX = 0x00003020;       /* 48 bits virtual, 32 bits physical */
1995 #  else
1996 /* XXX: The physical address space is limited to 42 bits in exec.c. */
1997         EAX = 0x00003028;       /* 48 bits virtual, 40 bits physical */
1998 #  endif
1999 #else
2000 # if defined(USE_KQEMU)
2001         EAX = 0x00000020;       /* 32 bits physical */
2002 #  else
2003         EAX = 0x00000024;       /* 36 bits physical */
2004 #  endif
2005 #endif
2006         EBX = 0;
2007         ECX = 0;
2008         EDX = 0;
2009         break;
2010     case 0x8000000A:
2011         EAX = 0x00000001;
2012         EBX = 0;
2013         ECX = 0;
2014         EDX = 0;
2015         break;
2016     default:
2017         /* reserved values: zero */
2018         EAX = 0;
2019         EBX = 0;
2020         ECX = 0;
2021         EDX = 0;
2022         break;
2023     }
2024 }
2025
2026 void helper_enter_level(int level, int data32, target_ulong t1)
2027 {
2028     target_ulong ssp;
2029     uint32_t esp_mask, esp, ebp;
2030
2031     esp_mask = get_sp_mask(env->segs[R_SS].flags);
2032     ssp = env->segs[R_SS].base;
2033     ebp = EBP;
2034     esp = ESP;
2035     if (data32) {
2036         /* 32 bit */
2037         esp -= 4;
2038         while (--level) {
2039             esp -= 4;
2040             ebp -= 4;
2041             stl(ssp + (esp & esp_mask), ldl(ssp + (ebp & esp_mask)));
2042         }
2043         esp -= 4;
2044         stl(ssp + (esp & esp_mask), t1);
2045     } else {
2046         /* 16 bit */
2047         esp -= 2;
2048         while (--level) {
2049             esp -= 2;
2050             ebp -= 2;
2051             stw(ssp + (esp & esp_mask), lduw(ssp + (ebp & esp_mask)));
2052         }
2053         esp -= 2;
2054         stw(ssp + (esp & esp_mask), t1);
2055     }
2056 }
2057
2058 #ifdef TARGET_X86_64
2059 void helper_enter64_level(int level, int data64, target_ulong t1)
2060 {
2061     target_ulong esp, ebp;
2062     ebp = EBP;
2063     esp = ESP;
2064
2065     if (data64) {
2066         /* 64 bit */
2067         esp -= 8;
2068         while (--level) {
2069             esp -= 8;
2070             ebp -= 8;
2071             stq(esp, ldq(ebp));
2072         }
2073         esp -= 8;
2074         stq(esp, t1);
2075     } else {
2076         /* 16 bit */
2077         esp -= 2;
2078         while (--level) {
2079             esp -= 2;
2080             ebp -= 2;
2081             stw(esp, lduw(ebp));
2082         }
2083         esp -= 2;
2084         stw(esp, t1);
2085     }
2086 }
2087 #endif
2088
2089 void helper_lldt(int selector)
2090 {
2091     SegmentCache *dt;
2092     uint32_t e1, e2;
2093     int index, entry_limit;
2094     target_ulong ptr;
2095
2096     selector &= 0xffff;
2097     if ((selector & 0xfffc) == 0) {
2098         /* XXX: NULL selector case: invalid LDT */
2099         env->ldt.base = 0;
2100         env->ldt.limit = 0;
2101     } else {
2102         if (selector & 0x4)
2103             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2104         dt = &env->gdt;
2105         index = selector & ~7;
2106 #ifdef TARGET_X86_64
2107         if (env->hflags & HF_LMA_MASK)
2108             entry_limit = 15;
2109         else
2110 #endif
2111             entry_limit = 7;
2112         if ((index + entry_limit) > dt->limit)
2113             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2114         ptr = dt->base + index;
2115         e1 = ldl_kernel(ptr);
2116         e2 = ldl_kernel(ptr + 4);
2117         if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
2118             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2119         if (!(e2 & DESC_P_MASK))
2120             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2121 #ifdef TARGET_X86_64
2122         if (env->hflags & HF_LMA_MASK) {
2123             uint32_t e3;
2124             e3 = ldl_kernel(ptr + 8);
2125             load_seg_cache_raw_dt(&env->ldt, e1, e2);
2126             env->ldt.base |= (target_ulong)e3 << 32;
2127         } else
2128 #endif
2129         {
2130             load_seg_cache_raw_dt(&env->ldt, e1, e2);
2131         }
2132     }
2133     env->ldt.selector = selector;
2134 }
2135
2136 void helper_ltr(int selector)
2137 {
2138     SegmentCache *dt;
2139     uint32_t e1, e2;
2140     int index, type, entry_limit;
2141     target_ulong ptr;
2142
2143     selector &= 0xffff;
2144     if ((selector & 0xfffc) == 0) {
2145         /* NULL selector case: invalid TR */
2146         env->tr.base = 0;
2147         env->tr.limit = 0;
2148         env->tr.flags = 0;
2149     } else {
2150         if (selector & 0x4)
2151             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2152         dt = &env->gdt;
2153         index = selector & ~7;
2154 #ifdef TARGET_X86_64
2155         if (env->hflags & HF_LMA_MASK)
2156             entry_limit = 15;
2157         else
2158 #endif
2159             entry_limit = 7;
2160         if ((index + entry_limit) > dt->limit)
2161             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2162         ptr = dt->base + index;
2163         e1 = ldl_kernel(ptr);
2164         e2 = ldl_kernel(ptr + 4);
2165         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2166         if ((e2 & DESC_S_MASK) ||
2167             (type != 1 && type != 9))
2168             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2169         if (!(e2 & DESC_P_MASK))
2170             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2171 #ifdef TARGET_X86_64
2172         if (env->hflags & HF_LMA_MASK) {
2173             uint32_t e3, e4;
2174             e3 = ldl_kernel(ptr + 8);
2175             e4 = ldl_kernel(ptr + 12);
2176             if ((e4 >> DESC_TYPE_SHIFT) & 0xf)
2177                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2178             load_seg_cache_raw_dt(&env->tr, e1, e2);
2179             env->tr.base |= (target_ulong)e3 << 32;
2180         } else
2181 #endif
2182         {
2183             load_seg_cache_raw_dt(&env->tr, e1, e2);
2184         }
2185         e2 |= DESC_TSS_BUSY_MASK;
2186         stl_kernel(ptr + 4, e2);
2187     }
2188     env->tr.selector = selector;
2189 }
2190
2191 /* only works if protected mode and not VM86. seg_reg must be != R_CS */
2192 void helper_load_seg(int seg_reg, int selector)
2193 {
2194     uint32_t e1, e2;
2195     int cpl, dpl, rpl;
2196     SegmentCache *dt;
2197     int index;
2198     target_ulong ptr;
2199
2200     selector &= 0xffff;
2201     cpl = env->hflags & HF_CPL_MASK;
2202     if ((selector & 0xfffc) == 0) {
2203         /* null selector case */
2204         if (seg_reg == R_SS
2205 #ifdef TARGET_X86_64
2206             && (!(env->hflags & HF_CS64_MASK) || cpl == 3)
2207 #endif
2208             )
2209             raise_exception_err(EXCP0D_GPF, 0);
2210         cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0);
2211     } else {
2212
2213         if (selector & 0x4)
2214             dt = &env->ldt;
2215         else
2216             dt = &env->gdt;
2217         index = selector & ~7;
2218         if ((index + 7) > dt->limit)
2219             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2220         ptr = dt->base + index;
2221         e1 = ldl_kernel(ptr);
2222         e2 = ldl_kernel(ptr + 4);
2223
2224         if (!(e2 & DESC_S_MASK))
2225             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2226         rpl = selector & 3;
2227         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2228         if (seg_reg == R_SS) {
2229             /* must be writable segment */
2230             if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
2231                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2232             if (rpl != cpl || dpl != cpl)
2233                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2234         } else {
2235             /* must be readable segment */
2236             if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK)
2237                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2238
2239             if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
2240                 /* if not conforming code, test rights */
2241                 if (dpl < cpl || dpl < rpl)
2242                     raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2243             }
2244         }
2245
2246         if (!(e2 & DESC_P_MASK)) {
2247             if (seg_reg == R_SS)
2248                 raise_exception_err(EXCP0C_STACK, selector & 0xfffc);
2249             else
2250                 raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2251         }
2252
2253         /* set the access bit if not already set */
2254         if (!(e2 & DESC_A_MASK)) {
2255             e2 |= DESC_A_MASK;
2256             stl_kernel(ptr + 4, e2);
2257         }
2258
2259         cpu_x86_load_seg_cache(env, seg_reg, selector,
2260                        get_seg_base(e1, e2),
2261                        get_seg_limit(e1, e2),
2262                        e2);
2263 #if 0
2264         fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx flags=%08x\n",
2265                 selector, (unsigned long)sc->base, sc->limit, sc->flags);
2266 #endif
2267     }
2268 }
2269
2270 /* protected mode jump */
2271 void helper_ljmp_protected(int new_cs, target_ulong new_eip,
2272                            int next_eip_addend)
2273 {
2274     int gate_cs, type;
2275     uint32_t e1, e2, cpl, dpl, rpl, limit;
2276     target_ulong next_eip;
2277
2278     if ((new_cs & 0xfffc) == 0)
2279         raise_exception_err(EXCP0D_GPF, 0);
2280     if (load_segment(&e1, &e2, new_cs) != 0)
2281         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2282     cpl = env->hflags & HF_CPL_MASK;
2283     if (e2 & DESC_S_MASK) {
2284         if (!(e2 & DESC_CS_MASK))
2285             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2286         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2287         if (e2 & DESC_C_MASK) {
2288             /* conforming code segment */
2289             if (dpl > cpl)
2290                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2291         } else {
2292             /* non conforming code segment */
2293             rpl = new_cs & 3;
2294             if (rpl > cpl)
2295                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2296             if (dpl != cpl)
2297                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2298         }
2299         if (!(e2 & DESC_P_MASK))
2300             raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2301         limit = get_seg_limit(e1, e2);
2302         if (new_eip > limit &&
2303             !(env->hflags & HF_LMA_MASK) && !(e2 & DESC_L_MASK))
2304             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2305         cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2306                        get_seg_base(e1, e2), limit, e2);
2307         EIP = new_eip;
2308     } else {
2309         /* jump to call or task gate */
2310         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2311         rpl = new_cs & 3;
2312         cpl = env->hflags & HF_CPL_MASK;
2313         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2314         switch(type) {
2315         case 1: /* 286 TSS */
2316         case 9: /* 386 TSS */
2317         case 5: /* task gate */
2318             if (dpl < cpl || dpl < rpl)
2319                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2320             next_eip = env->eip + next_eip_addend;
2321             switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip);
2322             CC_OP = CC_OP_EFLAGS;
2323             break;
2324         case 4: /* 286 call gate */
2325         case 12: /* 386 call gate */
2326             if ((dpl < cpl) || (dpl < rpl))
2327                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2328             if (!(e2 & DESC_P_MASK))
2329                 raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2330             gate_cs = e1 >> 16;
2331             new_eip = (e1 & 0xffff);
2332             if (type == 12)
2333                 new_eip |= (e2 & 0xffff0000);
2334             if (load_segment(&e1, &e2, gate_cs) != 0)
2335                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2336             dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2337             /* must be code segment */
2338             if (((e2 & (DESC_S_MASK | DESC_CS_MASK)) !=
2339                  (DESC_S_MASK | DESC_CS_MASK)))
2340                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2341             if (((e2 & DESC_C_MASK) && (dpl > cpl)) ||
2342                 (!(e2 & DESC_C_MASK) && (dpl != cpl)))
2343                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2344             if (!(e2 & DESC_P_MASK))
2345                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2346             limit = get_seg_limit(e1, e2);
2347             if (new_eip > limit)
2348                 raise_exception_err(EXCP0D_GPF, 0);
2349             cpu_x86_load_seg_cache(env, R_CS, (gate_cs & 0xfffc) | cpl,
2350                                    get_seg_base(e1, e2), limit, e2);
2351             EIP = new_eip;
2352             break;
2353         default:
2354             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2355             break;
2356         }
2357     }
2358 }
2359
2360 /* real mode call */
2361 void helper_lcall_real(int new_cs, target_ulong new_eip1,
2362                        int shift, int next_eip)
2363 {
2364     int new_eip;
2365     uint32_t esp, esp_mask;
2366     target_ulong ssp;
2367
2368     new_eip = new_eip1;
2369     esp = ESP;
2370     esp_mask = get_sp_mask(env->segs[R_SS].flags);
2371     ssp = env->segs[R_SS].base;
2372     if (shift) {
2373         PUSHL(ssp, esp, esp_mask, env->segs[R_CS].selector);
2374         PUSHL(ssp, esp, esp_mask, next_eip);
2375     } else {
2376         PUSHW(ssp, esp, esp_mask, env->segs[R_CS].selector);
2377         PUSHW(ssp, esp, esp_mask, next_eip);
2378     }
2379
2380     SET_ESP(esp, esp_mask);
2381     env->eip = new_eip;
2382     env->segs[R_CS].selector = new_cs;
2383     env->segs[R_CS].base = (new_cs << 4);
2384 }
2385
2386 /* protected mode call */
2387 void helper_lcall_protected(int new_cs, target_ulong new_eip, 
2388                             int shift, int next_eip_addend)
2389 {
2390     int new_stack, i;
2391     uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;
2392     uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask;
2393     uint32_t val, limit, old_sp_mask;
2394     target_ulong ssp, old_ssp, next_eip;
2395
2396     next_eip = env->eip + next_eip_addend;
2397 #ifdef DEBUG_PCALL
2398     if (loglevel & CPU_LOG_PCALL) {
2399         fprintf(logfile, "lcall %04x:%08x s=%d\n",
2400                 new_cs, (uint32_t)new_eip, shift);
2401         cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
2402     }
2403 #endif
2404     if ((new_cs & 0xfffc) == 0)
2405         raise_exception_err(EXCP0D_GPF, 0);
2406     if (load_segment(&e1, &e2, new_cs) != 0)
2407         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2408     cpl = env->hflags & HF_CPL_MASK;
2409 #ifdef DEBUG_PCALL
2410     if (loglevel & CPU_LOG_PCALL) {
2411         fprintf(logfile, "desc=%08x:%08x\n", e1, e2);
2412     }
2413 #endif
2414     if (e2 & DESC_S_MASK) {
2415         if (!(e2 & DESC_CS_MASK))
2416             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2417         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2418         if (e2 & DESC_C_MASK) {
2419             /* conforming code segment */
2420             if (dpl > cpl)
2421                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2422         } else {
2423             /* non conforming code segment */
2424             rpl = new_cs & 3;
2425             if (rpl > cpl)
2426                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2427             if (dpl != cpl)
2428                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2429         }
2430         if (!(e2 & DESC_P_MASK))
2431             raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2432
2433 #ifdef TARGET_X86_64
2434         /* XXX: check 16/32 bit cases in long mode */
2435         if (shift == 2) {
2436             target_ulong rsp;
2437             /* 64 bit case */
2438             rsp = ESP;
2439             PUSHQ(rsp, env->segs[R_CS].selector);
2440             PUSHQ(rsp, next_eip);
2441             /* from this point, not restartable */
2442             ESP = rsp;
2443             cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2444                                    get_seg_base(e1, e2),
2445                                    get_seg_limit(e1, e2), e2);
2446             EIP = new_eip;
2447         } else
2448 #endif
2449         {
2450             sp = ESP;
2451             sp_mask = get_sp_mask(env->segs[R_SS].flags);
2452             ssp = env->segs[R_SS].base;
2453             if (shift) {
2454                 PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
2455                 PUSHL(ssp, sp, sp_mask, next_eip);
2456             } else {
2457                 PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
2458                 PUSHW(ssp, sp, sp_mask, next_eip);
2459             }
2460
2461             limit = get_seg_limit(e1, e2);
2462             if (new_eip > limit)
2463                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2464             /* from this point, not restartable */
2465             SET_ESP(sp, sp_mask);
2466             cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2467                                    get_seg_base(e1, e2), limit, e2);
2468             EIP = new_eip;
2469         }
2470     } else {
2471         /* check gate type */
2472         type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
2473         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2474         rpl = new_cs & 3;
2475         switch(type) {
2476         case 1: /* available 286 TSS */
2477         case 9: /* available 386 TSS */
2478         case 5: /* task gate */
2479             if (dpl < cpl || dpl < rpl)
2480                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2481             switch_tss(new_cs, e1, e2, SWITCH_TSS_CALL, next_eip);
2482             CC_OP = CC_OP_EFLAGS;
2483             return;
2484         case 4: /* 286 call gate */
2485         case 12: /* 386 call gate */
2486             break;
2487         default:
2488             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2489             break;
2490         }
2491         shift = type >> 3;
2492
2493         if (dpl < cpl || dpl < rpl)
2494             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2495         /* check valid bit */
2496         if (!(e2 & DESC_P_MASK))
2497             raise_exception_err(EXCP0B_NOSEG,  new_cs & 0xfffc);
2498         selector = e1 >> 16;
2499         offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
2500         param_count = e2 & 0x1f;
2501         if ((selector & 0xfffc) == 0)
2502             raise_exception_err(EXCP0D_GPF, 0);
2503
2504         if (load_segment(&e1, &e2, selector) != 0)
2505             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2506         if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
2507             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2508         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2509         if (dpl > cpl)
2510             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2511         if (!(e2 & DESC_P_MASK))
2512             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2513
2514         if (!(e2 & DESC_C_MASK) && dpl < cpl) {
2515             /* to inner privilege */
2516             get_ss_esp_from_tss(&ss, &sp, dpl);
2517 #ifdef DEBUG_PCALL
2518             if (loglevel & CPU_LOG_PCALL)
2519                 fprintf(logfile, "new ss:esp=%04x:%08x param_count=%d ESP=" TARGET_FMT_lx "\n",
2520                         ss, sp, param_count, ESP);
2521 #endif
2522             if ((ss & 0xfffc) == 0)
2523                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2524             if ((ss & 3) != dpl)
2525                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2526             if (load_segment(&ss_e1, &ss_e2, ss) != 0)
2527                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2528             ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
2529             if (ss_dpl != dpl)
2530                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2531             if (!(ss_e2 & DESC_S_MASK) ||
2532                 (ss_e2 & DESC_CS_MASK) ||
2533                 !(ss_e2 & DESC_W_MASK))
2534                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2535             if (!(ss_e2 & DESC_P_MASK))
2536                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2537
2538             //            push_size = ((param_count * 2) + 8) << shift;
2539
2540             old_sp_mask = get_sp_mask(env->segs[R_SS].flags);
2541             old_ssp = env->segs[R_SS].base;
2542
2543             sp_mask = get_sp_mask(ss_e2);
2544             ssp = get_seg_base(ss_e1, ss_e2);
2545             if (shift) {
2546                 PUSHL(ssp, sp, sp_mask, env->segs[R_SS].selector);
2547                 PUSHL(ssp, sp, sp_mask, ESP);
2548                 for(i = param_count - 1; i >= 0; i--) {
2549                     val = ldl_kernel(old_ssp + ((ESP + i * 4) & old_sp_mask));
2550                     PUSHL(ssp, sp, sp_mask, val);
2551                 }
2552             } else {
2553                 PUSHW(ssp, sp, sp_mask, env->segs[R_SS].selector);
2554                 PUSHW(ssp, sp, sp_mask, ESP);
2555                 for(i = param_count - 1; i >= 0; i--) {
2556                     val = lduw_kernel(old_ssp + ((ESP + i * 2) & old_sp_mask));
2557                     PUSHW(ssp, sp, sp_mask, val);
2558                 }
2559             }
2560             new_stack = 1;
2561         } else {
2562             /* to same privilege */
2563             sp = ESP;
2564             sp_mask = get_sp_mask(env->segs[R_SS].flags);
2565             ssp = env->segs[R_SS].base;
2566             //            push_size = (4 << shift);
2567             new_stack = 0;
2568         }
2569
2570         if (shift) {
2571             PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
2572             PUSHL(ssp, sp, sp_mask, next_eip);
2573         } else {
2574             PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
2575             PUSHW(ssp, sp, sp_mask, next_eip);
2576         }
2577
2578         /* from this point, not restartable */
2579
2580         if (new_stack) {
2581             ss = (ss & ~3) | dpl;
2582             cpu_x86_load_seg_cache(env, R_SS, ss,
2583                                    ssp,
2584                                    get_seg_limit(ss_e1, ss_e2),
2585                                    ss_e2);
2586         }
2587
2588         selector = (selector & ~3) | dpl;
2589         cpu_x86_load_seg_cache(env, R_CS, selector,
2590                        get_seg_base(e1, e2),
2591                        get_seg_limit(e1, e2),
2592                        e2);
2593         cpu_x86_set_cpl(env, dpl);
2594         SET_ESP(sp, sp_mask);
2595         EIP = offset;
2596     }
2597 #ifdef USE_KQEMU
2598     if (kqemu_is_ok(env)) {
2599         env->exception_index = -1;
2600         cpu_loop_exit();
2601     }
2602 #endif
2603 }
2604
2605 /* real and vm86 mode iret */
2606 void helper_iret_real(int shift)
2607 {
2608     uint32_t sp, new_cs, new_eip, new_eflags, sp_mask;
2609     target_ulong ssp;
2610     int eflags_mask;
2611
2612     sp_mask = 0xffff; /* XXXX: use SS segment size ? */
2613     sp = ESP;
2614     ssp = env->segs[R_SS].base;
2615     if (shift == 1) {
2616         /* 32 bits */
2617         POPL(ssp, sp, sp_mask, new_eip);
2618         POPL(ssp, sp, sp_mask, new_cs);
2619         new_cs &= 0xffff;
2620         POPL(ssp, sp, sp_mask, new_eflags);
2621     } else {
2622         /* 16 bits */
2623         POPW(ssp, sp, sp_mask, new_eip);
2624         POPW(ssp, sp, sp_mask, new_cs);
2625         POPW(ssp, sp, sp_mask, new_eflags);
2626     }
2627     ESP = (ESP & ~sp_mask) | (sp & sp_mask);
2628     load_seg_vm(R_CS, new_cs);
2629     env->eip = new_eip;
2630     if (env->eflags & VM_MASK)
2631         eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK | NT_MASK;
2632     else
2633         eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK | RF_MASK | NT_MASK;
2634     if (shift == 0)
2635         eflags_mask &= 0xffff;
2636     load_eflags(new_eflags, eflags_mask);
2637     env->hflags &= ~HF_NMI_MASK;
2638 }
2639
2640 static inline void validate_seg(int seg_reg, int cpl)
2641 {
2642     int dpl;
2643     uint32_t e2;
2644
2645     /* XXX: on x86_64, we do not want to nullify FS and GS because
2646        they may still contain a valid base. I would be interested to
2647        know how a real x86_64 CPU behaves */
2648     if ((seg_reg == R_FS || seg_reg == R_GS) &&
2649         (env->segs[seg_reg].selector & 0xfffc) == 0)
2650         return;
2651
2652     e2 = env->segs[seg_reg].flags;
2653     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2654     if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
2655         /* data or non conforming code segment */
2656         if (dpl < cpl) {
2657             cpu_x86_load_seg_cache(env, seg_reg, 0, 0, 0, 0);
2658         }
2659     }
2660 }
2661
2662 /* protected mode iret */
2663 static inline void helper_ret_protected(int shift, int is_iret, int addend)
2664 {
2665     uint32_t new_cs, new_eflags, new_ss;
2666     uint32_t new_es, new_ds, new_fs, new_gs;
2667     uint32_t e1, e2, ss_e1, ss_e2;
2668     int cpl, dpl, rpl, eflags_mask, iopl;
2669     target_ulong ssp, sp, new_eip, new_esp, sp_mask;
2670
2671 #ifdef TARGET_X86_64
2672     if (shift == 2)
2673         sp_mask = -1;
2674     else
2675 #endif
2676         sp_mask = get_sp_mask(env->segs[R_SS].flags);
2677     sp = ESP;
2678     ssp = env->segs[R_SS].base;
2679     new_eflags = 0; /* avoid warning */
2680 #ifdef TARGET_X86_64
2681     if (shift == 2) {
2682         POPQ(sp, new_eip);
2683         POPQ(sp, new_cs);
2684         new_cs &= 0xffff;
2685         if (is_iret) {
2686             POPQ(sp, new_eflags);
2687         }
2688     } else
2689 #endif
2690     if (shift == 1) {
2691         /* 32 bits */
2692         POPL(ssp, sp, sp_mask, new_eip);
2693         POPL(ssp, sp, sp_mask, new_cs);
2694         new_cs &= 0xffff;
2695         if (is_iret) {
2696             POPL(ssp, sp, sp_mask, new_eflags);
2697             if (new_eflags & VM_MASK)
2698                 goto return_to_vm86;
2699         }
2700     } else {
2701         /* 16 bits */
2702         POPW(ssp, sp, sp_mask, new_eip);
2703         POPW(ssp, sp, sp_mask, new_cs);
2704         if (is_iret)
2705             POPW(ssp, sp, sp_mask, new_eflags);
2706     }
2707 #ifdef DEBUG_PCALL
2708     if (loglevel & CPU_LOG_PCALL) {
2709         fprintf(logfile, "lret new %04x:" TARGET_FMT_lx " s=%d addend=0x%x\n",
2710                 new_cs, new_eip, shift, addend);
2711         cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
2712     }
2713 #endif
2714     if ((new_cs & 0xfffc) == 0)
2715         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2716     if (load_segment(&e1, &e2, new_cs) != 0)
2717         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2718     if (!(e2 & DESC_S_MASK) ||
2719         !(e2 & DESC_CS_MASK))
2720         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2721     cpl = env->hflags & HF_CPL_MASK;
2722     rpl = new_cs & 3;
2723     if (rpl < cpl)
2724         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2725     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2726     if (e2 & DESC_C_MASK) {
2727         if (dpl > rpl)
2728             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2729     } else {
2730         if (dpl != rpl)
2731             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2732     }
2733     if (!(e2 & DESC_P_MASK))
2734         raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2735
2736     sp += addend;
2737     if (rpl == cpl && (!(env->hflags & HF_CS64_MASK) ||
2738                        ((env->hflags & HF_CS64_MASK) && !is_iret))) {
2739         /* return to same priledge level */
2740         cpu_x86_load_seg_cache(env, R_CS, new_cs,
2741                        get_seg_base(e1, e2),
2742                        get_seg_limit(e1, e2),
2743                        e2);
2744     } else {
2745         /* return to different privilege level */
2746 #ifdef TARGET_X86_64
2747         if (shift == 2) {
2748             POPQ(sp, new_esp);
2749             POPQ(sp, new_ss);
2750             new_ss &= 0xffff;
2751         } else
2752 #endif
2753         if (shift == 1) {
2754             /* 32 bits */
2755             POPL(ssp, sp, sp_mask, new_esp);
2756             POPL(ssp, sp, sp_mask, new_ss);
2757             new_ss &= 0xffff;
2758         } else {
2759             /* 16 bits */
2760             POPW(ssp, sp, sp_mask, new_esp);
2761             POPW(ssp, sp, sp_mask, new_ss);
2762         }
2763 #ifdef DEBUG_PCALL
2764         if (loglevel & CPU_LOG_PCALL) {
2765             fprintf(logfile, "new ss:esp=%04x:" TARGET_FMT_lx "\n",
2766                     new_ss, new_esp);
2767         }
2768 #endif
2769         if ((new_ss & 0xfffc) == 0) {
2770 #ifdef TARGET_X86_64
2771             /* NULL ss is allowed in long mode if cpl != 3*/
2772             /* XXX: test CS64 ? */
2773             if ((env->hflags & HF_LMA_MASK) && rpl != 3) {
2774                 cpu_x86_load_seg_cache(env, R_SS, new_ss,
2775                                        0, 0xffffffff,
2776                                        DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2777                                        DESC_S_MASK | (rpl << DESC_DPL_SHIFT) |
2778                                        DESC_W_MASK | DESC_A_MASK);
2779                 ss_e2 = DESC_B_MASK; /* XXX: should not be needed ? */
2780             } else
2781 #endif
2782             {
2783                 raise_exception_err(EXCP0D_GPF, 0);
2784             }
2785         } else {
2786             if ((new_ss & 3) != rpl)
2787                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2788             if (load_segment(&ss_e1, &ss_e2, new_ss) != 0)
2789                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2790             if (!(ss_e2 & DESC_S_MASK) ||
2791                 (ss_e2 & DESC_CS_MASK) ||
2792                 !(ss_e2 & DESC_W_MASK))
2793                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2794             dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
2795             if (dpl != rpl)
2796                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2797             if (!(ss_e2 & DESC_P_MASK))
2798                 raise_exception_err(EXCP0B_NOSEG, new_ss & 0xfffc);
2799             cpu_x86_load_seg_cache(env, R_SS, new_ss,
2800                                    get_seg_base(ss_e1, ss_e2),
2801                                    get_seg_limit(ss_e1, ss_e2),
2802                                    ss_e2);
2803         }
2804
2805         cpu_x86_load_seg_cache(env, R_CS, new_cs,
2806                        get_seg_base(e1, e2),
2807                        get_seg_limit(e1, e2),
2808                        e2);
2809         cpu_x86_set_cpl(env, rpl);
2810         sp = new_esp;
2811 #ifdef TARGET_X86_64
2812         if (env->hflags & HF_CS64_MASK)
2813             sp_mask = -1;
2814         else
2815 #endif
2816             sp_mask = get_sp_mask(ss_e2);
2817
2818         /* validate data segments */
2819         validate_seg(R_ES, rpl);
2820         validate_seg(R_DS, rpl);
2821         validate_seg(R_FS, rpl);
2822         validate_seg(R_GS, rpl);
2823
2824         sp += addend;
2825     }
2826     SET_ESP(sp, sp_mask);
2827     env->eip = new_eip;
2828     if (is_iret) {
2829         /* NOTE: 'cpl' is the _old_ CPL */
2830         eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK | NT_MASK;
2831         if (cpl == 0)
2832             eflags_mask |= IOPL_MASK;
2833         iopl = (env->eflags >> IOPL_SHIFT) & 3;
2834         if (cpl <= iopl)
2835             eflags_mask |= IF_MASK;
2836         if (shift == 0)
2837             eflags_mask &= 0xffff;
2838         load_eflags(new_eflags, eflags_mask);
2839     }
2840     return;
2841
2842  return_to_vm86:
2843     POPL(ssp, sp, sp_mask, new_esp);
2844     POPL(ssp, sp, sp_mask, new_ss);
2845     POPL(ssp, sp, sp_mask, new_es);
2846     POPL(ssp, sp, sp_mask, new_ds);
2847     POPL(ssp, sp, sp_mask, new_fs);
2848     POPL(ssp, sp, sp_mask, new_gs);
2849
2850     /* modify processor state */
2851     load_eflags(new_eflags, TF_MASK | AC_MASK | ID_MASK |
2852                 IF_MASK | IOPL_MASK | VM_MASK | NT_MASK | VIF_MASK | VIP_MASK);
2853     load_seg_vm(R_CS, new_cs & 0xffff);
2854     cpu_x86_set_cpl(env, 3);
2855     load_seg_vm(R_SS, new_ss & 0xffff);
2856     load_seg_vm(R_ES, new_es & 0xffff);
2857     load_seg_vm(R_DS, new_ds & 0xffff);
2858     load_seg_vm(R_FS, new_fs & 0xffff);
2859     load_seg_vm(R_GS, new_gs & 0xffff);
2860
2861     env->eip = new_eip & 0xffff;
2862     ESP = new_esp;
2863 }
2864
2865 void helper_iret_protected(int shift, int next_eip)
2866 {
2867     int tss_selector, type;
2868     uint32_t e1, e2;
2869
2870     /* specific case for TSS */
2871     if (env->eflags & NT_MASK) {
2872 #ifdef TARGET_X86_64
2873         if (env->hflags & HF_LMA_MASK)
2874             raise_exception_err(EXCP0D_GPF, 0);
2875 #endif
2876         tss_selector = lduw_kernel(env->tr.base + 0);
2877         if (tss_selector & 4)
2878             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2879         if (load_segment(&e1, &e2, tss_selector) != 0)
2880             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2881         type = (e2 >> DESC_TYPE_SHIFT) & 0x17;
2882         /* NOTE: we check both segment and busy TSS */
2883         if (type != 3)
2884             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2885         switch_tss(tss_selector, e1, e2, SWITCH_TSS_IRET, next_eip);
2886     } else {
2887         helper_ret_protected(shift, 1, 0);
2888     }
2889     env->hflags &= ~HF_NMI_MASK;
2890 #ifdef USE_KQEMU
2891     if (kqemu_is_ok(env)) {
2892         CC_OP = CC_OP_EFLAGS;
2893         env->exception_index = -1;
2894         cpu_loop_exit();
2895     }
2896 #endif
2897 }
2898
2899 void helper_lret_protected(int shift, int addend)
2900 {
2901     helper_ret_protected(shift, 0, addend);
2902 #ifdef USE_KQEMU
2903     if (kqemu_is_ok(env)) {
2904         env->exception_index = -1;
2905         cpu_loop_exit();
2906     }
2907 #endif
2908 }
2909
2910 void helper_sysenter(void)
2911 {
2912     if (env->sysenter_cs == 0) {
2913         raise_exception_err(EXCP0D_GPF, 0);
2914     }
2915     env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK);
2916     cpu_x86_set_cpl(env, 0);
2917     cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
2918                            0, 0xffffffff,
2919                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2920                            DESC_S_MASK |
2921                            DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2922     cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc,
2923                            0, 0xffffffff,
2924                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2925                            DESC_S_MASK |
2926                            DESC_W_MASK | DESC_A_MASK);
2927     ESP = env->sysenter_esp;
2928     EIP = env->sysenter_eip;
2929 }
2930
2931 void helper_sysexit(void)
2932 {
2933     int cpl;
2934
2935     cpl = env->hflags & HF_CPL_MASK;
2936     if (env->sysenter_cs == 0 || cpl != 0) {
2937         raise_exception_err(EXCP0D_GPF, 0);
2938     }
2939     cpu_x86_set_cpl(env, 3);
2940     cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3,
2941                            0, 0xffffffff,
2942                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2943                            DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2944                            DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2945     cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3,
2946                            0, 0xffffffff,
2947                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2948                            DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2949                            DESC_W_MASK | DESC_A_MASK);
2950     ESP = ECX;
2951     EIP = EDX;
2952 #ifdef USE_KQEMU
2953     if (kqemu_is_ok(env)) {
2954         env->exception_index = -1;
2955         cpu_loop_exit();
2956     }
2957 #endif
2958 }
2959
2960 void helper_movl_crN_T0(int reg, target_ulong t0)
2961 {
2962 #if !defined(CONFIG_USER_ONLY)
2963     switch(reg) {
2964     case 0:
2965         cpu_x86_update_cr0(env, t0);
2966         break;
2967     case 3:
2968         cpu_x86_update_cr3(env, t0);
2969         break;
2970     case 4:
2971         cpu_x86_update_cr4(env, t0);
2972         break;
2973     case 8:
2974         cpu_set_apic_tpr(env, t0);
2975         env->cr[8] = t0;
2976         break;
2977     default:
2978         env->cr[reg] = t0;
2979         break;
2980     }
2981 #endif
2982 }
2983
2984 void helper_lmsw(target_ulong t0)
2985 {
2986     /* only 4 lower bits of CR0 are modified. PE cannot be set to zero
2987        if already set to one. */
2988     t0 = (env->cr[0] & ~0xe) | (t0 & 0xf);
2989     helper_movl_crN_T0(0, t0);
2990 }
2991
2992 void helper_clts(void)
2993 {
2994     env->cr[0] &= ~CR0_TS_MASK;
2995     env->hflags &= ~HF_TS_MASK;
2996 }
2997
2998 #if !defined(CONFIG_USER_ONLY)
2999 target_ulong helper_movtl_T0_cr8(void)
3000 {
3001     return cpu_get_apic_tpr(env);
3002 }
3003 #endif
3004
3005 /* XXX: do more */
3006 void helper_movl_drN_T0(int reg, target_ulong t0)
3007 {
3008     env->dr[reg] = t0;
3009 }
3010
3011 void helper_invlpg(target_ulong addr)
3012 {
3013     cpu_x86_flush_tlb(env, addr);
3014 }
3015
3016 void helper_rdtsc(void)
3017 {
3018     uint64_t val;
3019
3020     if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
3021         raise_exception(EXCP0D_GPF);
3022     }
3023     val = cpu_get_tsc(env);
3024     EAX = (uint32_t)(val);
3025     EDX = (uint32_t)(val >> 32);
3026 }
3027
3028 void helper_rdpmc(void)
3029 {
3030     if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
3031         raise_exception(EXCP0D_GPF);
3032     }
3033
3034     helper_svm_check_intercept_param(SVM_EXIT_RDPMC, 0);
3035     
3036     /* currently unimplemented */
3037     raise_exception_err(EXCP06_ILLOP, 0);
3038 }
3039
3040 #if defined(CONFIG_USER_ONLY)
3041 void helper_wrmsr(void)
3042 {
3043 }
3044
3045 void helper_rdmsr(void)
3046 {
3047 }
3048 #else
3049 void helper_wrmsr(void)
3050 {
3051     uint64_t val;
3052
3053     val = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
3054
3055     switch((uint32_t)ECX) {
3056     case MSR_IA32_SYSENTER_CS:
3057         env->sysenter_cs = val & 0xffff;
3058         break;
3059     case MSR_IA32_SYSENTER_ESP:
3060         env->sysenter_esp = val;
3061         break;
3062     case MSR_IA32_SYSENTER_EIP:
3063         env->sysenter_eip = val;
3064         break;
3065     case MSR_IA32_APICBASE:
3066         cpu_set_apic_base(env, val);
3067         break;
3068     case MSR_EFER:
3069         {
3070             uint64_t update_mask;
3071             update_mask = 0;
3072             if (env->cpuid_ext2_features & CPUID_EXT2_SYSCALL)
3073                 update_mask |= MSR_EFER_SCE;
3074             if (env->cpuid_ext2_features & CPUID_EXT2_LM)
3075                 update_mask |= MSR_EFER_LME;
3076             if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR)
3077                 update_mask |= MSR_EFER_FFXSR;
3078             if (env->cpuid_ext2_features & CPUID_EXT2_NX)
3079                 update_mask |= MSR_EFER_NXE;
3080             env->efer = (env->efer & ~update_mask) |
3081             (val & update_mask);
3082         }
3083         break;
3084     case MSR_STAR:
3085         env->star = val;
3086         break;
3087     case MSR_PAT:
3088         env->pat = val;
3089         break;
3090     case MSR_VM_HSAVE_PA:
3091         env->vm_hsave = val;
3092         break;
3093 #ifdef TARGET_X86_64
3094     case MSR_LSTAR:
3095         env->lstar = val;
3096         break;
3097     case MSR_CSTAR:
3098         env->cstar = val;
3099         break;
3100     case MSR_FMASK:
3101         env->fmask = val;
3102         break;
3103     case MSR_FSBASE:
3104         env->segs[R_FS].base = val;
3105         break;
3106     case MSR_GSBASE:
3107         env->segs[R_GS].base = val;
3108         break;
3109     case MSR_KERNELGSBASE:
3110         env->kernelgsbase = val;
3111         break;
3112 #endif
3113     default:
3114         /* XXX: exception ? */
3115         break;
3116     }
3117 }
3118
3119 void helper_rdmsr(void)
3120 {
3121     uint64_t val;
3122     switch((uint32_t)ECX) {
3123     case MSR_IA32_SYSENTER_CS:
3124         val = env->sysenter_cs;
3125         break;
3126     case MSR_IA32_SYSENTER_ESP:
3127         val = env->sysenter_esp;
3128         break;
3129     case MSR_IA32_SYSENTER_EIP:
3130         val = env->sysenter_eip;
3131         break;
3132     case MSR_IA32_APICBASE:
3133         val = cpu_get_apic_base(env);
3134         break;
3135     case MSR_EFER:
3136         val = env->efer;
3137         break;
3138     case MSR_STAR:
3139         val = env->star;
3140         break;
3141     case MSR_PAT:
3142         val = env->pat;
3143         break;
3144     case MSR_VM_HSAVE_PA:
3145         val = env->vm_hsave;
3146         break;
3147 #ifdef TARGET_X86_64
3148     case MSR_LSTAR:
3149         val = env->lstar;
3150         break;
3151     case MSR_CSTAR:
3152         val = env->cstar;
3153         break;
3154     case MSR_FMASK:
3155         val = env->fmask;
3156         break;
3157     case MSR_FSBASE:
3158         val = env->segs[R_FS].base;
3159         break;
3160     case MSR_GSBASE:
3161         val = env->segs[R_GS].base;
3162         break;
3163     case MSR_KERNELGSBASE:
3164         val = env->kernelgsbase;
3165         break;
3166 #endif
3167     default:
3168         /* XXX: exception ? */
3169         val = 0;
3170         break;
3171     }
3172     EAX = (uint32_t)(val);
3173     EDX = (uint32_t)(val >> 32);
3174 }
3175 #endif
3176
3177 target_ulong helper_lsl(target_ulong selector1)
3178 {
3179     unsigned int limit;
3180     uint32_t e1, e2, eflags, selector;
3181     int rpl, dpl, cpl, type;
3182
3183     selector = selector1 & 0xffff;
3184     eflags = cc_table[CC_OP].compute_all();
3185     if (load_segment(&e1, &e2, selector) != 0)
3186         goto fail;
3187     rpl = selector & 3;
3188     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3189     cpl = env->hflags & HF_CPL_MASK;
3190     if (e2 & DESC_S_MASK) {
3191         if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
3192             /* conforming */
3193         } else {
3194             if (dpl < cpl || dpl < rpl)
3195                 goto fail;
3196         }
3197     } else {
3198         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
3199         switch(type) {
3200         case 1:
3201         case 2:
3202         case 3:
3203         case 9:
3204         case 11:
3205             break;
3206         default:
3207             goto fail;
3208         }
3209         if (dpl < cpl || dpl < rpl) {
3210         fail:
3211             CC_SRC = eflags & ~CC_Z;
3212             return 0;
3213         }
3214     }
3215     limit = get_seg_limit(e1, e2);
3216     CC_SRC = eflags | CC_Z;
3217     return limit;
3218 }
3219
3220 target_ulong helper_lar(target_ulong selector1)
3221 {
3222     uint32_t e1, e2, eflags, selector;
3223     int rpl, dpl, cpl, type;
3224
3225     selector = selector1 & 0xffff;
3226     eflags = cc_table[CC_OP].compute_all();
3227     if ((selector & 0xfffc) == 0)
3228         goto fail;
3229     if (load_segment(&e1, &e2, selector) != 0)
3230         goto fail;
3231     rpl = selector & 3;
3232     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3233     cpl = env->hflags & HF_CPL_MASK;
3234     if (e2 & DESC_S_MASK) {
3235         if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
3236             /* conforming */
3237         } else {
3238             if (dpl < cpl || dpl < rpl)
3239                 goto fail;
3240         }
3241     } else {
3242         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
3243         switch(type) {
3244         case 1:
3245         case 2:
3246         case 3:
3247         case 4:
3248         case 5:
3249         case 9:
3250         case 11:
3251         case 12:
3252             break;
3253         default:
3254             goto fail;
3255         }
3256         if (dpl < cpl || dpl < rpl) {
3257         fail:
3258             CC_SRC = eflags & ~CC_Z;
3259             return 0;
3260         }
3261     }
3262     CC_SRC = eflags | CC_Z;
3263     return e2 & 0x00f0ff00;
3264 }
3265
3266 void helper_verr(target_ulong selector1)
3267 {
3268     uint32_t e1, e2, eflags, selector;
3269     int rpl, dpl, cpl;
3270
3271     selector = selector1 & 0xffff;
3272     eflags = cc_table[CC_OP].compute_all();
3273     if ((selector & 0xfffc) == 0)
3274         goto fail;
3275     if (load_segment(&e1, &e2, selector) != 0)
3276         goto fail;
3277     if (!(e2 & DESC_S_MASK))
3278         goto fail;
3279     rpl = selector & 3;
3280     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3281     cpl = env->hflags & HF_CPL_MASK;
3282     if (e2 & DESC_CS_MASK) {
3283         if (!(e2 & DESC_R_MASK))
3284             goto fail;
3285         if (!(e2 & DESC_C_MASK)) {
3286             if (dpl < cpl || dpl < rpl)
3287                 goto fail;
3288         }
3289     } else {
3290         if (dpl < cpl || dpl < rpl) {
3291         fail:
3292             CC_SRC = eflags & ~CC_Z;
3293             return;
3294         }
3295     }
3296     CC_SRC = eflags | CC_Z;
3297 }
3298
3299 void helper_verw(target_ulong selector1)
3300 {
3301     uint32_t e1, e2, eflags, selector;
3302     int rpl, dpl, cpl;
3303
3304     selector = selector1 & 0xffff;
3305     eflags = cc_table[CC_OP].compute_all();
3306     if ((selector & 0xfffc) == 0)
3307         goto fail;
3308     if (load_segment(&e1, &e2, selector) != 0)
3309         goto fail;
3310     if (!(e2 & DESC_S_MASK))
3311         goto fail;
3312     rpl = selector & 3;
3313     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3314     cpl = env->hflags & HF_CPL_MASK;
3315     if (e2 & DESC_CS_MASK) {
3316         goto fail;
3317     } else {
3318         if (dpl < cpl || dpl < rpl)
3319             goto fail;
3320         if (!(e2 & DESC_W_MASK)) {
3321         fail:
3322             CC_SRC = eflags & ~CC_Z;
3323             return;
3324         }
3325     }
3326     CC_SRC = eflags | CC_Z;
3327 }
3328
3329 /* x87 FPU helpers */
3330
3331 static void fpu_set_exception(int mask)
3332 {
3333     env->fpus |= mask;
3334     if (env->fpus & (~env->fpuc & FPUC_EM))
3335         env->fpus |= FPUS_SE | FPUS_B;
3336 }
3337
3338 static inline CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b)
3339 {
3340     if (b == 0.0)
3341         fpu_set_exception(FPUS_ZE);
3342     return a / b;
3343 }
3344
3345 void fpu_raise_exception(void)
3346 {
3347     if (env->cr[0] & CR0_NE_MASK) {
3348         raise_exception(EXCP10_COPR);
3349     }
3350 #if !defined(CONFIG_USER_ONLY)
3351     else {
3352         cpu_set_ferr(env);
3353     }
3354 #endif
3355 }
3356
3357 void helper_flds_FT0(uint32_t val)
3358 {
3359     union {
3360         float32 f;
3361         uint32_t i;
3362     } u;
3363     u.i = val;
3364     FT0 = float32_to_floatx(u.f, &env->fp_status);
3365 }
3366
3367 void helper_fldl_FT0(uint64_t val)
3368 {
3369     union {
3370         float64 f;
3371         uint64_t i;
3372     } u;
3373     u.i = val;
3374     FT0 = float64_to_floatx(u.f, &env->fp_status);
3375 }
3376
3377 void helper_fildl_FT0(int32_t val)
3378 {
3379     FT0 = int32_to_floatx(val, &env->fp_status);
3380 }
3381
3382 void helper_flds_ST0(uint32_t val)
3383 {
3384     int new_fpstt;
3385     union {
3386         float32 f;
3387         uint32_t i;
3388     } u;
3389     new_fpstt = (env->fpstt - 1) & 7;
3390     u.i = val;
3391     env->fpregs[new_fpstt].d = float32_to_floatx(u.f, &env->fp_status);
3392     env->fpstt = new_fpstt;
3393     env->fptags[new_fpstt] = 0; /* validate stack entry */
3394 }
3395
3396 void helper_fldl_ST0(uint64_t val)
3397 {
3398     int new_fpstt;
3399     union {
3400         float64 f;
3401         uint64_t i;
3402     } u;
3403     new_fpstt = (env->fpstt - 1) & 7;
3404     u.i = val;
3405     env->fpregs[new_fpstt].d = float64_to_floatx(u.f, &env->fp_status);
3406     env->fpstt = new_fpstt;
3407     env->fptags[new_fpstt] = 0; /* validate stack entry */
3408 }
3409
3410 void helper_fildl_ST0(int32_t val)
3411 {
3412     int new_fpstt;
3413     new_fpstt = (env->fpstt - 1) & 7;
3414     env->fpregs[new_fpstt].d = int32_to_floatx(val, &env->fp_status);
3415     env->fpstt = new_fpstt;
3416     env->fptags[new_fpstt] = 0; /* validate stack entry */
3417 }
3418
3419 void helper_fildll_ST0(int64_t val)
3420 {
3421     int new_fpstt;
3422     new_fpstt = (env->fpstt - 1) & 7;
3423     env->fpregs[new_fpstt].d = int64_to_floatx(val, &env->fp_status);
3424     env->fpstt = new_fpstt;
3425     env->fptags[new_fpstt] = 0; /* validate stack entry */
3426 }
3427
3428 uint32_t helper_fsts_ST0(void)
3429 {
3430     union {
3431         float32 f;
3432         uint32_t i;
3433     } u;
3434     u.f = floatx_to_float32(ST0, &env->fp_status);
3435     return u.i;
3436 }
3437
3438 uint64_t helper_fstl_ST0(void)
3439 {
3440     union {
3441         float64 f;
3442         uint64_t i;
3443     } u;
3444     u.f = floatx_to_float64(ST0, &env->fp_status);
3445     return u.i;
3446 }
3447
3448 int32_t helper_fist_ST0(void)
3449 {
3450     int32_t val;
3451     val = floatx_to_int32(ST0, &env->fp_status);
3452     if (val != (int16_t)val)
3453         val = -32768;
3454     return val;
3455 }
3456
3457 int32_t helper_fistl_ST0(void)
3458 {
3459     int32_t val;
3460     val = floatx_to_int32(ST0, &env->fp_status);
3461     return val;
3462 }
3463
3464 int64_t helper_fistll_ST0(void)
3465 {
3466     int64_t val;
3467     val = floatx_to_int64(ST0, &env->fp_status);
3468     return val;
3469 }
3470
3471 int32_t helper_fistt_ST0(void)
3472 {
3473     int32_t val;
3474     val = floatx_to_int32_round_to_zero(ST0, &env->fp_status);
3475     if (val != (int16_t)val)
3476         val = -32768;
3477     return val;
3478 }
3479
3480 int32_t helper_fisttl_ST0(void)
3481 {
3482     int32_t val;
3483     val = floatx_to_int32_round_to_zero(ST0, &env->fp_status);
3484     return val;
3485 }
3486
3487 int64_t helper_fisttll_ST0(void)
3488 {
3489     int64_t val;
3490     val = floatx_to_int64_round_to_zero(ST0, &env->fp_status);
3491     return val;
3492 }
3493
3494 void helper_fldt_ST0(target_ulong ptr)
3495 {
3496     int new_fpstt;
3497     new_fpstt = (env->fpstt - 1) & 7;
3498     env->fpregs[new_fpstt].d = helper_fldt(ptr);
3499     env->fpstt = new_fpstt;
3500     env->fptags[new_fpstt] = 0; /* validate stack entry */
3501 }
3502
3503 void helper_fstt_ST0(target_ulong ptr)
3504 {
3505     helper_fstt(ST0, ptr);
3506 }
3507
3508 void helper_fpush(void)
3509 {
3510     fpush();
3511 }
3512
3513 void helper_fpop(void)
3514 {
3515     fpop();
3516 }
3517
3518 void helper_fdecstp(void)
3519 {
3520     env->fpstt = (env->fpstt - 1) & 7;
3521     env->fpus &= (~0x4700);
3522 }
3523
3524 void helper_fincstp(void)
3525 {
3526     env->fpstt = (env->fpstt + 1) & 7;
3527     env->fpus &= (~0x4700);
3528 }
3529
3530 /* FPU move */
3531
3532 void helper_ffree_STN(int st_index)
3533 {
3534     env->fptags[(env->fpstt + st_index) & 7] = 1;
3535 }
3536
3537 void helper_fmov_ST0_FT0(void)
3538 {
3539     ST0 = FT0;
3540 }
3541
3542 void helper_fmov_FT0_STN(int st_index)
3543 {
3544     FT0 = ST(st_index);
3545 }
3546
3547 void helper_fmov_ST0_STN(int st_index)
3548 {
3549     ST0 = ST(st_index);
3550 }
3551
3552 void helper_fmov_STN_ST0(int st_index)
3553 {
3554     ST(st_index) = ST0;
3555 }
3556
3557 void helper_fxchg_ST0_STN(int st_index)
3558 {
3559     CPU86_LDouble tmp;
3560     tmp = ST(st_index);
3561     ST(st_index) = ST0;
3562     ST0 = tmp;
3563 }
3564
3565 /* FPU operations */
3566
3567 static const int fcom_ccval[4] = {0x0100, 0x4000, 0x0000, 0x4500};
3568
3569 void helper_fcom_ST0_FT0(void)
3570 {
3571     int ret;
3572
3573     ret = floatx_compare(ST0, FT0, &env->fp_status);
3574     env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
3575     FORCE_RET();
3576 }
3577
3578 void helper_fucom_ST0_FT0(void)
3579 {
3580     int ret;
3581
3582     ret = floatx_compare_quiet(ST0, FT0, &env->fp_status);
3583     env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret+ 1];
3584     FORCE_RET();
3585 }
3586
3587 static const int fcomi_ccval[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C};
3588
3589 void helper_fcomi_ST0_FT0(void)
3590 {
3591     int eflags;
3592     int ret;
3593
3594     ret = floatx_compare(ST0, FT0, &env->fp_status);
3595     eflags = cc_table[CC_OP].compute_all();
3596     eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
3597     CC_SRC = eflags;
3598     FORCE_RET();
3599 }
3600
3601 void helper_fucomi_ST0_FT0(void)
3602 {
3603     int eflags;
3604     int ret;
3605
3606     ret = floatx_compare_quiet(ST0, FT0, &env->fp_status);
3607     eflags = cc_table[CC_OP].compute_all();
3608     eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
3609     CC_SRC = eflags;
3610     FORCE_RET();
3611 }
3612
3613 void helper_fadd_ST0_FT0(void)
3614 {
3615     ST0 += FT0;
3616 }
3617
3618 void helper_fmul_ST0_FT0(void)
3619 {
3620     ST0 *= FT0;
3621 }
3622
3623 void helper_fsub_ST0_FT0(void)
3624 {
3625     ST0 -= FT0;
3626 }
3627
3628 void helper_fsubr_ST0_FT0(void)
3629 {
3630     ST0 = FT0 - ST0;
3631 }
3632
3633 void helper_fdiv_ST0_FT0(void)
3634 {
3635     ST0 = helper_fdiv(ST0, FT0);
3636 }
3637
3638 void helper_fdivr_ST0_FT0(void)
3639 {
3640     ST0 = helper_fdiv(FT0, ST0);
3641 }
3642
3643 /* fp operations between STN and ST0 */
3644
3645 void helper_fadd_STN_ST0(int st_index)
3646 {
3647     ST(st_index) += ST0;
3648 }
3649
3650 void helper_fmul_STN_ST0(int st_index)
3651 {
3652     ST(st_index) *= ST0;
3653 }
3654
3655 void helper_fsub_STN_ST0(int st_index)
3656 {
3657     ST(st_index) -= ST0;
3658 }
3659
3660 void helper_fsubr_STN_ST0(int st_index)
3661 {
3662     CPU86_LDouble *p;
3663     p = &ST(st_index);
3664     *p = ST0 - *p;
3665 }
3666
3667 void helper_fdiv_STN_ST0(int st_index)
3668 {
3669     CPU86_LDouble *p;
3670     p = &ST(st_index);
3671     *p = helper_fdiv(*p, ST0);
3672 }
3673
3674 void helper_fdivr_STN_ST0(int st_index)
3675 {
3676     CPU86_LDouble *p;
3677     p = &ST(st_index);
3678     *p = helper_fdiv(ST0, *p);
3679 }
3680
3681 /* misc FPU operations */
3682 void helper_fchs_ST0(void)
3683 {
3684     ST0 = floatx_chs(ST0);
3685 }
3686
3687 void helper_fabs_ST0(void)
3688 {
3689     ST0 = floatx_abs(ST0);
3690 }
3691
3692 void helper_fld1_ST0(void)
3693 {
3694     ST0 = f15rk[1];
3695 }
3696
3697 void helper_fldl2t_ST0(void)
3698 {
3699     ST0 = f15rk[6];
3700 }
3701
3702 void helper_fldl2e_ST0(void)
3703 {
3704     ST0 = f15rk[5];
3705 }
3706
3707 void helper_fldpi_ST0(void)
3708 {
3709     ST0 = f15rk[2];
3710 }
3711
3712 void helper_fldlg2_ST0(void)
3713 {
3714     ST0 = f15rk[3];
3715 }
3716
3717 void helper_fldln2_ST0(void)
3718 {
3719     ST0 = f15rk[4];
3720 }
3721
3722 void helper_fldz_ST0(void)
3723 {
3724     ST0 = f15rk[0];
3725 }
3726
3727 void helper_fldz_FT0(void)
3728 {
3729     FT0 = f15rk[0];
3730 }
3731
3732 uint32_t helper_fnstsw(void)
3733 {
3734     return (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
3735 }
3736
3737 uint32_t helper_fnstcw(void)
3738 {
3739     return env->fpuc;
3740 }
3741
3742 static void update_fp_status(void)
3743 {
3744     int rnd_type;
3745
3746     /* set rounding mode */
3747     switch(env->fpuc & RC_MASK) {
3748     default:
3749     case RC_NEAR:
3750         rnd_type = float_round_nearest_even;
3751         break;
3752     case RC_DOWN:
3753         rnd_type = float_round_down;
3754         break;
3755     case RC_UP:
3756         rnd_type = float_round_up;
3757         break;
3758     case RC_CHOP:
3759         rnd_type = float_round_to_zero;
3760         break;
3761     }
3762     set_float_rounding_mode(rnd_type, &env->fp_status);
3763 #ifdef FLOATX80
3764     switch((env->fpuc >> 8) & 3) {
3765     case 0:
3766         rnd_type = 32;
3767         break;
3768     case 2:
3769         rnd_type = 64;
3770         break;
3771     case 3:
3772     default:
3773         rnd_type = 80;
3774         break;
3775     }
3776     set_floatx80_rounding_precision(rnd_type, &env->fp_status);
3777 #endif
3778 }
3779
3780 void helper_fldcw(uint32_t val)
3781 {
3782     env->fpuc = val;
3783     update_fp_status();
3784 }
3785
3786 void helper_fclex(void)
3787 {
3788     env->fpus &= 0x7f00;
3789 }
3790
3791 void helper_fwait(void)
3792 {
3793     if (env->fpus & FPUS_SE)
3794         fpu_raise_exception();
3795     FORCE_RET();
3796 }
3797
3798 void helper_fninit(void)
3799 {
3800     env->fpus = 0;
3801     env->fpstt = 0;
3802     env->fpuc = 0x37f;
3803     env->fptags[0] = 1;
3804     env->fptags[1] = 1;
3805     env->fptags[2] = 1;
3806     env->fptags[3] = 1;
3807     env->fptags[4] = 1;
3808     env->fptags[5] = 1;
3809     env->fptags[6] = 1;
3810     env->fptags[7] = 1;
3811 }
3812
3813 /* BCD ops */
3814
3815 void helper_fbld_ST0(target_ulong ptr)
3816 {
3817     CPU86_LDouble tmp;
3818     uint64_t val;
3819     unsigned int v;
3820     int i;
3821
3822     val = 0;
3823     for(i = 8; i >= 0; i--) {
3824         v = ldub(ptr + i);
3825         val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
3826     }
3827     tmp = val;
3828     if (ldub(ptr + 9) & 0x80)
3829         tmp = -tmp;
3830     fpush();
3831     ST0 = tmp;
3832 }
3833
3834 void helper_fbst_ST0(target_ulong ptr)
3835 {
3836     int v;
3837     target_ulong mem_ref, mem_end;
3838     int64_t val;
3839
3840     val = floatx_to_int64(ST0, &env->fp_status);
3841     mem_ref = ptr;
3842     mem_end = mem_ref + 9;
3843     if (val < 0) {
3844         stb(mem_end, 0x80);
3845         val = -val;
3846     } else {
3847         stb(mem_end, 0x00);
3848     }
3849     while (mem_ref < mem_end) {
3850         if (val == 0)
3851             break;
3852         v = val % 100;
3853         val = val / 100;
3854         v = ((v / 10) << 4) | (v % 10);
3855         stb(mem_ref++, v);
3856     }
3857     while (mem_ref < mem_end) {
3858         stb(mem_ref++, 0);
3859     }
3860 }
3861
3862 void helper_f2xm1(void)
3863 {
3864     ST0 = pow(2.0,ST0) - 1.0;
3865 }
3866
3867 void helper_fyl2x(void)
3868 {
3869     CPU86_LDouble fptemp;
3870
3871     fptemp = ST0;
3872     if (fptemp>0.0){
3873         fptemp = log(fptemp)/log(2.0);   /* log2(ST) */
3874         ST1 *= fptemp;
3875         fpop();
3876     } else {
3877         env->fpus &= (~0x4700);
3878         env->fpus |= 0x400;
3879     }
3880 }
3881
3882 void helper_fptan(void)
3883 {
3884     CPU86_LDouble fptemp;
3885
3886     fptemp = ST0;
3887     if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
3888         env->fpus |= 0x400;
3889     } else {
3890         ST0 = tan(fptemp);
3891         fpush();
3892         ST0 = 1.0;
3893         env->fpus &= (~0x400);  /* C2 <-- 0 */
3894         /* the above code is for  |arg| < 2**52 only */
3895     }
3896 }
3897
3898 void helper_fpatan(void)
3899 {
3900     CPU86_LDouble fptemp, fpsrcop;
3901
3902     fpsrcop = ST1;
3903     fptemp = ST0;
3904     ST1 = atan2(fpsrcop,fptemp);
3905     fpop();
3906 }
3907
3908 void helper_fxtract(void)
3909 {
3910     CPU86_LDoubleU temp;
3911     unsigned int expdif;
3912
3913     temp.d = ST0;
3914     expdif = EXPD(temp) - EXPBIAS;
3915     /*DP exponent bias*/
3916     ST0 = expdif;
3917     fpush();
3918     BIASEXPONENT(temp);
3919     ST0 = temp.d;
3920 }
3921
3922 void helper_fprem1(void)
3923 {
3924     CPU86_LDouble dblq, fpsrcop, fptemp;
3925     CPU86_LDoubleU fpsrcop1, fptemp1;
3926     int expdif;
3927     signed long long int q;
3928
3929     if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
3930         ST0 = 0.0 / 0.0; /* NaN */
3931         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
3932         return;
3933     }
3934
3935     fpsrcop = ST0;
3936     fptemp = ST1;
3937     fpsrcop1.d = fpsrcop;
3938     fptemp1.d = fptemp;
3939     expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
3940
3941     if (expdif < 0) {
3942         /* optimisation? taken from the AMD docs */
3943         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
3944         /* ST0 is unchanged */
3945         return;
3946     }
3947
3948     if (expdif < 53) {
3949         dblq = fpsrcop / fptemp;
3950         /* round dblq towards nearest integer */
3951         dblq = rint(dblq);
3952         ST0 = fpsrcop - fptemp * dblq;
3953
3954         /* convert dblq to q by truncating towards zero */
3955         if (dblq < 0.0)
3956            q = (signed long long int)(-dblq);
3957         else
3958            q = (signed long long int)dblq;
3959
3960         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
3961                                 /* (C0,C3,C1) <-- (q2,q1,q0) */
3962         env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
3963         env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
3964         env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
3965     } else {
3966         env->fpus |= 0x400;  /* C2 <-- 1 */
3967         fptemp = pow(2.0, expdif - 50);
3968         fpsrcop = (ST0 / ST1) / fptemp;
3969         /* fpsrcop = integer obtained by chopping */
3970         fpsrcop = (fpsrcop < 0.0) ?
3971                   -(floor(fabs(fpsrcop))) : floor(fpsrcop);
3972         ST0 -= (ST1 * fpsrcop * fptemp);
3973     }
3974 }
3975
3976 void helper_fprem(void)
3977 {
3978     CPU86_LDouble dblq, fpsrcop, fptemp;
3979     CPU86_LDoubleU fpsrcop1, fptemp1;
3980     int expdif;
3981     signed long long int q;
3982
3983     if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
3984        ST0 = 0.0 / 0.0; /* NaN */
3985        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
3986        return;
3987     }
3988
3989     fpsrcop = (CPU86_LDouble)ST0;
3990     fptemp = (CPU86_LDouble)ST1;
3991     fpsrcop1.d = fpsrcop;
3992     fptemp1.d = fptemp;
3993     expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
3994
3995     if (expdif < 0) {
3996         /* optimisation? taken from the AMD docs */
3997         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
3998         /* ST0 is unchanged */
3999         return;
4000     }
4001
4002     if ( expdif < 53 ) {
4003         dblq = fpsrcop/*ST0*/ / fptemp/*ST1*/;
4004         /* round dblq towards zero */
4005         dblq = (dblq < 0.0) ? ceil(dblq) : floor(dblq);
4006         ST0 = fpsrcop/*ST0*/ - fptemp * dblq;
4007
4008         /* convert dblq to q by truncating towards zero */
4009         if (dblq < 0.0)
4010            q = (signed long long int)(-dblq);
4011         else
4012            q = (signed long long int)dblq;
4013
4014         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4015                                 /* (C0,C3,C1) <-- (q2,q1,q0) */
4016         env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
4017         env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
4018         env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
4019     } else {
4020         int N = 32 + (expdif % 32); /* as per AMD docs */
4021         env->fpus |= 0x400;  /* C2 <-- 1 */
4022         fptemp = pow(2.0, (double)(expdif - N));
4023         fpsrcop = (ST0 / ST1) / fptemp;
4024         /* fpsrcop = integer obtained by chopping */
4025         fpsrcop = (fpsrcop < 0.0) ?
4026                   -(floor(fabs(fpsrcop))) : floor(fpsrcop);
4027         ST0 -= (ST1 * fpsrcop * fptemp);
4028     }
4029 }
4030
4031 void helper_fyl2xp1(void)
4032 {
4033     CPU86_LDouble fptemp;
4034
4035     fptemp = ST0;
4036     if ((fptemp+1.0)>0.0) {
4037         fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
4038         ST1 *= fptemp;
4039         fpop();
4040     } else {
4041         env->fpus &= (~0x4700);
4042         env->fpus |= 0x400;
4043     }
4044 }
4045
4046 void helper_fsqrt(void)
4047 {
4048     CPU86_LDouble fptemp;
4049
4050     fptemp = ST0;
4051     if (fptemp<0.0) {
4052         env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
4053         env->fpus |= 0x400;
4054     }
4055     ST0 = sqrt(fptemp);
4056 }
4057
4058 void helper_fsincos(void)
4059 {
4060     CPU86_LDouble fptemp;
4061
4062     fptemp = ST0;
4063     if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4064         env->fpus |= 0x400;
4065     } else {
4066         ST0 = sin(fptemp);
4067         fpush();
4068         ST0 = cos(fptemp);
4069         env->fpus &= (~0x400);  /* C2 <-- 0 */
4070         /* the above code is for  |arg| < 2**63 only */
4071     }
4072 }
4073
4074 void helper_frndint(void)
4075 {
4076     ST0 = floatx_round_to_int(ST0, &env->fp_status);
4077 }
4078
4079 void helper_fscale(void)
4080 {
4081     ST0 = ldexp (ST0, (int)(ST1));
4082 }
4083
4084 void helper_fsin(void)
4085 {
4086     CPU86_LDouble fptemp;
4087
4088     fptemp = ST0;
4089     if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4090         env->fpus |= 0x400;
4091     } else {
4092         ST0 = sin(fptemp);
4093         env->fpus &= (~0x400);  /* C2 <-- 0 */
4094         /* the above code is for  |arg| < 2**53 only */
4095     }
4096 }
4097
4098 void helper_fcos(void)
4099 {
4100     CPU86_LDouble fptemp;
4101
4102     fptemp = ST0;
4103     if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4104         env->fpus |= 0x400;
4105     } else {
4106         ST0 = cos(fptemp);
4107         env->fpus &= (~0x400);  /* C2 <-- 0 */
4108         /* the above code is for  |arg5 < 2**63 only */
4109     }
4110 }
4111
4112 void helper_fxam_ST0(void)
4113 {
4114     CPU86_LDoubleU temp;
4115     int expdif;
4116
4117     temp.d = ST0;
4118
4119     env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
4120     if (SIGND(temp))
4121         env->fpus |= 0x200; /* C1 <-- 1 */
4122
4123     /* XXX: test fptags too */
4124     expdif = EXPD(temp);
4125     if (expdif == MAXEXPD) {
4126 #ifdef USE_X86LDOUBLE
4127         if (MANTD(temp) == 0x8000000000000000ULL)
4128 #else
4129         if (MANTD(temp) == 0)
4130 #endif
4131             env->fpus |=  0x500 /*Infinity*/;
4132         else
4133             env->fpus |=  0x100 /*NaN*/;
4134     } else if (expdif == 0) {
4135         if (MANTD(temp) == 0)
4136             env->fpus |=  0x4000 /*Zero*/;
4137         else
4138             env->fpus |= 0x4400 /*Denormal*/;
4139     } else {
4140         env->fpus |= 0x400;
4141     }
4142 }
4143
4144 void helper_fstenv(target_ulong ptr, int data32)
4145 {
4146     int fpus, fptag, exp, i;
4147     uint64_t mant;
4148     CPU86_LDoubleU tmp;
4149
4150     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
4151     fptag = 0;
4152     for (i=7; i>=0; i--) {
4153         fptag <<= 2;
4154         if (env->fptags[i]) {
4155             fptag |= 3;
4156         } else {
4157             tmp.d = env->fpregs[i].d;
4158             exp = EXPD(tmp);
4159             mant = MANTD(tmp);
4160             if (exp == 0 && mant == 0) {
4161                 /* zero */
4162                 fptag |= 1;
4163             } else if (exp == 0 || exp == MAXEXPD
4164 #ifdef USE_X86LDOUBLE
4165                        || (mant & (1LL << 63)) == 0
4166 #endif
4167                        ) {
4168                 /* NaNs, infinity, denormal */
4169                 fptag |= 2;
4170             }
4171         }
4172     }
4173     if (data32) {
4174         /* 32 bit */
4175         stl(ptr, env->fpuc);
4176         stl(ptr + 4, fpus);
4177         stl(ptr + 8, fptag);
4178         stl(ptr + 12, 0); /* fpip */
4179         stl(ptr + 16, 0); /* fpcs */
4180         stl(ptr + 20, 0); /* fpoo */
4181         stl(ptr + 24, 0); /* fpos */
4182     } else {
4183         /* 16 bit */
4184         stw(ptr, env->fpuc);
4185         stw(ptr + 2, fpus);
4186         stw(ptr + 4, fptag);
4187         stw(ptr + 6, 0);
4188         stw(ptr + 8, 0);
4189         stw(ptr + 10, 0);
4190         stw(ptr + 12, 0);
4191     }
4192 }
4193
4194 void helper_fldenv(target_ulong ptr, int data32)
4195 {
4196     int i, fpus, fptag;
4197
4198     if (data32) {
4199         env->fpuc = lduw(ptr);
4200         fpus = lduw(ptr + 4);
4201         fptag = lduw(ptr + 8);
4202     }
4203     else {
4204         env->fpuc = lduw(ptr);
4205         fpus = lduw(ptr + 2);
4206         fptag = lduw(ptr + 4);
4207     }
4208     env->fpstt = (fpus >> 11) & 7;
4209     env->fpus = fpus & ~0x3800;
4210     for(i = 0;i < 8; i++) {
4211         env->fptags[i] = ((fptag & 3) == 3);
4212         fptag >>= 2;
4213     }
4214 }
4215
4216 void helper_fsave(target_ulong ptr, int data32)
4217 {
4218     CPU86_LDouble tmp;
4219     int i;
4220
4221     helper_fstenv(ptr, data32);
4222
4223     ptr += (14 << data32);
4224     for(i = 0;i < 8; i++) {
4225         tmp = ST(i);
4226         helper_fstt(tmp, ptr);
4227         ptr += 10;
4228     }
4229
4230     /* fninit */
4231     env->fpus = 0;
4232     env->fpstt = 0;
4233     env->fpuc = 0x37f;
4234     env->fptags[0] = 1;
4235     env->fptags[1] = 1;
4236     env->fptags[2] = 1;
4237     env->fptags[3] = 1;
4238     env->fptags[4] = 1;
4239     env->fptags[5] = 1;
4240     env->fptags[6] = 1;
4241     env->fptags[7] = 1;
4242 }
4243
4244 void helper_frstor(target_ulong ptr, int data32)
4245 {
4246     CPU86_LDouble tmp;
4247     int i;
4248
4249     helper_fldenv(ptr, data32);
4250     ptr += (14 << data32);
4251
4252     for(i = 0;i < 8; i++) {
4253         tmp = helper_fldt(ptr);
4254         ST(i) = tmp;
4255         ptr += 10;
4256     }
4257 }
4258
4259 void helper_fxsave(target_ulong ptr, int data64)
4260 {
4261     int fpus, fptag, i, nb_xmm_regs;
4262     CPU86_LDouble tmp;
4263     target_ulong addr;
4264
4265     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
4266     fptag = 0;
4267     for(i = 0; i < 8; i++) {
4268         fptag |= (env->fptags[i] << i);
4269     }
4270     stw(ptr, env->fpuc);
4271     stw(ptr + 2, fpus);
4272     stw(ptr + 4, fptag ^ 0xff);
4273 #ifdef TARGET_X86_64
4274     if (data64) {
4275         stq(ptr + 0x08, 0); /* rip */
4276         stq(ptr + 0x10, 0); /* rdp */
4277     } else 
4278 #endif
4279     {
4280         stl(ptr + 0x08, 0); /* eip */
4281         stl(ptr + 0x0c, 0); /* sel  */
4282         stl(ptr + 0x10, 0); /* dp */
4283         stl(ptr + 0x14, 0); /* sel  */
4284     }
4285
4286     addr = ptr + 0x20;
4287     for(i = 0;i < 8; i++) {
4288         tmp = ST(i);
4289         helper_fstt(tmp, addr);
4290         addr += 16;
4291     }
4292
4293     if (env->cr[4] & CR4_OSFXSR_MASK) {
4294         /* XXX: finish it */
4295         stl(ptr + 0x18, env->mxcsr); /* mxcsr */
4296         stl(ptr + 0x1c, 0x0000ffff); /* mxcsr_mask */
4297         if (env->hflags & HF_CS64_MASK)
4298             nb_xmm_regs = 16;
4299         else
4300             nb_xmm_regs = 8;
4301         addr = ptr + 0xa0;
4302         for(i = 0; i < nb_xmm_regs; i++) {
4303             stq(addr, env->xmm_regs[i].XMM_Q(0));
4304             stq(addr + 8, env->xmm_regs[i].XMM_Q(1));
4305             addr += 16;
4306         }
4307     }
4308 }
4309
4310 void helper_fxrstor(target_ulong ptr, int data64)
4311 {
4312     int i, fpus, fptag, nb_xmm_regs;
4313     CPU86_LDouble tmp;
4314     target_ulong addr;
4315
4316     env->fpuc = lduw(ptr);
4317     fpus = lduw(ptr + 2);
4318     fptag = lduw(ptr + 4);
4319     env->fpstt = (fpus >> 11) & 7;
4320     env->fpus = fpus & ~0x3800;
4321     fptag ^= 0xff;
4322     for(i = 0;i < 8; i++) {
4323         env->fptags[i] = ((fptag >> i) & 1);
4324     }
4325
4326     addr = ptr + 0x20;
4327     for(i = 0;i < 8; i++) {
4328         tmp = helper_fldt(addr);
4329         ST(i) = tmp;
4330         addr += 16;
4331     }
4332
4333     if (env->cr[4] & CR4_OSFXSR_MASK) {
4334         /* XXX: finish it */
4335         env->mxcsr = ldl(ptr + 0x18);
4336         //ldl(ptr + 0x1c);
4337         if (env->hflags & HF_CS64_MASK)
4338             nb_xmm_regs = 16;
4339         else
4340             nb_xmm_regs = 8;
4341         addr = ptr + 0xa0;
4342         for(i = 0; i < nb_xmm_regs; i++) {
4343             env->xmm_regs[i].XMM_Q(0) = ldq(addr);
4344             env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
4345             addr += 16;
4346         }
4347     }
4348 }
4349
4350 #ifndef USE_X86LDOUBLE
4351
4352 void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
4353 {
4354     CPU86_LDoubleU temp;
4355     int e;
4356
4357     temp.d = f;
4358     /* mantissa */
4359     *pmant = (MANTD(temp) << 11) | (1LL << 63);
4360     /* exponent + sign */
4361     e = EXPD(temp) - EXPBIAS + 16383;
4362     e |= SIGND(temp) >> 16;
4363     *pexp = e;
4364 }
4365
4366 CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
4367 {
4368     CPU86_LDoubleU temp;
4369     int e;
4370     uint64_t ll;
4371
4372     /* XXX: handle overflow ? */
4373     e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
4374     e |= (upper >> 4) & 0x800; /* sign */
4375     ll = (mant >> 11) & ((1LL << 52) - 1);
4376 #ifdef __arm__
4377     temp.l.upper = (e << 20) | (ll >> 32);
4378     temp.l.lower = ll;
4379 #else
4380     temp.ll = ll | ((uint64_t)e << 52);
4381 #endif
4382     return temp.d;
4383 }
4384
4385 #else
4386
4387 void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
4388 {
4389     CPU86_LDoubleU temp;
4390
4391     temp.d = f;
4392     *pmant = temp.l.lower;
4393     *pexp = temp.l.upper;
4394 }
4395
4396 CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
4397 {
4398     CPU86_LDoubleU temp;
4399
4400     temp.l.upper = upper;
4401     temp.l.lower = mant;
4402     return temp.d;
4403 }
4404 #endif
4405
4406 #ifdef TARGET_X86_64
4407
4408 //#define DEBUG_MULDIV
4409
4410 static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
4411 {
4412     *plow += a;
4413     /* carry test */
4414     if (*plow < a)
4415         (*phigh)++;
4416     *phigh += b;
4417 }
4418
4419 static void neg128(uint64_t *plow, uint64_t *phigh)
4420 {
4421     *plow = ~ *plow;
4422     *phigh = ~ *phigh;
4423     add128(plow, phigh, 1, 0);
4424 }
4425
4426 /* return TRUE if overflow */
4427 static int div64(uint64_t *plow, uint64_t *phigh, uint64_t b)
4428 {
4429     uint64_t q, r, a1, a0;
4430     int i, qb, ab;
4431
4432     a0 = *plow;
4433     a1 = *phigh;
4434     if (a1 == 0) {
4435         q = a0 / b;
4436         r = a0 % b;
4437         *plow = q;
4438         *phigh = r;
4439     } else {
4440         if (a1 >= b)
4441             return 1;
4442         /* XXX: use a better algorithm */
4443         for(i = 0; i < 64; i++) {
4444             ab = a1 >> 63;
4445             a1 = (a1 << 1) | (a0 >> 63);
4446             if (ab || a1 >= b) {
4447                 a1 -= b;
4448                 qb = 1;
4449             } else {
4450                 qb = 0;
4451             }
4452             a0 = (a0 << 1) | qb;
4453         }
4454 #if defined(DEBUG_MULDIV)
4455         printf("div: 0x%016" PRIx64 "%016" PRIx64 " / 0x%016" PRIx64 ": q=0x%016" PRIx64 " r=0x%016" PRIx64 "\n",
4456                *phigh, *plow, b, a0, a1);
4457 #endif
4458         *plow = a0;
4459         *phigh = a1;
4460     }
4461     return 0;
4462 }
4463
4464 /* return TRUE if overflow */
4465 static int idiv64(uint64_t *plow, uint64_t *phigh, int64_t b)
4466 {
4467     int sa, sb;
4468     sa = ((int64_t)*phigh < 0);
4469     if (sa)
4470         neg128(plow, phigh);
4471     sb = (b < 0);
4472     if (sb)
4473         b = -b;
4474     if (div64(plow, phigh, b) != 0)
4475         return 1;
4476     if (sa ^ sb) {
4477         if (*plow > (1ULL << 63))
4478             return 1;
4479         *plow = - *plow;
4480     } else {
4481         if (*plow >= (1ULL << 63))
4482             return 1;
4483     }
4484     if (sa)
4485         *phigh = - *phigh;
4486     return 0;
4487 }
4488
4489 void helper_mulq_EAX_T0(target_ulong t0)
4490 {
4491     uint64_t r0, r1;
4492
4493     mulu64(&r0, &r1, EAX, t0);
4494     EAX = r0;
4495     EDX = r1;
4496     CC_DST = r0;
4497     CC_SRC = r1;
4498 }
4499
4500 void helper_imulq_EAX_T0(target_ulong t0)
4501 {
4502     uint64_t r0, r1;
4503
4504     muls64(&r0, &r1, EAX, t0);
4505     EAX = r0;
4506     EDX = r1;
4507     CC_DST = r0;
4508     CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
4509 }
4510
4511 target_ulong helper_imulq_T0_T1(target_ulong t0, target_ulong t1)
4512 {
4513     uint64_t r0, r1;
4514
4515     muls64(&r0, &r1, t0, t1);
4516     CC_DST = r0;
4517     CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
4518     return r0;
4519 }
4520
4521 void helper_divq_EAX(target_ulong t0)
4522 {
4523     uint64_t r0, r1;
4524     if (t0 == 0) {
4525         raise_exception(EXCP00_DIVZ);
4526     }
4527     r0 = EAX;
4528     r1 = EDX;
4529     if (div64(&r0, &r1, t0))
4530         raise_exception(EXCP00_DIVZ);
4531     EAX = r0;
4532     EDX = r1;
4533 }
4534
4535 void helper_idivq_EAX(target_ulong t0)
4536 {
4537     uint64_t r0, r1;
4538     if (t0 == 0) {
4539         raise_exception(EXCP00_DIVZ);
4540     }
4541     r0 = EAX;
4542     r1 = EDX;
4543     if (idiv64(&r0, &r1, t0))
4544         raise_exception(EXCP00_DIVZ);
4545     EAX = r0;
4546     EDX = r1;
4547 }
4548 #endif
4549
4550 void helper_hlt(void)
4551 {
4552     env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
4553     env->hflags |= HF_HALTED_MASK;
4554     env->exception_index = EXCP_HLT;
4555     cpu_loop_exit();
4556 }
4557
4558 void helper_monitor(target_ulong ptr)
4559 {
4560     if ((uint32_t)ECX != 0)
4561         raise_exception(EXCP0D_GPF);
4562     /* XXX: store address ? */
4563 }
4564
4565 void helper_mwait(void)
4566 {
4567     if ((uint32_t)ECX != 0)
4568         raise_exception(EXCP0D_GPF);
4569     /* XXX: not complete but not completely erroneous */
4570     if (env->cpu_index != 0 || env->next_cpu != NULL) {
4571         /* more than one CPU: do not sleep because another CPU may
4572            wake this one */
4573     } else {
4574         helper_hlt();
4575     }
4576 }
4577
4578 void helper_debug(void)
4579 {
4580     env->exception_index = EXCP_DEBUG;
4581     cpu_loop_exit();
4582 }
4583
4584 void helper_raise_interrupt(int intno, int next_eip_addend)
4585 {
4586     raise_interrupt(intno, 1, 0, next_eip_addend);
4587 }
4588
4589 void helper_raise_exception(int exception_index)
4590 {
4591     raise_exception(exception_index);
4592 }
4593
4594 void helper_cli(void)
4595 {
4596     env->eflags &= ~IF_MASK;
4597 }
4598
4599 void helper_sti(void)
4600 {
4601     env->eflags |= IF_MASK;
4602 }
4603
4604 #if 0
4605 /* vm86plus instructions */
4606 void helper_cli_vm(void)
4607 {
4608     env->eflags &= ~VIF_MASK;
4609 }
4610
4611 void helper_sti_vm(void)
4612 {
4613     env->eflags |= VIF_MASK;
4614     if (env->eflags & VIP_MASK) {
4615         raise_exception(EXCP0D_GPF);
4616     }
4617 }
4618 #endif
4619
4620 void helper_set_inhibit_irq(void)
4621 {
4622     env->hflags |= HF_INHIBIT_IRQ_MASK;
4623 }
4624
4625 void helper_reset_inhibit_irq(void)
4626 {
4627     env->hflags &= ~HF_INHIBIT_IRQ_MASK;
4628 }
4629
4630 void helper_boundw(target_ulong a0, int v)
4631 {
4632     int low, high;
4633     low = ldsw(a0);
4634     high = ldsw(a0 + 2);
4635     v = (int16_t)v;
4636     if (v < low || v > high) {
4637         raise_exception(EXCP05_BOUND);
4638     }
4639     FORCE_RET();
4640 }
4641
4642 void helper_boundl(target_ulong a0, int v)
4643 {
4644     int low, high;
4645     low = ldl(a0);
4646     high = ldl(a0 + 4);
4647     if (v < low || v > high) {
4648         raise_exception(EXCP05_BOUND);
4649     }
4650     FORCE_RET();
4651 }
4652
4653 static float approx_rsqrt(float a)
4654 {
4655     return 1.0 / sqrt(a);
4656 }
4657
4658 static float approx_rcp(float a)
4659 {
4660     return 1.0 / a;
4661 }
4662
4663 #if !defined(CONFIG_USER_ONLY)
4664
4665 #define MMUSUFFIX _mmu
4666
4667 #define SHIFT 0
4668 #include "softmmu_template.h"
4669
4670 #define SHIFT 1
4671 #include "softmmu_template.h"
4672
4673 #define SHIFT 2
4674 #include "softmmu_template.h"
4675
4676 #define SHIFT 3
4677 #include "softmmu_template.h"
4678
4679 #endif
4680
4681 /* try to fill the TLB and return an exception if error. If retaddr is
4682    NULL, it means that the function was called in C code (i.e. not
4683    from generated code or from helper.c) */
4684 /* XXX: fix it to restore all registers */
4685 void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
4686 {
4687     TranslationBlock *tb;
4688     int ret;
4689     unsigned long pc;
4690     CPUX86State *saved_env;
4691
4692     /* XXX: hack to restore env in all cases, even if not called from
4693        generated code */
4694     saved_env = env;
4695     env = cpu_single_env;
4696
4697     ret = cpu_x86_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
4698     if (ret) {
4699         if (retaddr) {
4700             /* now we have a real cpu fault */
4701             pc = (unsigned long)retaddr;
4702             tb = tb_find_pc(pc);
4703             if (tb) {
4704                 /* the PC is inside the translated code. It means that we have
4705                    a virtual CPU fault */
4706                 cpu_restore_state(tb, env, pc, NULL);
4707             }
4708         }
4709         if (retaddr)
4710             raise_exception_err(env->exception_index, env->error_code);
4711         else
4712             raise_exception_err_norestore(env->exception_index, env->error_code);
4713     }
4714     env = saved_env;
4715 }
4716
4717
4718 /* Secure Virtual Machine helpers */
4719
4720 void helper_stgi(void)
4721 {
4722     env->hflags |= HF_GIF_MASK;
4723 }
4724
4725 void helper_clgi(void)
4726 {
4727     env->hflags &= ~HF_GIF_MASK;
4728 }
4729
4730 #if defined(CONFIG_USER_ONLY)
4731
4732 void helper_vmrun(void) 
4733
4734 }
4735 void helper_vmmcall(void) 
4736
4737 }
4738 void helper_vmload(void) 
4739
4740 }
4741 void helper_vmsave(void) 
4742
4743 }
4744 void helper_skinit(void) 
4745
4746 }
4747 void helper_invlpga(void) 
4748
4749 }
4750 void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) 
4751
4752 }
4753 void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
4754 {
4755 }
4756
4757 void helper_svm_check_io(uint32_t port, uint32_t param, 
4758                          uint32_t next_eip_addend)
4759 {
4760 }
4761 #else
4762
4763 static inline uint32_t
4764 vmcb2cpu_attrib(uint16_t vmcb_attrib, uint32_t vmcb_base, uint32_t vmcb_limit)
4765 {
4766     return    ((vmcb_attrib & 0x00ff) << 8)          /* Type, S, DPL, P */
4767             | ((vmcb_attrib & 0x0f00) << 12)         /* AVL, L, DB, G */
4768             | ((vmcb_base >> 16) & 0xff)             /* Base 23-16 */
4769             | (vmcb_base & 0xff000000)               /* Base 31-24 */
4770             | (vmcb_limit & 0xf0000);                /* Limit 19-16 */
4771 }
4772
4773 static inline uint16_t cpu2vmcb_attrib(uint32_t cpu_attrib)
4774 {
4775     return    ((cpu_attrib >> 8) & 0xff)             /* Type, S, DPL, P */
4776             | ((cpu_attrib & 0xf00000) >> 12);       /* AVL, L, DB, G */
4777 }
4778
4779 void helper_vmrun(void)
4780 {
4781     target_ulong addr;
4782     uint32_t event_inj;
4783     uint32_t int_ctl;
4784
4785     addr = EAX;
4786     if (loglevel & CPU_LOG_TB_IN_ASM)
4787         fprintf(logfile,"vmrun! " TARGET_FMT_lx "\n", addr);
4788
4789     env->vm_vmcb = addr;
4790
4791     /* save the current CPU state in the hsave page */
4792     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
4793     stl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
4794
4795     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base), env->idt.base);
4796     stl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
4797
4798     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0), env->cr[0]);
4799     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr2), env->cr[2]);
4800     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3), env->cr[3]);
4801     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4), env->cr[4]);
4802     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr8), env->cr[8]);
4803     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6), env->dr[6]);
4804     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7), env->dr[7]);
4805
4806     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer), env->efer);
4807     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags), compute_eflags());
4808
4809     SVM_SAVE_SEG(env->vm_hsave, segs[R_ES], es);
4810     SVM_SAVE_SEG(env->vm_hsave, segs[R_CS], cs);
4811     SVM_SAVE_SEG(env->vm_hsave, segs[R_SS], ss);
4812     SVM_SAVE_SEG(env->vm_hsave, segs[R_DS], ds);
4813
4814     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip), EIP);
4815     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp), ESP);
4816     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax), EAX);
4817
4818     /* load the interception bitmaps so we do not need to access the
4819        vmcb in svm mode */
4820     /* We shift all the intercept bits so we can OR them with the TB
4821        flags later on */
4822     env->intercept            = (ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept)) << INTERCEPT_INTR) | INTERCEPT_SVM_MASK;
4823     env->intercept_cr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_read));
4824     env->intercept_cr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_write));
4825     env->intercept_dr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_read));
4826     env->intercept_dr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_write));
4827     env->intercept_exceptions = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_exceptions));
4828
4829     env->gdt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base));
4830     env->gdt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit));
4831
4832     env->idt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base));
4833     env->idt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit));
4834
4835     /* clear exit_info_2 so we behave like the real hardware */
4836     stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 0);
4837
4838     cpu_x86_update_cr0(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0)));
4839     cpu_x86_update_cr4(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4)));
4840     cpu_x86_update_cr3(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3)));
4841     env->cr[2] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2));
4842     int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
4843     if (int_ctl & V_INTR_MASKING_MASK) {
4844         env->cr[8] = int_ctl & V_TPR_MASK;
4845         cpu_set_apic_tpr(env, env->cr[8]);
4846         if (env->eflags & IF_MASK)
4847             env->hflags |= HF_HIF_MASK;
4848     }
4849
4850 #ifdef TARGET_X86_64
4851     env->efer = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer));
4852     env->hflags &= ~HF_LMA_MASK;
4853     if (env->efer & MSR_EFER_LMA)
4854        env->hflags |= HF_LMA_MASK;
4855 #endif
4856     env->eflags = 0;
4857     load_eflags(ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags)),
4858                 ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
4859     CC_OP = CC_OP_EFLAGS;
4860     CC_DST = 0xffffffff;
4861
4862     SVM_LOAD_SEG(env->vm_vmcb, ES, es);
4863     SVM_LOAD_SEG(env->vm_vmcb, CS, cs);
4864     SVM_LOAD_SEG(env->vm_vmcb, SS, ss);
4865     SVM_LOAD_SEG(env->vm_vmcb, DS, ds);
4866
4867     EIP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip));
4868     env->eip = EIP;
4869     ESP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp));
4870     EAX = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax));
4871     env->dr[7] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7));
4872     env->dr[6] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6));
4873     cpu_x86_set_cpl(env, ldub_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl)));
4874
4875     /* FIXME: guest state consistency checks */
4876
4877     switch(ldub_phys(env->vm_vmcb + offsetof(struct vmcb, control.tlb_ctl))) {
4878         case TLB_CONTROL_DO_NOTHING:
4879             break;
4880         case TLB_CONTROL_FLUSH_ALL_ASID:
4881             /* FIXME: this is not 100% correct but should work for now */
4882             tlb_flush(env, 1);
4883         break;
4884     }
4885
4886     helper_stgi();
4887
4888     /* maybe we need to inject an event */
4889     event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj));
4890     if (event_inj & SVM_EVTINJ_VALID) {
4891         uint8_t vector = event_inj & SVM_EVTINJ_VEC_MASK;
4892         uint16_t valid_err = event_inj & SVM_EVTINJ_VALID_ERR;
4893         uint32_t event_inj_err = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err));
4894         stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj & ~SVM_EVTINJ_VALID);
4895
4896         if (loglevel & CPU_LOG_TB_IN_ASM)
4897             fprintf(logfile, "Injecting(%#hx): ", valid_err);
4898         /* FIXME: need to implement valid_err */
4899         switch (event_inj & SVM_EVTINJ_TYPE_MASK) {
4900         case SVM_EVTINJ_TYPE_INTR:
4901                 env->exception_index = vector;
4902                 env->error_code = event_inj_err;
4903                 env->exception_is_int = 0;
4904                 env->exception_next_eip = -1;
4905                 if (loglevel & CPU_LOG_TB_IN_ASM)
4906                     fprintf(logfile, "INTR");
4907                 break;
4908         case SVM_EVTINJ_TYPE_NMI:
4909                 env->exception_index = vector;
4910                 env->error_code = event_inj_err;
4911                 env->exception_is_int = 0;
4912                 env->exception_next_eip = EIP;
4913                 if (loglevel & CPU_LOG_TB_IN_ASM)
4914                     fprintf(logfile, "NMI");
4915                 break;
4916         case SVM_EVTINJ_TYPE_EXEPT:
4917                 env->exception_index = vector;
4918                 env->error_code = event_inj_err;
4919                 env->exception_is_int = 0;
4920                 env->exception_next_eip = -1;
4921                 if (loglevel & CPU_LOG_TB_IN_ASM)
4922                     fprintf(logfile, "EXEPT");
4923                 break;
4924         case SVM_EVTINJ_TYPE_SOFT:
4925                 env->exception_index = vector;
4926                 env->error_code = event_inj_err;
4927                 env->exception_is_int = 1;
4928                 env->exception_next_eip = EIP;
4929                 if (loglevel & CPU_LOG_TB_IN_ASM)
4930                     fprintf(logfile, "SOFT");
4931                 break;
4932         }
4933         if (loglevel & CPU_LOG_TB_IN_ASM)
4934             fprintf(logfile, " %#x %#x\n", env->exception_index, env->error_code);
4935     }
4936     if ((int_ctl & V_IRQ_MASK) || (env->intercept & INTERCEPT_VINTR)) {
4937         env->interrupt_request |= CPU_INTERRUPT_VIRQ;
4938     }
4939
4940     cpu_loop_exit();
4941 }
4942
4943 void helper_vmmcall(void)
4944 {
4945     if (loglevel & CPU_LOG_TB_IN_ASM)
4946         fprintf(logfile,"vmmcall!\n");
4947 }
4948
4949 void helper_vmload(void)
4950 {
4951     target_ulong addr;
4952     addr = EAX;
4953     if (loglevel & CPU_LOG_TB_IN_ASM)
4954         fprintf(logfile,"vmload! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
4955                 addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
4956                 env->segs[R_FS].base);
4957
4958     SVM_LOAD_SEG2(addr, segs[R_FS], fs);
4959     SVM_LOAD_SEG2(addr, segs[R_GS], gs);
4960     SVM_LOAD_SEG2(addr, tr, tr);
4961     SVM_LOAD_SEG2(addr, ldt, ldtr);
4962
4963 #ifdef TARGET_X86_64
4964     env->kernelgsbase = ldq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base));
4965     env->lstar = ldq_phys(addr + offsetof(struct vmcb, save.lstar));
4966     env->cstar = ldq_phys(addr + offsetof(struct vmcb, save.cstar));
4967     env->fmask = ldq_phys(addr + offsetof(struct vmcb, save.sfmask));
4968 #endif
4969     env->star = ldq_phys(addr + offsetof(struct vmcb, save.star));
4970     env->sysenter_cs = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_cs));
4971     env->sysenter_esp = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_esp));
4972     env->sysenter_eip = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_eip));
4973 }
4974
4975 void helper_vmsave(void)
4976 {
4977     target_ulong addr;
4978     addr = EAX;
4979     if (loglevel & CPU_LOG_TB_IN_ASM)
4980         fprintf(logfile,"vmsave! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
4981                 addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
4982                 env->segs[R_FS].base);
4983
4984     SVM_SAVE_SEG(addr, segs[R_FS], fs);
4985     SVM_SAVE_SEG(addr, segs[R_GS], gs);
4986     SVM_SAVE_SEG(addr, tr, tr);
4987     SVM_SAVE_SEG(addr, ldt, ldtr);
4988
4989 #ifdef TARGET_X86_64
4990     stq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base), env->kernelgsbase);
4991     stq_phys(addr + offsetof(struct vmcb, save.lstar), env->lstar);
4992     stq_phys(addr + offsetof(struct vmcb, save.cstar), env->cstar);
4993     stq_phys(addr + offsetof(struct vmcb, save.sfmask), env->fmask);
4994 #endif
4995     stq_phys(addr + offsetof(struct vmcb, save.star), env->star);
4996     stq_phys(addr + offsetof(struct vmcb, save.sysenter_cs), env->sysenter_cs);
4997     stq_phys(addr + offsetof(struct vmcb, save.sysenter_esp), env->sysenter_esp);
4998     stq_phys(addr + offsetof(struct vmcb, save.sysenter_eip), env->sysenter_eip);
4999 }
5000
5001 void helper_skinit(void)
5002 {
5003     if (loglevel & CPU_LOG_TB_IN_ASM)
5004         fprintf(logfile,"skinit!\n");
5005 }
5006
5007 void helper_invlpga(void)
5008 {
5009     tlb_flush(env, 0);
5010 }
5011
5012 void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
5013 {
5014     switch(type) {
5015     case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR0 + 8:
5016         if (INTERCEPTEDw(_cr_read, (1 << (type - SVM_EXIT_READ_CR0)))) {
5017             helper_vmexit(type, param);
5018         }
5019         break;
5020     case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR0 + 8:
5021         if (INTERCEPTEDw(_dr_read, (1 << (type - SVM_EXIT_READ_DR0)))) {
5022             helper_vmexit(type, param);
5023         }
5024         break;
5025     case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR0 + 8:
5026         if (INTERCEPTEDw(_cr_write, (1 << (type - SVM_EXIT_WRITE_CR0)))) {
5027             helper_vmexit(type, param);
5028         }
5029         break;
5030     case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR0 + 8:
5031         if (INTERCEPTEDw(_dr_write, (1 << (type - SVM_EXIT_WRITE_DR0)))) {
5032             helper_vmexit(type, param);
5033         }
5034         break;
5035     case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 16:
5036         if (INTERCEPTEDl(_exceptions, (1 << (type - SVM_EXIT_EXCP_BASE)))) {
5037             helper_vmexit(type, param);
5038         }
5039         break;
5040     case SVM_EXIT_IOIO:
5041         break;
5042
5043     case SVM_EXIT_MSR:
5044         if (INTERCEPTED(1ULL << INTERCEPT_MSR_PROT)) {
5045             /* FIXME: this should be read in at vmrun (faster this way?) */
5046             uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.msrpm_base_pa));
5047             uint32_t t0, t1;
5048             switch((uint32_t)ECX) {
5049             case 0 ... 0x1fff:
5050                 t0 = (ECX * 2) % 8;
5051                 t1 = ECX / 8;
5052                 break;
5053             case 0xc0000000 ... 0xc0001fff:
5054                 t0 = (8192 + ECX - 0xc0000000) * 2;
5055                 t1 = (t0 / 8);
5056                 t0 %= 8;
5057                 break;
5058             case 0xc0010000 ... 0xc0011fff:
5059                 t0 = (16384 + ECX - 0xc0010000) * 2;
5060                 t1 = (t0 / 8);
5061                 t0 %= 8;
5062                 break;
5063             default:
5064                 helper_vmexit(type, param);
5065                 t0 = 0;
5066                 t1 = 0;
5067                 break;
5068             }
5069             if (ldub_phys(addr + t1) & ((1 << param) << t0))
5070                 helper_vmexit(type, param);
5071         }
5072         break;
5073     default:
5074         if (INTERCEPTED((1ULL << ((type - SVM_EXIT_INTR) + INTERCEPT_INTR)))) {
5075             helper_vmexit(type, param);
5076         }
5077         break;
5078     }
5079 }
5080
5081 void helper_svm_check_io(uint32_t port, uint32_t param, 
5082                          uint32_t next_eip_addend)
5083 {
5084     if (INTERCEPTED(1ULL << INTERCEPT_IOIO_PROT)) {
5085         /* FIXME: this should be read in at vmrun (faster this way?) */
5086         uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.iopm_base_pa));
5087         uint16_t mask = (1 << ((param >> 4) & 7)) - 1;
5088         if(lduw_phys(addr + port / 8) & (mask << (port & 7))) {
5089             /* next EIP */
5090             stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 
5091                      env->eip + next_eip_addend);
5092             helper_vmexit(SVM_EXIT_IOIO, param | (port << 16));
5093         }
5094     }
5095 }
5096
5097 /* Note: currently only 32 bits of exit_code are used */
5098 void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1)
5099 {
5100     uint32_t int_ctl;
5101
5102     if (loglevel & CPU_LOG_TB_IN_ASM)
5103         fprintf(logfile,"vmexit(%08x, %016" PRIx64 ", %016" PRIx64 ", " TARGET_FMT_lx ")!\n",
5104                 exit_code, exit_info_1,
5105                 ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2)),
5106                 EIP);
5107
5108     if(env->hflags & HF_INHIBIT_IRQ_MASK) {
5109         stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), SVM_INTERRUPT_SHADOW_MASK);
5110         env->hflags &= ~HF_INHIBIT_IRQ_MASK;
5111     } else {
5112         stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), 0);
5113     }
5114
5115     /* Save the VM state in the vmcb */
5116     SVM_SAVE_SEG(env->vm_vmcb, segs[R_ES], es);
5117     SVM_SAVE_SEG(env->vm_vmcb, segs[R_CS], cs);
5118     SVM_SAVE_SEG(env->vm_vmcb, segs[R_SS], ss);
5119     SVM_SAVE_SEG(env->vm_vmcb, segs[R_DS], ds);
5120
5121     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
5122     stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
5123
5124     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base), env->idt.base);
5125     stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
5126
5127     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer), env->efer);
5128     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0), env->cr[0]);
5129     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2), env->cr[2]);
5130     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3), env->cr[3]);
5131     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4), env->cr[4]);
5132
5133     if ((int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl))) & V_INTR_MASKING_MASK) {
5134         int_ctl &= ~V_TPR_MASK;
5135         int_ctl |= env->cr[8] & V_TPR_MASK;
5136         stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), int_ctl);
5137     }
5138
5139     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags), compute_eflags());
5140     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip), env->eip);
5141     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp), ESP);
5142     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax), EAX);
5143     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7), env->dr[7]);
5144     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6), env->dr[6]);
5145     stb_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl), env->hflags & HF_CPL_MASK);
5146
5147     /* Reload the host state from vm_hsave */
5148     env->hflags &= ~HF_HIF_MASK;
5149     env->intercept = 0;
5150     env->intercept_exceptions = 0;
5151     env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
5152
5153     env->gdt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base));
5154     env->gdt.limit = ldl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit));
5155
5156     env->idt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base));
5157     env->idt.limit = ldl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit));
5158
5159     cpu_x86_update_cr0(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0)) | CR0_PE_MASK);
5160     cpu_x86_update_cr4(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4)));
5161     cpu_x86_update_cr3(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3)));
5162     if (int_ctl & V_INTR_MASKING_MASK) {
5163         env->cr[8] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr8));
5164         cpu_set_apic_tpr(env, env->cr[8]);
5165     }
5166     /* we need to set the efer after the crs so the hidden flags get set properly */
5167 #ifdef TARGET_X86_64
5168     env->efer  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer));
5169     env->hflags &= ~HF_LMA_MASK;
5170     if (env->efer & MSR_EFER_LMA)
5171        env->hflags |= HF_LMA_MASK;
5172 #endif
5173
5174     env->eflags = 0;
5175     load_eflags(ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags)),
5176                 ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
5177     CC_OP = CC_OP_EFLAGS;
5178
5179     SVM_LOAD_SEG(env->vm_hsave, ES, es);
5180     SVM_LOAD_SEG(env->vm_hsave, CS, cs);
5181     SVM_LOAD_SEG(env->vm_hsave, SS, ss);
5182     SVM_LOAD_SEG(env->vm_hsave, DS, ds);
5183
5184     EIP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip));
5185     ESP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp));
5186     EAX = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax));
5187
5188     env->dr[6] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6));
5189     env->dr[7] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7));
5190
5191     /* other setups */
5192     cpu_x86_set_cpl(env, 0);
5193     stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code), exit_code);
5194     stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_1), exit_info_1);
5195
5196     helper_clgi();
5197     /* FIXME: Resets the current ASID register to zero (host ASID). */
5198
5199     /* Clears the V_IRQ and V_INTR_MASKING bits inside the processor. */
5200
5201     /* Clears the TSC_OFFSET inside the processor. */
5202
5203     /* If the host is in PAE mode, the processor reloads the host's PDPEs
5204        from the page table indicated the host's CR3. If the PDPEs contain
5205        illegal state, the processor causes a shutdown. */
5206
5207     /* Forces CR0.PE = 1, RFLAGS.VM = 0. */
5208     env->cr[0] |= CR0_PE_MASK;
5209     env->eflags &= ~VM_MASK;
5210
5211     /* Disables all breakpoints in the host DR7 register. */
5212
5213     /* Checks the reloaded host state for consistency. */
5214
5215     /* If the host's rIP reloaded by #VMEXIT is outside the limit of the
5216        host's code segment or non-canonical (in the case of long mode), a
5217        #GP fault is delivered inside the host.) */
5218
5219     /* remove any pending exception */
5220     env->exception_index = -1;
5221     env->error_code = 0;
5222     env->old_exception = -1;
5223
5224     cpu_loop_exit();
5225 }
5226
5227 #endif
5228
5229 /* MMX/SSE */
5230 /* XXX: optimize by storing fptt and fptags in the static cpu state */
5231 void helper_enter_mmx(void)
5232 {
5233     env->fpstt = 0;
5234     *(uint32_t *)(env->fptags) = 0;
5235     *(uint32_t *)(env->fptags + 4) = 0;
5236 }
5237
5238 void helper_emms(void)
5239 {
5240     /* set to empty state */
5241     *(uint32_t *)(env->fptags) = 0x01010101;
5242     *(uint32_t *)(env->fptags + 4) = 0x01010101;
5243 }
5244
5245 /* XXX: suppress */
5246 void helper_movq(uint64_t *d, uint64_t *s)
5247 {
5248     *d = *s;
5249 }
5250
5251 #define SHIFT 0
5252 #include "ops_sse.h"
5253
5254 #define SHIFT 1
5255 #include "ops_sse.h"
5256
5257 #define SHIFT 0
5258 #include "helper_template.h"
5259 #undef SHIFT
5260
5261 #define SHIFT 1
5262 #include "helper_template.h"
5263 #undef SHIFT
5264
5265 #define SHIFT 2
5266 #include "helper_template.h"
5267 #undef SHIFT
5268
5269 #ifdef TARGET_X86_64
5270
5271 #define SHIFT 3
5272 #include "helper_template.h"
5273 #undef SHIFT
5274
5275 #endif
5276
5277 /* bit operations */
5278 target_ulong helper_bsf(target_ulong t0)
5279 {
5280     int count;
5281     target_ulong res;
5282
5283     res = t0;
5284     count = 0;
5285     while ((res & 1) == 0) {
5286         count++;
5287         res >>= 1;
5288     }
5289     return count;
5290 }
5291
5292 target_ulong helper_bsr(target_ulong t0)
5293 {
5294     int count;
5295     target_ulong res, mask;
5296     
5297     res = t0;
5298     count = TARGET_LONG_BITS - 1;
5299     mask = (target_ulong)1 << (TARGET_LONG_BITS - 1);
5300     while ((res & mask) == 0) {
5301         count--;
5302         res <<= 1;
5303     }
5304     return count;
5305 }
5306
5307
5308 static int compute_all_eflags(void)
5309 {
5310     return CC_SRC;
5311 }
5312
5313 static int compute_c_eflags(void)
5314 {
5315     return CC_SRC & CC_C;
5316 }
5317
5318 CCTable cc_table[CC_OP_NB] = {
5319     [CC_OP_DYNAMIC] = { /* should never happen */ },
5320
5321     [CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags },
5322
5323     [CC_OP_MULB] = { compute_all_mulb, compute_c_mull },
5324     [CC_OP_MULW] = { compute_all_mulw, compute_c_mull },
5325     [CC_OP_MULL] = { compute_all_mull, compute_c_mull },
5326
5327     [CC_OP_ADDB] = { compute_all_addb, compute_c_addb },
5328     [CC_OP_ADDW] = { compute_all_addw, compute_c_addw  },
5329     [CC_OP_ADDL] = { compute_all_addl, compute_c_addl  },
5330
5331     [CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb },
5332     [CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw  },
5333     [CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl  },
5334
5335     [CC_OP_SUBB] = { compute_all_subb, compute_c_subb  },
5336     [CC_OP_SUBW] = { compute_all_subw, compute_c_subw  },
5337     [CC_OP_SUBL] = { compute_all_subl, compute_c_subl  },
5338
5339     [CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb  },
5340     [CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw  },
5341     [CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl  },
5342
5343     [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb },
5344     [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw },
5345     [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl },
5346
5347     [CC_OP_INCB] = { compute_all_incb, compute_c_incl },
5348     [CC_OP_INCW] = { compute_all_incw, compute_c_incl },
5349     [CC_OP_INCL] = { compute_all_incl, compute_c_incl },
5350
5351     [CC_OP_DECB] = { compute_all_decb, compute_c_incl },
5352     [CC_OP_DECW] = { compute_all_decw, compute_c_incl },
5353     [CC_OP_DECL] = { compute_all_decl, compute_c_incl },
5354
5355     [CC_OP_SHLB] = { compute_all_shlb, compute_c_shlb },
5356     [CC_OP_SHLW] = { compute_all_shlw, compute_c_shlw },
5357     [CC_OP_SHLL] = { compute_all_shll, compute_c_shll },
5358
5359     [CC_OP_SARB] = { compute_all_sarb, compute_c_sarl },
5360     [CC_OP_SARW] = { compute_all_sarw, compute_c_sarl },
5361     [CC_OP_SARL] = { compute_all_sarl, compute_c_sarl },
5362
5363 #ifdef TARGET_X86_64
5364     [CC_OP_MULQ] = { compute_all_mulq, compute_c_mull },
5365
5366     [CC_OP_ADDQ] = { compute_all_addq, compute_c_addq  },
5367
5368     [CC_OP_ADCQ] = { compute_all_adcq, compute_c_adcq  },
5369
5370     [CC_OP_SUBQ] = { compute_all_subq, compute_c_subq  },
5371
5372     [CC_OP_SBBQ] = { compute_all_sbbq, compute_c_sbbq  },
5373
5374     [CC_OP_LOGICQ] = { compute_all_logicq, compute_c_logicq },
5375
5376     [CC_OP_INCQ] = { compute_all_incq, compute_c_incl },
5377
5378     [CC_OP_DECQ] = { compute_all_decq, compute_c_incl },
5379
5380     [CC_OP_SHLQ] = { compute_all_shlq, compute_c_shlq },
5381
5382     [CC_OP_SARQ] = { compute_all_sarq, compute_c_sarl },
5383 #endif
5384 };
5385