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