]> Git Repo - qemu.git/blob - target-i386/helper.c
MMX/SSE support
[qemu.git] / target-i386 / helper.c
1 /*
2  *  i386 helpers
3  * 
4  *  Copyright (c) 2003 Fabrice Bellard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include "exec.h"
21
22 //#define DEBUG_PCALL
23
24 #if 0
25 #define raise_exception_err(a, b)\
26 do {\
27     fprintf(logfile, "raise_exception line=%d\n", __LINE__);\
28     (raise_exception_err)(a, b);\
29 } while (0)
30 #endif
31
32 const uint8_t parity_table[256] = {
33     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
34     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
35     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
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     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
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     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
42     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
43     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
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     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
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     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
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     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
55     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
56     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
57     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
58     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
59     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
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     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
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 };
66
67 /* modulo 17 table */
68 const uint8_t rclw_table[32] = {
69     0, 1, 2, 3, 4, 5, 6, 7, 
70     8, 9,10,11,12,13,14,15,
71    16, 0, 1, 2, 3, 4, 5, 6,
72     7, 8, 9,10,11,12,13,14,
73 };
74
75 /* modulo 9 table */
76 const uint8_t rclb_table[32] = {
77     0, 1, 2, 3, 4, 5, 6, 7, 
78     8, 0, 1, 2, 3, 4, 5, 6,
79     7, 8, 0, 1, 2, 3, 4, 5, 
80     6, 7, 8, 0, 1, 2, 3, 4,
81 };
82
83 const CPU86_LDouble f15rk[7] =
84 {
85     0.00000000000000000000L,
86     1.00000000000000000000L,
87     3.14159265358979323851L,  /*pi*/
88     0.30102999566398119523L,  /*lg2*/
89     0.69314718055994530943L,  /*ln2*/
90     1.44269504088896340739L,  /*l2e*/
91     3.32192809488736234781L,  /*l2t*/
92 };
93     
94 /* thread support */
95
96 spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
97
98 void cpu_lock(void)
99 {
100     spin_lock(&global_cpu_lock);
101 }
102
103 void cpu_unlock(void)
104 {
105     spin_unlock(&global_cpu_lock);
106 }
107
108 void cpu_loop_exit(void)
109 {
110     /* NOTE: the register at this point must be saved by hand because
111        longjmp restore them */
112     regs_to_env();
113     longjmp(env->jmp_env, 1);
114 }
115
116 /* return non zero if error */
117 static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr,
118                                int selector)
119 {
120     SegmentCache *dt;
121     int index;
122     target_ulong ptr;
123
124     if (selector & 0x4)
125         dt = &env->ldt;
126     else
127         dt = &env->gdt;
128     index = selector & ~7;
129     if ((index + 7) > dt->limit)
130         return -1;
131     ptr = dt->base + index;
132     *e1_ptr = ldl_kernel(ptr);
133     *e2_ptr = ldl_kernel(ptr + 4);
134     return 0;
135 }
136                                      
137 static inline unsigned int get_seg_limit(uint32_t e1, uint32_t e2)
138 {
139     unsigned int limit;
140     limit = (e1 & 0xffff) | (e2 & 0x000f0000);
141     if (e2 & DESC_G_MASK)
142         limit = (limit << 12) | 0xfff;
143     return limit;
144 }
145
146 static inline uint32_t get_seg_base(uint32_t e1, uint32_t e2)
147 {
148     return ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
149 }
150
151 static inline void load_seg_cache_raw_dt(SegmentCache *sc, uint32_t e1, uint32_t e2)
152 {
153     sc->base = get_seg_base(e1, e2);
154     sc->limit = get_seg_limit(e1, e2);
155     sc->flags = e2;
156 }
157
158 /* init the segment cache in vm86 mode. */
159 static inline void load_seg_vm(int seg, int selector)
160 {
161     selector &= 0xffff;
162     cpu_x86_load_seg_cache(env, seg, selector, 
163                            (selector << 4), 0xffff, 0);
164 }
165
166 static inline void get_ss_esp_from_tss(uint32_t *ss_ptr, 
167                                        uint32_t *esp_ptr, int dpl)
168 {
169     int type, index, shift;
170     
171 #if 0
172     {
173         int i;
174         printf("TR: base=%p limit=%x\n", env->tr.base, env->tr.limit);
175         for(i=0;i<env->tr.limit;i++) {
176             printf("%02x ", env->tr.base[i]);
177             if ((i & 7) == 7) printf("\n");
178         }
179         printf("\n");
180     }
181 #endif
182
183     if (!(env->tr.flags & DESC_P_MASK))
184         cpu_abort(env, "invalid tss");
185     type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
186     if ((type & 7) != 1)
187         cpu_abort(env, "invalid tss type");
188     shift = type >> 3;
189     index = (dpl * 4 + 2) << shift;
190     if (index + (4 << shift) - 1 > env->tr.limit)
191         raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
192     if (shift == 0) {
193         *esp_ptr = lduw_kernel(env->tr.base + index);
194         *ss_ptr = lduw_kernel(env->tr.base + index + 2);
195     } else {
196         *esp_ptr = ldl_kernel(env->tr.base + index);
197         *ss_ptr = lduw_kernel(env->tr.base + index + 4);
198     }
199 }
200
201 /* XXX: merge with load_seg() */
202 static void tss_load_seg(int seg_reg, int selector)
203 {
204     uint32_t e1, e2;
205     int rpl, dpl, cpl;
206
207     if ((selector & 0xfffc) != 0) {
208         if (load_segment(&e1, &e2, selector) != 0)
209             raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
210         if (!(e2 & DESC_S_MASK))
211             raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
212         rpl = selector & 3;
213         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
214         cpl = env->hflags & HF_CPL_MASK;
215         if (seg_reg == R_CS) {
216             if (!(e2 & DESC_CS_MASK))
217                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
218             if (dpl != rpl)
219                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
220             if ((e2 & DESC_C_MASK) && dpl > rpl)
221                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
222                 
223         } else if (seg_reg == R_SS) {
224             /* SS must be writable data */
225             if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
226                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
227             if (dpl != cpl || dpl != rpl)
228                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
229         } else {
230             /* not readable code */
231             if ((e2 & DESC_CS_MASK) && !(e2 & DESC_R_MASK))
232                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
233             /* if data or non conforming code, checks the rights */
234             if (((e2 >> DESC_TYPE_SHIFT) & 0xf) < 12) {
235                 if (dpl < cpl || dpl < rpl)
236                     raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
237             }
238         }
239         if (!(e2 & DESC_P_MASK))
240             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
241         cpu_x86_load_seg_cache(env, seg_reg, selector, 
242                        get_seg_base(e1, e2),
243                        get_seg_limit(e1, e2),
244                        e2);
245     } else {
246         if (seg_reg == R_SS || seg_reg == R_CS) 
247             raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
248     }
249 }
250
251 #define SWITCH_TSS_JMP  0
252 #define SWITCH_TSS_IRET 1
253 #define SWITCH_TSS_CALL 2
254
255 /* XXX: restore CPU state in registers (PowerPC case) */
256 static void switch_tss(int tss_selector, 
257                        uint32_t e1, uint32_t e2, int source,
258                        uint32_t next_eip)
259 {
260     int tss_limit, tss_limit_max, type, old_tss_limit_max, old_type, v1, v2, i;
261     target_ulong tss_base;
262     uint32_t new_regs[8], new_segs[6];
263     uint32_t new_eflags, new_eip, new_cr3, new_ldt, new_trap;
264     uint32_t old_eflags, eflags_mask;
265     SegmentCache *dt;
266     int index;
267     target_ulong ptr;
268
269     type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
270 #ifdef DEBUG_PCALL
271     if (loglevel & CPU_LOG_PCALL)
272         fprintf(logfile, "switch_tss: sel=0x%04x type=%d src=%d\n", tss_selector, type, source);
273 #endif
274
275     /* if task gate, we read the TSS segment and we load it */
276     if (type == 5) {
277         if (!(e2 & DESC_P_MASK))
278             raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
279         tss_selector = e1 >> 16;
280         if (tss_selector & 4)
281             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
282         if (load_segment(&e1, &e2, tss_selector) != 0)
283             raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
284         if (e2 & DESC_S_MASK)
285             raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
286         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
287         if ((type & 7) != 1)
288             raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
289     }
290
291     if (!(e2 & DESC_P_MASK))
292         raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
293
294     if (type & 8)
295         tss_limit_max = 103;
296     else
297         tss_limit_max = 43;
298     tss_limit = get_seg_limit(e1, e2);
299     tss_base = get_seg_base(e1, e2);
300     if ((tss_selector & 4) != 0 || 
301         tss_limit < tss_limit_max)
302         raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
303     old_type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
304     if (old_type & 8)
305         old_tss_limit_max = 103;
306     else
307         old_tss_limit_max = 43;
308
309     /* read all the registers from the new TSS */
310     if (type & 8) {
311         /* 32 bit */
312         new_cr3 = ldl_kernel(tss_base + 0x1c);
313         new_eip = ldl_kernel(tss_base + 0x20);
314         new_eflags = ldl_kernel(tss_base + 0x24);
315         for(i = 0; i < 8; i++)
316             new_regs[i] = ldl_kernel(tss_base + (0x28 + i * 4));
317         for(i = 0; i < 6; i++)
318             new_segs[i] = lduw_kernel(tss_base + (0x48 + i * 4));
319         new_ldt = lduw_kernel(tss_base + 0x60);
320         new_trap = ldl_kernel(tss_base + 0x64);
321     } else {
322         /* 16 bit */
323         new_cr3 = 0;
324         new_eip = lduw_kernel(tss_base + 0x0e);
325         new_eflags = lduw_kernel(tss_base + 0x10);
326         for(i = 0; i < 8; i++)
327             new_regs[i] = lduw_kernel(tss_base + (0x12 + i * 2)) | 0xffff0000;
328         for(i = 0; i < 4; i++)
329             new_segs[i] = lduw_kernel(tss_base + (0x22 + i * 4));
330         new_ldt = lduw_kernel(tss_base + 0x2a);
331         new_segs[R_FS] = 0;
332         new_segs[R_GS] = 0;
333         new_trap = 0;
334     }
335     
336     /* NOTE: we must avoid memory exceptions during the task switch,
337        so we make dummy accesses before */
338     /* XXX: it can still fail in some cases, so a bigger hack is
339        necessary to valid the TLB after having done the accesses */
340
341     v1 = ldub_kernel(env->tr.base);
342     v2 = ldub(env->tr.base + old_tss_limit_max);
343     stb_kernel(env->tr.base, v1);
344     stb_kernel(env->tr.base + old_tss_limit_max, v2);
345     
346     /* clear busy bit (it is restartable) */
347     if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_IRET) {
348         target_ulong ptr;
349         uint32_t e2;
350         ptr = env->gdt.base + (env->tr.selector & ~7);
351         e2 = ldl_kernel(ptr + 4);
352         e2 &= ~DESC_TSS_BUSY_MASK;
353         stl_kernel(ptr + 4, e2);
354     }
355     old_eflags = compute_eflags();
356     if (source == SWITCH_TSS_IRET)
357         old_eflags &= ~NT_MASK;
358     
359     /* save the current state in the old TSS */
360     if (type & 8) {
361         /* 32 bit */
362         stl_kernel(env->tr.base + 0x20, next_eip);
363         stl_kernel(env->tr.base + 0x24, old_eflags);
364         stl_kernel(env->tr.base + (0x28 + 0 * 4), EAX);
365         stl_kernel(env->tr.base + (0x28 + 1 * 4), ECX);
366         stl_kernel(env->tr.base + (0x28 + 2 * 4), EDX);
367         stl_kernel(env->tr.base + (0x28 + 3 * 4), EBX);
368         stl_kernel(env->tr.base + (0x28 + 4 * 4), ESP);
369         stl_kernel(env->tr.base + (0x28 + 5 * 4), EBP);
370         stl_kernel(env->tr.base + (0x28 + 6 * 4), ESI);
371         stl_kernel(env->tr.base + (0x28 + 7 * 4), EDI);
372         for(i = 0; i < 6; i++)
373             stw_kernel(env->tr.base + (0x48 + i * 4), env->segs[i].selector);
374     } else {
375         /* 16 bit */
376         stw_kernel(env->tr.base + 0x0e, next_eip);
377         stw_kernel(env->tr.base + 0x10, old_eflags);
378         stw_kernel(env->tr.base + (0x12 + 0 * 2), EAX);
379         stw_kernel(env->tr.base + (0x12 + 1 * 2), ECX);
380         stw_kernel(env->tr.base + (0x12 + 2 * 2), EDX);
381         stw_kernel(env->tr.base + (0x12 + 3 * 2), EBX);
382         stw_kernel(env->tr.base + (0x12 + 4 * 2), ESP);
383         stw_kernel(env->tr.base + (0x12 + 5 * 2), EBP);
384         stw_kernel(env->tr.base + (0x12 + 6 * 2), ESI);
385         stw_kernel(env->tr.base + (0x12 + 7 * 2), EDI);
386         for(i = 0; i < 4; i++)
387             stw_kernel(env->tr.base + (0x22 + i * 4), env->segs[i].selector);
388     }
389     
390     /* now if an exception occurs, it will occurs in the next task
391        context */
392
393     if (source == SWITCH_TSS_CALL) {
394         stw_kernel(tss_base, env->tr.selector);
395         new_eflags |= NT_MASK;
396     }
397
398     /* set busy bit */
399     if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_CALL) {
400         target_ulong ptr;
401         uint32_t e2;
402         ptr = env->gdt.base + (tss_selector & ~7);
403         e2 = ldl_kernel(ptr + 4);
404         e2 |= DESC_TSS_BUSY_MASK;
405         stl_kernel(ptr + 4, e2);
406     }
407
408     /* set the new CPU state */
409     /* from this point, any exception which occurs can give problems */
410     env->cr[0] |= CR0_TS_MASK;
411     env->hflags |= HF_TS_MASK;
412     env->tr.selector = tss_selector;
413     env->tr.base = tss_base;
414     env->tr.limit = tss_limit;
415     env->tr.flags = e2 & ~DESC_TSS_BUSY_MASK;
416     
417     if ((type & 8) && (env->cr[0] & CR0_PG_MASK)) {
418         cpu_x86_update_cr3(env, new_cr3);
419     }
420     
421     /* load all registers without an exception, then reload them with
422        possible exception */
423     env->eip = new_eip;
424     eflags_mask = TF_MASK | AC_MASK | ID_MASK | 
425         IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK;
426     if (!(type & 8))
427         eflags_mask &= 0xffff;
428     load_eflags(new_eflags, eflags_mask);
429     /* XXX: what to do in 16 bit case ? */
430     EAX = new_regs[0];
431     ECX = new_regs[1];
432     EDX = new_regs[2];
433     EBX = new_regs[3];
434     ESP = new_regs[4];
435     EBP = new_regs[5];
436     ESI = new_regs[6];
437     EDI = new_regs[7];
438     if (new_eflags & VM_MASK) {
439         for(i = 0; i < 6; i++) 
440             load_seg_vm(i, new_segs[i]);
441         /* in vm86, CPL is always 3 */
442         cpu_x86_set_cpl(env, 3);
443     } else {
444         /* CPL is set the RPL of CS */
445         cpu_x86_set_cpl(env, new_segs[R_CS] & 3);
446         /* first just selectors as the rest may trigger exceptions */
447         for(i = 0; i < 6; i++)
448             cpu_x86_load_seg_cache(env, i, new_segs[i], 0, 0, 0);
449     }
450     
451     env->ldt.selector = new_ldt & ~4;
452     env->ldt.base = 0;
453     env->ldt.limit = 0;
454     env->ldt.flags = 0;
455
456     /* load the LDT */
457     if (new_ldt & 4)
458         raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
459
460     if ((new_ldt & 0xfffc) != 0) {
461         dt = &env->gdt;
462         index = new_ldt & ~7;
463         if ((index + 7) > dt->limit)
464             raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
465         ptr = dt->base + index;
466         e1 = ldl_kernel(ptr);
467         e2 = ldl_kernel(ptr + 4);
468         if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
469             raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
470         if (!(e2 & DESC_P_MASK))
471             raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
472         load_seg_cache_raw_dt(&env->ldt, e1, e2);
473     }
474     
475     /* load the segments */
476     if (!(new_eflags & VM_MASK)) {
477         tss_load_seg(R_CS, new_segs[R_CS]);
478         tss_load_seg(R_SS, new_segs[R_SS]);
479         tss_load_seg(R_ES, new_segs[R_ES]);
480         tss_load_seg(R_DS, new_segs[R_DS]);
481         tss_load_seg(R_FS, new_segs[R_FS]);
482         tss_load_seg(R_GS, new_segs[R_GS]);
483     }
484     
485     /* check that EIP is in the CS segment limits */
486     if (new_eip > env->segs[R_CS].limit) {
487         /* XXX: different exception if CALL ? */
488         raise_exception_err(EXCP0D_GPF, 0);
489     }
490 }
491
492 /* check if Port I/O is allowed in TSS */
493 static inline void check_io(int addr, int size)
494 {
495     int io_offset, val, mask;
496     
497     /* TSS must be a valid 32 bit one */
498     if (!(env->tr.flags & DESC_P_MASK) ||
499         ((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 ||
500         env->tr.limit < 103)
501         goto fail;
502     io_offset = lduw_kernel(env->tr.base + 0x66);
503     io_offset += (addr >> 3);
504     /* Note: the check needs two bytes */
505     if ((io_offset + 1) > env->tr.limit)
506         goto fail;
507     val = lduw_kernel(env->tr.base + io_offset);
508     val >>= (addr & 7);
509     mask = (1 << size) - 1;
510     /* all bits must be zero to allow the I/O */
511     if ((val & mask) != 0) {
512     fail:
513         raise_exception_err(EXCP0D_GPF, 0);
514     }
515 }
516
517 void check_iob_T0(void)
518 {
519     check_io(T0, 1);
520 }
521
522 void check_iow_T0(void)
523 {
524     check_io(T0, 2);
525 }
526
527 void check_iol_T0(void)
528 {
529     check_io(T0, 4);
530 }
531
532 void check_iob_DX(void)
533 {
534     check_io(EDX & 0xffff, 1);
535 }
536
537 void check_iow_DX(void)
538 {
539     check_io(EDX & 0xffff, 2);
540 }
541
542 void check_iol_DX(void)
543 {
544     check_io(EDX & 0xffff, 4);
545 }
546
547 static inline unsigned int get_sp_mask(unsigned int e2)
548 {
549     if (e2 & DESC_B_MASK)
550         return 0xffffffff;
551     else
552         return 0xffff;
553 }
554
555 /* XXX: add a is_user flag to have proper security support */
556 #define PUSHW(ssp, sp, sp_mask, val)\
557 {\
558     sp -= 2;\
559     stw_kernel((ssp) + (sp & (sp_mask)), (val));\
560 }
561
562 #define PUSHL(ssp, sp, sp_mask, val)\
563 {\
564     sp -= 4;\
565     stl_kernel((ssp) + (sp & (sp_mask)), (val));\
566 }
567
568 #define POPW(ssp, sp, sp_mask, val)\
569 {\
570     val = lduw_kernel((ssp) + (sp & (sp_mask)));\
571     sp += 2;\
572 }
573
574 #define POPL(ssp, sp, sp_mask, val)\
575 {\
576     val = (uint32_t)ldl_kernel((ssp) + (sp & (sp_mask)));\
577     sp += 4;\
578 }
579
580 /* protected mode interrupt */
581 static void do_interrupt_protected(int intno, int is_int, int error_code,
582                                    unsigned int next_eip, int is_hw)
583 {
584     SegmentCache *dt;
585     target_ulong ptr, ssp;
586     int type, dpl, selector, ss_dpl, cpl, sp_mask;
587     int has_error_code, new_stack, shift;
588     uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2;
589     uint32_t old_eip;
590
591     has_error_code = 0;
592     if (!is_int && !is_hw) {
593         switch(intno) {
594         case 8:
595         case 10:
596         case 11:
597         case 12:
598         case 13:
599         case 14:
600         case 17:
601             has_error_code = 1;
602             break;
603         }
604     }
605     if (is_int)
606         old_eip = next_eip;
607     else
608         old_eip = env->eip;
609
610     dt = &env->idt;
611     if (intno * 8 + 7 > dt->limit)
612         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
613     ptr = dt->base + intno * 8;
614     e1 = ldl_kernel(ptr);
615     e2 = ldl_kernel(ptr + 4);
616     /* check gate type */
617     type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
618     switch(type) {
619     case 5: /* task gate */
620         /* must do that check here to return the correct error code */
621         if (!(e2 & DESC_P_MASK))
622             raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
623         switch_tss(intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip);
624         if (has_error_code) {
625             int mask;
626             /* push the error code */
627             shift = (env->segs[R_CS].flags >> DESC_B_SHIFT) & 1;
628             if (env->segs[R_SS].flags & DESC_B_MASK)
629                 mask = 0xffffffff;
630             else
631                 mask = 0xffff;
632             esp = (ESP - (2 << shift)) & mask;
633             ssp = env->segs[R_SS].base + esp;
634             if (shift)
635                 stl_kernel(ssp, error_code);
636             else
637                 stw_kernel(ssp, error_code);
638             ESP = (esp & mask) | (ESP & ~mask);
639         }
640         return;
641     case 6: /* 286 interrupt gate */
642     case 7: /* 286 trap gate */
643     case 14: /* 386 interrupt gate */
644     case 15: /* 386 trap gate */
645         break;
646     default:
647         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
648         break;
649     }
650     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
651     cpl = env->hflags & HF_CPL_MASK;
652     /* check privledge if software int */
653     if (is_int && dpl < cpl)
654         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
655     /* check valid bit */
656     if (!(e2 & DESC_P_MASK))
657         raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
658     selector = e1 >> 16;
659     offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
660     if ((selector & 0xfffc) == 0)
661         raise_exception_err(EXCP0D_GPF, 0);
662
663     if (load_segment(&e1, &e2, selector) != 0)
664         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
665     if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
666         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
667     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
668     if (dpl > cpl)
669         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
670     if (!(e2 & DESC_P_MASK))
671         raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
672     if (!(e2 & DESC_C_MASK) && dpl < cpl) {
673         /* to inner priviledge */
674         get_ss_esp_from_tss(&ss, &esp, dpl);
675         if ((ss & 0xfffc) == 0)
676             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
677         if ((ss & 3) != dpl)
678             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
679         if (load_segment(&ss_e1, &ss_e2, ss) != 0)
680             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
681         ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
682         if (ss_dpl != dpl)
683             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
684         if (!(ss_e2 & DESC_S_MASK) ||
685             (ss_e2 & DESC_CS_MASK) ||
686             !(ss_e2 & DESC_W_MASK))
687             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
688         if (!(ss_e2 & DESC_P_MASK))
689             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
690         new_stack = 1;
691         sp_mask = get_sp_mask(ss_e2);
692         ssp = get_seg_base(ss_e1, ss_e2);
693     } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
694         /* to same priviledge */
695         if (env->eflags & VM_MASK)
696             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
697         new_stack = 0;
698         sp_mask = get_sp_mask(env->segs[R_SS].flags);
699         ssp = env->segs[R_SS].base;
700         esp = ESP;
701         dpl = cpl;
702     } else {
703         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
704         new_stack = 0; /* avoid warning */
705         sp_mask = 0; /* avoid warning */
706         ssp = 0; /* avoid warning */
707         esp = 0; /* avoid warning */
708     }
709
710     shift = type >> 3;
711
712 #if 0
713     /* XXX: check that enough room is available */
714     push_size = 6 + (new_stack << 2) + (has_error_code << 1);
715     if (env->eflags & VM_MASK)
716         push_size += 8;
717     push_size <<= shift;
718 #endif
719     if (shift == 1) {
720         if (new_stack) {
721             if (env->eflags & VM_MASK) {
722                 PUSHL(ssp, esp, sp_mask, env->segs[R_GS].selector);
723                 PUSHL(ssp, esp, sp_mask, env->segs[R_FS].selector);
724                 PUSHL(ssp, esp, sp_mask, env->segs[R_DS].selector);
725                 PUSHL(ssp, esp, sp_mask, env->segs[R_ES].selector);
726             }
727             PUSHL(ssp, esp, sp_mask, env->segs[R_SS].selector);
728             PUSHL(ssp, esp, sp_mask, ESP);
729         }
730         PUSHL(ssp, esp, sp_mask, compute_eflags());
731         PUSHL(ssp, esp, sp_mask, env->segs[R_CS].selector);
732         PUSHL(ssp, esp, sp_mask, old_eip);
733         if (has_error_code) {
734             PUSHL(ssp, esp, sp_mask, error_code);
735         }
736     } else {
737         if (new_stack) {
738             if (env->eflags & VM_MASK) {
739                 PUSHW(ssp, esp, sp_mask, env->segs[R_GS].selector);
740                 PUSHW(ssp, esp, sp_mask, env->segs[R_FS].selector);
741                 PUSHW(ssp, esp, sp_mask, env->segs[R_DS].selector);
742                 PUSHW(ssp, esp, sp_mask, env->segs[R_ES].selector);
743             }
744             PUSHW(ssp, esp, sp_mask, env->segs[R_SS].selector);
745             PUSHW(ssp, esp, sp_mask, ESP);
746         }
747         PUSHW(ssp, esp, sp_mask, compute_eflags());
748         PUSHW(ssp, esp, sp_mask, env->segs[R_CS].selector);
749         PUSHW(ssp, esp, sp_mask, old_eip);
750         if (has_error_code) {
751             PUSHW(ssp, esp, sp_mask, error_code);
752         }
753     }
754     
755     if (new_stack) {
756         if (env->eflags & VM_MASK) {
757             cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0, 0);
758             cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0, 0);
759             cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0, 0);
760             cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0, 0);
761         }
762         ss = (ss & ~3) | dpl;
763         cpu_x86_load_seg_cache(env, R_SS, ss, 
764                                ssp, get_seg_limit(ss_e1, ss_e2), ss_e2);
765     }
766     ESP = (ESP & ~sp_mask) | (esp & sp_mask);
767
768     selector = (selector & ~3) | dpl;
769     cpu_x86_load_seg_cache(env, R_CS, selector, 
770                    get_seg_base(e1, e2),
771                    get_seg_limit(e1, e2),
772                    e2);
773     cpu_x86_set_cpl(env, dpl);
774     env->eip = offset;
775
776     /* interrupt gate clear IF mask */
777     if ((type & 1) == 0) {
778         env->eflags &= ~IF_MASK;
779     }
780     env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
781 }
782
783 #ifdef TARGET_X86_64
784
785 #define PUSHQ(sp, val)\
786 {\
787     sp -= 8;\
788     stq_kernel(sp, (val));\
789 }
790
791 #define POPQ(sp, val)\
792 {\
793     val = ldq_kernel(sp);\
794     sp += 8;\
795 }
796
797 static inline target_ulong get_rsp_from_tss(int level)
798 {
799     int index;
800     
801 #if 0
802     printf("TR: base=" TARGET_FMT_lx " limit=%x\n", 
803            env->tr.base, env->tr.limit);
804 #endif
805
806     if (!(env->tr.flags & DESC_P_MASK))
807         cpu_abort(env, "invalid tss");
808     index = 8 * level + 4;
809     if ((index + 7) > env->tr.limit)
810         raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
811     return ldq_kernel(env->tr.base + index);
812 }
813
814 /* 64 bit interrupt */
815 static void do_interrupt64(int intno, int is_int, int error_code,
816                            target_ulong next_eip, int is_hw)
817 {
818     SegmentCache *dt;
819     target_ulong ptr;
820     int type, dpl, selector, cpl, ist;
821     int has_error_code, new_stack;
822     uint32_t e1, e2, e3, ss;
823     target_ulong old_eip, esp, offset;
824
825     has_error_code = 0;
826     if (!is_int && !is_hw) {
827         switch(intno) {
828         case 8:
829         case 10:
830         case 11:
831         case 12:
832         case 13:
833         case 14:
834         case 17:
835             has_error_code = 1;
836             break;
837         }
838     }
839     if (is_int)
840         old_eip = next_eip;
841     else
842         old_eip = env->eip;
843
844     dt = &env->idt;
845     if (intno * 16 + 15 > dt->limit)
846         raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
847     ptr = dt->base + intno * 16;
848     e1 = ldl_kernel(ptr);
849     e2 = ldl_kernel(ptr + 4);
850     e3 = ldl_kernel(ptr + 8);
851     /* check gate type */
852     type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
853     switch(type) {
854     case 14: /* 386 interrupt gate */
855     case 15: /* 386 trap gate */
856         break;
857     default:
858         raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
859         break;
860     }
861     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
862     cpl = env->hflags & HF_CPL_MASK;
863     /* check privledge if software int */
864     if (is_int && dpl < cpl)
865         raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
866     /* check valid bit */
867     if (!(e2 & DESC_P_MASK))
868         raise_exception_err(EXCP0B_NOSEG, intno * 16 + 2);
869     selector = e1 >> 16;
870     offset = ((target_ulong)e3 << 32) | (e2 & 0xffff0000) | (e1 & 0x0000ffff);
871     ist = e2 & 7;
872     if ((selector & 0xfffc) == 0)
873         raise_exception_err(EXCP0D_GPF, 0);
874
875     if (load_segment(&e1, &e2, selector) != 0)
876         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
877     if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
878         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
879     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
880     if (dpl > cpl)
881         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
882     if (!(e2 & DESC_P_MASK))
883         raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
884     if (!(e2 & DESC_L_MASK) || (e2 & DESC_B_MASK))
885         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
886     if ((!(e2 & DESC_C_MASK) && dpl < cpl) || ist != 0) {
887         /* to inner priviledge */
888         if (ist != 0)
889             esp = get_rsp_from_tss(ist + 3);
890         else
891             esp = get_rsp_from_tss(dpl);
892         ss = 0;
893         new_stack = 1;
894     } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
895         /* to same priviledge */
896         if (env->eflags & VM_MASK)
897             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
898         new_stack = 0;
899         esp = ESP & ~0xf; /* align stack */
900         dpl = cpl;
901     } else {
902         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
903         new_stack = 0; /* avoid warning */
904         esp = 0; /* avoid warning */
905     }
906
907     PUSHQ(esp, env->segs[R_SS].selector);
908     PUSHQ(esp, ESP);
909     PUSHQ(esp, compute_eflags());
910     PUSHQ(esp, env->segs[R_CS].selector);
911     PUSHQ(esp, old_eip);
912     if (has_error_code) {
913         PUSHQ(esp, error_code);
914     }
915     
916     if (new_stack) {
917         ss = 0 | dpl;
918         cpu_x86_load_seg_cache(env, R_SS, ss, 0, 0, 0);
919     }
920     ESP = esp;
921
922     selector = (selector & ~3) | dpl;
923     cpu_x86_load_seg_cache(env, R_CS, selector, 
924                    get_seg_base(e1, e2),
925                    get_seg_limit(e1, e2),
926                    e2);
927     cpu_x86_set_cpl(env, dpl);
928     env->eip = offset;
929
930     /* interrupt gate clear IF mask */
931     if ((type & 1) == 0) {
932         env->eflags &= ~IF_MASK;
933     }
934     env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
935 }
936
937 void helper_syscall(int next_eip_addend)
938 {
939     int selector;
940
941     if (!(env->efer & MSR_EFER_SCE)) {
942         raise_exception_err(EXCP06_ILLOP, 0);
943     }
944     selector = (env->star >> 32) & 0xffff;
945     if (env->hflags & HF_LMA_MASK) {
946         ECX = env->eip + next_eip_addend;
947         env->regs[11] = compute_eflags();
948
949         cpu_x86_set_cpl(env, 0);
950         cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, 
951                            0, 0xffffffff, 
952                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
953                                DESC_S_MASK |
954                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
955         cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc, 
956                                0, 0xffffffff,
957                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
958                                DESC_S_MASK |
959                                DESC_W_MASK | DESC_A_MASK);
960         env->eflags &= ~env->fmask;
961         if (env->hflags & HF_CS64_MASK)
962             env->eip = env->lstar;
963         else
964             env->eip = env->cstar;
965     } else {
966         ECX = (uint32_t)(env->eip + next_eip_addend);
967         
968         cpu_x86_set_cpl(env, 0);
969         cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, 
970                            0, 0xffffffff, 
971                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
972                                DESC_S_MASK |
973                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
974         cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc, 
975                                0, 0xffffffff,
976                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
977                                DESC_S_MASK |
978                                DESC_W_MASK | DESC_A_MASK);
979         env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
980         env->eip = (uint32_t)env->star;
981     }
982 }
983
984 void helper_sysret(int dflag)
985 {
986     int cpl, selector;
987
988     cpl = env->hflags & HF_CPL_MASK;
989     if (!(env->cr[0] & CR0_PE_MASK) || cpl != 0) {
990         raise_exception_err(EXCP0D_GPF, 0);
991     }
992     selector = (env->star >> 48) & 0xffff;
993     if (env->hflags & HF_LMA_MASK) {
994         if (dflag == 2) {
995             cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3, 
996                                    0, 0xffffffff, 
997                                    DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
998                                    DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
999                                    DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | 
1000                                    DESC_L_MASK);
1001             env->eip = ECX;
1002         } else {
1003             cpu_x86_load_seg_cache(env, R_CS, selector | 3, 
1004                                    0, 0xffffffff, 
1005                                    DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1006                                    DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1007                                    DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1008             env->eip = (uint32_t)ECX;
1009         }
1010         cpu_x86_load_seg_cache(env, R_SS, selector + 8, 
1011                                0, 0xffffffff,
1012                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1013                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1014                                DESC_W_MASK | DESC_A_MASK);
1015         load_eflags((uint32_t)(env->regs[11]), 0xffffffff);
1016         cpu_x86_set_cpl(env, 3);
1017     } else {
1018         cpu_x86_load_seg_cache(env, R_CS, selector | 3, 
1019                                0, 0xffffffff, 
1020                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1021                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1022                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1023         env->eip = (uint32_t)ECX;
1024         cpu_x86_load_seg_cache(env, R_SS, selector + 8, 
1025                                0, 0xffffffff,
1026                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1027                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1028                                DESC_W_MASK | DESC_A_MASK);
1029         env->eflags |= IF_MASK;
1030         cpu_x86_set_cpl(env, 3);
1031     }
1032 }
1033 #endif
1034
1035 /* real mode interrupt */
1036 static void do_interrupt_real(int intno, int is_int, int error_code,
1037                               unsigned int next_eip)
1038 {
1039     SegmentCache *dt;
1040     target_ulong ptr, ssp;
1041     int selector;
1042     uint32_t offset, esp;
1043     uint32_t old_cs, old_eip;
1044
1045     /* real mode (simpler !) */
1046     dt = &env->idt;
1047     if (intno * 4 + 3 > dt->limit)
1048         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
1049     ptr = dt->base + intno * 4;
1050     offset = lduw_kernel(ptr);
1051     selector = lduw_kernel(ptr + 2);
1052     esp = ESP;
1053     ssp = env->segs[R_SS].base;
1054     if (is_int)
1055         old_eip = next_eip;
1056     else
1057         old_eip = env->eip;
1058     old_cs = env->segs[R_CS].selector;
1059     /* XXX: use SS segment size ? */
1060     PUSHW(ssp, esp, 0xffff, compute_eflags());
1061     PUSHW(ssp, esp, 0xffff, old_cs);
1062     PUSHW(ssp, esp, 0xffff, old_eip);
1063     
1064     /* update processor state */
1065     ESP = (ESP & ~0xffff) | (esp & 0xffff);
1066     env->eip = offset;
1067     env->segs[R_CS].selector = selector;
1068     env->segs[R_CS].base = (selector << 4);
1069     env->eflags &= ~(IF_MASK | TF_MASK | AC_MASK | RF_MASK);
1070 }
1071
1072 /* fake user mode interrupt */
1073 void do_interrupt_user(int intno, int is_int, int error_code, 
1074                        target_ulong next_eip)
1075 {
1076     SegmentCache *dt;
1077     target_ulong ptr;
1078     int dpl, cpl;
1079     uint32_t e2;
1080
1081     dt = &env->idt;
1082     ptr = dt->base + (intno * 8);
1083     e2 = ldl_kernel(ptr + 4);
1084     
1085     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1086     cpl = env->hflags & HF_CPL_MASK;
1087     /* check privledge if software int */
1088     if (is_int && dpl < cpl)
1089         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
1090
1091     /* Since we emulate only user space, we cannot do more than
1092        exiting the emulation with the suitable exception and error
1093        code */
1094     if (is_int)
1095         EIP = next_eip;
1096 }
1097
1098 /*
1099  * Begin execution of an interruption. is_int is TRUE if coming from
1100  * the int instruction. next_eip is the EIP value AFTER the interrupt
1101  * instruction. It is only relevant if is_int is TRUE.  
1102  */
1103 void do_interrupt(int intno, int is_int, int error_code, 
1104                   target_ulong next_eip, int is_hw)
1105 {
1106 #ifdef DEBUG_PCALL
1107     if (loglevel & (CPU_LOG_PCALL | CPU_LOG_INT)) {
1108         if ((env->cr[0] & CR0_PE_MASK)) {
1109             static int count;
1110             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,
1111                     count, intno, error_code, is_int,
1112                     env->hflags & HF_CPL_MASK,
1113                     env->segs[R_CS].selector, EIP,
1114                     (int)env->segs[R_CS].base + EIP,
1115                     env->segs[R_SS].selector, ESP);
1116             if (intno == 0x0e) {
1117                 fprintf(logfile, " CR2=" TARGET_FMT_lx, env->cr[2]);
1118             } else {
1119                 fprintf(logfile, " EAX=" TARGET_FMT_lx, EAX);
1120             }
1121             fprintf(logfile, "\n");
1122 #if 0
1123             cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1124             {
1125                 int i;
1126                 uint8_t *ptr;
1127                 fprintf(logfile, "       code=");
1128                 ptr = env->segs[R_CS].base + env->eip;
1129                 for(i = 0; i < 16; i++) {
1130                     fprintf(logfile, " %02x", ldub(ptr + i));
1131                 }
1132                 fprintf(logfile, "\n");
1133             }
1134 #endif
1135             count++;
1136         }
1137     }
1138 #endif
1139     if (env->cr[0] & CR0_PE_MASK) {
1140 #if TARGET_X86_64
1141         if (env->hflags & HF_LMA_MASK) {
1142             do_interrupt64(intno, is_int, error_code, next_eip, is_hw);
1143         } else
1144 #endif
1145         {
1146             do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);
1147         }
1148     } else {
1149         do_interrupt_real(intno, is_int, error_code, next_eip);
1150     }
1151 }
1152
1153 /*
1154  * Signal an interruption. It is executed in the main CPU loop.
1155  * is_int is TRUE if coming from the int instruction. next_eip is the
1156  * EIP value AFTER the interrupt instruction. It is only relevant if
1157  * is_int is TRUE.  
1158  */
1159 void raise_interrupt(int intno, int is_int, int error_code, 
1160                      int next_eip_addend)
1161 {
1162     env->exception_index = intno;
1163     env->error_code = error_code;
1164     env->exception_is_int = is_int;
1165     env->exception_next_eip = env->eip + next_eip_addend;
1166     cpu_loop_exit();
1167 }
1168
1169 /* same as raise_exception_err, but do not restore global registers */
1170 static void raise_exception_err_norestore(int exception_index, int error_code)
1171 {
1172     env->exception_index = exception_index;
1173     env->error_code = error_code;
1174     env->exception_is_int = 0;
1175     env->exception_next_eip = 0;
1176     longjmp(env->jmp_env, 1);
1177 }
1178
1179 /* shortcuts to generate exceptions */
1180
1181 void (raise_exception_err)(int exception_index, int error_code)
1182 {
1183     raise_interrupt(exception_index, 0, error_code, 0);
1184 }
1185
1186 void raise_exception(int exception_index)
1187 {
1188     raise_interrupt(exception_index, 0, 0, 0);
1189 }
1190
1191 #ifdef BUGGY_GCC_DIV64
1192 /* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we
1193    call it from another function */
1194 uint32_t div32(uint32_t *q_ptr, uint64_t num, uint32_t den)
1195 {
1196     *q_ptr = num / den;
1197     return num % den;
1198 }
1199
1200 int32_t idiv32(int32_t *q_ptr, int64_t num, int32_t den)
1201 {
1202     *q_ptr = num / den;
1203     return num % den;
1204 }
1205 #endif
1206
1207 void helper_divl_EAX_T0(void)
1208 {
1209     unsigned int den, q, r;
1210     uint64_t num;
1211     
1212     num = EAX | ((uint64_t)EDX << 32);
1213     den = T0;
1214     if (den == 0) {
1215         raise_exception(EXCP00_DIVZ);
1216     }
1217 #ifdef BUGGY_GCC_DIV64
1218     r = div32(&q, num, den);
1219 #else
1220     q = (num / den);
1221     r = (num % den);
1222 #endif
1223     EAX = (uint32_t)q;
1224     EDX = (uint32_t)r;
1225 }
1226
1227 void helper_idivl_EAX_T0(void)
1228 {
1229     int den, q, r;
1230     int64_t num;
1231     
1232     num = EAX | ((uint64_t)EDX << 32);
1233     den = T0;
1234     if (den == 0) {
1235         raise_exception(EXCP00_DIVZ);
1236     }
1237 #ifdef BUGGY_GCC_DIV64
1238     r = idiv32(&q, num, den);
1239 #else
1240     q = (num / den);
1241     r = (num % den);
1242 #endif
1243     EAX = (uint32_t)q;
1244     EDX = (uint32_t)r;
1245 }
1246
1247 void helper_cmpxchg8b(void)
1248 {
1249     uint64_t d;
1250     int eflags;
1251
1252     eflags = cc_table[CC_OP].compute_all();
1253     d = ldq(A0);
1254     if (d == (((uint64_t)EDX << 32) | EAX)) {
1255         stq(A0, ((uint64_t)ECX << 32) | EBX);
1256         eflags |= CC_Z;
1257     } else {
1258         EDX = d >> 32;
1259         EAX = d;
1260         eflags &= ~CC_Z;
1261     }
1262     CC_SRC = eflags;
1263 }
1264
1265 void helper_cpuid(void)
1266 {
1267     switch((uint32_t)EAX) {
1268     case 0:
1269         EAX = 2; /* max EAX index supported */
1270         EBX = env->cpuid_vendor1;
1271         EDX = env->cpuid_vendor2;
1272         ECX = env->cpuid_vendor3;
1273         break;
1274     case 1:
1275         EAX = env->cpuid_version;
1276         EBX = 0;
1277         ECX = 0;
1278         EDX = env->cpuid_features;
1279         break;
1280     default:
1281         /* cache info: needed for Pentium Pro compatibility */
1282         EAX = 0x410601;
1283         EBX = 0;
1284         ECX = 0;
1285         EDX = 0;
1286         break;
1287 #ifdef TARGET_X86_64
1288     case 0x80000000:
1289         EAX = 0x80000008;
1290         EBX = env->cpuid_vendor1;
1291         EDX = env->cpuid_vendor2;
1292         ECX = env->cpuid_vendor3;
1293         break;
1294     case 0x80000001:
1295         EAX = env->cpuid_features;
1296         EBX = 0;
1297         ECX = 0;
1298         /* long mode + syscall/sysret features */
1299         EDX = (env->cpuid_features & 0x0183F3FF) | (1 << 29) | (1 << 11);
1300         break;
1301     case 0x80000008:
1302         /* virtual & phys address size in low 2 bytes. */
1303         EAX = 0x00003028;
1304         EBX = 0;
1305         ECX = 0;
1306         EDX = 0;
1307         break;
1308 #endif
1309     }
1310 }
1311
1312 void helper_enter_level(int level, int data32)
1313 {
1314     target_ulong ssp;
1315     uint32_t esp_mask, esp, ebp;
1316
1317     esp_mask = get_sp_mask(env->segs[R_SS].flags);
1318     ssp = env->segs[R_SS].base;
1319     ebp = EBP;
1320     esp = ESP;
1321     if (data32) {
1322         /* 32 bit */
1323         esp -= 4;
1324         while (--level) {
1325             esp -= 4;
1326             ebp -= 4;
1327             stl(ssp + (esp & esp_mask), ldl(ssp + (ebp & esp_mask)));
1328         }
1329         esp -= 4;
1330         stl(ssp + (esp & esp_mask), T1);
1331     } else {
1332         /* 16 bit */
1333         esp -= 2;
1334         while (--level) {
1335             esp -= 2;
1336             ebp -= 2;
1337             stw(ssp + (esp & esp_mask), lduw(ssp + (ebp & esp_mask)));
1338         }
1339         esp -= 2;
1340         stw(ssp + (esp & esp_mask), T1);
1341     }
1342 }
1343
1344 void helper_lldt_T0(void)
1345 {
1346     int selector;
1347     SegmentCache *dt;
1348     uint32_t e1, e2;
1349     int index, entry_limit;
1350     target_ulong ptr;
1351     
1352     selector = T0 & 0xffff;
1353     if ((selector & 0xfffc) == 0) {
1354         /* XXX: NULL selector case: invalid LDT */
1355         env->ldt.base = 0;
1356         env->ldt.limit = 0;
1357     } else {
1358         if (selector & 0x4)
1359             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1360         dt = &env->gdt;
1361         index = selector & ~7;
1362 #ifdef TARGET_X86_64
1363         if (env->hflags & HF_LMA_MASK)
1364             entry_limit = 15;
1365         else
1366 #endif            
1367             entry_limit = 7;
1368         if ((index + entry_limit) > dt->limit)
1369             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1370         ptr = dt->base + index;
1371         e1 = ldl_kernel(ptr);
1372         e2 = ldl_kernel(ptr + 4);
1373         if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
1374             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1375         if (!(e2 & DESC_P_MASK))
1376             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
1377 #ifdef TARGET_X86_64
1378         if (env->hflags & HF_LMA_MASK) {
1379             uint32_t e3;
1380             e3 = ldl_kernel(ptr + 8);
1381             load_seg_cache_raw_dt(&env->ldt, e1, e2);
1382             env->ldt.base |= (target_ulong)e3 << 32;
1383         } else
1384 #endif
1385         {
1386             load_seg_cache_raw_dt(&env->ldt, e1, e2);
1387         }
1388     }
1389     env->ldt.selector = selector;
1390 }
1391
1392 void helper_ltr_T0(void)
1393 {
1394     int selector;
1395     SegmentCache *dt;
1396     uint32_t e1, e2;
1397     int index, type, entry_limit;
1398     target_ulong ptr;
1399     
1400     selector = T0 & 0xffff;
1401     if ((selector & 0xfffc) == 0) {
1402         /* NULL selector case: invalid TR */
1403         env->tr.base = 0;
1404         env->tr.limit = 0;
1405         env->tr.flags = 0;
1406     } else {
1407         if (selector & 0x4)
1408             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1409         dt = &env->gdt;
1410         index = selector & ~7;
1411 #ifdef TARGET_X86_64
1412         if (env->hflags & HF_LMA_MASK)
1413             entry_limit = 15;
1414         else
1415 #endif            
1416             entry_limit = 7;
1417         if ((index + entry_limit) > dt->limit)
1418             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1419         ptr = dt->base + index;
1420         e1 = ldl_kernel(ptr);
1421         e2 = ldl_kernel(ptr + 4);
1422         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
1423         if ((e2 & DESC_S_MASK) || 
1424             (type != 1 && type != 9))
1425             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1426         if (!(e2 & DESC_P_MASK))
1427             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
1428 #ifdef TARGET_X86_64
1429         if (env->hflags & HF_LMA_MASK) {
1430             uint32_t e3;
1431             e3 = ldl_kernel(ptr + 8);
1432             load_seg_cache_raw_dt(&env->tr, e1, e2);
1433             env->tr.base |= (target_ulong)e3 << 32;
1434         } else 
1435 #endif
1436         {
1437             load_seg_cache_raw_dt(&env->tr, e1, e2);
1438         }
1439         e2 |= DESC_TSS_BUSY_MASK;
1440         stl_kernel(ptr + 4, e2);
1441     }
1442     env->tr.selector = selector;
1443 }
1444
1445 /* only works if protected mode and not VM86. seg_reg must be != R_CS */
1446 void load_seg(int seg_reg, int selector)
1447 {
1448     uint32_t e1, e2;
1449     int cpl, dpl, rpl;
1450     SegmentCache *dt;
1451     int index;
1452     target_ulong ptr;
1453
1454     selector &= 0xffff;
1455     if ((selector & 0xfffc) == 0) {
1456         /* null selector case */
1457         if (seg_reg == R_SS)
1458             raise_exception_err(EXCP0D_GPF, 0);
1459         cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0);
1460     } else {
1461         
1462         if (selector & 0x4)
1463             dt = &env->ldt;
1464         else
1465             dt = &env->gdt;
1466         index = selector & ~7;
1467         if ((index + 7) > dt->limit)
1468             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1469         ptr = dt->base + index;
1470         e1 = ldl_kernel(ptr);
1471         e2 = ldl_kernel(ptr + 4);
1472         
1473         if (!(e2 & DESC_S_MASK))
1474             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1475         rpl = selector & 3;
1476         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1477         cpl = env->hflags & HF_CPL_MASK;
1478         if (seg_reg == R_SS) {
1479             /* must be writable segment */
1480             if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
1481                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1482             if (rpl != cpl || dpl != cpl)
1483                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1484         } else {
1485             /* must be readable segment */
1486             if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK)
1487                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1488             
1489             if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
1490                 /* if not conforming code, test rights */
1491                 if (dpl < cpl || dpl < rpl)
1492                     raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1493             }
1494         }
1495
1496         if (!(e2 & DESC_P_MASK)) {
1497             if (seg_reg == R_SS)
1498                 raise_exception_err(EXCP0C_STACK, selector & 0xfffc);
1499             else
1500                 raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
1501         }
1502
1503         /* set the access bit if not already set */
1504         if (!(e2 & DESC_A_MASK)) {
1505             e2 |= DESC_A_MASK;
1506             stl_kernel(ptr + 4, e2);
1507         }
1508
1509         cpu_x86_load_seg_cache(env, seg_reg, selector, 
1510                        get_seg_base(e1, e2),
1511                        get_seg_limit(e1, e2),
1512                        e2);
1513 #if 0
1514         fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx flags=%08x\n", 
1515                 selector, (unsigned long)sc->base, sc->limit, sc->flags);
1516 #endif
1517     }
1518 }
1519
1520 /* protected mode jump */
1521 void helper_ljmp_protected_T0_T1(int next_eip)
1522 {
1523     int new_cs, gate_cs, type;
1524     uint32_t e1, e2, cpl, dpl, rpl, limit;
1525     target_ulong new_eip;
1526     
1527     new_cs = T0;
1528     new_eip = T1;
1529     if ((new_cs & 0xfffc) == 0)
1530         raise_exception_err(EXCP0D_GPF, 0);
1531     if (load_segment(&e1, &e2, new_cs) != 0)
1532         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1533     cpl = env->hflags & HF_CPL_MASK;
1534     if (e2 & DESC_S_MASK) {
1535         if (!(e2 & DESC_CS_MASK))
1536             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1537         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1538         if (e2 & DESC_C_MASK) {
1539             /* conforming code segment */
1540             if (dpl > cpl)
1541                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1542         } else {
1543             /* non conforming code segment */
1544             rpl = new_cs & 3;
1545             if (rpl > cpl)
1546                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1547             if (dpl != cpl)
1548                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1549         }
1550         if (!(e2 & DESC_P_MASK))
1551             raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
1552         limit = get_seg_limit(e1, e2);
1553         if (new_eip > limit)
1554             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1555         cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
1556                        get_seg_base(e1, e2), limit, e2);
1557         EIP = new_eip;
1558     } else {
1559         /* jump to call or task gate */
1560         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1561         rpl = new_cs & 3;
1562         cpl = env->hflags & HF_CPL_MASK;
1563         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
1564         switch(type) {
1565         case 1: /* 286 TSS */
1566         case 9: /* 386 TSS */
1567         case 5: /* task gate */
1568             if (dpl < cpl || dpl < rpl)
1569                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1570             switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip);
1571             break;
1572         case 4: /* 286 call gate */
1573         case 12: /* 386 call gate */
1574             if ((dpl < cpl) || (dpl < rpl))
1575                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1576             if (!(e2 & DESC_P_MASK))
1577                 raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
1578             gate_cs = e1 >> 16;
1579             new_eip = (e1 & 0xffff);
1580             if (type == 12)
1581                 new_eip |= (e2 & 0xffff0000);
1582             if (load_segment(&e1, &e2, gate_cs) != 0)
1583                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
1584             dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1585             /* must be code segment */
1586             if (((e2 & (DESC_S_MASK | DESC_CS_MASK)) != 
1587                  (DESC_S_MASK | DESC_CS_MASK)))
1588                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
1589             if (((e2 & DESC_C_MASK) && (dpl > cpl)) || 
1590                 (!(e2 & DESC_C_MASK) && (dpl != cpl)))
1591                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
1592             if (!(e2 & DESC_P_MASK))
1593                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
1594             limit = get_seg_limit(e1, e2);
1595             if (new_eip > limit)
1596                 raise_exception_err(EXCP0D_GPF, 0);
1597             cpu_x86_load_seg_cache(env, R_CS, (gate_cs & 0xfffc) | cpl,
1598                                    get_seg_base(e1, e2), limit, e2);
1599             EIP = new_eip;
1600             break;
1601         default:
1602             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1603             break;
1604         }
1605     }
1606 }
1607
1608 /* real mode call */
1609 void helper_lcall_real_T0_T1(int shift, int next_eip)
1610 {
1611     int new_cs, new_eip;
1612     uint32_t esp, esp_mask;
1613     target_ulong ssp;
1614
1615     new_cs = T0;
1616     new_eip = T1;
1617     esp = ESP;
1618     esp_mask = get_sp_mask(env->segs[R_SS].flags);
1619     ssp = env->segs[R_SS].base;
1620     if (shift) {
1621         PUSHL(ssp, esp, esp_mask, env->segs[R_CS].selector);
1622         PUSHL(ssp, esp, esp_mask, next_eip);
1623     } else {
1624         PUSHW(ssp, esp, esp_mask, env->segs[R_CS].selector);
1625         PUSHW(ssp, esp, esp_mask, next_eip);
1626     }
1627
1628     ESP = (ESP & ~esp_mask) | (esp & esp_mask);
1629     env->eip = new_eip;
1630     env->segs[R_CS].selector = new_cs;
1631     env->segs[R_CS].base = (new_cs << 4);
1632 }
1633
1634 /* protected mode call */
1635 void helper_lcall_protected_T0_T1(int shift, int next_eip)
1636 {
1637     int new_cs, new_eip, new_stack, i;
1638     uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;
1639     uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask;
1640     uint32_t val, limit, old_sp_mask;
1641     target_ulong ssp, old_ssp;
1642     
1643     new_cs = T0;
1644     new_eip = T1;
1645 #ifdef DEBUG_PCALL
1646     if (loglevel & CPU_LOG_PCALL) {
1647         fprintf(logfile, "lcall %04x:%08x s=%d\n",
1648                 new_cs, new_eip, shift);
1649         cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1650     }
1651 #endif
1652     if ((new_cs & 0xfffc) == 0)
1653         raise_exception_err(EXCP0D_GPF, 0);
1654     if (load_segment(&e1, &e2, new_cs) != 0)
1655         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1656     cpl = env->hflags & HF_CPL_MASK;
1657 #ifdef DEBUG_PCALL
1658     if (loglevel & CPU_LOG_PCALL) {
1659         fprintf(logfile, "desc=%08x:%08x\n", e1, e2);
1660     }
1661 #endif
1662     if (e2 & DESC_S_MASK) {
1663         if (!(e2 & DESC_CS_MASK))
1664             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1665         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1666         if (e2 & DESC_C_MASK) {
1667             /* conforming code segment */
1668             if (dpl > cpl)
1669                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1670         } else {
1671             /* non conforming code segment */
1672             rpl = new_cs & 3;
1673             if (rpl > cpl)
1674                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1675             if (dpl != cpl)
1676                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1677         }
1678         if (!(e2 & DESC_P_MASK))
1679             raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
1680
1681         sp = ESP;
1682         sp_mask = get_sp_mask(env->segs[R_SS].flags);
1683         ssp = env->segs[R_SS].base;
1684         if (shift) {
1685             PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
1686             PUSHL(ssp, sp, sp_mask, next_eip);
1687         } else {
1688             PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
1689             PUSHW(ssp, sp, sp_mask, next_eip);
1690         }
1691         
1692         limit = get_seg_limit(e1, e2);
1693         if (new_eip > limit)
1694             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1695         /* from this point, not restartable */
1696         ESP = (ESP & ~sp_mask) | (sp & sp_mask);
1697         cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
1698                        get_seg_base(e1, e2), limit, e2);
1699         EIP = new_eip;
1700     } else {
1701         /* check gate type */
1702         type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
1703         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1704         rpl = new_cs & 3;
1705         switch(type) {
1706         case 1: /* available 286 TSS */
1707         case 9: /* available 386 TSS */
1708         case 5: /* task gate */
1709             if (dpl < cpl || dpl < rpl)
1710                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1711             switch_tss(new_cs, e1, e2, SWITCH_TSS_CALL, next_eip);
1712             return;
1713         case 4: /* 286 call gate */
1714         case 12: /* 386 call gate */
1715             break;
1716         default:
1717             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1718             break;
1719         }
1720         shift = type >> 3;
1721
1722         if (dpl < cpl || dpl < rpl)
1723             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1724         /* check valid bit */
1725         if (!(e2 & DESC_P_MASK))
1726             raise_exception_err(EXCP0B_NOSEG,  new_cs & 0xfffc);
1727         selector = e1 >> 16;
1728         offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
1729         param_count = e2 & 0x1f;
1730         if ((selector & 0xfffc) == 0)
1731             raise_exception_err(EXCP0D_GPF, 0);
1732
1733         if (load_segment(&e1, &e2, selector) != 0)
1734             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1735         if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
1736             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1737         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1738         if (dpl > cpl)
1739             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1740         if (!(e2 & DESC_P_MASK))
1741             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
1742
1743         if (!(e2 & DESC_C_MASK) && dpl < cpl) {
1744             /* to inner priviledge */
1745             get_ss_esp_from_tss(&ss, &sp, dpl);
1746 #ifdef DEBUG_PCALL
1747             if (loglevel & CPU_LOG_PCALL)
1748                 fprintf(logfile, "new ss:esp=%04x:%08x param_count=%d ESP=" TARGET_FMT_lx "\n", 
1749                         ss, sp, param_count, ESP);
1750 #endif
1751             if ((ss & 0xfffc) == 0)
1752                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
1753             if ((ss & 3) != dpl)
1754                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
1755             if (load_segment(&ss_e1, &ss_e2, ss) != 0)
1756                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
1757             ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
1758             if (ss_dpl != dpl)
1759                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
1760             if (!(ss_e2 & DESC_S_MASK) ||
1761                 (ss_e2 & DESC_CS_MASK) ||
1762                 !(ss_e2 & DESC_W_MASK))
1763                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
1764             if (!(ss_e2 & DESC_P_MASK))
1765                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
1766             
1767             //            push_size = ((param_count * 2) + 8) << shift;
1768
1769             old_sp_mask = get_sp_mask(env->segs[R_SS].flags);
1770             old_ssp = env->segs[R_SS].base;
1771             
1772             sp_mask = get_sp_mask(ss_e2);
1773             ssp = get_seg_base(ss_e1, ss_e2);
1774             if (shift) {
1775                 PUSHL(ssp, sp, sp_mask, env->segs[R_SS].selector);
1776                 PUSHL(ssp, sp, sp_mask, ESP);
1777                 for(i = param_count - 1; i >= 0; i--) {
1778                     val = ldl_kernel(old_ssp + ((ESP + i * 4) & old_sp_mask));
1779                     PUSHL(ssp, sp, sp_mask, val);
1780                 }
1781             } else {
1782                 PUSHW(ssp, sp, sp_mask, env->segs[R_SS].selector);
1783                 PUSHW(ssp, sp, sp_mask, ESP);
1784                 for(i = param_count - 1; i >= 0; i--) {
1785                     val = lduw_kernel(old_ssp + ((ESP + i * 2) & old_sp_mask));
1786                     PUSHW(ssp, sp, sp_mask, val);
1787                 }
1788             }
1789             new_stack = 1;
1790         } else {
1791             /* to same priviledge */
1792             sp = ESP;
1793             sp_mask = get_sp_mask(env->segs[R_SS].flags);
1794             ssp = env->segs[R_SS].base;
1795             //            push_size = (4 << shift);
1796             new_stack = 0;
1797         }
1798
1799         if (shift) {
1800             PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
1801             PUSHL(ssp, sp, sp_mask, next_eip);
1802         } else {
1803             PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
1804             PUSHW(ssp, sp, sp_mask, next_eip);
1805         }
1806
1807         /* from this point, not restartable */
1808
1809         if (new_stack) {
1810             ss = (ss & ~3) | dpl;
1811             cpu_x86_load_seg_cache(env, R_SS, ss, 
1812                                    ssp,
1813                                    get_seg_limit(ss_e1, ss_e2),
1814                                    ss_e2);
1815         }
1816
1817         selector = (selector & ~3) | dpl;
1818         cpu_x86_load_seg_cache(env, R_CS, selector, 
1819                        get_seg_base(e1, e2),
1820                        get_seg_limit(e1, e2),
1821                        e2);
1822         cpu_x86_set_cpl(env, dpl);
1823         ESP = (ESP & ~sp_mask) | (sp & sp_mask);
1824         EIP = offset;
1825     }
1826 }
1827
1828 /* real and vm86 mode iret */
1829 void helper_iret_real(int shift)
1830 {
1831     uint32_t sp, new_cs, new_eip, new_eflags, sp_mask;
1832     target_ulong ssp;
1833     int eflags_mask;
1834
1835     sp_mask = 0xffff; /* XXXX: use SS segment size ? */
1836     sp = ESP;
1837     ssp = env->segs[R_SS].base;
1838     if (shift == 1) {
1839         /* 32 bits */
1840         POPL(ssp, sp, sp_mask, new_eip);
1841         POPL(ssp, sp, sp_mask, new_cs);
1842         new_cs &= 0xffff;
1843         POPL(ssp, sp, sp_mask, new_eflags);
1844     } else {
1845         /* 16 bits */
1846         POPW(ssp, sp, sp_mask, new_eip);
1847         POPW(ssp, sp, sp_mask, new_cs);
1848         POPW(ssp, sp, sp_mask, new_eflags);
1849     }
1850     ESP = (ESP & ~sp_mask) | (sp & sp_mask);
1851     load_seg_vm(R_CS, new_cs);
1852     env->eip = new_eip;
1853     if (env->eflags & VM_MASK)
1854         eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK | NT_MASK;
1855     else
1856         eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK | RF_MASK | NT_MASK;
1857     if (shift == 0)
1858         eflags_mask &= 0xffff;
1859     load_eflags(new_eflags, eflags_mask);
1860 }
1861
1862 static inline void validate_seg(int seg_reg, int cpl)
1863 {
1864     int dpl;
1865     uint32_t e2;
1866     
1867     e2 = env->segs[seg_reg].flags;
1868     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1869     if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
1870         /* data or non conforming code segment */
1871         if (dpl < cpl) {
1872             cpu_x86_load_seg_cache(env, seg_reg, 0, 0, 0, 0);
1873         }
1874     }
1875 }
1876
1877 /* protected mode iret */
1878 static inline void helper_ret_protected(int shift, int is_iret, int addend)
1879 {
1880     uint32_t new_cs, new_eflags, new_ss;
1881     uint32_t new_es, new_ds, new_fs, new_gs;
1882     uint32_t e1, e2, ss_e1, ss_e2;
1883     int cpl, dpl, rpl, eflags_mask, iopl;
1884     target_ulong ssp, sp, new_eip, new_esp, sp_mask;
1885     
1886 #ifdef TARGET_X86_64
1887     if (shift == 2)
1888         sp_mask = -1;
1889     else
1890 #endif
1891         sp_mask = get_sp_mask(env->segs[R_SS].flags);
1892     sp = ESP;
1893     ssp = env->segs[R_SS].base;
1894     new_eflags = 0; /* avoid warning */
1895 #ifdef TARGET_X86_64
1896     if (shift == 2) {
1897         POPQ(sp, new_eip);
1898         POPQ(sp, new_cs);
1899         new_cs &= 0xffff;
1900         if (is_iret) {
1901             POPQ(sp, new_eflags);
1902         }
1903     } else
1904 #endif
1905     if (shift == 1) {
1906         /* 32 bits */
1907         POPL(ssp, sp, sp_mask, new_eip);
1908         POPL(ssp, sp, sp_mask, new_cs);
1909         new_cs &= 0xffff;
1910         if (is_iret) {
1911             POPL(ssp, sp, sp_mask, new_eflags);
1912             if (new_eflags & VM_MASK)
1913                 goto return_to_vm86;
1914         }
1915     } else {
1916         /* 16 bits */
1917         POPW(ssp, sp, sp_mask, new_eip);
1918         POPW(ssp, sp, sp_mask, new_cs);
1919         if (is_iret)
1920             POPW(ssp, sp, sp_mask, new_eflags);
1921     }
1922 #ifdef DEBUG_PCALL
1923     if (loglevel & CPU_LOG_PCALL) {
1924         fprintf(logfile, "lret new %04x:" TARGET_FMT_lx " s=%d addend=0x%x\n",
1925                 new_cs, new_eip, shift, addend);
1926         cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1927     }
1928 #endif
1929     if ((new_cs & 0xfffc) == 0)
1930         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1931     if (load_segment(&e1, &e2, new_cs) != 0)
1932         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1933     if (!(e2 & DESC_S_MASK) ||
1934         !(e2 & DESC_CS_MASK))
1935         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1936     cpl = env->hflags & HF_CPL_MASK;
1937     rpl = new_cs & 3; 
1938     if (rpl < cpl)
1939         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1940     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1941     if (e2 & DESC_C_MASK) {
1942         if (dpl > rpl)
1943             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1944     } else {
1945         if (dpl != rpl)
1946             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1947     }
1948     if (!(e2 & DESC_P_MASK))
1949         raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
1950     
1951     sp += addend;
1952     if (rpl == cpl && !(env->hflags & HF_CS64_MASK)) {
1953         /* return to same priledge level */
1954         cpu_x86_load_seg_cache(env, R_CS, new_cs, 
1955                        get_seg_base(e1, e2),
1956                        get_seg_limit(e1, e2),
1957                        e2);
1958     } else {
1959         /* return to different priviledge level */
1960 #ifdef TARGET_X86_64
1961         if (shift == 2) {
1962             POPQ(sp, new_esp);
1963             POPQ(sp, new_ss);
1964             new_ss &= 0xffff;
1965         } else
1966 #endif
1967         if (shift == 1) {
1968             /* 32 bits */
1969             POPL(ssp, sp, sp_mask, new_esp);
1970             POPL(ssp, sp, sp_mask, new_ss);
1971             new_ss &= 0xffff;
1972         } else {
1973             /* 16 bits */
1974             POPW(ssp, sp, sp_mask, new_esp);
1975             POPW(ssp, sp, sp_mask, new_ss);
1976         }
1977 #ifdef DEBUG_PCALL
1978         if (loglevel & CPU_LOG_PCALL) {
1979             fprintf(logfile, "new ss:esp=%04x:" TARGET_FMT_lx "\n",
1980                     new_ss, new_esp);
1981         }
1982 #endif
1983         if ((env->hflags & HF_LMA_MASK) && (new_ss & 0xfffc) == 0) {
1984             /* NULL ss is allowed in long mode */
1985             cpu_x86_load_seg_cache(env, R_SS, new_ss, 
1986                                    0, 0xffffffff,
1987                                    DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1988                                    DESC_S_MASK | (rpl << DESC_DPL_SHIFT) |
1989                                    DESC_W_MASK | DESC_A_MASK);
1990         } else {
1991             if ((new_ss & 3) != rpl)
1992                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
1993             if (load_segment(&ss_e1, &ss_e2, new_ss) != 0)
1994                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
1995             if (!(ss_e2 & DESC_S_MASK) ||
1996                 (ss_e2 & DESC_CS_MASK) ||
1997                 !(ss_e2 & DESC_W_MASK))
1998                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
1999             dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
2000             if (dpl != rpl)
2001                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2002             if (!(ss_e2 & DESC_P_MASK))
2003                 raise_exception_err(EXCP0B_NOSEG, new_ss & 0xfffc);
2004             cpu_x86_load_seg_cache(env, R_SS, new_ss, 
2005                                    get_seg_base(ss_e1, ss_e2),
2006                                    get_seg_limit(ss_e1, ss_e2),
2007                                    ss_e2);
2008         }
2009
2010         cpu_x86_load_seg_cache(env, R_CS, new_cs, 
2011                        get_seg_base(e1, e2),
2012                        get_seg_limit(e1, e2),
2013                        e2);
2014         cpu_x86_set_cpl(env, rpl);
2015         sp = new_esp;
2016 #ifdef TARGET_X86_64
2017         if (shift == 2)
2018             sp_mask = -1;
2019         else
2020 #endif
2021             sp_mask = get_sp_mask(ss_e2);
2022
2023         /* validate data segments */
2024         validate_seg(R_ES, cpl);
2025         validate_seg(R_DS, cpl);
2026         validate_seg(R_FS, cpl);
2027         validate_seg(R_GS, cpl);
2028
2029         sp += addend;
2030     }
2031     ESP = (ESP & ~sp_mask) | (sp & sp_mask);
2032     env->eip = new_eip;
2033     if (is_iret) {
2034         /* NOTE: 'cpl' is the _old_ CPL */
2035         eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK | NT_MASK;
2036         if (cpl == 0)
2037             eflags_mask |= IOPL_MASK;
2038         iopl = (env->eflags >> IOPL_SHIFT) & 3;
2039         if (cpl <= iopl)
2040             eflags_mask |= IF_MASK;
2041         if (shift == 0)
2042             eflags_mask &= 0xffff;
2043         load_eflags(new_eflags, eflags_mask);
2044     }
2045     return;
2046
2047  return_to_vm86:
2048     POPL(ssp, sp, sp_mask, new_esp);
2049     POPL(ssp, sp, sp_mask, new_ss);
2050     POPL(ssp, sp, sp_mask, new_es);
2051     POPL(ssp, sp, sp_mask, new_ds);
2052     POPL(ssp, sp, sp_mask, new_fs);
2053     POPL(ssp, sp, sp_mask, new_gs);
2054     
2055     /* modify processor state */
2056     load_eflags(new_eflags, TF_MASK | AC_MASK | ID_MASK | 
2057                 IF_MASK | IOPL_MASK | VM_MASK | NT_MASK | VIF_MASK | VIP_MASK);
2058     load_seg_vm(R_CS, new_cs & 0xffff);
2059     cpu_x86_set_cpl(env, 3);
2060     load_seg_vm(R_SS, new_ss & 0xffff);
2061     load_seg_vm(R_ES, new_es & 0xffff);
2062     load_seg_vm(R_DS, new_ds & 0xffff);
2063     load_seg_vm(R_FS, new_fs & 0xffff);
2064     load_seg_vm(R_GS, new_gs & 0xffff);
2065
2066     env->eip = new_eip & 0xffff;
2067     ESP = new_esp;
2068 }
2069
2070 void helper_iret_protected(int shift, int next_eip)
2071 {
2072     int tss_selector, type;
2073     uint32_t e1, e2;
2074     
2075     /* specific case for TSS */
2076     if (env->eflags & NT_MASK) {
2077 #ifdef TARGET_X86_64
2078         if (env->hflags & HF_LMA_MASK)
2079             raise_exception_err(EXCP0D_GPF, 0);
2080 #endif
2081         tss_selector = lduw_kernel(env->tr.base + 0);
2082         if (tss_selector & 4)
2083             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2084         if (load_segment(&e1, &e2, tss_selector) != 0)
2085             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2086         type = (e2 >> DESC_TYPE_SHIFT) & 0x17;
2087         /* NOTE: we check both segment and busy TSS */
2088         if (type != 3)
2089             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2090         switch_tss(tss_selector, e1, e2, SWITCH_TSS_IRET, next_eip);
2091     } else {
2092         helper_ret_protected(shift, 1, 0);
2093     }
2094 }
2095
2096 void helper_lret_protected(int shift, int addend)
2097 {
2098     helper_ret_protected(shift, 0, addend);
2099 }
2100
2101 void helper_sysenter(void)
2102 {
2103     if (env->sysenter_cs == 0) {
2104         raise_exception_err(EXCP0D_GPF, 0);
2105     }
2106     env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK);
2107     cpu_x86_set_cpl(env, 0);
2108     cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc, 
2109                            0, 0xffffffff, 
2110                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2111                            DESC_S_MASK |
2112                            DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2113     cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc, 
2114                            0, 0xffffffff,
2115                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2116                            DESC_S_MASK |
2117                            DESC_W_MASK | DESC_A_MASK);
2118     ESP = env->sysenter_esp;
2119     EIP = env->sysenter_eip;
2120 }
2121
2122 void helper_sysexit(void)
2123 {
2124     int cpl;
2125
2126     cpl = env->hflags & HF_CPL_MASK;
2127     if (env->sysenter_cs == 0 || cpl != 0) {
2128         raise_exception_err(EXCP0D_GPF, 0);
2129     }
2130     cpu_x86_set_cpl(env, 3);
2131     cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3, 
2132                            0, 0xffffffff, 
2133                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2134                            DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2135                            DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2136     cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3, 
2137                            0, 0xffffffff,
2138                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2139                            DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2140                            DESC_W_MASK | DESC_A_MASK);
2141     ESP = ECX;
2142     EIP = EDX;
2143 }
2144
2145 void helper_movl_crN_T0(int reg)
2146 {
2147     switch(reg) {
2148     case 0:
2149         cpu_x86_update_cr0(env, T0);
2150         break;
2151     case 3:
2152         cpu_x86_update_cr3(env, T0);
2153         break;
2154     case 4:
2155         cpu_x86_update_cr4(env, T0);
2156         break;
2157     default:
2158         env->cr[reg] = T0;
2159         break;
2160     }
2161 }
2162
2163 /* XXX: do more */
2164 void helper_movl_drN_T0(int reg)
2165 {
2166     env->dr[reg] = T0;
2167 }
2168
2169 void helper_invlpg(unsigned int addr)
2170 {
2171     cpu_x86_flush_tlb(env, addr);
2172 }
2173
2174 void helper_rdtsc(void)
2175 {
2176     uint64_t val;
2177     
2178     val = cpu_get_tsc(env);
2179     EAX = (uint32_t)(val);
2180     EDX = (uint32_t)(val >> 32);
2181 }
2182
2183 #if defined(CONFIG_USER_ONLY) 
2184 void helper_wrmsr(void)
2185 {
2186 }
2187
2188 void helper_rdmsr(void)
2189 {
2190 }
2191 #else
2192 void helper_wrmsr(void)
2193 {
2194     uint64_t val;
2195
2196     val = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
2197
2198     switch((uint32_t)ECX) {
2199     case MSR_IA32_SYSENTER_CS:
2200         env->sysenter_cs = val & 0xffff;
2201         break;
2202     case MSR_IA32_SYSENTER_ESP:
2203         env->sysenter_esp = val;
2204         break;
2205     case MSR_IA32_SYSENTER_EIP:
2206         env->sysenter_eip = val;
2207         break;
2208     case MSR_IA32_APICBASE:
2209         cpu_set_apic_base(env, val);
2210         break;
2211 #ifdef TARGET_X86_64
2212     case MSR_EFER:
2213 #define MSR_EFER_UPDATE_MASK (MSR_EFER_SCE | MSR_EFER_LME | \
2214                               MSR_EFER_NXE | MSR_EFER_FFXSR)
2215         env->efer = (env->efer & ~MSR_EFER_UPDATE_MASK) | 
2216             (val & MSR_EFER_UPDATE_MASK);
2217         break;
2218     case MSR_STAR:
2219         env->star = val;
2220         break;
2221     case MSR_LSTAR:
2222         env->lstar = val;
2223         break;
2224     case MSR_CSTAR:
2225         env->cstar = val;
2226         break;
2227     case MSR_FMASK:
2228         env->fmask = val;
2229         break;
2230     case MSR_FSBASE:
2231         env->segs[R_FS].base = val;
2232         break;
2233     case MSR_GSBASE:
2234         env->segs[R_GS].base = val;
2235         break;
2236     case MSR_KERNELGSBASE:
2237         env->kernelgsbase = val;
2238         break;
2239 #endif
2240     default:
2241         /* XXX: exception ? */
2242         break; 
2243     }
2244 }
2245
2246 void helper_rdmsr(void)
2247 {
2248     uint64_t val;
2249     switch((uint32_t)ECX) {
2250     case MSR_IA32_SYSENTER_CS:
2251         val = env->sysenter_cs;
2252         break;
2253     case MSR_IA32_SYSENTER_ESP:
2254         val = env->sysenter_esp;
2255         break;
2256     case MSR_IA32_SYSENTER_EIP:
2257         val = env->sysenter_eip;
2258         break;
2259     case MSR_IA32_APICBASE:
2260         val = cpu_get_apic_base(env);
2261         break;
2262 #ifdef TARGET_X86_64
2263     case MSR_EFER:
2264         val = env->efer;
2265         break;
2266     case MSR_STAR:
2267         val = env->star;
2268         break;
2269     case MSR_LSTAR:
2270         val = env->lstar;
2271         break;
2272     case MSR_CSTAR:
2273         val = env->cstar;
2274         break;
2275     case MSR_FMASK:
2276         val = env->fmask;
2277         break;
2278     case MSR_FSBASE:
2279         val = env->segs[R_FS].base;
2280         break;
2281     case MSR_GSBASE:
2282         val = env->segs[R_GS].base;
2283         break;
2284     case MSR_KERNELGSBASE:
2285         val = env->kernelgsbase;
2286         break;
2287 #endif
2288     default:
2289         /* XXX: exception ? */
2290         val = 0;
2291         break; 
2292     }
2293     EAX = (uint32_t)(val);
2294     EDX = (uint32_t)(val >> 32);
2295 }
2296 #endif
2297
2298 void helper_lsl(void)
2299 {
2300     unsigned int selector, limit;
2301     uint32_t e1, e2;
2302     int rpl, dpl, cpl, type;
2303
2304     CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z;
2305     selector = T0 & 0xffff;
2306     if (load_segment(&e1, &e2, selector) != 0)
2307         return;
2308     rpl = selector & 3;
2309     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2310     cpl = env->hflags & HF_CPL_MASK;
2311     if (e2 & DESC_S_MASK) {
2312         if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
2313             /* conforming */
2314         } else {
2315             if (dpl < cpl || dpl < rpl)
2316                 return;
2317         }
2318     } else {
2319         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2320         switch(type) {
2321         case 1:
2322         case 2:
2323         case 3:
2324         case 9:
2325         case 11:
2326             break;
2327         default:
2328             return;
2329         }
2330         if (dpl < cpl || dpl < rpl)
2331             return;
2332     }
2333     limit = get_seg_limit(e1, e2);
2334     T1 = limit;
2335     CC_SRC |= CC_Z;
2336 }
2337
2338 void helper_lar(void)
2339 {
2340     unsigned int selector;
2341     uint32_t e1, e2;
2342     int rpl, dpl, cpl, type;
2343
2344     CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z;
2345     selector = T0 & 0xffff;
2346     if ((selector & 0xfffc) == 0)
2347         return;
2348     if (load_segment(&e1, &e2, selector) != 0)
2349         return;
2350     rpl = selector & 3;
2351     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2352     cpl = env->hflags & HF_CPL_MASK;
2353     if (e2 & DESC_S_MASK) {
2354         if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
2355             /* conforming */
2356         } else {
2357             if (dpl < cpl || dpl < rpl)
2358                 return;
2359         }
2360     } else {
2361         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2362         switch(type) {
2363         case 1:
2364         case 2:
2365         case 3:
2366         case 4:
2367         case 5:
2368         case 9:
2369         case 11:
2370         case 12:
2371             break;
2372         default:
2373             return;
2374         }
2375         if (dpl < cpl || dpl < rpl)
2376             return;
2377     }
2378     T1 = e2 & 0x00f0ff00;
2379     CC_SRC |= CC_Z;
2380 }
2381
2382 void helper_verr(void)
2383 {
2384     unsigned int selector;
2385     uint32_t e1, e2;
2386     int rpl, dpl, cpl;
2387
2388     CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z;
2389     selector = T0 & 0xffff;
2390     if ((selector & 0xfffc) == 0)
2391         return;
2392     if (load_segment(&e1, &e2, selector) != 0)
2393         return;
2394     if (!(e2 & DESC_S_MASK))
2395         return;
2396     rpl = selector & 3;
2397     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2398     cpl = env->hflags & HF_CPL_MASK;
2399     if (e2 & DESC_CS_MASK) {
2400         if (!(e2 & DESC_R_MASK))
2401             return;
2402         if (!(e2 & DESC_C_MASK)) {
2403             if (dpl < cpl || dpl < rpl)
2404                 return;
2405         }
2406     } else {
2407         if (dpl < cpl || dpl < rpl)
2408             return;
2409     }
2410     CC_SRC |= CC_Z;
2411 }
2412
2413 void helper_verw(void)
2414 {
2415     unsigned int selector;
2416     uint32_t e1, e2;
2417     int rpl, dpl, cpl;
2418
2419     CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z;
2420     selector = T0 & 0xffff;
2421     if ((selector & 0xfffc) == 0)
2422         return;
2423     if (load_segment(&e1, &e2, selector) != 0)
2424         return;
2425     if (!(e2 & DESC_S_MASK))
2426         return;
2427     rpl = selector & 3;
2428     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2429     cpl = env->hflags & HF_CPL_MASK;
2430     if (e2 & DESC_CS_MASK) {
2431         return;
2432     } else {
2433         if (dpl < cpl || dpl < rpl)
2434             return;
2435         if (!(e2 & DESC_W_MASK))
2436             return;
2437     }
2438     CC_SRC |= CC_Z;
2439 }
2440
2441 /* FPU helpers */
2442
2443 void helper_fldt_ST0_A0(void)
2444 {
2445     int new_fpstt;
2446     new_fpstt = (env->fpstt - 1) & 7;
2447     env->fpregs[new_fpstt].d = helper_fldt(A0);
2448     env->fpstt = new_fpstt;
2449     env->fptags[new_fpstt] = 0; /* validate stack entry */
2450 }
2451
2452 void helper_fstt_ST0_A0(void)
2453 {
2454     helper_fstt(ST0, A0);
2455 }
2456
2457 void fpu_set_exception(int mask)
2458 {
2459     env->fpus |= mask;
2460     if (env->fpus & (~env->fpuc & FPUC_EM))
2461         env->fpus |= FPUS_SE | FPUS_B;
2462 }
2463
2464 CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b)
2465 {
2466     if (b == 0.0) 
2467         fpu_set_exception(FPUS_ZE);
2468     return a / b;
2469 }
2470
2471 void fpu_raise_exception(void)
2472 {
2473     if (env->cr[0] & CR0_NE_MASK) {
2474         raise_exception(EXCP10_COPR);
2475     } 
2476 #if !defined(CONFIG_USER_ONLY) 
2477     else {
2478         cpu_set_ferr(env);
2479     }
2480 #endif
2481 }
2482
2483 /* BCD ops */
2484
2485 void helper_fbld_ST0_A0(void)
2486 {
2487     CPU86_LDouble tmp;
2488     uint64_t val;
2489     unsigned int v;
2490     int i;
2491
2492     val = 0;
2493     for(i = 8; i >= 0; i--) {
2494         v = ldub(A0 + i);
2495         val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
2496     }
2497     tmp = val;
2498     if (ldub(A0 + 9) & 0x80)
2499         tmp = -tmp;
2500     fpush();
2501     ST0 = tmp;
2502 }
2503
2504 void helper_fbst_ST0_A0(void)
2505 {
2506     CPU86_LDouble tmp;
2507     int v;
2508     target_ulong mem_ref, mem_end;
2509     int64_t val;
2510
2511     tmp = rint(ST0);
2512     val = (int64_t)tmp;
2513     mem_ref = A0;
2514     mem_end = mem_ref + 9;
2515     if (val < 0) {
2516         stb(mem_end, 0x80);
2517         val = -val;
2518     } else {
2519         stb(mem_end, 0x00);
2520     }
2521     while (mem_ref < mem_end) {
2522         if (val == 0)
2523             break;
2524         v = val % 100;
2525         val = val / 100;
2526         v = ((v / 10) << 4) | (v % 10);
2527         stb(mem_ref++, v);
2528     }
2529     while (mem_ref < mem_end) {
2530         stb(mem_ref++, 0);
2531     }
2532 }
2533
2534 void helper_f2xm1(void)
2535 {
2536     ST0 = pow(2.0,ST0) - 1.0;
2537 }
2538
2539 void helper_fyl2x(void)
2540 {
2541     CPU86_LDouble fptemp;
2542     
2543     fptemp = ST0;
2544     if (fptemp>0.0){
2545         fptemp = log(fptemp)/log(2.0);   /* log2(ST) */
2546         ST1 *= fptemp;
2547         fpop();
2548     } else { 
2549         env->fpus &= (~0x4700);
2550         env->fpus |= 0x400;
2551     }
2552 }
2553
2554 void helper_fptan(void)
2555 {
2556     CPU86_LDouble fptemp;
2557
2558     fptemp = ST0;
2559     if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2560         env->fpus |= 0x400;
2561     } else {
2562         ST0 = tan(fptemp);
2563         fpush();
2564         ST0 = 1.0;
2565         env->fpus &= (~0x400);  /* C2 <-- 0 */
2566         /* the above code is for  |arg| < 2**52 only */
2567     }
2568 }
2569
2570 void helper_fpatan(void)
2571 {
2572     CPU86_LDouble fptemp, fpsrcop;
2573
2574     fpsrcop = ST1;
2575     fptemp = ST0;
2576     ST1 = atan2(fpsrcop,fptemp);
2577     fpop();
2578 }
2579
2580 void helper_fxtract(void)
2581 {
2582     CPU86_LDoubleU temp;
2583     unsigned int expdif;
2584
2585     temp.d = ST0;
2586     expdif = EXPD(temp) - EXPBIAS;
2587     /*DP exponent bias*/
2588     ST0 = expdif;
2589     fpush();
2590     BIASEXPONENT(temp);
2591     ST0 = temp.d;
2592 }
2593
2594 void helper_fprem1(void)
2595 {
2596     CPU86_LDouble dblq, fpsrcop, fptemp;
2597     CPU86_LDoubleU fpsrcop1, fptemp1;
2598     int expdif;
2599     int q;
2600
2601     fpsrcop = ST0;
2602     fptemp = ST1;
2603     fpsrcop1.d = fpsrcop;
2604     fptemp1.d = fptemp;
2605     expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
2606     if (expdif < 53) {
2607         dblq = fpsrcop / fptemp;
2608         dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
2609         ST0 = fpsrcop - fptemp*dblq;
2610         q = (int)dblq; /* cutting off top bits is assumed here */
2611         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
2612                                 /* (C0,C1,C3) <-- (q2,q1,q0) */
2613         env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
2614         env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
2615         env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
2616     } else {
2617         env->fpus |= 0x400;  /* C2 <-- 1 */
2618         fptemp = pow(2.0, expdif-50);
2619         fpsrcop = (ST0 / ST1) / fptemp;
2620         /* fpsrcop = integer obtained by rounding to the nearest */
2621         fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)?
2622             floor(fpsrcop): ceil(fpsrcop);
2623         ST0 -= (ST1 * fpsrcop * fptemp);
2624     }
2625 }
2626
2627 void helper_fprem(void)
2628 {
2629     CPU86_LDouble dblq, fpsrcop, fptemp;
2630     CPU86_LDoubleU fpsrcop1, fptemp1;
2631     int expdif;
2632     int q;
2633     
2634     fpsrcop = ST0;
2635     fptemp = ST1;
2636     fpsrcop1.d = fpsrcop;
2637     fptemp1.d = fptemp;
2638     expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
2639     if ( expdif < 53 ) {
2640         dblq = fpsrcop / fptemp;
2641         dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
2642         ST0 = fpsrcop - fptemp*dblq;
2643         q = (int)dblq; /* cutting off top bits is assumed here */
2644         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
2645                                 /* (C0,C1,C3) <-- (q2,q1,q0) */
2646         env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
2647         env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
2648         env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
2649     } else {
2650         env->fpus |= 0x400;  /* C2 <-- 1 */
2651         fptemp = pow(2.0, expdif-50);
2652         fpsrcop = (ST0 / ST1) / fptemp;
2653         /* fpsrcop = integer obtained by chopping */
2654         fpsrcop = (fpsrcop < 0.0)?
2655             -(floor(fabs(fpsrcop))): floor(fpsrcop);
2656         ST0 -= (ST1 * fpsrcop * fptemp);
2657     }
2658 }
2659
2660 void helper_fyl2xp1(void)
2661 {
2662     CPU86_LDouble fptemp;
2663
2664     fptemp = ST0;
2665     if ((fptemp+1.0)>0.0) {
2666         fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
2667         ST1 *= fptemp;
2668         fpop();
2669     } else { 
2670         env->fpus &= (~0x4700);
2671         env->fpus |= 0x400;
2672     }
2673 }
2674
2675 void helper_fsqrt(void)
2676 {
2677     CPU86_LDouble fptemp;
2678
2679     fptemp = ST0;
2680     if (fptemp<0.0) { 
2681         env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
2682         env->fpus |= 0x400;
2683     }
2684     ST0 = sqrt(fptemp);
2685 }
2686
2687 void helper_fsincos(void)
2688 {
2689     CPU86_LDouble fptemp;
2690
2691     fptemp = ST0;
2692     if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2693         env->fpus |= 0x400;
2694     } else {
2695         ST0 = sin(fptemp);
2696         fpush();
2697         ST0 = cos(fptemp);
2698         env->fpus &= (~0x400);  /* C2 <-- 0 */
2699         /* the above code is for  |arg| < 2**63 only */
2700     }
2701 }
2702
2703 void helper_frndint(void)
2704 {
2705     CPU86_LDouble a;
2706
2707     a = ST0;
2708 #ifdef __arm__
2709     switch(env->fpuc & RC_MASK) {
2710     default:
2711     case RC_NEAR:
2712         asm("rndd %0, %1" : "=f" (a) : "f"(a));
2713         break;
2714     case RC_DOWN:
2715         asm("rnddm %0, %1" : "=f" (a) : "f"(a));
2716         break;
2717     case RC_UP:
2718         asm("rnddp %0, %1" : "=f" (a) : "f"(a));
2719         break;
2720     case RC_CHOP:
2721         asm("rnddz %0, %1" : "=f" (a) : "f"(a));
2722         break;
2723     }
2724 #else
2725     a = rint(a);
2726 #endif
2727     ST0 = a;
2728 }
2729
2730 void helper_fscale(void)
2731 {
2732     CPU86_LDouble fpsrcop, fptemp;
2733
2734     fpsrcop = 2.0;
2735     fptemp = pow(fpsrcop,ST1);
2736     ST0 *= fptemp;
2737 }
2738
2739 void helper_fsin(void)
2740 {
2741     CPU86_LDouble fptemp;
2742
2743     fptemp = ST0;
2744     if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2745         env->fpus |= 0x400;
2746     } else {
2747         ST0 = sin(fptemp);
2748         env->fpus &= (~0x400);  /* C2 <-- 0 */
2749         /* the above code is for  |arg| < 2**53 only */
2750     }
2751 }
2752
2753 void helper_fcos(void)
2754 {
2755     CPU86_LDouble fptemp;
2756
2757     fptemp = ST0;
2758     if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2759         env->fpus |= 0x400;
2760     } else {
2761         ST0 = cos(fptemp);
2762         env->fpus &= (~0x400);  /* C2 <-- 0 */
2763         /* the above code is for  |arg5 < 2**63 only */
2764     }
2765 }
2766
2767 void helper_fxam_ST0(void)
2768 {
2769     CPU86_LDoubleU temp;
2770     int expdif;
2771
2772     temp.d = ST0;
2773
2774     env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
2775     if (SIGND(temp))
2776         env->fpus |= 0x200; /* C1 <-- 1 */
2777
2778     expdif = EXPD(temp);
2779     if (expdif == MAXEXPD) {
2780         if (MANTD(temp) == 0)
2781             env->fpus |=  0x500 /*Infinity*/;
2782         else
2783             env->fpus |=  0x100 /*NaN*/;
2784     } else if (expdif == 0) {
2785         if (MANTD(temp) == 0)
2786             env->fpus |=  0x4000 /*Zero*/;
2787         else
2788             env->fpus |= 0x4400 /*Denormal*/;
2789     } else {
2790         env->fpus |= 0x400;
2791     }
2792 }
2793
2794 void helper_fstenv(target_ulong ptr, int data32)
2795 {
2796     int fpus, fptag, exp, i;
2797     uint64_t mant;
2798     CPU86_LDoubleU tmp;
2799
2800     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2801     fptag = 0;
2802     for (i=7; i>=0; i--) {
2803         fptag <<= 2;
2804         if (env->fptags[i]) {
2805             fptag |= 3;
2806         } else {
2807             tmp.d = env->fpregs[i].d;
2808             exp = EXPD(tmp);
2809             mant = MANTD(tmp);
2810             printf("mant=%llx exp=%x\n", mant, exp);
2811             if (exp == 0 && mant == 0) {
2812                 /* zero */
2813                 fptag |= 1;
2814             } else if (exp == 0 || exp == MAXEXPD
2815 #ifdef USE_X86LDOUBLE
2816                        || (mant & (1LL << 63)) == 0
2817 #endif
2818                        ) {
2819                 /* NaNs, infinity, denormal */
2820                 fptag |= 2;
2821             }
2822         }
2823     }
2824     if (data32) {
2825         /* 32 bit */
2826         stl(ptr, env->fpuc);
2827         stl(ptr + 4, fpus);
2828         stl(ptr + 8, fptag);
2829         stl(ptr + 12, 0); /* fpip */
2830         stl(ptr + 16, 0); /* fpcs */
2831         stl(ptr + 20, 0); /* fpoo */
2832         stl(ptr + 24, 0); /* fpos */
2833     } else {
2834         /* 16 bit */
2835         stw(ptr, env->fpuc);
2836         stw(ptr + 2, fpus);
2837         stw(ptr + 4, fptag);
2838         stw(ptr + 6, 0);
2839         stw(ptr + 8, 0);
2840         stw(ptr + 10, 0);
2841         stw(ptr + 12, 0);
2842     }
2843 }
2844
2845 void helper_fldenv(target_ulong ptr, int data32)
2846 {
2847     int i, fpus, fptag;
2848
2849     if (data32) {
2850         env->fpuc = lduw(ptr);
2851         fpus = lduw(ptr + 4);
2852         fptag = lduw(ptr + 8);
2853     }
2854     else {
2855         env->fpuc = lduw(ptr);
2856         fpus = lduw(ptr + 2);
2857         fptag = lduw(ptr + 4);
2858     }
2859     env->fpstt = (fpus >> 11) & 7;
2860     env->fpus = fpus & ~0x3800;
2861     for(i = 0;i < 8; i++) {
2862         env->fptags[i] = ((fptag & 3) == 3);
2863         fptag >>= 2;
2864     }
2865 }
2866
2867 void helper_fsave(target_ulong ptr, int data32)
2868 {
2869     CPU86_LDouble tmp;
2870     int i;
2871
2872     helper_fstenv(ptr, data32);
2873
2874     ptr += (14 << data32);
2875     for(i = 0;i < 8; i++) {
2876         tmp = ST(i);
2877         helper_fstt(tmp, ptr);
2878         ptr += 10;
2879     }
2880
2881     /* fninit */
2882     env->fpus = 0;
2883     env->fpstt = 0;
2884     env->fpuc = 0x37f;
2885     env->fptags[0] = 1;
2886     env->fptags[1] = 1;
2887     env->fptags[2] = 1;
2888     env->fptags[3] = 1;
2889     env->fptags[4] = 1;
2890     env->fptags[5] = 1;
2891     env->fptags[6] = 1;
2892     env->fptags[7] = 1;
2893 }
2894
2895 void helper_frstor(target_ulong ptr, int data32)
2896 {
2897     CPU86_LDouble tmp;
2898     int i;
2899
2900     helper_fldenv(ptr, data32);
2901     ptr += (14 << data32);
2902
2903     for(i = 0;i < 8; i++) {
2904         tmp = helper_fldt(ptr);
2905         ST(i) = tmp;
2906         ptr += 10;
2907     }
2908 }
2909
2910 void helper_fxsave(target_ulong ptr, int data64)
2911 {
2912     int fpus, fptag, i, nb_xmm_regs;
2913     CPU86_LDouble tmp;
2914     target_ulong addr;
2915
2916     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2917     fptag = 0;
2918     for(i = 0; i < 8; i++) {
2919         fptag |= ((!env->fptags[(env->fpstt + i) & 7]) << i);
2920     }
2921     stw(ptr, env->fpuc);
2922     stw(ptr + 2, fpus);
2923     stw(ptr + 4, fptag);
2924
2925     addr = ptr + 0x20;
2926     for(i = 0;i < 8; i++) {
2927         tmp = ST(i);
2928         helper_fstt(tmp, addr);
2929         addr += 16;
2930     }
2931     
2932     if (env->cr[4] & CR4_OSFXSR_MASK) {
2933         /* XXX: finish it */
2934         stl(ptr + 0x18, env->mxcsr); /* mxcsr */
2935         stl(ptr + 0x1c, 0); /* mxcsr_mask */
2936         nb_xmm_regs = 8 << data64;
2937         addr = ptr + 0xa0;
2938         for(i = 0; i < nb_xmm_regs; i++) {
2939             stq(addr, env->xmm_regs[i].XMM_Q(0));
2940             stq(addr + 8, env->xmm_regs[i].XMM_Q(1));
2941             addr += 16;
2942         }
2943     }
2944 }
2945
2946 void helper_fxrstor(target_ulong ptr, int data64)
2947 {
2948     int i, fpus, fptag, nb_xmm_regs;
2949     CPU86_LDouble tmp;
2950     target_ulong addr;
2951
2952     env->fpuc = lduw(ptr);
2953     fpus = lduw(ptr + 2);
2954     fptag = ldub(ptr + 4);
2955     env->fpstt = (fpus >> 11) & 7;
2956     env->fpus = fpus & ~0x3800;
2957     fptag ^= 0xff;
2958     for(i = 0;i < 8; i++) {
2959         env->fptags[(env->fpstt + i) & 7] = ((fptag >> i) & 1);
2960     }
2961
2962     addr = ptr + 0x20;
2963     for(i = 0;i < 8; i++) {
2964         tmp = helper_fldt(addr);
2965         ST(i) = tmp;
2966         addr += 16;
2967     }
2968
2969     if (env->cr[4] & CR4_OSFXSR_MASK) {
2970         /* XXX: finish it, endianness */
2971         env->mxcsr = ldl(ptr + 0x18);
2972         //ldl(ptr + 0x1c);
2973         nb_xmm_regs = 8 << data64;
2974         addr = ptr + 0xa0;
2975         for(i = 0; i < nb_xmm_regs; i++) {
2976             env->xmm_regs[i].XMM_Q(0) = ldq(addr);
2977             env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
2978             addr += 16;
2979         }
2980     }
2981 }
2982
2983 #ifndef USE_X86LDOUBLE
2984
2985 void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
2986 {
2987     CPU86_LDoubleU temp;
2988     int e;
2989
2990     temp.d = f;
2991     /* mantissa */
2992     *pmant = (MANTD(temp) << 11) | (1LL << 63);
2993     /* exponent + sign */
2994     e = EXPD(temp) - EXPBIAS + 16383;
2995     e |= SIGND(temp) >> 16;
2996     *pexp = e;
2997 }
2998
2999 CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
3000 {
3001     CPU86_LDoubleU temp;
3002     int e;
3003     uint64_t ll;
3004
3005     /* XXX: handle overflow ? */
3006     e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
3007     e |= (upper >> 4) & 0x800; /* sign */
3008     ll = (mant >> 11) & ((1LL << 52) - 1);
3009 #ifdef __arm__
3010     temp.l.upper = (e << 20) | (ll >> 32);
3011     temp.l.lower = ll;
3012 #else
3013     temp.ll = ll | ((uint64_t)e << 52);
3014 #endif
3015     return temp.d;
3016 }
3017
3018 #else
3019
3020 void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
3021 {
3022     CPU86_LDoubleU temp;
3023
3024     temp.d = f;
3025     *pmant = temp.l.lower;
3026     *pexp = temp.l.upper;
3027 }
3028
3029 CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
3030 {
3031     CPU86_LDoubleU temp;
3032
3033     temp.l.upper = upper;
3034     temp.l.lower = mant;
3035     return temp.d;
3036 }
3037 #endif
3038
3039 #ifdef TARGET_X86_64
3040
3041 //#define DEBUG_MULDIV
3042
3043 static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
3044 {
3045     *plow += a;
3046     /* carry test */
3047     if (*plow < a)
3048         (*phigh)++;
3049     *phigh += b;
3050 }
3051
3052 static void neg128(uint64_t *plow, uint64_t *phigh)
3053 {
3054     *plow = ~ *plow;
3055     *phigh = ~ *phigh;
3056     add128(plow, phigh, 1, 0);
3057 }
3058
3059 static void mul64(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
3060 {
3061     uint32_t a0, a1, b0, b1;
3062     uint64_t v;
3063
3064     a0 = a;
3065     a1 = a >> 32;
3066
3067     b0 = b;
3068     b1 = b >> 32;
3069     
3070     v = (uint64_t)a0 * (uint64_t)b0;
3071     *plow = v;
3072     *phigh = 0;
3073
3074     v = (uint64_t)a0 * (uint64_t)b1;
3075     add128(plow, phigh, v << 32, v >> 32);
3076     
3077     v = (uint64_t)a1 * (uint64_t)b0;
3078     add128(plow, phigh, v << 32, v >> 32);
3079     
3080     v = (uint64_t)a1 * (uint64_t)b1;
3081     *phigh += v;
3082 #ifdef DEBUG_MULDIV
3083     printf("mul: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n",
3084            a, b, *phigh, *plow);
3085 #endif
3086 }
3087
3088 static void imul64(uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b)
3089 {
3090     int sa, sb;
3091     sa = (a < 0);
3092     if (sa)
3093         a = -a;
3094     sb = (b < 0);
3095     if (sb)
3096         b = -b;
3097     mul64(plow, phigh, a, b);
3098     if (sa ^ sb) {
3099         neg128(plow, phigh);
3100     }
3101 }
3102
3103 /* XXX: overflow support */
3104 static void div64(uint64_t *plow, uint64_t *phigh, uint64_t b)
3105 {
3106     uint64_t q, r, a1, a0;
3107     int i, qb;
3108
3109     a0 = *plow;
3110     a1 = *phigh;
3111     if (a1 == 0) {
3112         q = a0 / b;
3113         r = a0 % b;
3114         *plow = q;
3115         *phigh = r;
3116     } else {
3117         /* XXX: use a better algorithm */
3118         for(i = 0; i < 64; i++) {
3119             a1 = (a1 << 1) | (a0 >> 63);
3120             if (a1 >= b) {
3121                 a1 -= b;
3122                 qb = 1;
3123             } else {
3124                 qb = 0;
3125             }
3126             a0 = (a0 << 1) | qb;
3127         }
3128 #if defined(DEBUG_MULDIV)
3129         printf("div: 0x%016llx%016llx / 0x%016llx: q=0x%016llx r=0x%016llx\n",
3130                *phigh, *plow, b, a0, a1);
3131 #endif
3132         *plow = a0;
3133         *phigh = a1;
3134     }
3135 }
3136
3137 static void idiv64(uint64_t *plow, uint64_t *phigh, uint64_t b)
3138 {
3139     int sa, sb;
3140     sa = ((int64_t)*phigh < 0);
3141     if (sa)
3142         neg128(plow, phigh);
3143     sb = (b < 0);
3144     if (sb)
3145         b = -b;
3146     div64(plow, phigh, b);
3147     if (sa ^ sb)
3148         *plow = - *plow;
3149     if (sb)
3150         *phigh = - *phigh;
3151 }
3152
3153 void helper_mulq_EAX_T0(void)
3154 {
3155     uint64_t r0, r1;
3156
3157     mul64(&r0, &r1, EAX, T0);
3158     EAX = r0;
3159     EDX = r1;
3160     CC_DST = r0;
3161     CC_SRC = r1;
3162 }
3163
3164 void helper_imulq_EAX_T0(void)
3165 {
3166     uint64_t r0, r1;
3167
3168     imul64(&r0, &r1, EAX, T0);
3169     EAX = r0;
3170     EDX = r1;
3171     CC_DST = r0;
3172     CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
3173 }
3174
3175 void helper_imulq_T0_T1(void)
3176 {
3177     uint64_t r0, r1;
3178
3179     imul64(&r0, &r1, T0, T1);
3180     T0 = r0;
3181     CC_DST = r0;
3182     CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
3183 }
3184
3185 void helper_divq_EAX_T0(void)
3186 {
3187     uint64_t r0, r1;
3188     if (T0 == 0) {
3189         raise_exception(EXCP00_DIVZ);
3190     }
3191     r0 = EAX;
3192     r1 = EDX;
3193     div64(&r0, &r1, T0);
3194     EAX = r0;
3195     EDX = r1;
3196 }
3197
3198 void helper_idivq_EAX_T0(void)
3199 {
3200     uint64_t r0, r1;
3201     if (T0 == 0) {
3202         raise_exception(EXCP00_DIVZ);
3203     }
3204     r0 = EAX;
3205     r1 = EDX;
3206     idiv64(&r0, &r1, T0);
3207     EAX = r0;
3208     EDX = r1;
3209 }
3210
3211 #endif
3212
3213 /* XXX: do it */
3214 int fpu_isnan(double a)
3215 {
3216     return 0;
3217 }
3218
3219 float approx_rsqrt(float a)
3220 {
3221     return 1.0 / sqrt(a);
3222 }
3223
3224 float approx_rcp(float a)
3225 {
3226     return 1.0 / a;
3227 }
3228
3229
3230 #if !defined(CONFIG_USER_ONLY) 
3231
3232 #define MMUSUFFIX _mmu
3233 #define GETPC() (__builtin_return_address(0))
3234
3235 #define SHIFT 0
3236 #include "softmmu_template.h"
3237
3238 #define SHIFT 1
3239 #include "softmmu_template.h"
3240
3241 #define SHIFT 2
3242 #include "softmmu_template.h"
3243
3244 #define SHIFT 3
3245 #include "softmmu_template.h"
3246
3247 #endif
3248
3249 /* try to fill the TLB and return an exception if error. If retaddr is
3250    NULL, it means that the function was called in C code (i.e. not
3251    from generated code or from helper.c) */
3252 /* XXX: fix it to restore all registers */
3253 void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
3254 {
3255     TranslationBlock *tb;
3256     int ret;
3257     unsigned long pc;
3258     CPUX86State *saved_env;
3259
3260     /* XXX: hack to restore env in all cases, even if not called from
3261        generated code */
3262     saved_env = env;
3263     env = cpu_single_env;
3264
3265     ret = cpu_x86_handle_mmu_fault(env, addr, is_write, is_user, 1);
3266     if (ret) {
3267         if (retaddr) {
3268             /* now we have a real cpu fault */
3269             pc = (unsigned long)retaddr;
3270             tb = tb_find_pc(pc);
3271             if (tb) {
3272                 /* the PC is inside the translated code. It means that we have
3273                    a virtual CPU fault */
3274                 cpu_restore_state(tb, env, pc, NULL);
3275             }
3276         }
3277         if (retaddr)
3278             raise_exception_err(EXCP0E_PAGE, env->error_code);
3279         else
3280             raise_exception_err_norestore(EXCP0E_PAGE, env->error_code);
3281     }
3282     env = saved_env;
3283 }
This page took 0.210612 seconds and 4 git commands to generate.