moved halted field to CPU_COMMON
[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 privledge 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 privledge 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 privledge 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     env->efer = 0;
1439     env->hflags &= ~HF_LMA_MASK;
1440 #endif
1441     load_eflags(0, ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1442     env->eip = 0x00008000;
1443     cpu_x86_load_seg_cache(env, R_CS, (env->smbase >> 4) & 0xffff, env->smbase,
1444                            0xffffffff, 0);
1445     cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffffffff, 0);
1446     cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffffffff, 0);
1447     cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffffffff, 0);
1448     cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffffffff, 0);
1449     cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffffffff, 0);
1450
1451     cpu_x86_update_cr0(env,
1452                        env->cr[0] & ~(CR0_PE_MASK | CR0_EM_MASK | CR0_TS_MASK | CR0_PG_MASK));
1453     cpu_x86_update_cr4(env, 0);
1454     env->dr[7] = 0x00000400;
1455     CC_OP = CC_OP_EFLAGS;
1456 }
1457
1458 void helper_rsm(void)
1459 {
1460     target_ulong sm_state;
1461     int i, offset;
1462     uint32_t val;
1463
1464     sm_state = env->smbase + 0x8000;
1465 #ifdef TARGET_X86_64
1466     env->efer = ldq_phys(sm_state + 0x7ed0);
1467     if (env->efer & MSR_EFER_LMA)
1468         env->hflags |= HF_LMA_MASK;
1469     else
1470         env->hflags &= ~HF_LMA_MASK;
1471
1472     for(i = 0; i < 6; i++) {
1473         offset = 0x7e00 + i * 16;
1474         cpu_x86_load_seg_cache(env, i,
1475                                lduw_phys(sm_state + offset),
1476                                ldq_phys(sm_state + offset + 8),
1477                                ldl_phys(sm_state + offset + 4),
1478                                (lduw_phys(sm_state + offset + 2) & 0xf0ff) << 8);
1479     }
1480
1481     env->gdt.base = ldq_phys(sm_state + 0x7e68);
1482     env->gdt.limit = ldl_phys(sm_state + 0x7e64);
1483
1484     env->ldt.selector = lduw_phys(sm_state + 0x7e70);
1485     env->ldt.base = ldq_phys(sm_state + 0x7e78);
1486     env->ldt.limit = ldl_phys(sm_state + 0x7e74);
1487     env->ldt.flags = (lduw_phys(sm_state + 0x7e72) & 0xf0ff) << 8;
1488
1489     env->idt.base = ldq_phys(sm_state + 0x7e88);
1490     env->idt.limit = ldl_phys(sm_state + 0x7e84);
1491
1492     env->tr.selector = lduw_phys(sm_state + 0x7e90);
1493     env->tr.base = ldq_phys(sm_state + 0x7e98);
1494     env->tr.limit = ldl_phys(sm_state + 0x7e94);
1495     env->tr.flags = (lduw_phys(sm_state + 0x7e92) & 0xf0ff) << 8;
1496
1497     EAX = ldq_phys(sm_state + 0x7ff8);
1498     ECX = ldq_phys(sm_state + 0x7ff0);
1499     EDX = ldq_phys(sm_state + 0x7fe8);
1500     EBX = ldq_phys(sm_state + 0x7fe0);
1501     ESP = ldq_phys(sm_state + 0x7fd8);
1502     EBP = ldq_phys(sm_state + 0x7fd0);
1503     ESI = ldq_phys(sm_state + 0x7fc8);
1504     EDI = ldq_phys(sm_state + 0x7fc0);
1505     for(i = 8; i < 16; i++)
1506         env->regs[i] = ldq_phys(sm_state + 0x7ff8 - i * 8);
1507     env->eip = ldq_phys(sm_state + 0x7f78);
1508     load_eflags(ldl_phys(sm_state + 0x7f70),
1509                 ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1510     env->dr[6] = ldl_phys(sm_state + 0x7f68);
1511     env->dr[7] = ldl_phys(sm_state + 0x7f60);
1512
1513     cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f48));
1514     cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7f50));
1515     cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7f58));
1516
1517     val = ldl_phys(sm_state + 0x7efc); /* revision ID */
1518     if (val & 0x20000) {
1519         env->smbase = ldl_phys(sm_state + 0x7f00) & ~0x7fff;
1520     }
1521 #else
1522     cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7ffc));
1523     cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7ff8));
1524     load_eflags(ldl_phys(sm_state + 0x7ff4),
1525                 ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1526     env->eip = ldl_phys(sm_state + 0x7ff0);
1527     EDI = ldl_phys(sm_state + 0x7fec);
1528     ESI = ldl_phys(sm_state + 0x7fe8);
1529     EBP = ldl_phys(sm_state + 0x7fe4);
1530     ESP = ldl_phys(sm_state + 0x7fe0);
1531     EBX = ldl_phys(sm_state + 0x7fdc);
1532     EDX = ldl_phys(sm_state + 0x7fd8);
1533     ECX = ldl_phys(sm_state + 0x7fd4);
1534     EAX = ldl_phys(sm_state + 0x7fd0);
1535     env->dr[6] = ldl_phys(sm_state + 0x7fcc);
1536     env->dr[7] = ldl_phys(sm_state + 0x7fc8);
1537
1538     env->tr.selector = ldl_phys(sm_state + 0x7fc4) & 0xffff;
1539     env->tr.base = ldl_phys(sm_state + 0x7f64);
1540     env->tr.limit = ldl_phys(sm_state + 0x7f60);
1541     env->tr.flags = (ldl_phys(sm_state + 0x7f5c) & 0xf0ff) << 8;
1542
1543     env->ldt.selector = ldl_phys(sm_state + 0x7fc0) & 0xffff;
1544     env->ldt.base = ldl_phys(sm_state + 0x7f80);
1545     env->ldt.limit = ldl_phys(sm_state + 0x7f7c);
1546     env->ldt.flags = (ldl_phys(sm_state + 0x7f78) & 0xf0ff) << 8;
1547
1548     env->gdt.base = ldl_phys(sm_state + 0x7f74);
1549     env->gdt.limit = ldl_phys(sm_state + 0x7f70);
1550
1551     env->idt.base = ldl_phys(sm_state + 0x7f58);
1552     env->idt.limit = ldl_phys(sm_state + 0x7f54);
1553
1554     for(i = 0; i < 6; i++) {
1555         if (i < 3)
1556             offset = 0x7f84 + i * 12;
1557         else
1558             offset = 0x7f2c + (i - 3) * 12;
1559         cpu_x86_load_seg_cache(env, i,
1560                                ldl_phys(sm_state + 0x7fa8 + i * 4) & 0xffff,
1561                                ldl_phys(sm_state + offset + 8),
1562                                ldl_phys(sm_state + offset + 4),
1563                                (ldl_phys(sm_state + offset) & 0xf0ff) << 8);
1564     }
1565     cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f14));
1566
1567     val = ldl_phys(sm_state + 0x7efc); /* revision ID */
1568     if (val & 0x20000) {
1569         env->smbase = ldl_phys(sm_state + 0x7ef8) & ~0x7fff;
1570     }
1571 #endif
1572     CC_OP = CC_OP_EFLAGS;
1573     env->hflags &= ~HF_SMM_MASK;
1574     cpu_smm_update(env);
1575
1576     if (loglevel & CPU_LOG_INT) {
1577         fprintf(logfile, "SMM: after RSM\n");
1578         cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1579     }
1580 }
1581
1582 #endif /* !CONFIG_USER_ONLY */
1583
1584
1585 /* division, flags are undefined */
1586
1587 void helper_divb_AL(target_ulong t0)
1588 {
1589     unsigned int num, den, q, r;
1590
1591     num = (EAX & 0xffff);
1592     den = (t0 & 0xff);
1593     if (den == 0) {
1594         raise_exception(EXCP00_DIVZ);
1595     }
1596     q = (num / den);
1597     if (q > 0xff)
1598         raise_exception(EXCP00_DIVZ);
1599     q &= 0xff;
1600     r = (num % den) & 0xff;
1601     EAX = (EAX & ~0xffff) | (r << 8) | q;
1602 }
1603
1604 void helper_idivb_AL(target_ulong t0)
1605 {
1606     int num, den, q, r;
1607
1608     num = (int16_t)EAX;
1609     den = (int8_t)t0;
1610     if (den == 0) {
1611         raise_exception(EXCP00_DIVZ);
1612     }
1613     q = (num / den);
1614     if (q != (int8_t)q)
1615         raise_exception(EXCP00_DIVZ);
1616     q &= 0xff;
1617     r = (num % den) & 0xff;
1618     EAX = (EAX & ~0xffff) | (r << 8) | q;
1619 }
1620
1621 void helper_divw_AX(target_ulong t0)
1622 {
1623     unsigned int num, den, q, r;
1624
1625     num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
1626     den = (t0 & 0xffff);
1627     if (den == 0) {
1628         raise_exception(EXCP00_DIVZ);
1629     }
1630     q = (num / den);
1631     if (q > 0xffff)
1632         raise_exception(EXCP00_DIVZ);
1633     q &= 0xffff;
1634     r = (num % den) & 0xffff;
1635     EAX = (EAX & ~0xffff) | q;
1636     EDX = (EDX & ~0xffff) | r;
1637 }
1638
1639 void helper_idivw_AX(target_ulong t0)
1640 {
1641     int num, den, q, r;
1642
1643     num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
1644     den = (int16_t)t0;
1645     if (den == 0) {
1646         raise_exception(EXCP00_DIVZ);
1647     }
1648     q = (num / den);
1649     if (q != (int16_t)q)
1650         raise_exception(EXCP00_DIVZ);
1651     q &= 0xffff;
1652     r = (num % den) & 0xffff;
1653     EAX = (EAX & ~0xffff) | q;
1654     EDX = (EDX & ~0xffff) | r;
1655 }
1656
1657 void helper_divl_EAX(target_ulong t0)
1658 {
1659     unsigned int den, r;
1660     uint64_t num, q;
1661
1662     num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1663     den = t0;
1664     if (den == 0) {
1665         raise_exception(EXCP00_DIVZ);
1666     }
1667     q = (num / den);
1668     r = (num % den);
1669     if (q > 0xffffffff)
1670         raise_exception(EXCP00_DIVZ);
1671     EAX = (uint32_t)q;
1672     EDX = (uint32_t)r;
1673 }
1674
1675 void helper_idivl_EAX(target_ulong t0)
1676 {
1677     int den, r;
1678     int64_t num, q;
1679
1680     num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1681     den = t0;
1682     if (den == 0) {
1683         raise_exception(EXCP00_DIVZ);
1684     }
1685     q = (num / den);
1686     r = (num % den);
1687     if (q != (int32_t)q)
1688         raise_exception(EXCP00_DIVZ);
1689     EAX = (uint32_t)q;
1690     EDX = (uint32_t)r;
1691 }
1692
1693 /* bcd */
1694
1695 /* XXX: exception */
1696 void helper_aam(int base)
1697 {
1698     int al, ah;
1699     al = EAX & 0xff;
1700     ah = al / base;
1701     al = al % base;
1702     EAX = (EAX & ~0xffff) | al | (ah << 8);
1703     CC_DST = al;
1704 }
1705
1706 void helper_aad(int base)
1707 {
1708     int al, ah;
1709     al = EAX & 0xff;
1710     ah = (EAX >> 8) & 0xff;
1711     al = ((ah * base) + al) & 0xff;
1712     EAX = (EAX & ~0xffff) | al;
1713     CC_DST = al;
1714 }
1715
1716 void helper_aaa(void)
1717 {
1718     int icarry;
1719     int al, ah, af;
1720     int eflags;
1721
1722     eflags = cc_table[CC_OP].compute_all();
1723     af = eflags & CC_A;
1724     al = EAX & 0xff;
1725     ah = (EAX >> 8) & 0xff;
1726
1727     icarry = (al > 0xf9);
1728     if (((al & 0x0f) > 9 ) || af) {
1729         al = (al + 6) & 0x0f;
1730         ah = (ah + 1 + icarry) & 0xff;
1731         eflags |= CC_C | CC_A;
1732     } else {
1733         eflags &= ~(CC_C | CC_A);
1734         al &= 0x0f;
1735     }
1736     EAX = (EAX & ~0xffff) | al | (ah << 8);
1737     CC_SRC = eflags;
1738     FORCE_RET();
1739 }
1740
1741 void helper_aas(void)
1742 {
1743     int icarry;
1744     int al, ah, af;
1745     int eflags;
1746
1747     eflags = cc_table[CC_OP].compute_all();
1748     af = eflags & CC_A;
1749     al = EAX & 0xff;
1750     ah = (EAX >> 8) & 0xff;
1751
1752     icarry = (al < 6);
1753     if (((al & 0x0f) > 9 ) || af) {
1754         al = (al - 6) & 0x0f;
1755         ah = (ah - 1 - icarry) & 0xff;
1756         eflags |= CC_C | CC_A;
1757     } else {
1758         eflags &= ~(CC_C | CC_A);
1759         al &= 0x0f;
1760     }
1761     EAX = (EAX & ~0xffff) | al | (ah << 8);
1762     CC_SRC = eflags;
1763     FORCE_RET();
1764 }
1765
1766 void helper_daa(void)
1767 {
1768     int al, af, cf;
1769     int eflags;
1770
1771     eflags = cc_table[CC_OP].compute_all();
1772     cf = eflags & CC_C;
1773     af = eflags & CC_A;
1774     al = EAX & 0xff;
1775
1776     eflags = 0;
1777     if (((al & 0x0f) > 9 ) || af) {
1778         al = (al + 6) & 0xff;
1779         eflags |= CC_A;
1780     }
1781     if ((al > 0x9f) || cf) {
1782         al = (al + 0x60) & 0xff;
1783         eflags |= CC_C;
1784     }
1785     EAX = (EAX & ~0xff) | al;
1786     /* well, speed is not an issue here, so we compute the flags by hand */
1787     eflags |= (al == 0) << 6; /* zf */
1788     eflags |= parity_table[al]; /* pf */
1789     eflags |= (al & 0x80); /* sf */
1790     CC_SRC = eflags;
1791     FORCE_RET();
1792 }
1793
1794 void helper_das(void)
1795 {
1796     int al, al1, af, cf;
1797     int eflags;
1798
1799     eflags = cc_table[CC_OP].compute_all();
1800     cf = eflags & CC_C;
1801     af = eflags & CC_A;
1802     al = EAX & 0xff;
1803
1804     eflags = 0;
1805     al1 = al;
1806     if (((al & 0x0f) > 9 ) || af) {
1807         eflags |= CC_A;
1808         if (al < 6 || cf)
1809             eflags |= CC_C;
1810         al = (al - 6) & 0xff;
1811     }
1812     if ((al1 > 0x99) || cf) {
1813         al = (al - 0x60) & 0xff;
1814         eflags |= CC_C;
1815     }
1816     EAX = (EAX & ~0xff) | al;
1817     /* well, speed is not an issue here, so we compute the flags by hand */
1818     eflags |= (al == 0) << 6; /* zf */
1819     eflags |= parity_table[al]; /* pf */
1820     eflags |= (al & 0x80); /* sf */
1821     CC_SRC = eflags;
1822     FORCE_RET();
1823 }
1824
1825 void helper_into(int next_eip_addend)
1826 {
1827     int eflags;
1828     eflags = cc_table[CC_OP].compute_all();
1829     if (eflags & CC_O) {
1830         raise_interrupt(EXCP04_INTO, 1, 0, next_eip_addend);
1831     }
1832 }
1833
1834 void helper_cmpxchg8b(target_ulong a0)
1835 {
1836     uint64_t d;
1837     int eflags;
1838
1839     eflags = cc_table[CC_OP].compute_all();
1840     d = ldq(a0);
1841     if (d == (((uint64_t)EDX << 32) | (uint32_t)EAX)) {
1842         stq(a0, ((uint64_t)ECX << 32) | (uint32_t)EBX);
1843         eflags |= CC_Z;
1844     } else {
1845         EDX = (uint32_t)(d >> 32);
1846         EAX = (uint32_t)d;
1847         eflags &= ~CC_Z;
1848     }
1849     CC_SRC = eflags;
1850 }
1851
1852 #ifdef TARGET_X86_64
1853 void helper_cmpxchg16b(target_ulong a0)
1854 {
1855     uint64_t d0, d1;
1856     int eflags;
1857
1858     eflags = cc_table[CC_OP].compute_all();
1859     d0 = ldq(a0);
1860     d1 = ldq(a0 + 8);
1861     if (d0 == EAX && d1 == EDX) {
1862         stq(a0, EBX);
1863         stq(a0 + 8, ECX);
1864         eflags |= CC_Z;
1865     } else {
1866         EDX = d1;
1867         EAX = d0;
1868         eflags &= ~CC_Z;
1869     }
1870     CC_SRC = eflags;
1871 }
1872 #endif
1873
1874 void helper_single_step(void)
1875 {
1876     env->dr[6] |= 0x4000;
1877     raise_exception(EXCP01_SSTP);
1878 }
1879
1880 void helper_cpuid(void)
1881 {
1882     uint32_t index;
1883
1884     helper_svm_check_intercept_param(SVM_EXIT_CPUID, 0);
1885     
1886     index = (uint32_t)EAX;
1887     /* test if maximum index reached */
1888     if (index & 0x80000000) {
1889         if (index > env->cpuid_xlevel)
1890             index = env->cpuid_level;
1891     } else {
1892         if (index > env->cpuid_level)
1893             index = env->cpuid_level;
1894     }
1895
1896     switch(index) {
1897     case 0:
1898         EAX = env->cpuid_level;
1899         EBX = env->cpuid_vendor1;
1900         EDX = env->cpuid_vendor2;
1901         ECX = env->cpuid_vendor3;
1902         break;
1903     case 1:
1904         EAX = env->cpuid_version;
1905         EBX = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
1906         ECX = env->cpuid_ext_features;
1907         EDX = env->cpuid_features;
1908         break;
1909     case 2:
1910         /* cache info: needed for Pentium Pro compatibility */
1911         EAX = 1;
1912         EBX = 0;
1913         ECX = 0;
1914         EDX = 0x2c307d;
1915         break;
1916     case 0x80000000:
1917         EAX = env->cpuid_xlevel;
1918         EBX = env->cpuid_vendor1;
1919         EDX = env->cpuid_vendor2;
1920         ECX = env->cpuid_vendor3;
1921         break;
1922     case 0x80000001:
1923         EAX = env->cpuid_features;
1924         EBX = 0;
1925         ECX = env->cpuid_ext3_features;
1926         EDX = env->cpuid_ext2_features;
1927         break;
1928     case 0x80000002:
1929     case 0x80000003:
1930     case 0x80000004:
1931         EAX = env->cpuid_model[(index - 0x80000002) * 4 + 0];
1932         EBX = env->cpuid_model[(index - 0x80000002) * 4 + 1];
1933         ECX = env->cpuid_model[(index - 0x80000002) * 4 + 2];
1934         EDX = env->cpuid_model[(index - 0x80000002) * 4 + 3];
1935         break;
1936     case 0x80000005:
1937         /* cache info (L1 cache) */
1938         EAX = 0x01ff01ff;
1939         EBX = 0x01ff01ff;
1940         ECX = 0x40020140;
1941         EDX = 0x40020140;
1942         break;
1943     case 0x80000006:
1944         /* cache info (L2 cache) */
1945         EAX = 0;
1946         EBX = 0x42004200;
1947         ECX = 0x02008140;
1948         EDX = 0;
1949         break;
1950     case 0x80000008:
1951         /* virtual & phys address size in low 2 bytes. */
1952 /* XXX: This value must match the one used in the MMU code. */ 
1953 #if defined(TARGET_X86_64)
1954 #  if defined(USE_KQEMU)
1955         EAX = 0x00003020;       /* 48 bits virtual, 32 bits physical */
1956 #  else
1957 /* XXX: The physical address space is limited to 42 bits in exec.c. */
1958         EAX = 0x00003028;       /* 48 bits virtual, 40 bits physical */
1959 #  endif
1960 #else
1961 # if defined(USE_KQEMU)
1962         EAX = 0x00000020;       /* 32 bits physical */
1963 #  else
1964         EAX = 0x00000024;       /* 36 bits physical */
1965 #  endif
1966 #endif
1967         EBX = 0;
1968         ECX = 0;
1969         EDX = 0;
1970         break;
1971     case 0x8000000A:
1972         EAX = 0x00000001;
1973         EBX = 0;
1974         ECX = 0;
1975         EDX = 0;
1976         break;
1977     default:
1978         /* reserved values: zero */
1979         EAX = 0;
1980         EBX = 0;
1981         ECX = 0;
1982         EDX = 0;
1983         break;
1984     }
1985 }
1986
1987 void helper_enter_level(int level, int data32, target_ulong t1)
1988 {
1989     target_ulong ssp;
1990     uint32_t esp_mask, esp, ebp;
1991
1992     esp_mask = get_sp_mask(env->segs[R_SS].flags);
1993     ssp = env->segs[R_SS].base;
1994     ebp = EBP;
1995     esp = ESP;
1996     if (data32) {
1997         /* 32 bit */
1998         esp -= 4;
1999         while (--level) {
2000             esp -= 4;
2001             ebp -= 4;
2002             stl(ssp + (esp & esp_mask), ldl(ssp + (ebp & esp_mask)));
2003         }
2004         esp -= 4;
2005         stl(ssp + (esp & esp_mask), t1);
2006     } else {
2007         /* 16 bit */
2008         esp -= 2;
2009         while (--level) {
2010             esp -= 2;
2011             ebp -= 2;
2012             stw(ssp + (esp & esp_mask), lduw(ssp + (ebp & esp_mask)));
2013         }
2014         esp -= 2;
2015         stw(ssp + (esp & esp_mask), t1);
2016     }
2017 }
2018
2019 #ifdef TARGET_X86_64
2020 void helper_enter64_level(int level, int data64, target_ulong t1)
2021 {
2022     target_ulong esp, ebp;
2023     ebp = EBP;
2024     esp = ESP;
2025
2026     if (data64) {
2027         /* 64 bit */
2028         esp -= 8;
2029         while (--level) {
2030             esp -= 8;
2031             ebp -= 8;
2032             stq(esp, ldq(ebp));
2033         }
2034         esp -= 8;
2035         stq(esp, t1);
2036     } else {
2037         /* 16 bit */
2038         esp -= 2;
2039         while (--level) {
2040             esp -= 2;
2041             ebp -= 2;
2042             stw(esp, lduw(ebp));
2043         }
2044         esp -= 2;
2045         stw(esp, t1);
2046     }
2047 }
2048 #endif
2049
2050 void helper_lldt(int selector)
2051 {
2052     SegmentCache *dt;
2053     uint32_t e1, e2;
2054     int index, entry_limit;
2055     target_ulong ptr;
2056
2057     selector &= 0xffff;
2058     if ((selector & 0xfffc) == 0) {
2059         /* XXX: NULL selector case: invalid LDT */
2060         env->ldt.base = 0;
2061         env->ldt.limit = 0;
2062     } else {
2063         if (selector & 0x4)
2064             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2065         dt = &env->gdt;
2066         index = selector & ~7;
2067 #ifdef TARGET_X86_64
2068         if (env->hflags & HF_LMA_MASK)
2069             entry_limit = 15;
2070         else
2071 #endif
2072             entry_limit = 7;
2073         if ((index + entry_limit) > dt->limit)
2074             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2075         ptr = dt->base + index;
2076         e1 = ldl_kernel(ptr);
2077         e2 = ldl_kernel(ptr + 4);
2078         if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
2079             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2080         if (!(e2 & DESC_P_MASK))
2081             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2082 #ifdef TARGET_X86_64
2083         if (env->hflags & HF_LMA_MASK) {
2084             uint32_t e3;
2085             e3 = ldl_kernel(ptr + 8);
2086             load_seg_cache_raw_dt(&env->ldt, e1, e2);
2087             env->ldt.base |= (target_ulong)e3 << 32;
2088         } else
2089 #endif
2090         {
2091             load_seg_cache_raw_dt(&env->ldt, e1, e2);
2092         }
2093     }
2094     env->ldt.selector = selector;
2095 }
2096
2097 void helper_ltr(int selector)
2098 {
2099     SegmentCache *dt;
2100     uint32_t e1, e2;
2101     int index, type, entry_limit;
2102     target_ulong ptr;
2103
2104     selector &= 0xffff;
2105     if ((selector & 0xfffc) == 0) {
2106         /* NULL selector case: invalid TR */
2107         env->tr.base = 0;
2108         env->tr.limit = 0;
2109         env->tr.flags = 0;
2110     } else {
2111         if (selector & 0x4)
2112             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2113         dt = &env->gdt;
2114         index = selector & ~7;
2115 #ifdef TARGET_X86_64
2116         if (env->hflags & HF_LMA_MASK)
2117             entry_limit = 15;
2118         else
2119 #endif
2120             entry_limit = 7;
2121         if ((index + entry_limit) > dt->limit)
2122             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2123         ptr = dt->base + index;
2124         e1 = ldl_kernel(ptr);
2125         e2 = ldl_kernel(ptr + 4);
2126         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2127         if ((e2 & DESC_S_MASK) ||
2128             (type != 1 && type != 9))
2129             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2130         if (!(e2 & DESC_P_MASK))
2131             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2132 #ifdef TARGET_X86_64
2133         if (env->hflags & HF_LMA_MASK) {
2134             uint32_t e3, e4;
2135             e3 = ldl_kernel(ptr + 8);
2136             e4 = ldl_kernel(ptr + 12);
2137             if ((e4 >> DESC_TYPE_SHIFT) & 0xf)
2138                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2139             load_seg_cache_raw_dt(&env->tr, e1, e2);
2140             env->tr.base |= (target_ulong)e3 << 32;
2141         } else
2142 #endif
2143         {
2144             load_seg_cache_raw_dt(&env->tr, e1, e2);
2145         }
2146         e2 |= DESC_TSS_BUSY_MASK;
2147         stl_kernel(ptr + 4, e2);
2148     }
2149     env->tr.selector = selector;
2150 }
2151
2152 /* only works if protected mode and not VM86. seg_reg must be != R_CS */
2153 void helper_load_seg(int seg_reg, int selector)
2154 {
2155     uint32_t e1, e2;
2156     int cpl, dpl, rpl;
2157     SegmentCache *dt;
2158     int index;
2159     target_ulong ptr;
2160
2161     selector &= 0xffff;
2162     cpl = env->hflags & HF_CPL_MASK;
2163     if ((selector & 0xfffc) == 0) {
2164         /* null selector case */
2165         if (seg_reg == R_SS
2166 #ifdef TARGET_X86_64
2167             && (!(env->hflags & HF_CS64_MASK) || cpl == 3)
2168 #endif
2169             )
2170             raise_exception_err(EXCP0D_GPF, 0);
2171         cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0);
2172     } else {
2173
2174         if (selector & 0x4)
2175             dt = &env->ldt;
2176         else
2177             dt = &env->gdt;
2178         index = selector & ~7;
2179         if ((index + 7) > dt->limit)
2180             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2181         ptr = dt->base + index;
2182         e1 = ldl_kernel(ptr);
2183         e2 = ldl_kernel(ptr + 4);
2184
2185         if (!(e2 & DESC_S_MASK))
2186             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2187         rpl = selector & 3;
2188         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2189         if (seg_reg == R_SS) {
2190             /* must be writable segment */
2191             if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
2192                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2193             if (rpl != cpl || dpl != cpl)
2194                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2195         } else {
2196             /* must be readable segment */
2197             if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK)
2198                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2199
2200             if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
2201                 /* if not conforming code, test rights */
2202                 if (dpl < cpl || dpl < rpl)
2203                     raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2204             }
2205         }
2206
2207         if (!(e2 & DESC_P_MASK)) {
2208             if (seg_reg == R_SS)
2209                 raise_exception_err(EXCP0C_STACK, selector & 0xfffc);
2210             else
2211                 raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2212         }
2213
2214         /* set the access bit if not already set */
2215         if (!(e2 & DESC_A_MASK)) {
2216             e2 |= DESC_A_MASK;
2217             stl_kernel(ptr + 4, e2);
2218         }
2219
2220         cpu_x86_load_seg_cache(env, seg_reg, selector,
2221                        get_seg_base(e1, e2),
2222                        get_seg_limit(e1, e2),
2223                        e2);
2224 #if 0
2225         fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx flags=%08x\n",
2226                 selector, (unsigned long)sc->base, sc->limit, sc->flags);
2227 #endif
2228     }
2229 }
2230
2231 /* protected mode jump */
2232 void helper_ljmp_protected(int new_cs, target_ulong new_eip,
2233                            int next_eip_addend)
2234 {
2235     int gate_cs, type;
2236     uint32_t e1, e2, cpl, dpl, rpl, limit;
2237     target_ulong next_eip;
2238
2239     if ((new_cs & 0xfffc) == 0)
2240         raise_exception_err(EXCP0D_GPF, 0);
2241     if (load_segment(&e1, &e2, new_cs) != 0)
2242         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2243     cpl = env->hflags & HF_CPL_MASK;
2244     if (e2 & DESC_S_MASK) {
2245         if (!(e2 & DESC_CS_MASK))
2246             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2247         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2248         if (e2 & DESC_C_MASK) {
2249             /* conforming code segment */
2250             if (dpl > cpl)
2251                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2252         } else {
2253             /* non conforming code segment */
2254             rpl = new_cs & 3;
2255             if (rpl > cpl)
2256                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2257             if (dpl != cpl)
2258                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2259         }
2260         if (!(e2 & DESC_P_MASK))
2261             raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2262         limit = get_seg_limit(e1, e2);
2263         if (new_eip > limit &&
2264             !(env->hflags & HF_LMA_MASK) && !(e2 & DESC_L_MASK))
2265             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2266         cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2267                        get_seg_base(e1, e2), limit, e2);
2268         EIP = new_eip;
2269     } else {
2270         /* jump to call or task gate */
2271         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2272         rpl = new_cs & 3;
2273         cpl = env->hflags & HF_CPL_MASK;
2274         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2275         switch(type) {
2276         case 1: /* 286 TSS */
2277         case 9: /* 386 TSS */
2278         case 5: /* task gate */
2279             if (dpl < cpl || dpl < rpl)
2280                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2281             next_eip = env->eip + next_eip_addend;
2282             switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip);
2283             CC_OP = CC_OP_EFLAGS;
2284             break;
2285         case 4: /* 286 call gate */
2286         case 12: /* 386 call gate */
2287             if ((dpl < cpl) || (dpl < rpl))
2288                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2289             if (!(e2 & DESC_P_MASK))
2290                 raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2291             gate_cs = e1 >> 16;
2292             new_eip = (e1 & 0xffff);
2293             if (type == 12)
2294                 new_eip |= (e2 & 0xffff0000);
2295             if (load_segment(&e1, &e2, gate_cs) != 0)
2296                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2297             dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2298             /* must be code segment */
2299             if (((e2 & (DESC_S_MASK | DESC_CS_MASK)) !=
2300                  (DESC_S_MASK | DESC_CS_MASK)))
2301                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2302             if (((e2 & DESC_C_MASK) && (dpl > cpl)) ||
2303                 (!(e2 & DESC_C_MASK) && (dpl != cpl)))
2304                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2305             if (!(e2 & DESC_P_MASK))
2306                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
2307             limit = get_seg_limit(e1, e2);
2308             if (new_eip > limit)
2309                 raise_exception_err(EXCP0D_GPF, 0);
2310             cpu_x86_load_seg_cache(env, R_CS, (gate_cs & 0xfffc) | cpl,
2311                                    get_seg_base(e1, e2), limit, e2);
2312             EIP = new_eip;
2313             break;
2314         default:
2315             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2316             break;
2317         }
2318     }
2319 }
2320
2321 /* real mode call */
2322 void helper_lcall_real(int new_cs, target_ulong new_eip1,
2323                        int shift, int next_eip)
2324 {
2325     int new_eip;
2326     uint32_t esp, esp_mask;
2327     target_ulong ssp;
2328
2329     new_eip = new_eip1;
2330     esp = ESP;
2331     esp_mask = get_sp_mask(env->segs[R_SS].flags);
2332     ssp = env->segs[R_SS].base;
2333     if (shift) {
2334         PUSHL(ssp, esp, esp_mask, env->segs[R_CS].selector);
2335         PUSHL(ssp, esp, esp_mask, next_eip);
2336     } else {
2337         PUSHW(ssp, esp, esp_mask, env->segs[R_CS].selector);
2338         PUSHW(ssp, esp, esp_mask, next_eip);
2339     }
2340
2341     SET_ESP(esp, esp_mask);
2342     env->eip = new_eip;
2343     env->segs[R_CS].selector = new_cs;
2344     env->segs[R_CS].base = (new_cs << 4);
2345 }
2346
2347 /* protected mode call */
2348 void helper_lcall_protected(int new_cs, target_ulong new_eip, 
2349                             int shift, int next_eip_addend)
2350 {
2351     int new_stack, i;
2352     uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;
2353     uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask;
2354     uint32_t val, limit, old_sp_mask;
2355     target_ulong ssp, old_ssp, next_eip;
2356
2357     next_eip = env->eip + next_eip_addend;
2358 #ifdef DEBUG_PCALL
2359     if (loglevel & CPU_LOG_PCALL) {
2360         fprintf(logfile, "lcall %04x:%08x s=%d\n",
2361                 new_cs, (uint32_t)new_eip, shift);
2362         cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
2363     }
2364 #endif
2365     if ((new_cs & 0xfffc) == 0)
2366         raise_exception_err(EXCP0D_GPF, 0);
2367     if (load_segment(&e1, &e2, new_cs) != 0)
2368         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2369     cpl = env->hflags & HF_CPL_MASK;
2370 #ifdef DEBUG_PCALL
2371     if (loglevel & CPU_LOG_PCALL) {
2372         fprintf(logfile, "desc=%08x:%08x\n", e1, e2);
2373     }
2374 #endif
2375     if (e2 & DESC_S_MASK) {
2376         if (!(e2 & DESC_CS_MASK))
2377             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2378         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2379         if (e2 & DESC_C_MASK) {
2380             /* conforming code segment */
2381             if (dpl > cpl)
2382                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2383         } else {
2384             /* non conforming code segment */
2385             rpl = new_cs & 3;
2386             if (rpl > cpl)
2387                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2388             if (dpl != cpl)
2389                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2390         }
2391         if (!(e2 & DESC_P_MASK))
2392             raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2393
2394 #ifdef TARGET_X86_64
2395         /* XXX: check 16/32 bit cases in long mode */
2396         if (shift == 2) {
2397             target_ulong rsp;
2398             /* 64 bit case */
2399             rsp = ESP;
2400             PUSHQ(rsp, env->segs[R_CS].selector);
2401             PUSHQ(rsp, next_eip);
2402             /* from this point, not restartable */
2403             ESP = rsp;
2404             cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2405                                    get_seg_base(e1, e2),
2406                                    get_seg_limit(e1, e2), e2);
2407             EIP = new_eip;
2408         } else
2409 #endif
2410         {
2411             sp = ESP;
2412             sp_mask = get_sp_mask(env->segs[R_SS].flags);
2413             ssp = env->segs[R_SS].base;
2414             if (shift) {
2415                 PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
2416                 PUSHL(ssp, sp, sp_mask, next_eip);
2417             } else {
2418                 PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
2419                 PUSHW(ssp, sp, sp_mask, next_eip);
2420             }
2421
2422             limit = get_seg_limit(e1, e2);
2423             if (new_eip > limit)
2424                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2425             /* from this point, not restartable */
2426             SET_ESP(sp, sp_mask);
2427             cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
2428                                    get_seg_base(e1, e2), limit, e2);
2429             EIP = new_eip;
2430         }
2431     } else {
2432         /* check gate type */
2433         type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
2434         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2435         rpl = new_cs & 3;
2436         switch(type) {
2437         case 1: /* available 286 TSS */
2438         case 9: /* available 386 TSS */
2439         case 5: /* task gate */
2440             if (dpl < cpl || dpl < rpl)
2441                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2442             switch_tss(new_cs, e1, e2, SWITCH_TSS_CALL, next_eip);
2443             CC_OP = CC_OP_EFLAGS;
2444             return;
2445         case 4: /* 286 call gate */
2446         case 12: /* 386 call gate */
2447             break;
2448         default:
2449             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2450             break;
2451         }
2452         shift = type >> 3;
2453
2454         if (dpl < cpl || dpl < rpl)
2455             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2456         /* check valid bit */
2457         if (!(e2 & DESC_P_MASK))
2458             raise_exception_err(EXCP0B_NOSEG,  new_cs & 0xfffc);
2459         selector = e1 >> 16;
2460         offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
2461         param_count = e2 & 0x1f;
2462         if ((selector & 0xfffc) == 0)
2463             raise_exception_err(EXCP0D_GPF, 0);
2464
2465         if (load_segment(&e1, &e2, selector) != 0)
2466             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2467         if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
2468             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2469         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2470         if (dpl > cpl)
2471             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
2472         if (!(e2 & DESC_P_MASK))
2473             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
2474
2475         if (!(e2 & DESC_C_MASK) && dpl < cpl) {
2476             /* to inner privilege */
2477             get_ss_esp_from_tss(&ss, &sp, dpl);
2478 #ifdef DEBUG_PCALL
2479             if (loglevel & CPU_LOG_PCALL)
2480                 fprintf(logfile, "new ss:esp=%04x:%08x param_count=%d ESP=" TARGET_FMT_lx "\n",
2481                         ss, sp, param_count, ESP);
2482 #endif
2483             if ((ss & 0xfffc) == 0)
2484                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2485             if ((ss & 3) != dpl)
2486                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2487             if (load_segment(&ss_e1, &ss_e2, ss) != 0)
2488                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2489             ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
2490             if (ss_dpl != dpl)
2491                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2492             if (!(ss_e2 & DESC_S_MASK) ||
2493                 (ss_e2 & DESC_CS_MASK) ||
2494                 !(ss_e2 & DESC_W_MASK))
2495                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2496             if (!(ss_e2 & DESC_P_MASK))
2497                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2498
2499             //            push_size = ((param_count * 2) + 8) << shift;
2500
2501             old_sp_mask = get_sp_mask(env->segs[R_SS].flags);
2502             old_ssp = env->segs[R_SS].base;
2503
2504             sp_mask = get_sp_mask(ss_e2);
2505             ssp = get_seg_base(ss_e1, ss_e2);
2506             if (shift) {
2507                 PUSHL(ssp, sp, sp_mask, env->segs[R_SS].selector);
2508                 PUSHL(ssp, sp, sp_mask, ESP);
2509                 for(i = param_count - 1; i >= 0; i--) {
2510                     val = ldl_kernel(old_ssp + ((ESP + i * 4) & old_sp_mask));
2511                     PUSHL(ssp, sp, sp_mask, val);
2512                 }
2513             } else {
2514                 PUSHW(ssp, sp, sp_mask, env->segs[R_SS].selector);
2515                 PUSHW(ssp, sp, sp_mask, ESP);
2516                 for(i = param_count - 1; i >= 0; i--) {
2517                     val = lduw_kernel(old_ssp + ((ESP + i * 2) & old_sp_mask));
2518                     PUSHW(ssp, sp, sp_mask, val);
2519                 }
2520             }
2521             new_stack = 1;
2522         } else {
2523             /* to same privilege */
2524             sp = ESP;
2525             sp_mask = get_sp_mask(env->segs[R_SS].flags);
2526             ssp = env->segs[R_SS].base;
2527             //            push_size = (4 << shift);
2528             new_stack = 0;
2529         }
2530
2531         if (shift) {
2532             PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
2533             PUSHL(ssp, sp, sp_mask, next_eip);
2534         } else {
2535             PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
2536             PUSHW(ssp, sp, sp_mask, next_eip);
2537         }
2538
2539         /* from this point, not restartable */
2540
2541         if (new_stack) {
2542             ss = (ss & ~3) | dpl;
2543             cpu_x86_load_seg_cache(env, R_SS, ss,
2544                                    ssp,
2545                                    get_seg_limit(ss_e1, ss_e2),
2546                                    ss_e2);
2547         }
2548
2549         selector = (selector & ~3) | dpl;
2550         cpu_x86_load_seg_cache(env, R_CS, selector,
2551                        get_seg_base(e1, e2),
2552                        get_seg_limit(e1, e2),
2553                        e2);
2554         cpu_x86_set_cpl(env, dpl);
2555         SET_ESP(sp, sp_mask);
2556         EIP = offset;
2557     }
2558 #ifdef USE_KQEMU
2559     if (kqemu_is_ok(env)) {
2560         env->exception_index = -1;
2561         cpu_loop_exit();
2562     }
2563 #endif
2564 }
2565
2566 /* real and vm86 mode iret */
2567 void helper_iret_real(int shift)
2568 {
2569     uint32_t sp, new_cs, new_eip, new_eflags, sp_mask;
2570     target_ulong ssp;
2571     int eflags_mask;
2572
2573     sp_mask = 0xffff; /* XXXX: use SS segment size ? */
2574     sp = ESP;
2575     ssp = env->segs[R_SS].base;
2576     if (shift == 1) {
2577         /* 32 bits */
2578         POPL(ssp, sp, sp_mask, new_eip);
2579         POPL(ssp, sp, sp_mask, new_cs);
2580         new_cs &= 0xffff;
2581         POPL(ssp, sp, sp_mask, new_eflags);
2582     } else {
2583         /* 16 bits */
2584         POPW(ssp, sp, sp_mask, new_eip);
2585         POPW(ssp, sp, sp_mask, new_cs);
2586         POPW(ssp, sp, sp_mask, new_eflags);
2587     }
2588     ESP = (ESP & ~sp_mask) | (sp & sp_mask);
2589     load_seg_vm(R_CS, new_cs);
2590     env->eip = new_eip;
2591     if (env->eflags & VM_MASK)
2592         eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK | NT_MASK;
2593     else
2594         eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK | RF_MASK | NT_MASK;
2595     if (shift == 0)
2596         eflags_mask &= 0xffff;
2597     load_eflags(new_eflags, eflags_mask);
2598     env->hflags &= ~HF_NMI_MASK;
2599 }
2600
2601 static inline void validate_seg(int seg_reg, int cpl)
2602 {
2603     int dpl;
2604     uint32_t e2;
2605
2606     /* XXX: on x86_64, we do not want to nullify FS and GS because
2607        they may still contain a valid base. I would be interested to
2608        know how a real x86_64 CPU behaves */
2609     if ((seg_reg == R_FS || seg_reg == R_GS) &&
2610         (env->segs[seg_reg].selector & 0xfffc) == 0)
2611         return;
2612
2613     e2 = env->segs[seg_reg].flags;
2614     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2615     if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
2616         /* data or non conforming code segment */
2617         if (dpl < cpl) {
2618             cpu_x86_load_seg_cache(env, seg_reg, 0, 0, 0, 0);
2619         }
2620     }
2621 }
2622
2623 /* protected mode iret */
2624 static inline void helper_ret_protected(int shift, int is_iret, int addend)
2625 {
2626     uint32_t new_cs, new_eflags, new_ss;
2627     uint32_t new_es, new_ds, new_fs, new_gs;
2628     uint32_t e1, e2, ss_e1, ss_e2;
2629     int cpl, dpl, rpl, eflags_mask, iopl;
2630     target_ulong ssp, sp, new_eip, new_esp, sp_mask;
2631
2632 #ifdef TARGET_X86_64
2633     if (shift == 2)
2634         sp_mask = -1;
2635     else
2636 #endif
2637         sp_mask = get_sp_mask(env->segs[R_SS].flags);
2638     sp = ESP;
2639     ssp = env->segs[R_SS].base;
2640     new_eflags = 0; /* avoid warning */
2641 #ifdef TARGET_X86_64
2642     if (shift == 2) {
2643         POPQ(sp, new_eip);
2644         POPQ(sp, new_cs);
2645         new_cs &= 0xffff;
2646         if (is_iret) {
2647             POPQ(sp, new_eflags);
2648         }
2649     } else
2650 #endif
2651     if (shift == 1) {
2652         /* 32 bits */
2653         POPL(ssp, sp, sp_mask, new_eip);
2654         POPL(ssp, sp, sp_mask, new_cs);
2655         new_cs &= 0xffff;
2656         if (is_iret) {
2657             POPL(ssp, sp, sp_mask, new_eflags);
2658             if (new_eflags & VM_MASK)
2659                 goto return_to_vm86;
2660         }
2661     } else {
2662         /* 16 bits */
2663         POPW(ssp, sp, sp_mask, new_eip);
2664         POPW(ssp, sp, sp_mask, new_cs);
2665         if (is_iret)
2666             POPW(ssp, sp, sp_mask, new_eflags);
2667     }
2668 #ifdef DEBUG_PCALL
2669     if (loglevel & CPU_LOG_PCALL) {
2670         fprintf(logfile, "lret new %04x:" TARGET_FMT_lx " s=%d addend=0x%x\n",
2671                 new_cs, new_eip, shift, addend);
2672         cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
2673     }
2674 #endif
2675     if ((new_cs & 0xfffc) == 0)
2676         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2677     if (load_segment(&e1, &e2, new_cs) != 0)
2678         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2679     if (!(e2 & DESC_S_MASK) ||
2680         !(e2 & DESC_CS_MASK))
2681         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2682     cpl = env->hflags & HF_CPL_MASK;
2683     rpl = new_cs & 3;
2684     if (rpl < cpl)
2685         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2686     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2687     if (e2 & DESC_C_MASK) {
2688         if (dpl > rpl)
2689             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2690     } else {
2691         if (dpl != rpl)
2692             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
2693     }
2694     if (!(e2 & DESC_P_MASK))
2695         raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2696
2697     sp += addend;
2698     if (rpl == cpl && (!(env->hflags & HF_CS64_MASK) ||
2699                        ((env->hflags & HF_CS64_MASK) && !is_iret))) {
2700         /* return to same priledge level */
2701         cpu_x86_load_seg_cache(env, R_CS, new_cs,
2702                        get_seg_base(e1, e2),
2703                        get_seg_limit(e1, e2),
2704                        e2);
2705     } else {
2706         /* return to different privilege level */
2707 #ifdef TARGET_X86_64
2708         if (shift == 2) {
2709             POPQ(sp, new_esp);
2710             POPQ(sp, new_ss);
2711             new_ss &= 0xffff;
2712         } else
2713 #endif
2714         if (shift == 1) {
2715             /* 32 bits */
2716             POPL(ssp, sp, sp_mask, new_esp);
2717             POPL(ssp, sp, sp_mask, new_ss);
2718             new_ss &= 0xffff;
2719         } else {
2720             /* 16 bits */
2721             POPW(ssp, sp, sp_mask, new_esp);
2722             POPW(ssp, sp, sp_mask, new_ss);
2723         }
2724 #ifdef DEBUG_PCALL
2725         if (loglevel & CPU_LOG_PCALL) {
2726             fprintf(logfile, "new ss:esp=%04x:" TARGET_FMT_lx "\n",
2727                     new_ss, new_esp);
2728         }
2729 #endif
2730         if ((new_ss & 0xfffc) == 0) {
2731 #ifdef TARGET_X86_64
2732             /* NULL ss is allowed in long mode if cpl != 3*/
2733             /* XXX: test CS64 ? */
2734             if ((env->hflags & HF_LMA_MASK) && rpl != 3) {
2735                 cpu_x86_load_seg_cache(env, R_SS, new_ss,
2736                                        0, 0xffffffff,
2737                                        DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2738                                        DESC_S_MASK | (rpl << DESC_DPL_SHIFT) |
2739                                        DESC_W_MASK | DESC_A_MASK);
2740                 ss_e2 = DESC_B_MASK; /* XXX: should not be needed ? */
2741             } else
2742 #endif
2743             {
2744                 raise_exception_err(EXCP0D_GPF, 0);
2745             }
2746         } else {
2747             if ((new_ss & 3) != rpl)
2748                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2749             if (load_segment(&ss_e1, &ss_e2, new_ss) != 0)
2750                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2751             if (!(ss_e2 & DESC_S_MASK) ||
2752                 (ss_e2 & DESC_CS_MASK) ||
2753                 !(ss_e2 & DESC_W_MASK))
2754                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2755             dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
2756             if (dpl != rpl)
2757                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2758             if (!(ss_e2 & DESC_P_MASK))
2759                 raise_exception_err(EXCP0B_NOSEG, new_ss & 0xfffc);
2760             cpu_x86_load_seg_cache(env, R_SS, new_ss,
2761                                    get_seg_base(ss_e1, ss_e2),
2762                                    get_seg_limit(ss_e1, ss_e2),
2763                                    ss_e2);
2764         }
2765
2766         cpu_x86_load_seg_cache(env, R_CS, new_cs,
2767                        get_seg_base(e1, e2),
2768                        get_seg_limit(e1, e2),
2769                        e2);
2770         cpu_x86_set_cpl(env, rpl);
2771         sp = new_esp;
2772 #ifdef TARGET_X86_64
2773         if (env->hflags & HF_CS64_MASK)
2774             sp_mask = -1;
2775         else
2776 #endif
2777             sp_mask = get_sp_mask(ss_e2);
2778
2779         /* validate data segments */
2780         validate_seg(R_ES, rpl);
2781         validate_seg(R_DS, rpl);
2782         validate_seg(R_FS, rpl);
2783         validate_seg(R_GS, rpl);
2784
2785         sp += addend;
2786     }
2787     SET_ESP(sp, sp_mask);
2788     env->eip = new_eip;
2789     if (is_iret) {
2790         /* NOTE: 'cpl' is the _old_ CPL */
2791         eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK | NT_MASK;
2792         if (cpl == 0)
2793             eflags_mask |= IOPL_MASK;
2794         iopl = (env->eflags >> IOPL_SHIFT) & 3;
2795         if (cpl <= iopl)
2796             eflags_mask |= IF_MASK;
2797         if (shift == 0)
2798             eflags_mask &= 0xffff;
2799         load_eflags(new_eflags, eflags_mask);
2800     }
2801     return;
2802
2803  return_to_vm86:
2804     POPL(ssp, sp, sp_mask, new_esp);
2805     POPL(ssp, sp, sp_mask, new_ss);
2806     POPL(ssp, sp, sp_mask, new_es);
2807     POPL(ssp, sp, sp_mask, new_ds);
2808     POPL(ssp, sp, sp_mask, new_fs);
2809     POPL(ssp, sp, sp_mask, new_gs);
2810
2811     /* modify processor state */
2812     load_eflags(new_eflags, TF_MASK | AC_MASK | ID_MASK |
2813                 IF_MASK | IOPL_MASK | VM_MASK | NT_MASK | VIF_MASK | VIP_MASK);
2814     load_seg_vm(R_CS, new_cs & 0xffff);
2815     cpu_x86_set_cpl(env, 3);
2816     load_seg_vm(R_SS, new_ss & 0xffff);
2817     load_seg_vm(R_ES, new_es & 0xffff);
2818     load_seg_vm(R_DS, new_ds & 0xffff);
2819     load_seg_vm(R_FS, new_fs & 0xffff);
2820     load_seg_vm(R_GS, new_gs & 0xffff);
2821
2822     env->eip = new_eip & 0xffff;
2823     ESP = new_esp;
2824 }
2825
2826 void helper_iret_protected(int shift, int next_eip)
2827 {
2828     int tss_selector, type;
2829     uint32_t e1, e2;
2830
2831     /* specific case for TSS */
2832     if (env->eflags & NT_MASK) {
2833 #ifdef TARGET_X86_64
2834         if (env->hflags & HF_LMA_MASK)
2835             raise_exception_err(EXCP0D_GPF, 0);
2836 #endif
2837         tss_selector = lduw_kernel(env->tr.base + 0);
2838         if (tss_selector & 4)
2839             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2840         if (load_segment(&e1, &e2, tss_selector) != 0)
2841             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2842         type = (e2 >> DESC_TYPE_SHIFT) & 0x17;
2843         /* NOTE: we check both segment and busy TSS */
2844         if (type != 3)
2845             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2846         switch_tss(tss_selector, e1, e2, SWITCH_TSS_IRET, next_eip);
2847     } else {
2848         helper_ret_protected(shift, 1, 0);
2849     }
2850     env->hflags &= ~HF_NMI_MASK;
2851 #ifdef USE_KQEMU
2852     if (kqemu_is_ok(env)) {
2853         CC_OP = CC_OP_EFLAGS;
2854         env->exception_index = -1;
2855         cpu_loop_exit();
2856     }
2857 #endif
2858 }
2859
2860 void helper_lret_protected(int shift, int addend)
2861 {
2862     helper_ret_protected(shift, 0, addend);
2863 #ifdef USE_KQEMU
2864     if (kqemu_is_ok(env)) {
2865         env->exception_index = -1;
2866         cpu_loop_exit();
2867     }
2868 #endif
2869 }
2870
2871 void helper_sysenter(void)
2872 {
2873     if (env->sysenter_cs == 0) {
2874         raise_exception_err(EXCP0D_GPF, 0);
2875     }
2876     env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK);
2877     cpu_x86_set_cpl(env, 0);
2878     cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
2879                            0, 0xffffffff,
2880                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2881                            DESC_S_MASK |
2882                            DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2883     cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc,
2884                            0, 0xffffffff,
2885                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2886                            DESC_S_MASK |
2887                            DESC_W_MASK | DESC_A_MASK);
2888     ESP = env->sysenter_esp;
2889     EIP = env->sysenter_eip;
2890 }
2891
2892 void helper_sysexit(void)
2893 {
2894     int cpl;
2895
2896     cpl = env->hflags & HF_CPL_MASK;
2897     if (env->sysenter_cs == 0 || cpl != 0) {
2898         raise_exception_err(EXCP0D_GPF, 0);
2899     }
2900     cpu_x86_set_cpl(env, 3);
2901     cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3,
2902                            0, 0xffffffff,
2903                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2904                            DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2905                            DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2906     cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3,
2907                            0, 0xffffffff,
2908                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2909                            DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2910                            DESC_W_MASK | DESC_A_MASK);
2911     ESP = ECX;
2912     EIP = EDX;
2913 #ifdef USE_KQEMU
2914     if (kqemu_is_ok(env)) {
2915         env->exception_index = -1;
2916         cpu_loop_exit();
2917     }
2918 #endif
2919 }
2920
2921 #if defined(CONFIG_USER_ONLY)
2922 target_ulong helper_read_crN(int reg)
2923 {
2924     return 0;
2925 }
2926
2927 void helper_write_crN(int reg, target_ulong t0)
2928 {
2929 }
2930 #else
2931 target_ulong helper_read_crN(int reg)
2932 {
2933     target_ulong val;
2934
2935     helper_svm_check_intercept_param(SVM_EXIT_READ_CR0 + reg, 0);
2936     switch(reg) {
2937     default:
2938         val = env->cr[reg];
2939         break;
2940     case 8:
2941         val = cpu_get_apic_tpr(env);
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         cpu_set_apic_tpr(env, t0);
2962         env->cr[8] = t0;
2963         break;
2964     default:
2965         env->cr[reg] = t0;
2966         break;
2967     }
2968 }
2969 #endif
2970
2971 void helper_lmsw(target_ulong t0)
2972 {
2973     /* only 4 lower bits of CR0 are modified. PE cannot be set to zero
2974        if already set to one. */
2975     t0 = (env->cr[0] & ~0xe) | (t0 & 0xf);
2976     helper_write_crN(0, t0);
2977 }
2978
2979 void helper_clts(void)
2980 {
2981     env->cr[0] &= ~CR0_TS_MASK;
2982     env->hflags &= ~HF_TS_MASK;
2983 }
2984
2985 #if !defined(CONFIG_USER_ONLY)
2986 target_ulong helper_movtl_T0_cr8(void)
2987 {
2988     return cpu_get_apic_tpr(env);
2989 }
2990 #endif
2991
2992 /* XXX: do more */
2993 void helper_movl_drN_T0(int reg, target_ulong t0)
2994 {
2995     env->dr[reg] = t0;
2996 }
2997
2998 void helper_invlpg(target_ulong addr)
2999 {
3000     helper_svm_check_intercept_param(SVM_EXIT_INVLPG, 0);
3001     cpu_x86_flush_tlb(env, addr);
3002 }
3003
3004 void helper_rdtsc(void)
3005 {
3006     uint64_t val;
3007
3008     if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
3009         raise_exception(EXCP0D_GPF);
3010     }
3011     helper_svm_check_intercept_param(SVM_EXIT_RDTSC, 0);
3012
3013     val = cpu_get_tsc(env);
3014     EAX = (uint32_t)(val);
3015     EDX = (uint32_t)(val >> 32);
3016 }
3017
3018 void helper_rdpmc(void)
3019 {
3020     if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
3021         raise_exception(EXCP0D_GPF);
3022     }
3023     helper_svm_check_intercept_param(SVM_EXIT_RDPMC, 0);
3024     
3025     /* currently unimplemented */
3026     raise_exception_err(EXCP06_ILLOP, 0);
3027 }
3028
3029 #if defined(CONFIG_USER_ONLY)
3030 void helper_wrmsr(void)
3031 {
3032 }
3033
3034 void helper_rdmsr(void)
3035 {
3036 }
3037 #else
3038 void helper_wrmsr(void)
3039 {
3040     uint64_t val;
3041
3042     helper_svm_check_intercept_param(SVM_EXIT_MSR, 1);
3043
3044     val = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
3045
3046     switch((uint32_t)ECX) {
3047     case MSR_IA32_SYSENTER_CS:
3048         env->sysenter_cs = val & 0xffff;
3049         break;
3050     case MSR_IA32_SYSENTER_ESP:
3051         env->sysenter_esp = val;
3052         break;
3053     case MSR_IA32_SYSENTER_EIP:
3054         env->sysenter_eip = val;
3055         break;
3056     case MSR_IA32_APICBASE:
3057         cpu_set_apic_base(env, val);
3058         break;
3059     case MSR_EFER:
3060         {
3061             uint64_t update_mask;
3062             update_mask = 0;
3063             if (env->cpuid_ext2_features & CPUID_EXT2_SYSCALL)
3064                 update_mask |= MSR_EFER_SCE;
3065             if (env->cpuid_ext2_features & CPUID_EXT2_LM)
3066                 update_mask |= MSR_EFER_LME;
3067             if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR)
3068                 update_mask |= MSR_EFER_FFXSR;
3069             if (env->cpuid_ext2_features & CPUID_EXT2_NX)
3070                 update_mask |= MSR_EFER_NXE;
3071             env->efer = (env->efer & ~update_mask) |
3072             (val & update_mask);
3073         }
3074         break;
3075     case MSR_STAR:
3076         env->star = val;
3077         break;
3078     case MSR_PAT:
3079         env->pat = val;
3080         break;
3081     case MSR_VM_HSAVE_PA:
3082         env->vm_hsave = val;
3083         break;
3084 #ifdef TARGET_X86_64
3085     case MSR_LSTAR:
3086         env->lstar = val;
3087         break;
3088     case MSR_CSTAR:
3089         env->cstar = val;
3090         break;
3091     case MSR_FMASK:
3092         env->fmask = val;
3093         break;
3094     case MSR_FSBASE:
3095         env->segs[R_FS].base = val;
3096         break;
3097     case MSR_GSBASE:
3098         env->segs[R_GS].base = val;
3099         break;
3100     case MSR_KERNELGSBASE:
3101         env->kernelgsbase = val;
3102         break;
3103 #endif
3104     default:
3105         /* XXX: exception ? */
3106         break;
3107     }
3108 }
3109
3110 void helper_rdmsr(void)
3111 {
3112     uint64_t val;
3113
3114     helper_svm_check_intercept_param(SVM_EXIT_MSR, 0);
3115
3116     switch((uint32_t)ECX) {
3117     case MSR_IA32_SYSENTER_CS:
3118         val = env->sysenter_cs;
3119         break;
3120     case MSR_IA32_SYSENTER_ESP:
3121         val = env->sysenter_esp;
3122         break;
3123     case MSR_IA32_SYSENTER_EIP:
3124         val = env->sysenter_eip;
3125         break;
3126     case MSR_IA32_APICBASE:
3127         val = cpu_get_apic_base(env);
3128         break;
3129     case MSR_EFER:
3130         val = env->efer;
3131         break;
3132     case MSR_STAR:
3133         val = env->star;
3134         break;
3135     case MSR_PAT:
3136         val = env->pat;
3137         break;
3138     case MSR_VM_HSAVE_PA:
3139         val = env->vm_hsave;
3140         break;
3141 #ifdef TARGET_X86_64
3142     case MSR_LSTAR:
3143         val = env->lstar;
3144         break;
3145     case MSR_CSTAR:
3146         val = env->cstar;
3147         break;
3148     case MSR_FMASK:
3149         val = env->fmask;
3150         break;
3151     case MSR_FSBASE:
3152         val = env->segs[R_FS].base;
3153         break;
3154     case MSR_GSBASE:
3155         val = env->segs[R_GS].base;
3156         break;
3157     case MSR_KERNELGSBASE:
3158         val = env->kernelgsbase;
3159         break;
3160 #endif
3161     default:
3162         /* XXX: exception ? */
3163         val = 0;
3164         break;
3165     }
3166     EAX = (uint32_t)(val);
3167     EDX = (uint32_t)(val >> 32);
3168 }
3169 #endif
3170
3171 target_ulong helper_lsl(target_ulong selector1)
3172 {
3173     unsigned int limit;
3174     uint32_t e1, e2, eflags, selector;
3175     int rpl, dpl, cpl, type;
3176
3177     selector = selector1 & 0xffff;
3178     eflags = cc_table[CC_OP].compute_all();
3179     if (load_segment(&e1, &e2, selector) != 0)
3180         goto fail;
3181     rpl = selector & 3;
3182     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3183     cpl = env->hflags & HF_CPL_MASK;
3184     if (e2 & DESC_S_MASK) {
3185         if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
3186             /* conforming */
3187         } else {
3188             if (dpl < cpl || dpl < rpl)
3189                 goto fail;
3190         }
3191     } else {
3192         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
3193         switch(type) {
3194         case 1:
3195         case 2:
3196         case 3:
3197         case 9:
3198         case 11:
3199             break;
3200         default:
3201             goto fail;
3202         }
3203         if (dpl < cpl || dpl < rpl) {
3204         fail:
3205             CC_SRC = eflags & ~CC_Z;
3206             return 0;
3207         }
3208     }
3209     limit = get_seg_limit(e1, e2);
3210     CC_SRC = eflags | CC_Z;
3211     return limit;
3212 }
3213
3214 target_ulong helper_lar(target_ulong selector1)
3215 {
3216     uint32_t e1, e2, eflags, selector;
3217     int rpl, dpl, cpl, type;
3218
3219     selector = selector1 & 0xffff;
3220     eflags = cc_table[CC_OP].compute_all();
3221     if ((selector & 0xfffc) == 0)
3222         goto fail;
3223     if (load_segment(&e1, &e2, selector) != 0)
3224         goto fail;
3225     rpl = selector & 3;
3226     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3227     cpl = env->hflags & HF_CPL_MASK;
3228     if (e2 & DESC_S_MASK) {
3229         if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
3230             /* conforming */
3231         } else {
3232             if (dpl < cpl || dpl < rpl)
3233                 goto fail;
3234         }
3235     } else {
3236         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
3237         switch(type) {
3238         case 1:
3239         case 2:
3240         case 3:
3241         case 4:
3242         case 5:
3243         case 9:
3244         case 11:
3245         case 12:
3246             break;
3247         default:
3248             goto fail;
3249         }
3250         if (dpl < cpl || dpl < rpl) {
3251         fail:
3252             CC_SRC = eflags & ~CC_Z;
3253             return 0;
3254         }
3255     }
3256     CC_SRC = eflags | CC_Z;
3257     return e2 & 0x00f0ff00;
3258 }
3259
3260 void helper_verr(target_ulong selector1)
3261 {
3262     uint32_t e1, e2, eflags, selector;
3263     int rpl, dpl, cpl;
3264
3265     selector = selector1 & 0xffff;
3266     eflags = cc_table[CC_OP].compute_all();
3267     if ((selector & 0xfffc) == 0)
3268         goto fail;
3269     if (load_segment(&e1, &e2, selector) != 0)
3270         goto fail;
3271     if (!(e2 & DESC_S_MASK))
3272         goto fail;
3273     rpl = selector & 3;
3274     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3275     cpl = env->hflags & HF_CPL_MASK;
3276     if (e2 & DESC_CS_MASK) {
3277         if (!(e2 & DESC_R_MASK))
3278             goto fail;
3279         if (!(e2 & DESC_C_MASK)) {
3280             if (dpl < cpl || dpl < rpl)
3281                 goto fail;
3282         }
3283     } else {
3284         if (dpl < cpl || dpl < rpl) {
3285         fail:
3286             CC_SRC = eflags & ~CC_Z;
3287             return;
3288         }
3289     }
3290     CC_SRC = eflags | CC_Z;
3291 }
3292
3293 void helper_verw(target_ulong selector1)
3294 {
3295     uint32_t e1, e2, eflags, selector;
3296     int rpl, dpl, cpl;
3297
3298     selector = selector1 & 0xffff;
3299     eflags = cc_table[CC_OP].compute_all();
3300     if ((selector & 0xfffc) == 0)
3301         goto fail;
3302     if (load_segment(&e1, &e2, selector) != 0)
3303         goto fail;
3304     if (!(e2 & DESC_S_MASK))
3305         goto fail;
3306     rpl = selector & 3;
3307     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
3308     cpl = env->hflags & HF_CPL_MASK;
3309     if (e2 & DESC_CS_MASK) {
3310         goto fail;
3311     } else {
3312         if (dpl < cpl || dpl < rpl)
3313             goto fail;
3314         if (!(e2 & DESC_W_MASK)) {
3315         fail:
3316             CC_SRC = eflags & ~CC_Z;
3317             return;
3318         }
3319     }
3320     CC_SRC = eflags | CC_Z;
3321 }
3322
3323 /* x87 FPU helpers */
3324
3325 static void fpu_set_exception(int mask)
3326 {
3327     env->fpus |= mask;
3328     if (env->fpus & (~env->fpuc & FPUC_EM))
3329         env->fpus |= FPUS_SE | FPUS_B;
3330 }
3331
3332 static inline CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b)
3333 {
3334     if (b == 0.0)
3335         fpu_set_exception(FPUS_ZE);
3336     return a / b;
3337 }
3338
3339 void fpu_raise_exception(void)
3340 {
3341     if (env->cr[0] & CR0_NE_MASK) {
3342         raise_exception(EXCP10_COPR);
3343     }
3344 #if !defined(CONFIG_USER_ONLY)
3345     else {
3346         cpu_set_ferr(env);
3347     }
3348 #endif
3349 }
3350
3351 void helper_flds_FT0(uint32_t val)
3352 {
3353     union {
3354         float32 f;
3355         uint32_t i;
3356     } u;
3357     u.i = val;
3358     FT0 = float32_to_floatx(u.f, &env->fp_status);
3359 }
3360
3361 void helper_fldl_FT0(uint64_t val)
3362 {
3363     union {
3364         float64 f;
3365         uint64_t i;
3366     } u;
3367     u.i = val;
3368     FT0 = float64_to_floatx(u.f, &env->fp_status);
3369 }
3370
3371 void helper_fildl_FT0(int32_t val)
3372 {
3373     FT0 = int32_to_floatx(val, &env->fp_status);
3374 }
3375
3376 void helper_flds_ST0(uint32_t val)
3377 {
3378     int new_fpstt;
3379     union {
3380         float32 f;
3381         uint32_t i;
3382     } u;
3383     new_fpstt = (env->fpstt - 1) & 7;
3384     u.i = val;
3385     env->fpregs[new_fpstt].d = float32_to_floatx(u.f, &env->fp_status);
3386     env->fpstt = new_fpstt;
3387     env->fptags[new_fpstt] = 0; /* validate stack entry */
3388 }
3389
3390 void helper_fldl_ST0(uint64_t val)
3391 {
3392     int new_fpstt;
3393     union {
3394         float64 f;
3395         uint64_t i;
3396     } u;
3397     new_fpstt = (env->fpstt - 1) & 7;
3398     u.i = val;
3399     env->fpregs[new_fpstt].d = float64_to_floatx(u.f, &env->fp_status);
3400     env->fpstt = new_fpstt;
3401     env->fptags[new_fpstt] = 0; /* validate stack entry */
3402 }
3403
3404 void helper_fildl_ST0(int32_t val)
3405 {
3406     int new_fpstt;
3407     new_fpstt = (env->fpstt - 1) & 7;
3408     env->fpregs[new_fpstt].d = int32_to_floatx(val, &env->fp_status);
3409     env->fpstt = new_fpstt;
3410     env->fptags[new_fpstt] = 0; /* validate stack entry */
3411 }
3412
3413 void helper_fildll_ST0(int64_t val)
3414 {
3415     int new_fpstt;
3416     new_fpstt = (env->fpstt - 1) & 7;
3417     env->fpregs[new_fpstt].d = int64_to_floatx(val, &env->fp_status);
3418     env->fpstt = new_fpstt;
3419     env->fptags[new_fpstt] = 0; /* validate stack entry */
3420 }
3421
3422 uint32_t helper_fsts_ST0(void)
3423 {
3424     union {
3425         float32 f;
3426         uint32_t i;
3427     } u;
3428     u.f = floatx_to_float32(ST0, &env->fp_status);
3429     return u.i;
3430 }
3431
3432 uint64_t helper_fstl_ST0(void)
3433 {
3434     union {
3435         float64 f;
3436         uint64_t i;
3437     } u;
3438     u.f = floatx_to_float64(ST0, &env->fp_status);
3439     return u.i;
3440 }
3441
3442 int32_t helper_fist_ST0(void)
3443 {
3444     int32_t val;
3445     val = floatx_to_int32(ST0, &env->fp_status);
3446     if (val != (int16_t)val)
3447         val = -32768;
3448     return val;
3449 }
3450
3451 int32_t helper_fistl_ST0(void)
3452 {
3453     int32_t val;
3454     val = floatx_to_int32(ST0, &env->fp_status);
3455     return val;
3456 }
3457
3458 int64_t helper_fistll_ST0(void)
3459 {
3460     int64_t val;
3461     val = floatx_to_int64(ST0, &env->fp_status);
3462     return val;
3463 }
3464
3465 int32_t helper_fistt_ST0(void)
3466 {
3467     int32_t val;
3468     val = floatx_to_int32_round_to_zero(ST0, &env->fp_status);
3469     if (val != (int16_t)val)
3470         val = -32768;
3471     return val;
3472 }
3473
3474 int32_t helper_fisttl_ST0(void)
3475 {
3476     int32_t val;
3477     val = floatx_to_int32_round_to_zero(ST0, &env->fp_status);
3478     return val;
3479 }
3480
3481 int64_t helper_fisttll_ST0(void)
3482 {
3483     int64_t val;
3484     val = floatx_to_int64_round_to_zero(ST0, &env->fp_status);
3485     return val;
3486 }
3487
3488 void helper_fldt_ST0(target_ulong ptr)
3489 {
3490     int new_fpstt;
3491     new_fpstt = (env->fpstt - 1) & 7;
3492     env->fpregs[new_fpstt].d = helper_fldt(ptr);
3493     env->fpstt = new_fpstt;
3494     env->fptags[new_fpstt] = 0; /* validate stack entry */
3495 }
3496
3497 void helper_fstt_ST0(target_ulong ptr)
3498 {
3499     helper_fstt(ST0, ptr);
3500 }
3501
3502 void helper_fpush(void)
3503 {
3504     fpush();
3505 }
3506
3507 void helper_fpop(void)
3508 {
3509     fpop();
3510 }
3511
3512 void helper_fdecstp(void)
3513 {
3514     env->fpstt = (env->fpstt - 1) & 7;
3515     env->fpus &= (~0x4700);
3516 }
3517
3518 void helper_fincstp(void)
3519 {
3520     env->fpstt = (env->fpstt + 1) & 7;
3521     env->fpus &= (~0x4700);
3522 }
3523
3524 /* FPU move */
3525
3526 void helper_ffree_STN(int st_index)
3527 {
3528     env->fptags[(env->fpstt + st_index) & 7] = 1;
3529 }
3530
3531 void helper_fmov_ST0_FT0(void)
3532 {
3533     ST0 = FT0;
3534 }
3535
3536 void helper_fmov_FT0_STN(int st_index)
3537 {
3538     FT0 = ST(st_index);
3539 }
3540
3541 void helper_fmov_ST0_STN(int st_index)
3542 {
3543     ST0 = ST(st_index);
3544 }
3545
3546 void helper_fmov_STN_ST0(int st_index)
3547 {
3548     ST(st_index) = ST0;
3549 }
3550
3551 void helper_fxchg_ST0_STN(int st_index)
3552 {
3553     CPU86_LDouble tmp;
3554     tmp = ST(st_index);
3555     ST(st_index) = ST0;
3556     ST0 = tmp;
3557 }
3558
3559 /* FPU operations */
3560
3561 static const int fcom_ccval[4] = {0x0100, 0x4000, 0x0000, 0x4500};
3562
3563 void helper_fcom_ST0_FT0(void)
3564 {
3565     int ret;
3566
3567     ret = floatx_compare(ST0, FT0, &env->fp_status);
3568     env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
3569     FORCE_RET();
3570 }
3571
3572 void helper_fucom_ST0_FT0(void)
3573 {
3574     int ret;
3575
3576     ret = floatx_compare_quiet(ST0, FT0, &env->fp_status);
3577     env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret+ 1];
3578     FORCE_RET();
3579 }
3580
3581 static const int fcomi_ccval[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C};
3582
3583 void helper_fcomi_ST0_FT0(void)
3584 {
3585     int eflags;
3586     int ret;
3587
3588     ret = floatx_compare(ST0, FT0, &env->fp_status);
3589     eflags = cc_table[CC_OP].compute_all();
3590     eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
3591     CC_SRC = eflags;
3592     FORCE_RET();
3593 }
3594
3595 void helper_fucomi_ST0_FT0(void)
3596 {
3597     int eflags;
3598     int ret;
3599
3600     ret = floatx_compare_quiet(ST0, FT0, &env->fp_status);
3601     eflags = cc_table[CC_OP].compute_all();
3602     eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
3603     CC_SRC = eflags;
3604     FORCE_RET();
3605 }
3606
3607 void helper_fadd_ST0_FT0(void)
3608 {
3609     ST0 += FT0;
3610 }
3611
3612 void helper_fmul_ST0_FT0(void)
3613 {
3614     ST0 *= FT0;
3615 }
3616
3617 void helper_fsub_ST0_FT0(void)
3618 {
3619     ST0 -= FT0;
3620 }
3621
3622 void helper_fsubr_ST0_FT0(void)
3623 {
3624     ST0 = FT0 - ST0;
3625 }
3626
3627 void helper_fdiv_ST0_FT0(void)
3628 {
3629     ST0 = helper_fdiv(ST0, FT0);
3630 }
3631
3632 void helper_fdivr_ST0_FT0(void)
3633 {
3634     ST0 = helper_fdiv(FT0, ST0);
3635 }
3636
3637 /* fp operations between STN and ST0 */
3638
3639 void helper_fadd_STN_ST0(int st_index)
3640 {
3641     ST(st_index) += ST0;
3642 }
3643
3644 void helper_fmul_STN_ST0(int st_index)
3645 {
3646     ST(st_index) *= ST0;
3647 }
3648
3649 void helper_fsub_STN_ST0(int st_index)
3650 {
3651     ST(st_index) -= ST0;
3652 }
3653
3654 void helper_fsubr_STN_ST0(int st_index)
3655 {
3656     CPU86_LDouble *p;
3657     p = &ST(st_index);
3658     *p = ST0 - *p;
3659 }
3660
3661 void helper_fdiv_STN_ST0(int st_index)
3662 {
3663     CPU86_LDouble *p;
3664     p = &ST(st_index);
3665     *p = helper_fdiv(*p, ST0);
3666 }
3667
3668 void helper_fdivr_STN_ST0(int st_index)
3669 {
3670     CPU86_LDouble *p;
3671     p = &ST(st_index);
3672     *p = helper_fdiv(ST0, *p);
3673 }
3674
3675 /* misc FPU operations */
3676 void helper_fchs_ST0(void)
3677 {
3678     ST0 = floatx_chs(ST0);
3679 }
3680
3681 void helper_fabs_ST0(void)
3682 {
3683     ST0 = floatx_abs(ST0);
3684 }
3685
3686 void helper_fld1_ST0(void)
3687 {
3688     ST0 = f15rk[1];
3689 }
3690
3691 void helper_fldl2t_ST0(void)
3692 {
3693     ST0 = f15rk[6];
3694 }
3695
3696 void helper_fldl2e_ST0(void)
3697 {
3698     ST0 = f15rk[5];
3699 }
3700
3701 void helper_fldpi_ST0(void)
3702 {
3703     ST0 = f15rk[2];
3704 }
3705
3706 void helper_fldlg2_ST0(void)
3707 {
3708     ST0 = f15rk[3];
3709 }
3710
3711 void helper_fldln2_ST0(void)
3712 {
3713     ST0 = f15rk[4];
3714 }
3715
3716 void helper_fldz_ST0(void)
3717 {
3718     ST0 = f15rk[0];
3719 }
3720
3721 void helper_fldz_FT0(void)
3722 {
3723     FT0 = f15rk[0];
3724 }
3725
3726 uint32_t helper_fnstsw(void)
3727 {
3728     return (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
3729 }
3730
3731 uint32_t helper_fnstcw(void)
3732 {
3733     return env->fpuc;
3734 }
3735
3736 static void update_fp_status(void)
3737 {
3738     int rnd_type;
3739
3740     /* set rounding mode */
3741     switch(env->fpuc & RC_MASK) {
3742     default:
3743     case RC_NEAR:
3744         rnd_type = float_round_nearest_even;
3745         break;
3746     case RC_DOWN:
3747         rnd_type = float_round_down;
3748         break;
3749     case RC_UP:
3750         rnd_type = float_round_up;
3751         break;
3752     case RC_CHOP:
3753         rnd_type = float_round_to_zero;
3754         break;
3755     }
3756     set_float_rounding_mode(rnd_type, &env->fp_status);
3757 #ifdef FLOATX80
3758     switch((env->fpuc >> 8) & 3) {
3759     case 0:
3760         rnd_type = 32;
3761         break;
3762     case 2:
3763         rnd_type = 64;
3764         break;
3765     case 3:
3766     default:
3767         rnd_type = 80;
3768         break;
3769     }
3770     set_floatx80_rounding_precision(rnd_type, &env->fp_status);
3771 #endif
3772 }
3773
3774 void helper_fldcw(uint32_t val)
3775 {
3776     env->fpuc = val;
3777     update_fp_status();
3778 }
3779
3780 void helper_fclex(void)
3781 {
3782     env->fpus &= 0x7f00;
3783 }
3784
3785 void helper_fwait(void)
3786 {
3787     if (env->fpus & FPUS_SE)
3788         fpu_raise_exception();
3789     FORCE_RET();
3790 }
3791
3792 void helper_fninit(void)
3793 {
3794     env->fpus = 0;
3795     env->fpstt = 0;
3796     env->fpuc = 0x37f;
3797     env->fptags[0] = 1;
3798     env->fptags[1] = 1;
3799     env->fptags[2] = 1;
3800     env->fptags[3] = 1;
3801     env->fptags[4] = 1;
3802     env->fptags[5] = 1;
3803     env->fptags[6] = 1;
3804     env->fptags[7] = 1;
3805 }
3806
3807 /* BCD ops */
3808
3809 void helper_fbld_ST0(target_ulong ptr)
3810 {
3811     CPU86_LDouble tmp;
3812     uint64_t val;
3813     unsigned int v;
3814     int i;
3815
3816     val = 0;
3817     for(i = 8; i >= 0; i--) {
3818         v = ldub(ptr + i);
3819         val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
3820     }
3821     tmp = val;
3822     if (ldub(ptr + 9) & 0x80)
3823         tmp = -tmp;
3824     fpush();
3825     ST0 = tmp;
3826 }
3827
3828 void helper_fbst_ST0(target_ulong ptr)
3829 {
3830     int v;
3831     target_ulong mem_ref, mem_end;
3832     int64_t val;
3833
3834     val = floatx_to_int64(ST0, &env->fp_status);
3835     mem_ref = ptr;
3836     mem_end = mem_ref + 9;
3837     if (val < 0) {
3838         stb(mem_end, 0x80);
3839         val = -val;
3840     } else {
3841         stb(mem_end, 0x00);
3842     }
3843     while (mem_ref < mem_end) {
3844         if (val == 0)
3845             break;
3846         v = val % 100;
3847         val = val / 100;
3848         v = ((v / 10) << 4) | (v % 10);
3849         stb(mem_ref++, v);
3850     }
3851     while (mem_ref < mem_end) {
3852         stb(mem_ref++, 0);
3853     }
3854 }
3855
3856 void helper_f2xm1(void)
3857 {
3858     ST0 = pow(2.0,ST0) - 1.0;
3859 }
3860
3861 void helper_fyl2x(void)
3862 {
3863     CPU86_LDouble fptemp;
3864
3865     fptemp = ST0;
3866     if (fptemp>0.0){
3867         fptemp = log(fptemp)/log(2.0);   /* log2(ST) */
3868         ST1 *= fptemp;
3869         fpop();
3870     } else {
3871         env->fpus &= (~0x4700);
3872         env->fpus |= 0x400;
3873     }
3874 }
3875
3876 void helper_fptan(void)
3877 {
3878     CPU86_LDouble fptemp;
3879
3880     fptemp = ST0;
3881     if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
3882         env->fpus |= 0x400;
3883     } else {
3884         ST0 = tan(fptemp);
3885         fpush();
3886         ST0 = 1.0;
3887         env->fpus &= (~0x400);  /* C2 <-- 0 */
3888         /* the above code is for  |arg| < 2**52 only */
3889     }
3890 }
3891
3892 void helper_fpatan(void)
3893 {
3894     CPU86_LDouble fptemp, fpsrcop;
3895
3896     fpsrcop = ST1;
3897     fptemp = ST0;
3898     ST1 = atan2(fpsrcop,fptemp);
3899     fpop();
3900 }
3901
3902 void helper_fxtract(void)
3903 {
3904     CPU86_LDoubleU temp;
3905     unsigned int expdif;
3906
3907     temp.d = ST0;
3908     expdif = EXPD(temp) - EXPBIAS;
3909     /*DP exponent bias*/
3910     ST0 = expdif;
3911     fpush();
3912     BIASEXPONENT(temp);
3913     ST0 = temp.d;
3914 }
3915
3916 void helper_fprem1(void)
3917 {
3918     CPU86_LDouble dblq, fpsrcop, fptemp;
3919     CPU86_LDoubleU fpsrcop1, fptemp1;
3920     int expdif;
3921     signed long long int q;
3922
3923     if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
3924         ST0 = 0.0 / 0.0; /* NaN */
3925         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
3926         return;
3927     }
3928
3929     fpsrcop = ST0;
3930     fptemp = ST1;
3931     fpsrcop1.d = fpsrcop;
3932     fptemp1.d = fptemp;
3933     expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
3934
3935     if (expdif < 0) {
3936         /* optimisation? taken from the AMD docs */
3937         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
3938         /* ST0 is unchanged */
3939         return;
3940     }
3941
3942     if (expdif < 53) {
3943         dblq = fpsrcop / fptemp;
3944         /* round dblq towards nearest integer */
3945         dblq = rint(dblq);
3946         ST0 = fpsrcop - fptemp * dblq;
3947
3948         /* convert dblq to q by truncating towards zero */
3949         if (dblq < 0.0)
3950            q = (signed long long int)(-dblq);
3951         else
3952            q = (signed long long int)dblq;
3953
3954         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
3955                                 /* (C0,C3,C1) <-- (q2,q1,q0) */
3956         env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
3957         env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
3958         env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
3959     } else {
3960         env->fpus |= 0x400;  /* C2 <-- 1 */
3961         fptemp = pow(2.0, expdif - 50);
3962         fpsrcop = (ST0 / ST1) / fptemp;
3963         /* fpsrcop = integer obtained by chopping */
3964         fpsrcop = (fpsrcop < 0.0) ?
3965                   -(floor(fabs(fpsrcop))) : floor(fpsrcop);
3966         ST0 -= (ST1 * fpsrcop * fptemp);
3967     }
3968 }
3969
3970 void helper_fprem(void)
3971 {
3972     CPU86_LDouble dblq, fpsrcop, fptemp;
3973     CPU86_LDoubleU fpsrcop1, fptemp1;
3974     int expdif;
3975     signed long long int q;
3976
3977     if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
3978        ST0 = 0.0 / 0.0; /* NaN */
3979        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
3980        return;
3981     }
3982
3983     fpsrcop = (CPU86_LDouble)ST0;
3984     fptemp = (CPU86_LDouble)ST1;
3985     fpsrcop1.d = fpsrcop;
3986     fptemp1.d = fptemp;
3987     expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
3988
3989     if (expdif < 0) {
3990         /* optimisation? taken from the AMD docs */
3991         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
3992         /* ST0 is unchanged */
3993         return;
3994     }
3995
3996     if ( expdif < 53 ) {
3997         dblq = fpsrcop/*ST0*/ / fptemp/*ST1*/;
3998         /* round dblq towards zero */
3999         dblq = (dblq < 0.0) ? ceil(dblq) : floor(dblq);
4000         ST0 = fpsrcop/*ST0*/ - fptemp * dblq;
4001
4002         /* convert dblq to q by truncating towards zero */
4003         if (dblq < 0.0)
4004            q = (signed long long int)(-dblq);
4005         else
4006            q = (signed long long int)dblq;
4007
4008         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
4009                                 /* (C0,C3,C1) <-- (q2,q1,q0) */
4010         env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
4011         env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
4012         env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
4013     } else {
4014         int N = 32 + (expdif % 32); /* as per AMD docs */
4015         env->fpus |= 0x400;  /* C2 <-- 1 */
4016         fptemp = pow(2.0, (double)(expdif - N));
4017         fpsrcop = (ST0 / ST1) / fptemp;
4018         /* fpsrcop = integer obtained by chopping */
4019         fpsrcop = (fpsrcop < 0.0) ?
4020                   -(floor(fabs(fpsrcop))) : floor(fpsrcop);
4021         ST0 -= (ST1 * fpsrcop * fptemp);
4022     }
4023 }
4024
4025 void helper_fyl2xp1(void)
4026 {
4027     CPU86_LDouble fptemp;
4028
4029     fptemp = ST0;
4030     if ((fptemp+1.0)>0.0) {
4031         fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
4032         ST1 *= fptemp;
4033         fpop();
4034     } else {
4035         env->fpus &= (~0x4700);
4036         env->fpus |= 0x400;
4037     }
4038 }
4039
4040 void helper_fsqrt(void)
4041 {
4042     CPU86_LDouble fptemp;
4043
4044     fptemp = ST0;
4045     if (fptemp<0.0) {
4046         env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
4047         env->fpus |= 0x400;
4048     }
4049     ST0 = sqrt(fptemp);
4050 }
4051
4052 void helper_fsincos(void)
4053 {
4054     CPU86_LDouble fptemp;
4055
4056     fptemp = ST0;
4057     if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4058         env->fpus |= 0x400;
4059     } else {
4060         ST0 = sin(fptemp);
4061         fpush();
4062         ST0 = cos(fptemp);
4063         env->fpus &= (~0x400);  /* C2 <-- 0 */
4064         /* the above code is for  |arg| < 2**63 only */
4065     }
4066 }
4067
4068 void helper_frndint(void)
4069 {
4070     ST0 = floatx_round_to_int(ST0, &env->fp_status);
4071 }
4072
4073 void helper_fscale(void)
4074 {
4075     ST0 = ldexp (ST0, (int)(ST1));
4076 }
4077
4078 void helper_fsin(void)
4079 {
4080     CPU86_LDouble fptemp;
4081
4082     fptemp = ST0;
4083     if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4084         env->fpus |= 0x400;
4085     } else {
4086         ST0 = sin(fptemp);
4087         env->fpus &= (~0x400);  /* C2 <-- 0 */
4088         /* the above code is for  |arg| < 2**53 only */
4089     }
4090 }
4091
4092 void helper_fcos(void)
4093 {
4094     CPU86_LDouble fptemp;
4095
4096     fptemp = ST0;
4097     if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
4098         env->fpus |= 0x400;
4099     } else {
4100         ST0 = cos(fptemp);
4101         env->fpus &= (~0x400);  /* C2 <-- 0 */
4102         /* the above code is for  |arg5 < 2**63 only */
4103     }
4104 }
4105
4106 void helper_fxam_ST0(void)
4107 {
4108     CPU86_LDoubleU temp;
4109     int expdif;
4110
4111     temp.d = ST0;
4112
4113     env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
4114     if (SIGND(temp))
4115         env->fpus |= 0x200; /* C1 <-- 1 */
4116
4117     /* XXX: test fptags too */
4118     expdif = EXPD(temp);
4119     if (expdif == MAXEXPD) {
4120 #ifdef USE_X86LDOUBLE
4121         if (MANTD(temp) == 0x8000000000000000ULL)
4122 #else
4123         if (MANTD(temp) == 0)
4124 #endif
4125             env->fpus |=  0x500 /*Infinity*/;
4126         else
4127             env->fpus |=  0x100 /*NaN*/;
4128     } else if (expdif == 0) {
4129         if (MANTD(temp) == 0)
4130             env->fpus |=  0x4000 /*Zero*/;
4131         else
4132             env->fpus |= 0x4400 /*Denormal*/;
4133     } else {
4134         env->fpus |= 0x400;
4135     }
4136 }
4137
4138 void helper_fstenv(target_ulong ptr, int data32)
4139 {
4140     int fpus, fptag, exp, i;
4141     uint64_t mant;
4142     CPU86_LDoubleU tmp;
4143
4144     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
4145     fptag = 0;
4146     for (i=7; i>=0; i--) {
4147         fptag <<= 2;
4148         if (env->fptags[i]) {
4149             fptag |= 3;
4150         } else {
4151             tmp.d = env->fpregs[i].d;
4152             exp = EXPD(tmp);
4153             mant = MANTD(tmp);
4154             if (exp == 0 && mant == 0) {
4155                 /* zero */
4156                 fptag |= 1;
4157             } else if (exp == 0 || exp == MAXEXPD
4158 #ifdef USE_X86LDOUBLE
4159                        || (mant & (1LL << 63)) == 0
4160 #endif
4161                        ) {
4162                 /* NaNs, infinity, denormal */
4163                 fptag |= 2;
4164             }
4165         }
4166     }
4167     if (data32) {
4168         /* 32 bit */
4169         stl(ptr, env->fpuc);
4170         stl(ptr + 4, fpus);
4171         stl(ptr + 8, fptag);
4172         stl(ptr + 12, 0); /* fpip */
4173         stl(ptr + 16, 0); /* fpcs */
4174         stl(ptr + 20, 0); /* fpoo */
4175         stl(ptr + 24, 0); /* fpos */
4176     } else {
4177         /* 16 bit */
4178         stw(ptr, env->fpuc);
4179         stw(ptr + 2, fpus);
4180         stw(ptr + 4, fptag);
4181         stw(ptr + 6, 0);
4182         stw(ptr + 8, 0);
4183         stw(ptr + 10, 0);
4184         stw(ptr + 12, 0);
4185     }
4186 }
4187
4188 void helper_fldenv(target_ulong ptr, int data32)
4189 {
4190     int i, fpus, fptag;
4191
4192     if (data32) {
4193         env->fpuc = lduw(ptr);
4194         fpus = lduw(ptr + 4);
4195         fptag = lduw(ptr + 8);
4196     }
4197     else {
4198         env->fpuc = lduw(ptr);
4199         fpus = lduw(ptr + 2);
4200         fptag = lduw(ptr + 4);
4201     }
4202     env->fpstt = (fpus >> 11) & 7;
4203     env->fpus = fpus & ~0x3800;
4204     for(i = 0;i < 8; i++) {
4205         env->fptags[i] = ((fptag & 3) == 3);
4206         fptag >>= 2;
4207     }
4208 }
4209
4210 void helper_fsave(target_ulong ptr, int data32)
4211 {
4212     CPU86_LDouble tmp;
4213     int i;
4214
4215     helper_fstenv(ptr, data32);
4216
4217     ptr += (14 << data32);
4218     for(i = 0;i < 8; i++) {
4219         tmp = ST(i);
4220         helper_fstt(tmp, ptr);
4221         ptr += 10;
4222     }
4223
4224     /* fninit */
4225     env->fpus = 0;
4226     env->fpstt = 0;
4227     env->fpuc = 0x37f;
4228     env->fptags[0] = 1;
4229     env->fptags[1] = 1;
4230     env->fptags[2] = 1;
4231     env->fptags[3] = 1;
4232     env->fptags[4] = 1;
4233     env->fptags[5] = 1;
4234     env->fptags[6] = 1;
4235     env->fptags[7] = 1;
4236 }
4237
4238 void helper_frstor(target_ulong ptr, int data32)
4239 {
4240     CPU86_LDouble tmp;
4241     int i;
4242
4243     helper_fldenv(ptr, data32);
4244     ptr += (14 << data32);
4245
4246     for(i = 0;i < 8; i++) {
4247         tmp = helper_fldt(ptr);
4248         ST(i) = tmp;
4249         ptr += 10;
4250     }
4251 }
4252
4253 void helper_fxsave(target_ulong ptr, int data64)
4254 {
4255     int fpus, fptag, i, nb_xmm_regs;
4256     CPU86_LDouble tmp;
4257     target_ulong addr;
4258
4259     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
4260     fptag = 0;
4261     for(i = 0; i < 8; i++) {
4262         fptag |= (env->fptags[i] << i);
4263     }
4264     stw(ptr, env->fpuc);
4265     stw(ptr + 2, fpus);
4266     stw(ptr + 4, fptag ^ 0xff);
4267 #ifdef TARGET_X86_64
4268     if (data64) {
4269         stq(ptr + 0x08, 0); /* rip */
4270         stq(ptr + 0x10, 0); /* rdp */
4271     } else 
4272 #endif
4273     {
4274         stl(ptr + 0x08, 0); /* eip */
4275         stl(ptr + 0x0c, 0); /* sel  */
4276         stl(ptr + 0x10, 0); /* dp */
4277         stl(ptr + 0x14, 0); /* sel  */
4278     }
4279
4280     addr = ptr + 0x20;
4281     for(i = 0;i < 8; i++) {
4282         tmp = ST(i);
4283         helper_fstt(tmp, addr);
4284         addr += 16;
4285     }
4286
4287     if (env->cr[4] & CR4_OSFXSR_MASK) {
4288         /* XXX: finish it */
4289         stl(ptr + 0x18, env->mxcsr); /* mxcsr */
4290         stl(ptr + 0x1c, 0x0000ffff); /* mxcsr_mask */
4291         if (env->hflags & HF_CS64_MASK)
4292             nb_xmm_regs = 16;
4293         else
4294             nb_xmm_regs = 8;
4295         addr = ptr + 0xa0;
4296         for(i = 0; i < nb_xmm_regs; i++) {
4297             stq(addr, env->xmm_regs[i].XMM_Q(0));
4298             stq(addr + 8, env->xmm_regs[i].XMM_Q(1));
4299             addr += 16;
4300         }
4301     }
4302 }
4303
4304 void helper_fxrstor(target_ulong ptr, int data64)
4305 {
4306     int i, fpus, fptag, nb_xmm_regs;
4307     CPU86_LDouble tmp;
4308     target_ulong addr;
4309
4310     env->fpuc = lduw(ptr);
4311     fpus = lduw(ptr + 2);
4312     fptag = lduw(ptr + 4);
4313     env->fpstt = (fpus >> 11) & 7;
4314     env->fpus = fpus & ~0x3800;
4315     fptag ^= 0xff;
4316     for(i = 0;i < 8; i++) {
4317         env->fptags[i] = ((fptag >> i) & 1);
4318     }
4319
4320     addr = ptr + 0x20;
4321     for(i = 0;i < 8; i++) {
4322         tmp = helper_fldt(addr);
4323         ST(i) = tmp;
4324         addr += 16;
4325     }
4326
4327     if (env->cr[4] & CR4_OSFXSR_MASK) {
4328         /* XXX: finish it */
4329         env->mxcsr = ldl(ptr + 0x18);
4330         //ldl(ptr + 0x1c);
4331         if (env->hflags & HF_CS64_MASK)
4332             nb_xmm_regs = 16;
4333         else
4334             nb_xmm_regs = 8;
4335         addr = ptr + 0xa0;
4336         for(i = 0; i < nb_xmm_regs; i++) {
4337             env->xmm_regs[i].XMM_Q(0) = ldq(addr);
4338             env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
4339             addr += 16;
4340         }
4341     }
4342 }
4343
4344 #ifndef USE_X86LDOUBLE
4345
4346 void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
4347 {
4348     CPU86_LDoubleU temp;
4349     int e;
4350
4351     temp.d = f;
4352     /* mantissa */
4353     *pmant = (MANTD(temp) << 11) | (1LL << 63);
4354     /* exponent + sign */
4355     e = EXPD(temp) - EXPBIAS + 16383;
4356     e |= SIGND(temp) >> 16;
4357     *pexp = e;
4358 }
4359
4360 CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
4361 {
4362     CPU86_LDoubleU temp;
4363     int e;
4364     uint64_t ll;
4365
4366     /* XXX: handle overflow ? */
4367     e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
4368     e |= (upper >> 4) & 0x800; /* sign */
4369     ll = (mant >> 11) & ((1LL << 52) - 1);
4370 #ifdef __arm__
4371     temp.l.upper = (e << 20) | (ll >> 32);
4372     temp.l.lower = ll;
4373 #else
4374     temp.ll = ll | ((uint64_t)e << 52);
4375 #endif
4376     return temp.d;
4377 }
4378
4379 #else
4380
4381 void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
4382 {
4383     CPU86_LDoubleU temp;
4384
4385     temp.d = f;
4386     *pmant = temp.l.lower;
4387     *pexp = temp.l.upper;
4388 }
4389
4390 CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
4391 {
4392     CPU86_LDoubleU temp;
4393
4394     temp.l.upper = upper;
4395     temp.l.lower = mant;
4396     return temp.d;
4397 }
4398 #endif
4399
4400 #ifdef TARGET_X86_64
4401
4402 //#define DEBUG_MULDIV
4403
4404 static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
4405 {
4406     *plow += a;
4407     /* carry test */
4408     if (*plow < a)
4409         (*phigh)++;
4410     *phigh += b;
4411 }
4412
4413 static void neg128(uint64_t *plow, uint64_t *phigh)
4414 {
4415     *plow = ~ *plow;
4416     *phigh = ~ *phigh;
4417     add128(plow, phigh, 1, 0);
4418 }
4419
4420 /* return TRUE if overflow */
4421 static int div64(uint64_t *plow, uint64_t *phigh, uint64_t b)
4422 {
4423     uint64_t q, r, a1, a0;
4424     int i, qb, ab;
4425
4426     a0 = *plow;
4427     a1 = *phigh;
4428     if (a1 == 0) {
4429         q = a0 / b;
4430         r = a0 % b;
4431         *plow = q;
4432         *phigh = r;
4433     } else {
4434         if (a1 >= b)
4435             return 1;
4436         /* XXX: use a better algorithm */
4437         for(i = 0; i < 64; i++) {
4438             ab = a1 >> 63;
4439             a1 = (a1 << 1) | (a0 >> 63);
4440             if (ab || a1 >= b) {
4441                 a1 -= b;
4442                 qb = 1;
4443             } else {
4444                 qb = 0;
4445             }
4446             a0 = (a0 << 1) | qb;
4447         }
4448 #if defined(DEBUG_MULDIV)
4449         printf("div: 0x%016" PRIx64 "%016" PRIx64 " / 0x%016" PRIx64 ": q=0x%016" PRIx64 " r=0x%016" PRIx64 "\n",
4450                *phigh, *plow, b, a0, a1);
4451 #endif
4452         *plow = a0;
4453         *phigh = a1;
4454     }
4455     return 0;
4456 }
4457
4458 /* return TRUE if overflow */
4459 static int idiv64(uint64_t *plow, uint64_t *phigh, int64_t b)
4460 {
4461     int sa, sb;
4462     sa = ((int64_t)*phigh < 0);
4463     if (sa)
4464         neg128(plow, phigh);
4465     sb = (b < 0);
4466     if (sb)
4467         b = -b;
4468     if (div64(plow, phigh, b) != 0)
4469         return 1;
4470     if (sa ^ sb) {
4471         if (*plow > (1ULL << 63))
4472             return 1;
4473         *plow = - *plow;
4474     } else {
4475         if (*plow >= (1ULL << 63))
4476             return 1;
4477     }
4478     if (sa)
4479         *phigh = - *phigh;
4480     return 0;
4481 }
4482
4483 void helper_mulq_EAX_T0(target_ulong t0)
4484 {
4485     uint64_t r0, r1;
4486
4487     mulu64(&r0, &r1, EAX, t0);
4488     EAX = r0;
4489     EDX = r1;
4490     CC_DST = r0;
4491     CC_SRC = r1;
4492 }
4493
4494 void helper_imulq_EAX_T0(target_ulong t0)
4495 {
4496     uint64_t r0, r1;
4497
4498     muls64(&r0, &r1, EAX, t0);
4499     EAX = r0;
4500     EDX = r1;
4501     CC_DST = r0;
4502     CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
4503 }
4504
4505 target_ulong helper_imulq_T0_T1(target_ulong t0, target_ulong t1)
4506 {
4507     uint64_t r0, r1;
4508
4509     muls64(&r0, &r1, t0, t1);
4510     CC_DST = r0;
4511     CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
4512     return r0;
4513 }
4514
4515 void helper_divq_EAX(target_ulong t0)
4516 {
4517     uint64_t r0, r1;
4518     if (t0 == 0) {
4519         raise_exception(EXCP00_DIVZ);
4520     }
4521     r0 = EAX;
4522     r1 = EDX;
4523     if (div64(&r0, &r1, t0))
4524         raise_exception(EXCP00_DIVZ);
4525     EAX = r0;
4526     EDX = r1;
4527 }
4528
4529 void helper_idivq_EAX(target_ulong t0)
4530 {
4531     uint64_t r0, r1;
4532     if (t0 == 0) {
4533         raise_exception(EXCP00_DIVZ);
4534     }
4535     r0 = EAX;
4536     r1 = EDX;
4537     if (idiv64(&r0, &r1, t0))
4538         raise_exception(EXCP00_DIVZ);
4539     EAX = r0;
4540     EDX = r1;
4541 }
4542 #endif
4543
4544 void helper_hlt(void)
4545 {
4546     helper_svm_check_intercept_param(SVM_EXIT_HLT, 0);
4547     
4548     env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
4549     env->halted = 1;
4550     env->exception_index = EXCP_HLT;
4551     cpu_loop_exit();
4552 }
4553
4554 void helper_monitor(target_ulong ptr)
4555 {
4556     if ((uint32_t)ECX != 0)
4557         raise_exception(EXCP0D_GPF);
4558     /* XXX: store address ? */
4559     helper_svm_check_intercept_param(SVM_EXIT_MONITOR, 0);
4560 }
4561
4562 void helper_mwait(void)
4563 {
4564     if ((uint32_t)ECX != 0)
4565         raise_exception(EXCP0D_GPF);
4566     helper_svm_check_intercept_param(SVM_EXIT_MWAIT, 0);
4567     /* XXX: not complete but not completely erroneous */
4568     if (env->cpu_index != 0 || env->next_cpu != NULL) {
4569         /* more than one CPU: do not sleep because another CPU may
4570            wake this one */
4571     } else {
4572         helper_hlt();
4573     }
4574 }
4575
4576 void helper_debug(void)
4577 {
4578     env->exception_index = EXCP_DEBUG;
4579     cpu_loop_exit();
4580 }
4581
4582 void helper_raise_interrupt(int intno, int next_eip_addend)
4583 {
4584     raise_interrupt(intno, 1, 0, next_eip_addend);
4585 }
4586
4587 void helper_raise_exception(int exception_index)
4588 {
4589     raise_exception(exception_index);
4590 }
4591
4592 void helper_cli(void)
4593 {
4594     env->eflags &= ~IF_MASK;
4595 }
4596
4597 void helper_sti(void)
4598 {
4599     env->eflags |= IF_MASK;
4600 }
4601
4602 #if 0
4603 /* vm86plus instructions */
4604 void helper_cli_vm(void)
4605 {
4606     env->eflags &= ~VIF_MASK;
4607 }
4608
4609 void helper_sti_vm(void)
4610 {
4611     env->eflags |= VIF_MASK;
4612     if (env->eflags & VIP_MASK) {
4613         raise_exception(EXCP0D_GPF);
4614     }
4615 }
4616 #endif
4617
4618 void helper_set_inhibit_irq(void)
4619 {
4620     env->hflags |= HF_INHIBIT_IRQ_MASK;
4621 }
4622
4623 void helper_reset_inhibit_irq(void)
4624 {
4625     env->hflags &= ~HF_INHIBIT_IRQ_MASK;
4626 }
4627
4628 void helper_boundw(target_ulong a0, int v)
4629 {
4630     int low, high;
4631     low = ldsw(a0);
4632     high = ldsw(a0 + 2);
4633     v = (int16_t)v;
4634     if (v < low || v > high) {
4635         raise_exception(EXCP05_BOUND);
4636     }
4637     FORCE_RET();
4638 }
4639
4640 void helper_boundl(target_ulong a0, int v)
4641 {
4642     int low, high;
4643     low = ldl(a0);
4644     high = ldl(a0 + 4);
4645     if (v < low || v > high) {
4646         raise_exception(EXCP05_BOUND);
4647     }
4648     FORCE_RET();
4649 }
4650
4651 static float approx_rsqrt(float a)
4652 {
4653     return 1.0 / sqrt(a);
4654 }
4655
4656 static float approx_rcp(float a)
4657 {
4658     return 1.0 / a;
4659 }
4660
4661 #if !defined(CONFIG_USER_ONLY)
4662
4663 #define MMUSUFFIX _mmu
4664
4665 #define SHIFT 0
4666 #include "softmmu_template.h"
4667
4668 #define SHIFT 1
4669 #include "softmmu_template.h"
4670
4671 #define SHIFT 2
4672 #include "softmmu_template.h"
4673
4674 #define SHIFT 3
4675 #include "softmmu_template.h"
4676
4677 #endif
4678
4679 /* try to fill the TLB and return an exception if error. If retaddr is
4680    NULL, it means that the function was called in C code (i.e. not
4681    from generated code or from helper.c) */
4682 /* XXX: fix it to restore all registers */
4683 void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
4684 {
4685     TranslationBlock *tb;
4686     int ret;
4687     unsigned long pc;
4688     CPUX86State *saved_env;
4689
4690     /* XXX: hack to restore env in all cases, even if not called from
4691        generated code */
4692     saved_env = env;
4693     env = cpu_single_env;
4694
4695     ret = cpu_x86_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
4696     if (ret) {
4697         if (retaddr) {
4698             /* now we have a real cpu fault */
4699             pc = (unsigned long)retaddr;
4700             tb = tb_find_pc(pc);
4701             if (tb) {
4702                 /* the PC is inside the translated code. It means that we have
4703                    a virtual CPU fault */
4704                 cpu_restore_state(tb, env, pc, NULL);
4705             }
4706         }
4707         raise_exception_err(env->exception_index, env->error_code);
4708     }
4709     env = saved_env;
4710 }
4711
4712
4713 /* Secure Virtual Machine helpers */
4714
4715 #if defined(CONFIG_USER_ONLY)
4716
4717 void helper_vmrun(void) 
4718
4719 }
4720 void helper_vmmcall(void) 
4721
4722 }
4723 void helper_vmload(void) 
4724
4725 }
4726 void helper_vmsave(void) 
4727
4728 }
4729 void helper_stgi(void)
4730 {
4731 }
4732 void helper_clgi(void)
4733 {
4734 }
4735 void helper_skinit(void) 
4736
4737 }
4738 void helper_invlpga(void) 
4739
4740 }
4741 void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) 
4742
4743 }
4744 void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
4745 {
4746 }
4747
4748 void helper_svm_check_io(uint32_t port, uint32_t param, 
4749                          uint32_t next_eip_addend)
4750 {
4751 }
4752 #else
4753
4754 static inline void svm_save_seg(target_phys_addr_t addr,
4755                                 const SegmentCache *sc)
4756 {
4757     stw_phys(addr + offsetof(struct vmcb_seg, selector), 
4758              sc->selector);
4759     stq_phys(addr + offsetof(struct vmcb_seg, base), 
4760              sc->base);
4761     stl_phys(addr + offsetof(struct vmcb_seg, limit), 
4762              sc->limit);
4763     stw_phys(addr + offsetof(struct vmcb_seg, attrib), 
4764              (sc->flags >> 8) | ((sc->flags >> 12) & 0x0f00));
4765 }
4766                                 
4767 static inline void svm_load_seg(target_phys_addr_t addr, SegmentCache *sc)
4768 {
4769     unsigned int flags;
4770
4771     sc->selector = lduw_phys(addr + offsetof(struct vmcb_seg, selector));
4772     sc->base = ldq_phys(addr + offsetof(struct vmcb_seg, base));
4773     sc->limit = ldl_phys(addr + offsetof(struct vmcb_seg, limit));
4774     flags = lduw_phys(addr + offsetof(struct vmcb_seg, attrib));
4775     sc->flags = ((flags & 0xff) << 8) | ((flags & 0x0f00) << 12);
4776 }
4777
4778 static inline void svm_load_seg_cache(target_phys_addr_t addr, 
4779                                       CPUState *env, int seg_reg)
4780 {
4781     SegmentCache sc1, *sc = &sc1;
4782     svm_load_seg(addr, sc);
4783     cpu_x86_load_seg_cache(env, seg_reg, sc->selector,
4784                            sc->base, sc->limit, sc->flags);
4785 }
4786
4787 void helper_vmrun(void)
4788 {
4789     target_ulong addr;
4790     uint32_t event_inj;
4791     uint32_t int_ctl;
4792
4793     helper_svm_check_intercept_param(SVM_EXIT_VMRUN, 0);
4794
4795     addr = EAX;
4796     if (loglevel & CPU_LOG_TB_IN_ASM)
4797         fprintf(logfile,"vmrun! " TARGET_FMT_lx "\n", addr);
4798
4799     env->vm_vmcb = addr;
4800
4801     /* save the current CPU state in the hsave page */
4802     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
4803     stl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
4804
4805     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base), env->idt.base);
4806     stl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
4807
4808     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0), env->cr[0]);
4809     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr2), env->cr[2]);
4810     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3), env->cr[3]);
4811     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4), env->cr[4]);
4812     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr8), env->cr[8]);
4813     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6), env->dr[6]);
4814     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7), env->dr[7]);
4815
4816     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer), env->efer);
4817     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags), compute_eflags());
4818
4819     svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.es), 
4820                   &env->segs[R_ES]);
4821     svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.cs), 
4822                  &env->segs[R_CS]);
4823     svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ss), 
4824                  &env->segs[R_SS]);
4825     svm_save_seg(env->vm_hsave + offsetof(struct vmcb, save.ds), 
4826                  &env->segs[R_DS]);
4827
4828     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip), EIP);
4829     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp), ESP);
4830     stq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax), EAX);
4831
4832     /* load the interception bitmaps so we do not need to access the
4833        vmcb in svm mode */
4834     env->intercept            = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept));
4835     env->intercept_cr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_read));
4836     env->intercept_cr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_cr_write));
4837     env->intercept_dr_read    = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_read));
4838     env->intercept_dr_write   = lduw_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_dr_write));
4839     env->intercept_exceptions = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.intercept_exceptions));
4840
4841     /* enable intercepts */
4842     env->hflags |= HF_SVMI_MASK;
4843
4844     env->gdt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base));
4845     env->gdt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit));
4846
4847     env->idt.base  = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base));
4848     env->idt.limit = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit));
4849
4850     /* clear exit_info_2 so we behave like the real hardware */
4851     stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 0);
4852
4853     cpu_x86_update_cr0(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0)));
4854     cpu_x86_update_cr4(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4)));
4855     cpu_x86_update_cr3(env, ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3)));
4856     env->cr[2] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2));
4857     int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
4858     if (int_ctl & V_INTR_MASKING_MASK) {
4859         env->cr[8] = int_ctl & V_TPR_MASK;
4860         cpu_set_apic_tpr(env, env->cr[8]);
4861         if (env->eflags & IF_MASK)
4862             env->hflags |= HF_HIF_MASK;
4863     }
4864
4865 #ifdef TARGET_X86_64
4866     env->efer = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer));
4867     env->hflags &= ~HF_LMA_MASK;
4868     if (env->efer & MSR_EFER_LMA)
4869        env->hflags |= HF_LMA_MASK;
4870 #endif
4871     env->eflags = 0;
4872     load_eflags(ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags)),
4873                 ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
4874     CC_OP = CC_OP_EFLAGS;
4875
4876     svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.es),
4877                        env, R_ES);
4878     svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.cs),
4879                        env, R_CS);
4880     svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ss),
4881                        env, R_SS);
4882     svm_load_seg_cache(env->vm_vmcb + offsetof(struct vmcb, save.ds),
4883                        env, R_DS);
4884
4885     EIP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip));
4886     env->eip = EIP;
4887     ESP = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp));
4888     EAX = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax));
4889     env->dr[7] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7));
4890     env->dr[6] = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6));
4891     cpu_x86_set_cpl(env, ldub_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl)));
4892
4893     /* FIXME: guest state consistency checks */
4894
4895     switch(ldub_phys(env->vm_vmcb + offsetof(struct vmcb, control.tlb_ctl))) {
4896         case TLB_CONTROL_DO_NOTHING:
4897             break;
4898         case TLB_CONTROL_FLUSH_ALL_ASID:
4899             /* FIXME: this is not 100% correct but should work for now */
4900             tlb_flush(env, 1);
4901         break;
4902     }
4903
4904     helper_stgi();
4905
4906     /* maybe we need to inject an event */
4907     event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj));
4908     if (event_inj & SVM_EVTINJ_VALID) {
4909         uint8_t vector = event_inj & SVM_EVTINJ_VEC_MASK;
4910         uint16_t valid_err = event_inj & SVM_EVTINJ_VALID_ERR;
4911         uint32_t event_inj_err = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err));
4912         stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj & ~SVM_EVTINJ_VALID);
4913
4914         if (loglevel & CPU_LOG_TB_IN_ASM)
4915             fprintf(logfile, "Injecting(%#hx): ", valid_err);
4916         /* FIXME: need to implement valid_err */
4917         switch (event_inj & SVM_EVTINJ_TYPE_MASK) {
4918         case SVM_EVTINJ_TYPE_INTR:
4919                 env->exception_index = vector;
4920                 env->error_code = event_inj_err;
4921                 env->exception_is_int = 0;
4922                 env->exception_next_eip = -1;
4923                 if (loglevel & CPU_LOG_TB_IN_ASM)
4924                     fprintf(logfile, "INTR");
4925                 break;
4926         case SVM_EVTINJ_TYPE_NMI:
4927                 env->exception_index = vector;
4928                 env->error_code = event_inj_err;
4929                 env->exception_is_int = 0;
4930                 env->exception_next_eip = EIP;
4931                 if (loglevel & CPU_LOG_TB_IN_ASM)
4932                     fprintf(logfile, "NMI");
4933                 break;
4934         case SVM_EVTINJ_TYPE_EXEPT:
4935                 env->exception_index = vector;
4936                 env->error_code = event_inj_err;
4937                 env->exception_is_int = 0;
4938                 env->exception_next_eip = -1;
4939                 if (loglevel & CPU_LOG_TB_IN_ASM)
4940                     fprintf(logfile, "EXEPT");
4941                 break;
4942         case SVM_EVTINJ_TYPE_SOFT:
4943                 env->exception_index = vector;
4944                 env->error_code = event_inj_err;
4945                 env->exception_is_int = 1;
4946                 env->exception_next_eip = EIP;
4947                 if (loglevel & CPU_LOG_TB_IN_ASM)
4948                     fprintf(logfile, "SOFT");
4949                 break;
4950         }
4951         if (loglevel & CPU_LOG_TB_IN_ASM)
4952             fprintf(logfile, " %#x %#x\n", env->exception_index, env->error_code);
4953     }
4954     if ((int_ctl & V_IRQ_MASK) || 
4955         (env->intercept & (1ULL << (SVM_EXIT_INTR - SVM_EXIT_INTR)))) {
4956         env->interrupt_request |= CPU_INTERRUPT_VIRQ;
4957     }
4958
4959     cpu_loop_exit();
4960 }
4961
4962 void helper_vmmcall(void)
4963 {
4964     helper_svm_check_intercept_param(SVM_EXIT_VMMCALL, 0);
4965     raise_exception(EXCP06_ILLOP);
4966 }
4967
4968 void helper_vmload(void)
4969 {
4970     target_ulong addr;
4971     helper_svm_check_intercept_param(SVM_EXIT_VMLOAD, 0);
4972
4973     /* XXX: invalid in 32 bit */
4974     addr = EAX;
4975     if (loglevel & CPU_LOG_TB_IN_ASM)
4976         fprintf(logfile,"vmload! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
4977                 addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
4978                 env->segs[R_FS].base);
4979
4980     svm_load_seg_cache(addr + offsetof(struct vmcb, save.fs),
4981                        env, R_FS);
4982     svm_load_seg_cache(addr + offsetof(struct vmcb, save.gs),
4983                        env, R_GS);
4984     svm_load_seg(addr + offsetof(struct vmcb, save.tr),
4985                  &env->tr);
4986     svm_load_seg(addr + offsetof(struct vmcb, save.ldtr),
4987                  &env->ldt);
4988
4989 #ifdef TARGET_X86_64
4990     env->kernelgsbase = ldq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base));
4991     env->lstar = ldq_phys(addr + offsetof(struct vmcb, save.lstar));
4992     env->cstar = ldq_phys(addr + offsetof(struct vmcb, save.cstar));
4993     env->fmask = ldq_phys(addr + offsetof(struct vmcb, save.sfmask));
4994 #endif
4995     env->star = ldq_phys(addr + offsetof(struct vmcb, save.star));
4996     env->sysenter_cs = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_cs));
4997     env->sysenter_esp = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_esp));
4998     env->sysenter_eip = ldq_phys(addr + offsetof(struct vmcb, save.sysenter_eip));
4999 }
5000
5001 void helper_vmsave(void)
5002 {
5003     target_ulong addr;
5004     helper_svm_check_intercept_param(SVM_EXIT_VMSAVE, 0);
5005     addr = EAX;
5006     if (loglevel & CPU_LOG_TB_IN_ASM)
5007         fprintf(logfile,"vmsave! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
5008                 addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
5009                 env->segs[R_FS].base);
5010
5011     svm_save_seg(addr + offsetof(struct vmcb, save.fs), 
5012                  &env->segs[R_FS]);
5013     svm_save_seg(addr + offsetof(struct vmcb, save.gs), 
5014                  &env->segs[R_GS]);
5015     svm_save_seg(addr + offsetof(struct vmcb, save.tr), 
5016                  &env->tr);
5017     svm_save_seg(addr + offsetof(struct vmcb, save.ldtr), 
5018                  &env->ldt);
5019
5020 #ifdef TARGET_X86_64
5021     stq_phys(addr + offsetof(struct vmcb, save.kernel_gs_base), env->kernelgsbase);
5022     stq_phys(addr + offsetof(struct vmcb, save.lstar), env->lstar);
5023     stq_phys(addr + offsetof(struct vmcb, save.cstar), env->cstar);
5024     stq_phys(addr + offsetof(struct vmcb, save.sfmask), env->fmask);
5025 #endif
5026     stq_phys(addr + offsetof(struct vmcb, save.star), env->star);
5027     stq_phys(addr + offsetof(struct vmcb, save.sysenter_cs), env->sysenter_cs);
5028     stq_phys(addr + offsetof(struct vmcb, save.sysenter_esp), env->sysenter_esp);
5029     stq_phys(addr + offsetof(struct vmcb, save.sysenter_eip), env->sysenter_eip);
5030 }
5031
5032 void helper_stgi(void)
5033 {
5034     helper_svm_check_intercept_param(SVM_EXIT_STGI, 0);
5035     env->hflags |= HF_GIF_MASK;
5036 }
5037
5038 void helper_clgi(void)
5039 {
5040     helper_svm_check_intercept_param(SVM_EXIT_CLGI, 0);
5041     env->hflags &= ~HF_GIF_MASK;
5042 }
5043
5044 void helper_skinit(void)
5045 {
5046     helper_svm_check_intercept_param(SVM_EXIT_SKINIT, 0);
5047     /* XXX: not implemented */
5048     if (loglevel & CPU_LOG_TB_IN_ASM)
5049         fprintf(logfile,"skinit!\n");
5050     raise_exception(EXCP06_ILLOP);
5051 }
5052
5053 void helper_invlpga(void)
5054 {
5055     helper_svm_check_intercept_param(SVM_EXIT_INVLPGA, 0);
5056     tlb_flush(env, 0);
5057 }
5058
5059 void helper_svm_check_intercept_param(uint32_t type, uint64_t param)
5060 {
5061     if (likely(!(env->hflags & HF_SVMI_MASK)))
5062         return;
5063     switch(type) {
5064     case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR0 + 8:
5065         if (env->intercept_cr_read & (1 << (type - SVM_EXIT_READ_CR0))) {
5066             helper_vmexit(type, param);
5067         }
5068         break;
5069     case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR0 + 8:
5070         if (env->intercept_cr_write & (1 << (type - SVM_EXIT_WRITE_CR0))) {
5071             helper_vmexit(type, param);
5072         }
5073         break;
5074     case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR0 + 7:
5075         if (env->intercept_dr_read & (1 << (type - SVM_EXIT_READ_DR0))) {
5076             helper_vmexit(type, param);
5077         }
5078         break;
5079     case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR0 + 7:
5080         if (env->intercept_dr_write & (1 << (type - SVM_EXIT_WRITE_DR0))) {
5081             helper_vmexit(type, param);
5082         }
5083         break;
5084     case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 31:
5085         if (env->intercept_exceptions & (1 << (type - SVM_EXIT_EXCP_BASE))) {
5086             helper_vmexit(type, param);
5087         }
5088         break;
5089     case SVM_EXIT_MSR:
5090         if (env->intercept & (1ULL << (SVM_EXIT_MSR - SVM_EXIT_INTR))) {
5091             /* FIXME: this should be read in at vmrun (faster this way?) */
5092             uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.msrpm_base_pa));
5093             uint32_t t0, t1;
5094             switch((uint32_t)ECX) {
5095             case 0 ... 0x1fff:
5096                 t0 = (ECX * 2) % 8;
5097                 t1 = ECX / 8;
5098                 break;
5099             case 0xc0000000 ... 0xc0001fff:
5100                 t0 = (8192 + ECX - 0xc0000000) * 2;
5101                 t1 = (t0 / 8);
5102                 t0 %= 8;
5103                 break;
5104             case 0xc0010000 ... 0xc0011fff:
5105                 t0 = (16384 + ECX - 0xc0010000) * 2;
5106                 t1 = (t0 / 8);
5107                 t0 %= 8;
5108                 break;
5109             default:
5110                 helper_vmexit(type, param);
5111                 t0 = 0;
5112                 t1 = 0;
5113                 break;
5114             }
5115             if (ldub_phys(addr + t1) & ((1 << param) << t0))
5116                 helper_vmexit(type, param);
5117         }
5118         break;
5119     default:
5120         if (env->intercept & (1ULL << (type - SVM_EXIT_INTR))) {
5121             helper_vmexit(type, param);
5122         }
5123         break;
5124     }
5125 }
5126
5127 void helper_svm_check_io(uint32_t port, uint32_t param, 
5128                          uint32_t next_eip_addend)
5129 {
5130     if (env->intercept & (1ULL << (SVM_EXIT_IOIO - SVM_EXIT_INTR))) {
5131         /* FIXME: this should be read in at vmrun (faster this way?) */
5132         uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.iopm_base_pa));
5133         uint16_t mask = (1 << ((param >> 4) & 7)) - 1;
5134         if(lduw_phys(addr + port / 8) & (mask << (port & 7))) {
5135             /* next EIP */
5136             stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 
5137                      env->eip + next_eip_addend);
5138             helper_vmexit(SVM_EXIT_IOIO, param | (port << 16));
5139         }
5140     }
5141 }
5142
5143 /* Note: currently only 32 bits of exit_code are used */
5144 void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1)
5145 {
5146     uint32_t int_ctl;
5147
5148     if (loglevel & CPU_LOG_TB_IN_ASM)
5149         fprintf(logfile,"vmexit(%08x, %016" PRIx64 ", %016" PRIx64 ", " TARGET_FMT_lx ")!\n",
5150                 exit_code, exit_info_1,
5151                 ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2)),
5152                 EIP);
5153
5154     if(env->hflags & HF_INHIBIT_IRQ_MASK) {
5155         stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), SVM_INTERRUPT_SHADOW_MASK);
5156         env->hflags &= ~HF_INHIBIT_IRQ_MASK;
5157     } else {
5158         stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), 0);
5159     }
5160
5161     /* Save the VM state in the vmcb */
5162     svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.es), 
5163                  &env->segs[R_ES]);
5164     svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.cs), 
5165                  &env->segs[R_CS]);
5166     svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.ss), 
5167                  &env->segs[R_SS]);
5168     svm_save_seg(env->vm_vmcb + offsetof(struct vmcb, save.ds), 
5169                  &env->segs[R_DS]);
5170
5171     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.base), env->gdt.base);
5172     stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.gdtr.limit), env->gdt.limit);
5173
5174     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.base), env->idt.base);
5175     stl_phys(env->vm_vmcb + offsetof(struct vmcb, save.idtr.limit), env->idt.limit);
5176
5177     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer), env->efer);
5178     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr0), env->cr[0]);
5179     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr2), env->cr[2]);
5180     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr3), env->cr[3]);
5181     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.cr4), env->cr[4]);
5182
5183     if ((int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl))) & V_INTR_MASKING_MASK) {
5184         int_ctl &= ~V_TPR_MASK;
5185         int_ctl |= env->cr[8] & V_TPR_MASK;
5186         stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), int_ctl);
5187     }
5188
5189     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags), compute_eflags());
5190     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rip), env->eip);
5191     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rsp), ESP);
5192     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rax), EAX);
5193     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr7), env->dr[7]);
5194     stq_phys(env->vm_vmcb + offsetof(struct vmcb, save.dr6), env->dr[6]);
5195     stb_phys(env->vm_vmcb + offsetof(struct vmcb, save.cpl), env->hflags & HF_CPL_MASK);
5196
5197     /* Reload the host state from vm_hsave */
5198     env->hflags &= ~HF_HIF_MASK;
5199     env->hflags &= ~HF_SVMI_MASK;
5200     env->intercept = 0;
5201     env->intercept_exceptions = 0;
5202     env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
5203
5204     env->gdt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base));
5205     env->gdt.limit = ldl_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.limit));
5206
5207     env->idt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.base));
5208     env->idt.limit = ldl_phys(env->vm_hsave + offsetof(struct vmcb, save.idtr.limit));
5209
5210     cpu_x86_update_cr0(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr0)) | CR0_PE_MASK);
5211     cpu_x86_update_cr4(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr4)));
5212     cpu_x86_update_cr3(env, ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr3)));
5213     if (int_ctl & V_INTR_MASKING_MASK) {
5214         env->cr[8] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr8));
5215         cpu_set_apic_tpr(env, env->cr[8]);
5216     }
5217     /* we need to set the efer after the crs so the hidden flags get set properly */
5218 #ifdef TARGET_X86_64
5219     env->efer  = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer));
5220     env->hflags &= ~HF_LMA_MASK;
5221     if (env->efer & MSR_EFER_LMA)
5222        env->hflags |= HF_LMA_MASK;
5223     /* XXX: should also emulate the VM_CR MSR */
5224     env->hflags &= ~HF_SVME_MASK;
5225     if (env->cpuid_ext3_features & CPUID_EXT3_SVM) {
5226         if (env->efer & MSR_EFER_SVME)
5227             env->hflags |= HF_SVME_MASK;
5228     } else {
5229         env->efer &= ~MSR_EFER_SVME;
5230     }
5231 #endif
5232
5233     env->eflags = 0;
5234     load_eflags(ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rflags)),
5235                 ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
5236     CC_OP = CC_OP_EFLAGS;
5237
5238     svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.es),
5239                        env, R_ES);
5240     svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.cs),
5241                        env, R_CS);
5242     svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.ss),
5243                        env, R_SS);
5244     svm_load_seg_cache(env->vm_hsave + offsetof(struct vmcb, save.ds),
5245                        env, R_DS);
5246
5247     EIP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rip));
5248     ESP = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rsp));
5249     EAX = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.rax));
5250
5251     env->dr[6] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr6));
5252     env->dr[7] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.dr7));
5253
5254     /* other setups */
5255     cpu_x86_set_cpl(env, 0);
5256     stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code), exit_code);
5257     stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_1), exit_info_1);
5258
5259     helper_clgi();
5260     /* FIXME: Resets the current ASID register to zero (host ASID). */
5261
5262     /* Clears the V_IRQ and V_INTR_MASKING bits inside the processor. */
5263
5264     /* Clears the TSC_OFFSET inside the processor. */
5265
5266     /* If the host is in PAE mode, the processor reloads the host's PDPEs
5267        from the page table indicated the host's CR3. If the PDPEs contain
5268        illegal state, the processor causes a shutdown. */
5269
5270     /* Forces CR0.PE = 1, RFLAGS.VM = 0. */
5271     env->cr[0] |= CR0_PE_MASK;
5272     env->eflags &= ~VM_MASK;
5273
5274     /* Disables all breakpoints in the host DR7 register. */
5275
5276     /* Checks the reloaded host state for consistency. */
5277
5278     /* If the host's rIP reloaded by #VMEXIT is outside the limit of the
5279        host's code segment or non-canonical (in the case of long mode), a
5280        #GP fault is delivered inside the host.) */
5281
5282     /* remove any pending exception */
5283     env->exception_index = -1;
5284     env->error_code = 0;
5285     env->old_exception = -1;
5286
5287     cpu_loop_exit();
5288 }
5289
5290 #endif
5291
5292 /* MMX/SSE */
5293 /* XXX: optimize by storing fptt and fptags in the static cpu state */
5294 void helper_enter_mmx(void)
5295 {
5296     env->fpstt = 0;
5297     *(uint32_t *)(env->fptags) = 0;
5298     *(uint32_t *)(env->fptags + 4) = 0;
5299 }
5300
5301 void helper_emms(void)
5302 {
5303     /* set to empty state */
5304     *(uint32_t *)(env->fptags) = 0x01010101;
5305     *(uint32_t *)(env->fptags + 4) = 0x01010101;
5306 }
5307
5308 /* XXX: suppress */
5309 void helper_movq(uint64_t *d, uint64_t *s)
5310 {
5311     *d = *s;
5312 }
5313
5314 #define SHIFT 0
5315 #include "ops_sse.h"
5316
5317 #define SHIFT 1
5318 #include "ops_sse.h"
5319
5320 #define SHIFT 0
5321 #include "helper_template.h"
5322 #undef SHIFT
5323
5324 #define SHIFT 1
5325 #include "helper_template.h"
5326 #undef SHIFT
5327
5328 #define SHIFT 2
5329 #include "helper_template.h"
5330 #undef SHIFT
5331
5332 #ifdef TARGET_X86_64
5333
5334 #define SHIFT 3
5335 #include "helper_template.h"
5336 #undef SHIFT
5337
5338 #endif
5339
5340 /* bit operations */
5341 target_ulong helper_bsf(target_ulong t0)
5342 {
5343     int count;
5344     target_ulong res;
5345
5346     res = t0;
5347     count = 0;
5348     while ((res & 1) == 0) {
5349         count++;
5350         res >>= 1;
5351     }
5352     return count;
5353 }
5354
5355 target_ulong helper_bsr(target_ulong t0)
5356 {
5357     int count;
5358     target_ulong res, mask;
5359     
5360     res = t0;
5361     count = TARGET_LONG_BITS - 1;
5362     mask = (target_ulong)1 << (TARGET_LONG_BITS - 1);
5363     while ((res & mask) == 0) {
5364         count--;
5365         res <<= 1;
5366     }
5367     return count;
5368 }
5369
5370
5371 static int compute_all_eflags(void)
5372 {
5373     return CC_SRC;
5374 }
5375
5376 static int compute_c_eflags(void)
5377 {
5378     return CC_SRC & CC_C;
5379 }
5380
5381 CCTable cc_table[CC_OP_NB] = {
5382     [CC_OP_DYNAMIC] = { /* should never happen */ },
5383
5384     [CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags },
5385
5386     [CC_OP_MULB] = { compute_all_mulb, compute_c_mull },
5387     [CC_OP_MULW] = { compute_all_mulw, compute_c_mull },
5388     [CC_OP_MULL] = { compute_all_mull, compute_c_mull },
5389
5390     [CC_OP_ADDB] = { compute_all_addb, compute_c_addb },
5391     [CC_OP_ADDW] = { compute_all_addw, compute_c_addw  },
5392     [CC_OP_ADDL] = { compute_all_addl, compute_c_addl  },
5393
5394     [CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb },
5395     [CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw  },
5396     [CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl  },
5397
5398     [CC_OP_SUBB] = { compute_all_subb, compute_c_subb  },
5399     [CC_OP_SUBW] = { compute_all_subw, compute_c_subw  },
5400     [CC_OP_SUBL] = { compute_all_subl, compute_c_subl  },
5401
5402     [CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb  },
5403     [CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw  },
5404     [CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl  },
5405
5406     [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb },
5407     [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw },
5408     [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl },
5409
5410     [CC_OP_INCB] = { compute_all_incb, compute_c_incl },
5411     [CC_OP_INCW] = { compute_all_incw, compute_c_incl },
5412     [CC_OP_INCL] = { compute_all_incl, compute_c_incl },
5413
5414     [CC_OP_DECB] = { compute_all_decb, compute_c_incl },
5415     [CC_OP_DECW] = { compute_all_decw, compute_c_incl },
5416     [CC_OP_DECL] = { compute_all_decl, compute_c_incl },
5417
5418     [CC_OP_SHLB] = { compute_all_shlb, compute_c_shlb },
5419     [CC_OP_SHLW] = { compute_all_shlw, compute_c_shlw },
5420     [CC_OP_SHLL] = { compute_all_shll, compute_c_shll },
5421
5422     [CC_OP_SARB] = { compute_all_sarb, compute_c_sarl },
5423     [CC_OP_SARW] = { compute_all_sarw, compute_c_sarl },
5424     [CC_OP_SARL] = { compute_all_sarl, compute_c_sarl },
5425
5426 #ifdef TARGET_X86_64
5427     [CC_OP_MULQ] = { compute_all_mulq, compute_c_mull },
5428
5429     [CC_OP_ADDQ] = { compute_all_addq, compute_c_addq  },
5430
5431     [CC_OP_ADCQ] = { compute_all_adcq, compute_c_adcq  },
5432
5433     [CC_OP_SUBQ] = { compute_all_subq, compute_c_subq  },
5434
5435     [CC_OP_SBBQ] = { compute_all_sbbq, compute_c_sbbq  },
5436
5437     [CC_OP_LOGICQ] = { compute_all_logicq, compute_c_logicq },
5438
5439     [CC_OP_INCQ] = { compute_all_incq, compute_c_incl },
5440
5441     [CC_OP_DECQ] = { compute_all_decq, compute_c_incl },
5442
5443     [CC_OP_SHLQ] = { compute_all_shlq, compute_c_shlq },
5444
5445     [CC_OP_SARQ] = { compute_all_sarq, compute_c_sarl },
5446 #endif
5447 };
5448