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