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