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