]> Git Repo - qemu.git/blob - target-i386/helper.c
make lsl, lar verr and verw exception safe
[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]), TF_MASK | AC_MASK | ID_MASK | 
1016                     IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK);
1017         cpu_x86_set_cpl(env, 3);
1018     } else {
1019         cpu_x86_load_seg_cache(env, R_CS, selector | 3, 
1020                                0, 0xffffffff, 
1021                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1022                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1023                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1024         env->eip = (uint32_t)ECX;
1025         cpu_x86_load_seg_cache(env, R_SS, selector + 8, 
1026                                0, 0xffffffff,
1027                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1028                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1029                                DESC_W_MASK | DESC_A_MASK);
1030         env->eflags |= IF_MASK;
1031         cpu_x86_set_cpl(env, 3);
1032     }
1033 }
1034 #endif
1035
1036 /* real mode interrupt */
1037 static void do_interrupt_real(int intno, int is_int, int error_code,
1038                               unsigned int next_eip)
1039 {
1040     SegmentCache *dt;
1041     target_ulong ptr, ssp;
1042     int selector;
1043     uint32_t offset, esp;
1044     uint32_t old_cs, old_eip;
1045
1046     /* real mode (simpler !) */
1047     dt = &env->idt;
1048     if (intno * 4 + 3 > dt->limit)
1049         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
1050     ptr = dt->base + intno * 4;
1051     offset = lduw_kernel(ptr);
1052     selector = lduw_kernel(ptr + 2);
1053     esp = ESP;
1054     ssp = env->segs[R_SS].base;
1055     if (is_int)
1056         old_eip = next_eip;
1057     else
1058         old_eip = env->eip;
1059     old_cs = env->segs[R_CS].selector;
1060     /* XXX: use SS segment size ? */
1061     PUSHW(ssp, esp, 0xffff, compute_eflags());
1062     PUSHW(ssp, esp, 0xffff, old_cs);
1063     PUSHW(ssp, esp, 0xffff, old_eip);
1064     
1065     /* update processor state */
1066     ESP = (ESP & ~0xffff) | (esp & 0xffff);
1067     env->eip = offset;
1068     env->segs[R_CS].selector = selector;
1069     env->segs[R_CS].base = (selector << 4);
1070     env->eflags &= ~(IF_MASK | TF_MASK | AC_MASK | RF_MASK);
1071 }
1072
1073 /* fake user mode interrupt */
1074 void do_interrupt_user(int intno, int is_int, int error_code, 
1075                        target_ulong next_eip)
1076 {
1077     SegmentCache *dt;
1078     target_ulong ptr;
1079     int dpl, cpl;
1080     uint32_t e2;
1081
1082     dt = &env->idt;
1083     ptr = dt->base + (intno * 8);
1084     e2 = ldl_kernel(ptr + 4);
1085     
1086     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1087     cpl = env->hflags & HF_CPL_MASK;
1088     /* check privledge if software int */
1089     if (is_int && dpl < cpl)
1090         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
1091
1092     /* Since we emulate only user space, we cannot do more than
1093        exiting the emulation with the suitable exception and error
1094        code */
1095     if (is_int)
1096         EIP = next_eip;
1097 }
1098
1099 /*
1100  * Begin execution of an interruption. is_int is TRUE if coming from
1101  * the int instruction. next_eip is the EIP value AFTER the interrupt
1102  * instruction. It is only relevant if is_int is TRUE.  
1103  */
1104 void do_interrupt(int intno, int is_int, int error_code, 
1105                   target_ulong next_eip, int is_hw)
1106 {
1107 #ifdef DEBUG_PCALL
1108     if (loglevel & (CPU_LOG_PCALL | CPU_LOG_INT)) {
1109         if ((env->cr[0] & CR0_PE_MASK)) {
1110             static int count;
1111             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,
1112                     count, intno, error_code, is_int,
1113                     env->hflags & HF_CPL_MASK,
1114                     env->segs[R_CS].selector, EIP,
1115                     (int)env->segs[R_CS].base + EIP,
1116                     env->segs[R_SS].selector, ESP);
1117             if (intno == 0x0e) {
1118                 fprintf(logfile, " CR2=" TARGET_FMT_lx, env->cr[2]);
1119             } else {
1120                 fprintf(logfile, " EAX=" TARGET_FMT_lx, EAX);
1121             }
1122             fprintf(logfile, "\n");
1123 #if 0
1124             cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1125             {
1126                 int i;
1127                 uint8_t *ptr;
1128                 fprintf(logfile, "       code=");
1129                 ptr = env->segs[R_CS].base + env->eip;
1130                 for(i = 0; i < 16; i++) {
1131                     fprintf(logfile, " %02x", ldub(ptr + i));
1132                 }
1133                 fprintf(logfile, "\n");
1134             }
1135 #endif
1136             count++;
1137         }
1138     }
1139 #endif
1140     if (env->cr[0] & CR0_PE_MASK) {
1141 #if TARGET_X86_64
1142         if (env->hflags & HF_LMA_MASK) {
1143             do_interrupt64(intno, is_int, error_code, next_eip, is_hw);
1144         } else
1145 #endif
1146         {
1147             do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);
1148         }
1149     } else {
1150         do_interrupt_real(intno, is_int, error_code, next_eip);
1151     }
1152 }
1153
1154 /*
1155  * Signal an interruption. It is executed in the main CPU loop.
1156  * is_int is TRUE if coming from the int instruction. next_eip is the
1157  * EIP value AFTER the interrupt instruction. It is only relevant if
1158  * is_int is TRUE.  
1159  */
1160 void raise_interrupt(int intno, int is_int, int error_code, 
1161                      int next_eip_addend)
1162 {
1163     env->exception_index = intno;
1164     env->error_code = error_code;
1165     env->exception_is_int = is_int;
1166     env->exception_next_eip = env->eip + next_eip_addend;
1167     cpu_loop_exit();
1168 }
1169
1170 /* same as raise_exception_err, but do not restore global registers */
1171 static void raise_exception_err_norestore(int exception_index, int error_code)
1172 {
1173     env->exception_index = exception_index;
1174     env->error_code = error_code;
1175     env->exception_is_int = 0;
1176     env->exception_next_eip = 0;
1177     longjmp(env->jmp_env, 1);
1178 }
1179
1180 /* shortcuts to generate exceptions */
1181
1182 void (raise_exception_err)(int exception_index, int error_code)
1183 {
1184     raise_interrupt(exception_index, 0, error_code, 0);
1185 }
1186
1187 void raise_exception(int exception_index)
1188 {
1189     raise_interrupt(exception_index, 0, 0, 0);
1190 }
1191
1192 #ifdef BUGGY_GCC_DIV64
1193 /* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we
1194    call it from another function */
1195 uint32_t div32(uint32_t *q_ptr, uint64_t num, uint32_t den)
1196 {
1197     *q_ptr = num / den;
1198     return num % den;
1199 }
1200
1201 int32_t idiv32(int32_t *q_ptr, int64_t num, int32_t den)
1202 {
1203     *q_ptr = num / den;
1204     return num % den;
1205 }
1206 #endif
1207
1208 void helper_divl_EAX_T0(void)
1209 {
1210     unsigned int den, q, r;
1211     uint64_t num;
1212     
1213     num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1214     den = T0;
1215     if (den == 0) {
1216         raise_exception(EXCP00_DIVZ);
1217     }
1218 #ifdef BUGGY_GCC_DIV64
1219     r = div32(&q, num, den);
1220 #else
1221     q = (num / den);
1222     r = (num % den);
1223 #endif
1224     EAX = (uint32_t)q;
1225     EDX = (uint32_t)r;
1226 }
1227
1228 void helper_idivl_EAX_T0(void)
1229 {
1230     int den, q, r;
1231     int64_t num;
1232     
1233     num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1234     den = T0;
1235     if (den == 0) {
1236         raise_exception(EXCP00_DIVZ);
1237     }
1238 #ifdef BUGGY_GCC_DIV64
1239     r = idiv32(&q, num, den);
1240 #else
1241     q = (num / den);
1242     r = (num % den);
1243 #endif
1244     EAX = (uint32_t)q;
1245     EDX = (uint32_t)r;
1246 }
1247
1248 void helper_cmpxchg8b(void)
1249 {
1250     uint64_t d;
1251     int eflags;
1252
1253     eflags = cc_table[CC_OP].compute_all();
1254     d = ldq(A0);
1255     if (d == (((uint64_t)EDX << 32) | EAX)) {
1256         stq(A0, ((uint64_t)ECX << 32) | EBX);
1257         eflags |= CC_Z;
1258     } else {
1259         EDX = d >> 32;
1260         EAX = d;
1261         eflags &= ~CC_Z;
1262     }
1263     CC_SRC = eflags;
1264 }
1265
1266 void helper_cpuid(void)
1267 {
1268     switch((uint32_t)EAX) {
1269     case 0:
1270         EAX = 2; /* max EAX index supported */
1271         EBX = env->cpuid_vendor1;
1272         EDX = env->cpuid_vendor2;
1273         ECX = env->cpuid_vendor3;
1274         break;
1275     case 1:
1276         EAX = env->cpuid_version;
1277         EBX = 0;
1278         ECX = env->cpuid_ext_features;
1279         EDX = env->cpuid_features;
1280         break;
1281     default:
1282         /* cache info: needed for Pentium Pro compatibility */
1283         EAX = 0x410601;
1284         EBX = 0;
1285         ECX = 0;
1286         EDX = 0;
1287         break;
1288 #ifdef TARGET_X86_64
1289     case 0x80000000:
1290         EAX = 0x80000008;
1291         EBX = env->cpuid_vendor1;
1292         EDX = env->cpuid_vendor2;
1293         ECX = env->cpuid_vendor3;
1294         break;
1295     case 0x80000001:
1296         EAX = env->cpuid_features;
1297         EBX = 0;
1298         ECX = 0;
1299         /* long mode + syscall/sysret features */
1300         EDX = (env->cpuid_features & 0x0183F3FF) | (1 << 29) | (1 << 11);
1301         break;
1302     case 0x80000008:
1303         /* virtual & phys address size in low 2 bytes. */
1304         EAX = 0x00003028;
1305         EBX = 0;
1306         ECX = 0;
1307         EDX = 0;
1308         break;
1309 #endif
1310     }
1311 }
1312
1313 void helper_enter_level(int level, int data32)
1314 {
1315     target_ulong ssp;
1316     uint32_t esp_mask, esp, ebp;
1317
1318     esp_mask = get_sp_mask(env->segs[R_SS].flags);
1319     ssp = env->segs[R_SS].base;
1320     ebp = EBP;
1321     esp = ESP;
1322     if (data32) {
1323         /* 32 bit */
1324         esp -= 4;
1325         while (--level) {
1326             esp -= 4;
1327             ebp -= 4;
1328             stl(ssp + (esp & esp_mask), ldl(ssp + (ebp & esp_mask)));
1329         }
1330         esp -= 4;
1331         stl(ssp + (esp & esp_mask), T1);
1332     } else {
1333         /* 16 bit */
1334         esp -= 2;
1335         while (--level) {
1336             esp -= 2;
1337             ebp -= 2;
1338             stw(ssp + (esp & esp_mask), lduw(ssp + (ebp & esp_mask)));
1339         }
1340         esp -= 2;
1341         stw(ssp + (esp & esp_mask), T1);
1342     }
1343 }
1344
1345 void helper_lldt_T0(void)
1346 {
1347     int selector;
1348     SegmentCache *dt;
1349     uint32_t e1, e2;
1350     int index, entry_limit;
1351     target_ulong ptr;
1352     
1353     selector = T0 & 0xffff;
1354     if ((selector & 0xfffc) == 0) {
1355         /* XXX: NULL selector case: invalid LDT */
1356         env->ldt.base = 0;
1357         env->ldt.limit = 0;
1358     } else {
1359         if (selector & 0x4)
1360             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1361         dt = &env->gdt;
1362         index = selector & ~7;
1363 #ifdef TARGET_X86_64
1364         if (env->hflags & HF_LMA_MASK)
1365             entry_limit = 15;
1366         else
1367 #endif            
1368             entry_limit = 7;
1369         if ((index + entry_limit) > dt->limit)
1370             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1371         ptr = dt->base + index;
1372         e1 = ldl_kernel(ptr);
1373         e2 = ldl_kernel(ptr + 4);
1374         if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
1375             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1376         if (!(e2 & DESC_P_MASK))
1377             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
1378 #ifdef TARGET_X86_64
1379         if (env->hflags & HF_LMA_MASK) {
1380             uint32_t e3;
1381             e3 = ldl_kernel(ptr + 8);
1382             load_seg_cache_raw_dt(&env->ldt, e1, e2);
1383             env->ldt.base |= (target_ulong)e3 << 32;
1384         } else
1385 #endif
1386         {
1387             load_seg_cache_raw_dt(&env->ldt, e1, e2);
1388         }
1389     }
1390     env->ldt.selector = selector;
1391 }
1392
1393 void helper_ltr_T0(void)
1394 {
1395     int selector;
1396     SegmentCache *dt;
1397     uint32_t e1, e2;
1398     int index, type, entry_limit;
1399     target_ulong ptr;
1400     
1401     selector = T0 & 0xffff;
1402     if ((selector & 0xfffc) == 0) {
1403         /* NULL selector case: invalid TR */
1404         env->tr.base = 0;
1405         env->tr.limit = 0;
1406         env->tr.flags = 0;
1407     } else {
1408         if (selector & 0x4)
1409             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1410         dt = &env->gdt;
1411         index = selector & ~7;
1412 #ifdef TARGET_X86_64
1413         if (env->hflags & HF_LMA_MASK)
1414             entry_limit = 15;
1415         else
1416 #endif            
1417             entry_limit = 7;
1418         if ((index + entry_limit) > dt->limit)
1419             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1420         ptr = dt->base + index;
1421         e1 = ldl_kernel(ptr);
1422         e2 = ldl_kernel(ptr + 4);
1423         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
1424         if ((e2 & DESC_S_MASK) || 
1425             (type != 1 && type != 9))
1426             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1427         if (!(e2 & DESC_P_MASK))
1428             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
1429 #ifdef TARGET_X86_64
1430         if (env->hflags & HF_LMA_MASK) {
1431             uint32_t e3;
1432             e3 = ldl_kernel(ptr + 8);
1433             load_seg_cache_raw_dt(&env->tr, e1, e2);
1434             env->tr.base |= (target_ulong)e3 << 32;
1435         } else 
1436 #endif
1437         {
1438             load_seg_cache_raw_dt(&env->tr, e1, e2);
1439         }
1440         e2 |= DESC_TSS_BUSY_MASK;
1441         stl_kernel(ptr + 4, e2);
1442     }
1443     env->tr.selector = selector;
1444 }
1445
1446 /* only works if protected mode and not VM86. seg_reg must be != R_CS */
1447 void load_seg(int seg_reg, int selector)
1448 {
1449     uint32_t e1, e2;
1450     int cpl, dpl, rpl;
1451     SegmentCache *dt;
1452     int index;
1453     target_ulong ptr;
1454
1455     selector &= 0xffff;
1456     if ((selector & 0xfffc) == 0) {
1457         /* null selector case */
1458         if (seg_reg == R_SS
1459 #ifdef TARGET_X86_64
1460             && !(env->hflags & HF_CS64_MASK)
1461 #endif
1462             )
1463             raise_exception_err(EXCP0D_GPF, 0);
1464         cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0);
1465     } else {
1466         
1467         if (selector & 0x4)
1468             dt = &env->ldt;
1469         else
1470             dt = &env->gdt;
1471         index = selector & ~7;
1472         if ((index + 7) > dt->limit)
1473             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1474         ptr = dt->base + index;
1475         e1 = ldl_kernel(ptr);
1476         e2 = ldl_kernel(ptr + 4);
1477         
1478         if (!(e2 & DESC_S_MASK))
1479             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1480         rpl = selector & 3;
1481         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1482         cpl = env->hflags & HF_CPL_MASK;
1483         if (seg_reg == R_SS) {
1484             /* must be writable segment */
1485             if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
1486                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1487             if (rpl != cpl || dpl != cpl)
1488                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1489         } else {
1490             /* must be readable segment */
1491             if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK)
1492                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1493             
1494             if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
1495                 /* if not conforming code, test rights */
1496                 if (dpl < cpl || dpl < rpl)
1497                     raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1498             }
1499         }
1500
1501         if (!(e2 & DESC_P_MASK)) {
1502             if (seg_reg == R_SS)
1503                 raise_exception_err(EXCP0C_STACK, selector & 0xfffc);
1504             else
1505                 raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
1506         }
1507
1508         /* set the access bit if not already set */
1509         if (!(e2 & DESC_A_MASK)) {
1510             e2 |= DESC_A_MASK;
1511             stl_kernel(ptr + 4, e2);
1512         }
1513
1514         cpu_x86_load_seg_cache(env, seg_reg, selector, 
1515                        get_seg_base(e1, e2),
1516                        get_seg_limit(e1, e2),
1517                        e2);
1518 #if 0
1519         fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx flags=%08x\n", 
1520                 selector, (unsigned long)sc->base, sc->limit, sc->flags);
1521 #endif
1522     }
1523 }
1524
1525 /* protected mode jump */
1526 void helper_ljmp_protected_T0_T1(int next_eip)
1527 {
1528     int new_cs, gate_cs, type;
1529     uint32_t e1, e2, cpl, dpl, rpl, limit;
1530     target_ulong new_eip;
1531     
1532     new_cs = T0;
1533     new_eip = T1;
1534     if ((new_cs & 0xfffc) == 0)
1535         raise_exception_err(EXCP0D_GPF, 0);
1536     if (load_segment(&e1, &e2, new_cs) != 0)
1537         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1538     cpl = env->hflags & HF_CPL_MASK;
1539     if (e2 & DESC_S_MASK) {
1540         if (!(e2 & DESC_CS_MASK))
1541             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1542         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1543         if (e2 & DESC_C_MASK) {
1544             /* conforming code segment */
1545             if (dpl > cpl)
1546                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1547         } else {
1548             /* non conforming code segment */
1549             rpl = new_cs & 3;
1550             if (rpl > cpl)
1551                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1552             if (dpl != cpl)
1553                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1554         }
1555         if (!(e2 & DESC_P_MASK))
1556             raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
1557         limit = get_seg_limit(e1, e2);
1558         if (new_eip > limit && 
1559             !(env->hflags & HF_LMA_MASK) && !(e2 & DESC_L_MASK))
1560             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1561         cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
1562                        get_seg_base(e1, e2), limit, e2);
1563         EIP = new_eip;
1564     } else {
1565         /* jump to call or task gate */
1566         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1567         rpl = new_cs & 3;
1568         cpl = env->hflags & HF_CPL_MASK;
1569         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
1570         switch(type) {
1571         case 1: /* 286 TSS */
1572         case 9: /* 386 TSS */
1573         case 5: /* task gate */
1574             if (dpl < cpl || dpl < rpl)
1575                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1576             switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip);
1577             break;
1578         case 4: /* 286 call gate */
1579         case 12: /* 386 call gate */
1580             if ((dpl < cpl) || (dpl < rpl))
1581                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1582             if (!(e2 & DESC_P_MASK))
1583                 raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
1584             gate_cs = e1 >> 16;
1585             new_eip = (e1 & 0xffff);
1586             if (type == 12)
1587                 new_eip |= (e2 & 0xffff0000);
1588             if (load_segment(&e1, &e2, gate_cs) != 0)
1589                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
1590             dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1591             /* must be code segment */
1592             if (((e2 & (DESC_S_MASK | DESC_CS_MASK)) != 
1593                  (DESC_S_MASK | DESC_CS_MASK)))
1594                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
1595             if (((e2 & DESC_C_MASK) && (dpl > cpl)) || 
1596                 (!(e2 & DESC_C_MASK) && (dpl != cpl)))
1597                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
1598             if (!(e2 & DESC_P_MASK))
1599                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
1600             limit = get_seg_limit(e1, e2);
1601             if (new_eip > limit)
1602                 raise_exception_err(EXCP0D_GPF, 0);
1603             cpu_x86_load_seg_cache(env, R_CS, (gate_cs & 0xfffc) | cpl,
1604                                    get_seg_base(e1, e2), limit, e2);
1605             EIP = new_eip;
1606             break;
1607         default:
1608             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1609             break;
1610         }
1611     }
1612 }
1613
1614 /* real mode call */
1615 void helper_lcall_real_T0_T1(int shift, int next_eip)
1616 {
1617     int new_cs, new_eip;
1618     uint32_t esp, esp_mask;
1619     target_ulong ssp;
1620
1621     new_cs = T0;
1622     new_eip = T1;
1623     esp = ESP;
1624     esp_mask = get_sp_mask(env->segs[R_SS].flags);
1625     ssp = env->segs[R_SS].base;
1626     if (shift) {
1627         PUSHL(ssp, esp, esp_mask, env->segs[R_CS].selector);
1628         PUSHL(ssp, esp, esp_mask, next_eip);
1629     } else {
1630         PUSHW(ssp, esp, esp_mask, env->segs[R_CS].selector);
1631         PUSHW(ssp, esp, esp_mask, next_eip);
1632     }
1633
1634     ESP = (ESP & ~esp_mask) | (esp & esp_mask);
1635     env->eip = new_eip;
1636     env->segs[R_CS].selector = new_cs;
1637     env->segs[R_CS].base = (new_cs << 4);
1638 }
1639
1640 /* protected mode call */
1641 void helper_lcall_protected_T0_T1(int shift, int next_eip)
1642 {
1643     int new_cs, new_eip, new_stack, i;
1644     uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;
1645     uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask;
1646     uint32_t val, limit, old_sp_mask;
1647     target_ulong ssp, old_ssp;
1648     
1649     new_cs = T0;
1650     new_eip = T1;
1651 #ifdef DEBUG_PCALL
1652     if (loglevel & CPU_LOG_PCALL) {
1653         fprintf(logfile, "lcall %04x:%08x s=%d\n",
1654                 new_cs, new_eip, shift);
1655         cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1656     }
1657 #endif
1658     if ((new_cs & 0xfffc) == 0)
1659         raise_exception_err(EXCP0D_GPF, 0);
1660     if (load_segment(&e1, &e2, new_cs) != 0)
1661         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1662     cpl = env->hflags & HF_CPL_MASK;
1663 #ifdef DEBUG_PCALL
1664     if (loglevel & CPU_LOG_PCALL) {
1665         fprintf(logfile, "desc=%08x:%08x\n", e1, e2);
1666     }
1667 #endif
1668     if (e2 & DESC_S_MASK) {
1669         if (!(e2 & DESC_CS_MASK))
1670             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1671         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1672         if (e2 & DESC_C_MASK) {
1673             /* conforming code segment */
1674             if (dpl > cpl)
1675                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1676         } else {
1677             /* non conforming code segment */
1678             rpl = new_cs & 3;
1679             if (rpl > cpl)
1680                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1681             if (dpl != cpl)
1682                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1683         }
1684         if (!(e2 & DESC_P_MASK))
1685             raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
1686
1687         sp = ESP;
1688         sp_mask = get_sp_mask(env->segs[R_SS].flags);
1689         ssp = env->segs[R_SS].base;
1690         if (shift) {
1691             PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
1692             PUSHL(ssp, sp, sp_mask, next_eip);
1693         } else {
1694             PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
1695             PUSHW(ssp, sp, sp_mask, next_eip);
1696         }
1697         
1698         limit = get_seg_limit(e1, e2);
1699         if (new_eip > limit)
1700             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1701         /* from this point, not restartable */
1702         ESP = (ESP & ~sp_mask) | (sp & sp_mask);
1703         cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
1704                        get_seg_base(e1, e2), limit, e2);
1705         EIP = new_eip;
1706     } else {
1707         /* check gate type */
1708         type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
1709         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1710         rpl = new_cs & 3;
1711         switch(type) {
1712         case 1: /* available 286 TSS */
1713         case 9: /* available 386 TSS */
1714         case 5: /* task gate */
1715             if (dpl < cpl || dpl < rpl)
1716                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1717             switch_tss(new_cs, e1, e2, SWITCH_TSS_CALL, next_eip);
1718             return;
1719         case 4: /* 286 call gate */
1720         case 12: /* 386 call gate */
1721             break;
1722         default:
1723             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1724             break;
1725         }
1726         shift = type >> 3;
1727
1728         if (dpl < cpl || dpl < rpl)
1729             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1730         /* check valid bit */
1731         if (!(e2 & DESC_P_MASK))
1732             raise_exception_err(EXCP0B_NOSEG,  new_cs & 0xfffc);
1733         selector = e1 >> 16;
1734         offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
1735         param_count = e2 & 0x1f;
1736         if ((selector & 0xfffc) == 0)
1737             raise_exception_err(EXCP0D_GPF, 0);
1738
1739         if (load_segment(&e1, &e2, selector) != 0)
1740             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1741         if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
1742             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1743         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1744         if (dpl > cpl)
1745             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1746         if (!(e2 & DESC_P_MASK))
1747             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
1748
1749         if (!(e2 & DESC_C_MASK) && dpl < cpl) {
1750             /* to inner priviledge */
1751             get_ss_esp_from_tss(&ss, &sp, dpl);
1752 #ifdef DEBUG_PCALL
1753             if (loglevel & CPU_LOG_PCALL)
1754                 fprintf(logfile, "new ss:esp=%04x:%08x param_count=%d ESP=" TARGET_FMT_lx "\n", 
1755                         ss, sp, param_count, ESP);
1756 #endif
1757             if ((ss & 0xfffc) == 0)
1758                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
1759             if ((ss & 3) != dpl)
1760                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
1761             if (load_segment(&ss_e1, &ss_e2, ss) != 0)
1762                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
1763             ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
1764             if (ss_dpl != dpl)
1765                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
1766             if (!(ss_e2 & DESC_S_MASK) ||
1767                 (ss_e2 & DESC_CS_MASK) ||
1768                 !(ss_e2 & DESC_W_MASK))
1769                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
1770             if (!(ss_e2 & DESC_P_MASK))
1771                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
1772             
1773             //            push_size = ((param_count * 2) + 8) << shift;
1774
1775             old_sp_mask = get_sp_mask(env->segs[R_SS].flags);
1776             old_ssp = env->segs[R_SS].base;
1777             
1778             sp_mask = get_sp_mask(ss_e2);
1779             ssp = get_seg_base(ss_e1, ss_e2);
1780             if (shift) {
1781                 PUSHL(ssp, sp, sp_mask, env->segs[R_SS].selector);
1782                 PUSHL(ssp, sp, sp_mask, ESP);
1783                 for(i = param_count - 1; i >= 0; i--) {
1784                     val = ldl_kernel(old_ssp + ((ESP + i * 4) & old_sp_mask));
1785                     PUSHL(ssp, sp, sp_mask, val);
1786                 }
1787             } else {
1788                 PUSHW(ssp, sp, sp_mask, env->segs[R_SS].selector);
1789                 PUSHW(ssp, sp, sp_mask, ESP);
1790                 for(i = param_count - 1; i >= 0; i--) {
1791                     val = lduw_kernel(old_ssp + ((ESP + i * 2) & old_sp_mask));
1792                     PUSHW(ssp, sp, sp_mask, val);
1793                 }
1794             }
1795             new_stack = 1;
1796         } else {
1797             /* to same priviledge */
1798             sp = ESP;
1799             sp_mask = get_sp_mask(env->segs[R_SS].flags);
1800             ssp = env->segs[R_SS].base;
1801             //            push_size = (4 << shift);
1802             new_stack = 0;
1803         }
1804
1805         if (shift) {
1806             PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
1807             PUSHL(ssp, sp, sp_mask, next_eip);
1808         } else {
1809             PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
1810             PUSHW(ssp, sp, sp_mask, next_eip);
1811         }
1812
1813         /* from this point, not restartable */
1814
1815         if (new_stack) {
1816             ss = (ss & ~3) | dpl;
1817             cpu_x86_load_seg_cache(env, R_SS, ss, 
1818                                    ssp,
1819                                    get_seg_limit(ss_e1, ss_e2),
1820                                    ss_e2);
1821         }
1822
1823         selector = (selector & ~3) | dpl;
1824         cpu_x86_load_seg_cache(env, R_CS, selector, 
1825                        get_seg_base(e1, e2),
1826                        get_seg_limit(e1, e2),
1827                        e2);
1828         cpu_x86_set_cpl(env, dpl);
1829         ESP = (ESP & ~sp_mask) | (sp & sp_mask);
1830         EIP = offset;
1831     }
1832 #ifdef USE_KQEMU
1833     if (kqemu_is_ok(env)) {
1834         env->exception_index = -1;
1835         cpu_loop_exit();
1836     }
1837 #endif
1838 }
1839
1840 /* real and vm86 mode iret */
1841 void helper_iret_real(int shift)
1842 {
1843     uint32_t sp, new_cs, new_eip, new_eflags, sp_mask;
1844     target_ulong ssp;
1845     int eflags_mask;
1846
1847     sp_mask = 0xffff; /* XXXX: use SS segment size ? */
1848     sp = ESP;
1849     ssp = env->segs[R_SS].base;
1850     if (shift == 1) {
1851         /* 32 bits */
1852         POPL(ssp, sp, sp_mask, new_eip);
1853         POPL(ssp, sp, sp_mask, new_cs);
1854         new_cs &= 0xffff;
1855         POPL(ssp, sp, sp_mask, new_eflags);
1856     } else {
1857         /* 16 bits */
1858         POPW(ssp, sp, sp_mask, new_eip);
1859         POPW(ssp, sp, sp_mask, new_cs);
1860         POPW(ssp, sp, sp_mask, new_eflags);
1861     }
1862     ESP = (ESP & ~sp_mask) | (sp & sp_mask);
1863     load_seg_vm(R_CS, new_cs);
1864     env->eip = new_eip;
1865     if (env->eflags & VM_MASK)
1866         eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK | NT_MASK;
1867     else
1868         eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK | RF_MASK | NT_MASK;
1869     if (shift == 0)
1870         eflags_mask &= 0xffff;
1871     load_eflags(new_eflags, eflags_mask);
1872 }
1873
1874 static inline void validate_seg(int seg_reg, int cpl)
1875 {
1876     int dpl;
1877     uint32_t e2;
1878     
1879     e2 = env->segs[seg_reg].flags;
1880     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1881     if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
1882         /* data or non conforming code segment */
1883         if (dpl < cpl) {
1884             cpu_x86_load_seg_cache(env, seg_reg, 0, 0, 0, 0);
1885         }
1886     }
1887 }
1888
1889 /* protected mode iret */
1890 static inline void helper_ret_protected(int shift, int is_iret, int addend)
1891 {
1892     uint32_t new_cs, new_eflags, new_ss;
1893     uint32_t new_es, new_ds, new_fs, new_gs;
1894     uint32_t e1, e2, ss_e1, ss_e2;
1895     int cpl, dpl, rpl, eflags_mask, iopl;
1896     target_ulong ssp, sp, new_eip, new_esp, sp_mask;
1897     
1898 #ifdef TARGET_X86_64
1899     if (shift == 2)
1900         sp_mask = -1;
1901     else
1902 #endif
1903         sp_mask = get_sp_mask(env->segs[R_SS].flags);
1904     sp = ESP;
1905     ssp = env->segs[R_SS].base;
1906     new_eflags = 0; /* avoid warning */
1907 #ifdef TARGET_X86_64
1908     if (shift == 2) {
1909         POPQ(sp, new_eip);
1910         POPQ(sp, new_cs);
1911         new_cs &= 0xffff;
1912         if (is_iret) {
1913             POPQ(sp, new_eflags);
1914         }
1915     } else
1916 #endif
1917     if (shift == 1) {
1918         /* 32 bits */
1919         POPL(ssp, sp, sp_mask, new_eip);
1920         POPL(ssp, sp, sp_mask, new_cs);
1921         new_cs &= 0xffff;
1922         if (is_iret) {
1923             POPL(ssp, sp, sp_mask, new_eflags);
1924             if (new_eflags & VM_MASK)
1925                 goto return_to_vm86;
1926         }
1927     } else {
1928         /* 16 bits */
1929         POPW(ssp, sp, sp_mask, new_eip);
1930         POPW(ssp, sp, sp_mask, new_cs);
1931         if (is_iret)
1932             POPW(ssp, sp, sp_mask, new_eflags);
1933     }
1934 #ifdef DEBUG_PCALL
1935     if (loglevel & CPU_LOG_PCALL) {
1936         fprintf(logfile, "lret new %04x:" TARGET_FMT_lx " s=%d addend=0x%x\n",
1937                 new_cs, new_eip, shift, addend);
1938         cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1939     }
1940 #endif
1941     if ((new_cs & 0xfffc) == 0)
1942         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1943     if (load_segment(&e1, &e2, new_cs) != 0)
1944         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1945     if (!(e2 & DESC_S_MASK) ||
1946         !(e2 & DESC_CS_MASK))
1947         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1948     cpl = env->hflags & HF_CPL_MASK;
1949     rpl = new_cs & 3; 
1950     if (rpl < cpl)
1951         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1952     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1953     if (e2 & DESC_C_MASK) {
1954         if (dpl > rpl)
1955             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1956     } else {
1957         if (dpl != rpl)
1958             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1959     }
1960     if (!(e2 & DESC_P_MASK))
1961         raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
1962     
1963     sp += addend;
1964     if (rpl == cpl && (!(env->hflags & HF_CS64_MASK) || 
1965                        ((env->hflags & HF_CS64_MASK) && !is_iret))) {
1966         /* return to same priledge level */
1967         cpu_x86_load_seg_cache(env, R_CS, new_cs, 
1968                        get_seg_base(e1, e2),
1969                        get_seg_limit(e1, e2),
1970                        e2);
1971     } else {
1972         /* return to different priviledge level */
1973 #ifdef TARGET_X86_64
1974         if (shift == 2) {
1975             POPQ(sp, new_esp);
1976             POPQ(sp, new_ss);
1977             new_ss &= 0xffff;
1978         } else
1979 #endif
1980         if (shift == 1) {
1981             /* 32 bits */
1982             POPL(ssp, sp, sp_mask, new_esp);
1983             POPL(ssp, sp, sp_mask, new_ss);
1984             new_ss &= 0xffff;
1985         } else {
1986             /* 16 bits */
1987             POPW(ssp, sp, sp_mask, new_esp);
1988             POPW(ssp, sp, sp_mask, new_ss);
1989         }
1990 #ifdef DEBUG_PCALL
1991         if (loglevel & CPU_LOG_PCALL) {
1992             fprintf(logfile, "new ss:esp=%04x:" TARGET_FMT_lx "\n",
1993                     new_ss, new_esp);
1994         }
1995 #endif
1996         if ((env->hflags & HF_LMA_MASK) && (new_ss & 0xfffc) == 0) {
1997             /* NULL ss is allowed in long mode */
1998             cpu_x86_load_seg_cache(env, R_SS, new_ss, 
1999                                    0, 0xffffffff,
2000                                    DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2001                                    DESC_S_MASK | (rpl << DESC_DPL_SHIFT) |
2002                                    DESC_W_MASK | DESC_A_MASK);
2003         } else {
2004             if ((new_ss & 3) != rpl)
2005                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2006             if (load_segment(&ss_e1, &ss_e2, new_ss) != 0)
2007                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2008             if (!(ss_e2 & DESC_S_MASK) ||
2009                 (ss_e2 & DESC_CS_MASK) ||
2010                 !(ss_e2 & DESC_W_MASK))
2011                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2012             dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
2013             if (dpl != rpl)
2014                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2015             if (!(ss_e2 & DESC_P_MASK))
2016                 raise_exception_err(EXCP0B_NOSEG, new_ss & 0xfffc);
2017             cpu_x86_load_seg_cache(env, R_SS, new_ss, 
2018                                    get_seg_base(ss_e1, ss_e2),
2019                                    get_seg_limit(ss_e1, ss_e2),
2020                                    ss_e2);
2021         }
2022
2023         cpu_x86_load_seg_cache(env, R_CS, new_cs, 
2024                        get_seg_base(e1, e2),
2025                        get_seg_limit(e1, e2),
2026                        e2);
2027         cpu_x86_set_cpl(env, rpl);
2028         sp = new_esp;
2029 #ifdef TARGET_X86_64
2030         if (shift == 2)
2031             sp_mask = -1;
2032         else
2033 #endif
2034             sp_mask = get_sp_mask(ss_e2);
2035
2036         /* validate data segments */
2037         validate_seg(R_ES, cpl);
2038         validate_seg(R_DS, cpl);
2039         validate_seg(R_FS, cpl);
2040         validate_seg(R_GS, cpl);
2041
2042         sp += addend;
2043     }
2044     ESP = (ESP & ~sp_mask) | (sp & sp_mask);
2045     env->eip = new_eip;
2046     if (is_iret) {
2047         /* NOTE: 'cpl' is the _old_ CPL */
2048         eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK | NT_MASK;
2049         if (cpl == 0)
2050             eflags_mask |= IOPL_MASK;
2051         iopl = (env->eflags >> IOPL_SHIFT) & 3;
2052         if (cpl <= iopl)
2053             eflags_mask |= IF_MASK;
2054         if (shift == 0)
2055             eflags_mask &= 0xffff;
2056         load_eflags(new_eflags, eflags_mask);
2057     }
2058     return;
2059
2060  return_to_vm86:
2061     POPL(ssp, sp, sp_mask, new_esp);
2062     POPL(ssp, sp, sp_mask, new_ss);
2063     POPL(ssp, sp, sp_mask, new_es);
2064     POPL(ssp, sp, sp_mask, new_ds);
2065     POPL(ssp, sp, sp_mask, new_fs);
2066     POPL(ssp, sp, sp_mask, new_gs);
2067     
2068     /* modify processor state */
2069     load_eflags(new_eflags, TF_MASK | AC_MASK | ID_MASK | 
2070                 IF_MASK | IOPL_MASK | VM_MASK | NT_MASK | VIF_MASK | VIP_MASK);
2071     load_seg_vm(R_CS, new_cs & 0xffff);
2072     cpu_x86_set_cpl(env, 3);
2073     load_seg_vm(R_SS, new_ss & 0xffff);
2074     load_seg_vm(R_ES, new_es & 0xffff);
2075     load_seg_vm(R_DS, new_ds & 0xffff);
2076     load_seg_vm(R_FS, new_fs & 0xffff);
2077     load_seg_vm(R_GS, new_gs & 0xffff);
2078
2079     env->eip = new_eip & 0xffff;
2080     ESP = new_esp;
2081 }
2082
2083 void helper_iret_protected(int shift, int next_eip)
2084 {
2085     int tss_selector, type;
2086     uint32_t e1, e2;
2087     
2088     /* specific case for TSS */
2089     if (env->eflags & NT_MASK) {
2090 #ifdef TARGET_X86_64
2091         if (env->hflags & HF_LMA_MASK)
2092             raise_exception_err(EXCP0D_GPF, 0);
2093 #endif
2094         tss_selector = lduw_kernel(env->tr.base + 0);
2095         if (tss_selector & 4)
2096             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2097         if (load_segment(&e1, &e2, tss_selector) != 0)
2098             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2099         type = (e2 >> DESC_TYPE_SHIFT) & 0x17;
2100         /* NOTE: we check both segment and busy TSS */
2101         if (type != 3)
2102             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
2103         switch_tss(tss_selector, e1, e2, SWITCH_TSS_IRET, next_eip);
2104     } else {
2105         helper_ret_protected(shift, 1, 0);
2106     }
2107 #ifdef USE_KQEMU
2108     if (kqemu_is_ok(env)) {
2109         CC_OP = CC_OP_EFLAGS;
2110         env->exception_index = -1;
2111         cpu_loop_exit();
2112     }
2113 #endif
2114 }
2115
2116 void helper_lret_protected(int shift, int addend)
2117 {
2118     helper_ret_protected(shift, 0, addend);
2119 #ifdef USE_KQEMU
2120     if (kqemu_is_ok(env)) {
2121         env->exception_index = -1;
2122         cpu_loop_exit();
2123     }
2124 #endif
2125 }
2126
2127 void helper_sysenter(void)
2128 {
2129     if (env->sysenter_cs == 0) {
2130         raise_exception_err(EXCP0D_GPF, 0);
2131     }
2132     env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK);
2133     cpu_x86_set_cpl(env, 0);
2134     cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc, 
2135                            0, 0xffffffff, 
2136                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2137                            DESC_S_MASK |
2138                            DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2139     cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc, 
2140                            0, 0xffffffff,
2141                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2142                            DESC_S_MASK |
2143                            DESC_W_MASK | DESC_A_MASK);
2144     ESP = env->sysenter_esp;
2145     EIP = env->sysenter_eip;
2146 }
2147
2148 void helper_sysexit(void)
2149 {
2150     int cpl;
2151
2152     cpl = env->hflags & HF_CPL_MASK;
2153     if (env->sysenter_cs == 0 || cpl != 0) {
2154         raise_exception_err(EXCP0D_GPF, 0);
2155     }
2156     cpu_x86_set_cpl(env, 3);
2157     cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3, 
2158                            0, 0xffffffff, 
2159                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2160                            DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2161                            DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2162     cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3, 
2163                            0, 0xffffffff,
2164                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2165                            DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2166                            DESC_W_MASK | DESC_A_MASK);
2167     ESP = ECX;
2168     EIP = EDX;
2169 #ifdef USE_KQEMU
2170     if (kqemu_is_ok(env)) {
2171         env->exception_index = -1;
2172         cpu_loop_exit();
2173     }
2174 #endif
2175 }
2176
2177 void helper_movl_crN_T0(int reg)
2178 {
2179 #if !defined(CONFIG_USER_ONLY) 
2180     switch(reg) {
2181     case 0:
2182         cpu_x86_update_cr0(env, T0);
2183         break;
2184     case 3:
2185         cpu_x86_update_cr3(env, T0);
2186         break;
2187     case 4:
2188         cpu_x86_update_cr4(env, T0);
2189         break;
2190     case 8:
2191         cpu_set_apic_tpr(env, T0);
2192         break;
2193     default:
2194         env->cr[reg] = T0;
2195         break;
2196     }
2197 #endif
2198 }
2199
2200 /* XXX: do more */
2201 void helper_movl_drN_T0(int reg)
2202 {
2203     env->dr[reg] = T0;
2204 }
2205
2206 void helper_invlpg(unsigned int addr)
2207 {
2208     cpu_x86_flush_tlb(env, addr);
2209 }
2210
2211 void helper_rdtsc(void)
2212 {
2213     uint64_t val;
2214     
2215     val = cpu_get_tsc(env);
2216     EAX = (uint32_t)(val);
2217     EDX = (uint32_t)(val >> 32);
2218 }
2219
2220 #if defined(CONFIG_USER_ONLY) 
2221 void helper_wrmsr(void)
2222 {
2223 }
2224
2225 void helper_rdmsr(void)
2226 {
2227 }
2228 #else
2229 void helper_wrmsr(void)
2230 {
2231     uint64_t val;
2232
2233     val = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
2234
2235     switch((uint32_t)ECX) {
2236     case MSR_IA32_SYSENTER_CS:
2237         env->sysenter_cs = val & 0xffff;
2238         break;
2239     case MSR_IA32_SYSENTER_ESP:
2240         env->sysenter_esp = val;
2241         break;
2242     case MSR_IA32_SYSENTER_EIP:
2243         env->sysenter_eip = val;
2244         break;
2245     case MSR_IA32_APICBASE:
2246         cpu_set_apic_base(env, val);
2247         break;
2248 #ifdef TARGET_X86_64
2249     case MSR_EFER:
2250 #define MSR_EFER_UPDATE_MASK (MSR_EFER_SCE | MSR_EFER_LME | \
2251                               MSR_EFER_NXE | MSR_EFER_FFXSR)
2252         env->efer = (env->efer & ~MSR_EFER_UPDATE_MASK) | 
2253             (val & MSR_EFER_UPDATE_MASK);
2254         break;
2255     case MSR_STAR:
2256         env->star = val;
2257         break;
2258     case MSR_LSTAR:
2259         env->lstar = val;
2260         break;
2261     case MSR_CSTAR:
2262         env->cstar = val;
2263         break;
2264     case MSR_FMASK:
2265         env->fmask = val;
2266         break;
2267     case MSR_FSBASE:
2268         env->segs[R_FS].base = val;
2269         break;
2270     case MSR_GSBASE:
2271         env->segs[R_GS].base = val;
2272         break;
2273     case MSR_KERNELGSBASE:
2274         env->kernelgsbase = val;
2275         break;
2276 #endif
2277     default:
2278         /* XXX: exception ? */
2279         break; 
2280     }
2281 }
2282
2283 void helper_rdmsr(void)
2284 {
2285     uint64_t val;
2286     switch((uint32_t)ECX) {
2287     case MSR_IA32_SYSENTER_CS:
2288         val = env->sysenter_cs;
2289         break;
2290     case MSR_IA32_SYSENTER_ESP:
2291         val = env->sysenter_esp;
2292         break;
2293     case MSR_IA32_SYSENTER_EIP:
2294         val = env->sysenter_eip;
2295         break;
2296     case MSR_IA32_APICBASE:
2297         val = cpu_get_apic_base(env);
2298         break;
2299 #ifdef TARGET_X86_64
2300     case MSR_EFER:
2301         val = env->efer;
2302         break;
2303     case MSR_STAR:
2304         val = env->star;
2305         break;
2306     case MSR_LSTAR:
2307         val = env->lstar;
2308         break;
2309     case MSR_CSTAR:
2310         val = env->cstar;
2311         break;
2312     case MSR_FMASK:
2313         val = env->fmask;
2314         break;
2315     case MSR_FSBASE:
2316         val = env->segs[R_FS].base;
2317         break;
2318     case MSR_GSBASE:
2319         val = env->segs[R_GS].base;
2320         break;
2321     case MSR_KERNELGSBASE:
2322         val = env->kernelgsbase;
2323         break;
2324 #endif
2325     default:
2326         /* XXX: exception ? */
2327         val = 0;
2328         break; 
2329     }
2330     EAX = (uint32_t)(val);
2331     EDX = (uint32_t)(val >> 32);
2332 }
2333 #endif
2334
2335 void helper_lsl(void)
2336 {
2337     unsigned int selector, limit;
2338     uint32_t e1, e2, eflags;
2339     int rpl, dpl, cpl, type;
2340
2341     eflags = cc_table[CC_OP].compute_all();
2342     selector = T0 & 0xffff;
2343     if (load_segment(&e1, &e2, selector) != 0)
2344         goto fail;
2345     rpl = selector & 3;
2346     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2347     cpl = env->hflags & HF_CPL_MASK;
2348     if (e2 & DESC_S_MASK) {
2349         if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
2350             /* conforming */
2351         } else {
2352             if (dpl < cpl || dpl < rpl)
2353                 goto fail;
2354         }
2355     } else {
2356         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2357         switch(type) {
2358         case 1:
2359         case 2:
2360         case 3:
2361         case 9:
2362         case 11:
2363             break;
2364         default:
2365             goto fail;
2366         }
2367         if (dpl < cpl || dpl < rpl) {
2368         fail:
2369             CC_SRC = eflags & ~CC_Z;
2370             return;
2371         }
2372     }
2373     limit = get_seg_limit(e1, e2);
2374     T1 = limit;
2375     CC_SRC = eflags | CC_Z;
2376 }
2377
2378 void helper_lar(void)
2379 {
2380     unsigned int selector;
2381     uint32_t e1, e2, eflags;
2382     int rpl, dpl, cpl, type;
2383
2384     eflags = cc_table[CC_OP].compute_all();
2385     selector = T0 & 0xffff;
2386     if ((selector & 0xfffc) == 0)
2387         goto fail;
2388     if (load_segment(&e1, &e2, selector) != 0)
2389         goto fail;
2390     rpl = selector & 3;
2391     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2392     cpl = env->hflags & HF_CPL_MASK;
2393     if (e2 & DESC_S_MASK) {
2394         if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
2395             /* conforming */
2396         } else {
2397             if (dpl < cpl || dpl < rpl)
2398                 goto fail;
2399         }
2400     } else {
2401         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
2402         switch(type) {
2403         case 1:
2404         case 2:
2405         case 3:
2406         case 4:
2407         case 5:
2408         case 9:
2409         case 11:
2410         case 12:
2411             break;
2412         default:
2413             goto fail;
2414         }
2415         if (dpl < cpl || dpl < rpl) {
2416         fail:
2417             CC_SRC = eflags & ~CC_Z;
2418             return;
2419         }
2420     }
2421     T1 = e2 & 0x00f0ff00;
2422     CC_SRC = eflags | CC_Z;
2423 }
2424
2425 void helper_verr(void)
2426 {
2427     unsigned int selector;
2428     uint32_t e1, e2, eflags;
2429     int rpl, dpl, cpl;
2430
2431     eflags = cc_table[CC_OP].compute_all();
2432     selector = T0 & 0xffff;
2433     if ((selector & 0xfffc) == 0)
2434         goto fail;
2435     if (load_segment(&e1, &e2, selector) != 0)
2436         goto fail;
2437     if (!(e2 & DESC_S_MASK))
2438         goto fail;
2439     rpl = selector & 3;
2440     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2441     cpl = env->hflags & HF_CPL_MASK;
2442     if (e2 & DESC_CS_MASK) {
2443         if (!(e2 & DESC_R_MASK))
2444             goto fail;
2445         if (!(e2 & DESC_C_MASK)) {
2446             if (dpl < cpl || dpl < rpl)
2447                 goto fail;
2448         }
2449     } else {
2450         if (dpl < cpl || dpl < rpl) {
2451         fail:
2452             CC_SRC = eflags & ~CC_Z;
2453             return;
2454         }
2455     }
2456     CC_SRC = eflags | CC_Z;
2457 }
2458
2459 void helper_verw(void)
2460 {
2461     unsigned int selector;
2462     uint32_t e1, e2, eflags;
2463     int rpl, dpl, cpl;
2464
2465     eflags = cc_table[CC_OP].compute_all();
2466     selector = T0 & 0xffff;
2467     if ((selector & 0xfffc) == 0)
2468         goto fail;
2469     if (load_segment(&e1, &e2, selector) != 0)
2470         goto fail;
2471     if (!(e2 & DESC_S_MASK))
2472         goto fail;
2473     rpl = selector & 3;
2474     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
2475     cpl = env->hflags & HF_CPL_MASK;
2476     if (e2 & DESC_CS_MASK) {
2477         goto fail;
2478     } else {
2479         if (dpl < cpl || dpl < rpl)
2480             goto fail;
2481         if (!(e2 & DESC_W_MASK)) {
2482         fail:
2483             CC_SRC = eflags & ~CC_Z;
2484             return;
2485         }
2486     }
2487     CC_SRC = eflags | CC_Z;
2488 }
2489
2490 /* FPU helpers */
2491
2492 void helper_fldt_ST0_A0(void)
2493 {
2494     int new_fpstt;
2495     new_fpstt = (env->fpstt - 1) & 7;
2496     env->fpregs[new_fpstt].d = helper_fldt(A0);
2497     env->fpstt = new_fpstt;
2498     env->fptags[new_fpstt] = 0; /* validate stack entry */
2499 }
2500
2501 void helper_fstt_ST0_A0(void)
2502 {
2503     helper_fstt(ST0, A0);
2504 }
2505
2506 void fpu_set_exception(int mask)
2507 {
2508     env->fpus |= mask;
2509     if (env->fpus & (~env->fpuc & FPUC_EM))
2510         env->fpus |= FPUS_SE | FPUS_B;
2511 }
2512
2513 CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b)
2514 {
2515     if (b == 0.0) 
2516         fpu_set_exception(FPUS_ZE);
2517     return a / b;
2518 }
2519
2520 void fpu_raise_exception(void)
2521 {
2522     if (env->cr[0] & CR0_NE_MASK) {
2523         raise_exception(EXCP10_COPR);
2524     } 
2525 #if !defined(CONFIG_USER_ONLY) 
2526     else {
2527         cpu_set_ferr(env);
2528     }
2529 #endif
2530 }
2531
2532 /* BCD ops */
2533
2534 void helper_fbld_ST0_A0(void)
2535 {
2536     CPU86_LDouble tmp;
2537     uint64_t val;
2538     unsigned int v;
2539     int i;
2540
2541     val = 0;
2542     for(i = 8; i >= 0; i--) {
2543         v = ldub(A0 + i);
2544         val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
2545     }
2546     tmp = val;
2547     if (ldub(A0 + 9) & 0x80)
2548         tmp = -tmp;
2549     fpush();
2550     ST0 = tmp;
2551 }
2552
2553 void helper_fbst_ST0_A0(void)
2554 {
2555     int v;
2556     target_ulong mem_ref, mem_end;
2557     int64_t val;
2558
2559     val = floatx_to_int64(ST0, &env->fp_status);
2560     mem_ref = A0;
2561     mem_end = mem_ref + 9;
2562     if (val < 0) {
2563         stb(mem_end, 0x80);
2564         val = -val;
2565     } else {
2566         stb(mem_end, 0x00);
2567     }
2568     while (mem_ref < mem_end) {
2569         if (val == 0)
2570             break;
2571         v = val % 100;
2572         val = val / 100;
2573         v = ((v / 10) << 4) | (v % 10);
2574         stb(mem_ref++, v);
2575     }
2576     while (mem_ref < mem_end) {
2577         stb(mem_ref++, 0);
2578     }
2579 }
2580
2581 void helper_f2xm1(void)
2582 {
2583     ST0 = pow(2.0,ST0) - 1.0;
2584 }
2585
2586 void helper_fyl2x(void)
2587 {
2588     CPU86_LDouble fptemp;
2589     
2590     fptemp = ST0;
2591     if (fptemp>0.0){
2592         fptemp = log(fptemp)/log(2.0);   /* log2(ST) */
2593         ST1 *= fptemp;
2594         fpop();
2595     } else { 
2596         env->fpus &= (~0x4700);
2597         env->fpus |= 0x400;
2598     }
2599 }
2600
2601 void helper_fptan(void)
2602 {
2603     CPU86_LDouble fptemp;
2604
2605     fptemp = ST0;
2606     if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2607         env->fpus |= 0x400;
2608     } else {
2609         ST0 = tan(fptemp);
2610         fpush();
2611         ST0 = 1.0;
2612         env->fpus &= (~0x400);  /* C2 <-- 0 */
2613         /* the above code is for  |arg| < 2**52 only */
2614     }
2615 }
2616
2617 void helper_fpatan(void)
2618 {
2619     CPU86_LDouble fptemp, fpsrcop;
2620
2621     fpsrcop = ST1;
2622     fptemp = ST0;
2623     ST1 = atan2(fpsrcop,fptemp);
2624     fpop();
2625 }
2626
2627 void helper_fxtract(void)
2628 {
2629     CPU86_LDoubleU temp;
2630     unsigned int expdif;
2631
2632     temp.d = ST0;
2633     expdif = EXPD(temp) - EXPBIAS;
2634     /*DP exponent bias*/
2635     ST0 = expdif;
2636     fpush();
2637     BIASEXPONENT(temp);
2638     ST0 = temp.d;
2639 }
2640
2641 void helper_fprem1(void)
2642 {
2643     CPU86_LDouble dblq, fpsrcop, fptemp;
2644     CPU86_LDoubleU fpsrcop1, fptemp1;
2645     int expdif;
2646     int q;
2647
2648     fpsrcop = ST0;
2649     fptemp = ST1;
2650     fpsrcop1.d = fpsrcop;
2651     fptemp1.d = fptemp;
2652     expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
2653     if (expdif < 53) {
2654         dblq = fpsrcop / fptemp;
2655         dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
2656         ST0 = fpsrcop - fptemp*dblq;
2657         q = (int)dblq; /* cutting off top bits is assumed here */
2658         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
2659                                 /* (C0,C1,C3) <-- (q2,q1,q0) */
2660         env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
2661         env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
2662         env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
2663     } else {
2664         env->fpus |= 0x400;  /* C2 <-- 1 */
2665         fptemp = pow(2.0, expdif-50);
2666         fpsrcop = (ST0 / ST1) / fptemp;
2667         /* fpsrcop = integer obtained by rounding to the nearest */
2668         fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)?
2669             floor(fpsrcop): ceil(fpsrcop);
2670         ST0 -= (ST1 * fpsrcop * fptemp);
2671     }
2672 }
2673
2674 void helper_fprem(void)
2675 {
2676     CPU86_LDouble dblq, fpsrcop, fptemp;
2677     CPU86_LDoubleU fpsrcop1, fptemp1;
2678     int expdif;
2679     int q;
2680     
2681     fpsrcop = ST0;
2682     fptemp = ST1;
2683     fpsrcop1.d = fpsrcop;
2684     fptemp1.d = fptemp;
2685     expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
2686     if ( expdif < 53 ) {
2687         dblq = fpsrcop / fptemp;
2688         dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
2689         ST0 = fpsrcop - fptemp*dblq;
2690         q = (int)dblq; /* cutting off top bits is assumed here */
2691         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
2692                                 /* (C0,C1,C3) <-- (q2,q1,q0) */
2693         env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
2694         env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
2695         env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
2696     } else {
2697         env->fpus |= 0x400;  /* C2 <-- 1 */
2698         fptemp = pow(2.0, expdif-50);
2699         fpsrcop = (ST0 / ST1) / fptemp;
2700         /* fpsrcop = integer obtained by chopping */
2701         fpsrcop = (fpsrcop < 0.0)?
2702             -(floor(fabs(fpsrcop))): floor(fpsrcop);
2703         ST0 -= (ST1 * fpsrcop * fptemp);
2704     }
2705 }
2706
2707 void helper_fyl2xp1(void)
2708 {
2709     CPU86_LDouble fptemp;
2710
2711     fptemp = ST0;
2712     if ((fptemp+1.0)>0.0) {
2713         fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
2714         ST1 *= fptemp;
2715         fpop();
2716     } else { 
2717         env->fpus &= (~0x4700);
2718         env->fpus |= 0x400;
2719     }
2720 }
2721
2722 void helper_fsqrt(void)
2723 {
2724     CPU86_LDouble fptemp;
2725
2726     fptemp = ST0;
2727     if (fptemp<0.0) { 
2728         env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
2729         env->fpus |= 0x400;
2730     }
2731     ST0 = sqrt(fptemp);
2732 }
2733
2734 void helper_fsincos(void)
2735 {
2736     CPU86_LDouble fptemp;
2737
2738     fptemp = ST0;
2739     if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2740         env->fpus |= 0x400;
2741     } else {
2742         ST0 = sin(fptemp);
2743         fpush();
2744         ST0 = cos(fptemp);
2745         env->fpus &= (~0x400);  /* C2 <-- 0 */
2746         /* the above code is for  |arg| < 2**63 only */
2747     }
2748 }
2749
2750 void helper_frndint(void)
2751 {
2752     ST0 = floatx_round_to_int(ST0, &env->fp_status);
2753 }
2754
2755 void helper_fscale(void)
2756 {
2757     CPU86_LDouble fpsrcop, fptemp;
2758
2759     fpsrcop = 2.0;
2760     fptemp = pow(fpsrcop,ST1);
2761     ST0 *= fptemp;
2762 }
2763
2764 void helper_fsin(void)
2765 {
2766     CPU86_LDouble fptemp;
2767
2768     fptemp = ST0;
2769     if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2770         env->fpus |= 0x400;
2771     } else {
2772         ST0 = sin(fptemp);
2773         env->fpus &= (~0x400);  /* C2 <-- 0 */
2774         /* the above code is for  |arg| < 2**53 only */
2775     }
2776 }
2777
2778 void helper_fcos(void)
2779 {
2780     CPU86_LDouble fptemp;
2781
2782     fptemp = ST0;
2783     if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
2784         env->fpus |= 0x400;
2785     } else {
2786         ST0 = cos(fptemp);
2787         env->fpus &= (~0x400);  /* C2 <-- 0 */
2788         /* the above code is for  |arg5 < 2**63 only */
2789     }
2790 }
2791
2792 void helper_fxam_ST0(void)
2793 {
2794     CPU86_LDoubleU temp;
2795     int expdif;
2796
2797     temp.d = ST0;
2798
2799     env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
2800     if (SIGND(temp))
2801         env->fpus |= 0x200; /* C1 <-- 1 */
2802
2803     expdif = EXPD(temp);
2804     if (expdif == MAXEXPD) {
2805         if (MANTD(temp) == 0)
2806             env->fpus |=  0x500 /*Infinity*/;
2807         else
2808             env->fpus |=  0x100 /*NaN*/;
2809     } else if (expdif == 0) {
2810         if (MANTD(temp) == 0)
2811             env->fpus |=  0x4000 /*Zero*/;
2812         else
2813             env->fpus |= 0x4400 /*Denormal*/;
2814     } else {
2815         env->fpus |= 0x400;
2816     }
2817 }
2818
2819 void helper_fstenv(target_ulong ptr, int data32)
2820 {
2821     int fpus, fptag, exp, i;
2822     uint64_t mant;
2823     CPU86_LDoubleU tmp;
2824
2825     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2826     fptag = 0;
2827     for (i=7; i>=0; i--) {
2828         fptag <<= 2;
2829         if (env->fptags[i]) {
2830             fptag |= 3;
2831         } else {
2832             tmp.d = env->fpregs[i].d;
2833             exp = EXPD(tmp);
2834             mant = MANTD(tmp);
2835             if (exp == 0 && mant == 0) {
2836                 /* zero */
2837                 fptag |= 1;
2838             } else if (exp == 0 || exp == MAXEXPD
2839 #ifdef USE_X86LDOUBLE
2840                        || (mant & (1LL << 63)) == 0
2841 #endif
2842                        ) {
2843                 /* NaNs, infinity, denormal */
2844                 fptag |= 2;
2845             }
2846         }
2847     }
2848     if (data32) {
2849         /* 32 bit */
2850         stl(ptr, env->fpuc);
2851         stl(ptr + 4, fpus);
2852         stl(ptr + 8, fptag);
2853         stl(ptr + 12, 0); /* fpip */
2854         stl(ptr + 16, 0); /* fpcs */
2855         stl(ptr + 20, 0); /* fpoo */
2856         stl(ptr + 24, 0); /* fpos */
2857     } else {
2858         /* 16 bit */
2859         stw(ptr, env->fpuc);
2860         stw(ptr + 2, fpus);
2861         stw(ptr + 4, fptag);
2862         stw(ptr + 6, 0);
2863         stw(ptr + 8, 0);
2864         stw(ptr + 10, 0);
2865         stw(ptr + 12, 0);
2866     }
2867 }
2868
2869 void helper_fldenv(target_ulong ptr, int data32)
2870 {
2871     int i, fpus, fptag;
2872
2873     if (data32) {
2874         env->fpuc = lduw(ptr);
2875         fpus = lduw(ptr + 4);
2876         fptag = lduw(ptr + 8);
2877     }
2878     else {
2879         env->fpuc = lduw(ptr);
2880         fpus = lduw(ptr + 2);
2881         fptag = lduw(ptr + 4);
2882     }
2883     env->fpstt = (fpus >> 11) & 7;
2884     env->fpus = fpus & ~0x3800;
2885     for(i = 0;i < 8; i++) {
2886         env->fptags[i] = ((fptag & 3) == 3);
2887         fptag >>= 2;
2888     }
2889 }
2890
2891 void helper_fsave(target_ulong ptr, int data32)
2892 {
2893     CPU86_LDouble tmp;
2894     int i;
2895
2896     helper_fstenv(ptr, data32);
2897
2898     ptr += (14 << data32);
2899     for(i = 0;i < 8; i++) {
2900         tmp = ST(i);
2901         helper_fstt(tmp, ptr);
2902         ptr += 10;
2903     }
2904
2905     /* fninit */
2906     env->fpus = 0;
2907     env->fpstt = 0;
2908     env->fpuc = 0x37f;
2909     env->fptags[0] = 1;
2910     env->fptags[1] = 1;
2911     env->fptags[2] = 1;
2912     env->fptags[3] = 1;
2913     env->fptags[4] = 1;
2914     env->fptags[5] = 1;
2915     env->fptags[6] = 1;
2916     env->fptags[7] = 1;
2917 }
2918
2919 void helper_frstor(target_ulong ptr, int data32)
2920 {
2921     CPU86_LDouble tmp;
2922     int i;
2923
2924     helper_fldenv(ptr, data32);
2925     ptr += (14 << data32);
2926
2927     for(i = 0;i < 8; i++) {
2928         tmp = helper_fldt(ptr);
2929         ST(i) = tmp;
2930         ptr += 10;
2931     }
2932 }
2933
2934 void helper_fxsave(target_ulong ptr, int data64)
2935 {
2936     int fpus, fptag, i, nb_xmm_regs;
2937     CPU86_LDouble tmp;
2938     target_ulong addr;
2939
2940     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2941     fptag = 0;
2942     for(i = 0; i < 8; i++) {
2943         fptag |= (env->fptags[i] << i);
2944     }
2945     stw(ptr, env->fpuc);
2946     stw(ptr + 2, fpus);
2947     stw(ptr + 4, fptag ^ 0xff);
2948
2949     addr = ptr + 0x20;
2950     for(i = 0;i < 8; i++) {
2951         tmp = ST(i);
2952         helper_fstt(tmp, addr);
2953         addr += 16;
2954     }
2955     
2956     if (env->cr[4] & CR4_OSFXSR_MASK) {
2957         /* XXX: finish it */
2958         stl(ptr + 0x18, env->mxcsr); /* mxcsr */
2959         stl(ptr + 0x1c, 0x0000ffff); /* mxcsr_mask */
2960         nb_xmm_regs = 8 << data64;
2961         addr = ptr + 0xa0;
2962         for(i = 0; i < nb_xmm_regs; i++) {
2963             stq(addr, env->xmm_regs[i].XMM_Q(0));
2964             stq(addr + 8, env->xmm_regs[i].XMM_Q(1));
2965             addr += 16;
2966         }
2967     }
2968 }
2969
2970 void helper_fxrstor(target_ulong ptr, int data64)
2971 {
2972     int i, fpus, fptag, nb_xmm_regs;
2973     CPU86_LDouble tmp;
2974     target_ulong addr;
2975
2976     env->fpuc = lduw(ptr);
2977     fpus = lduw(ptr + 2);
2978     fptag = lduw(ptr + 4);
2979     env->fpstt = (fpus >> 11) & 7;
2980     env->fpus = fpus & ~0x3800;
2981     fptag ^= 0xff;
2982     for(i = 0;i < 8; i++) {
2983         env->fptags[i] = ((fptag >> i) & 1);
2984     }
2985
2986     addr = ptr + 0x20;
2987     for(i = 0;i < 8; i++) {
2988         tmp = helper_fldt(addr);
2989         ST(i) = tmp;
2990         addr += 16;
2991     }
2992
2993     if (env->cr[4] & CR4_OSFXSR_MASK) {
2994         /* XXX: finish it */
2995         env->mxcsr = ldl(ptr + 0x18);
2996         //ldl(ptr + 0x1c);
2997         nb_xmm_regs = 8 << data64;
2998         addr = ptr + 0xa0;
2999         for(i = 0; i < nb_xmm_regs; i++) {
3000             env->xmm_regs[i].XMM_Q(0) = ldq(addr);
3001             env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
3002             addr += 16;
3003         }
3004     }
3005 }
3006
3007 #ifndef USE_X86LDOUBLE
3008
3009 void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
3010 {
3011     CPU86_LDoubleU temp;
3012     int e;
3013
3014     temp.d = f;
3015     /* mantissa */
3016     *pmant = (MANTD(temp) << 11) | (1LL << 63);
3017     /* exponent + sign */
3018     e = EXPD(temp) - EXPBIAS + 16383;
3019     e |= SIGND(temp) >> 16;
3020     *pexp = e;
3021 }
3022
3023 CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
3024 {
3025     CPU86_LDoubleU temp;
3026     int e;
3027     uint64_t ll;
3028
3029     /* XXX: handle overflow ? */
3030     e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
3031     e |= (upper >> 4) & 0x800; /* sign */
3032     ll = (mant >> 11) & ((1LL << 52) - 1);
3033 #ifdef __arm__
3034     temp.l.upper = (e << 20) | (ll >> 32);
3035     temp.l.lower = ll;
3036 #else
3037     temp.ll = ll | ((uint64_t)e << 52);
3038 #endif
3039     return temp.d;
3040 }
3041
3042 #else
3043
3044 void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
3045 {
3046     CPU86_LDoubleU temp;
3047
3048     temp.d = f;
3049     *pmant = temp.l.lower;
3050     *pexp = temp.l.upper;
3051 }
3052
3053 CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
3054 {
3055     CPU86_LDoubleU temp;
3056
3057     temp.l.upper = upper;
3058     temp.l.lower = mant;
3059     return temp.d;
3060 }
3061 #endif
3062
3063 #ifdef TARGET_X86_64
3064
3065 //#define DEBUG_MULDIV
3066
3067 static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
3068 {
3069     *plow += a;
3070     /* carry test */
3071     if (*plow < a)
3072         (*phigh)++;
3073     *phigh += b;
3074 }
3075
3076 static void neg128(uint64_t *plow, uint64_t *phigh)
3077 {
3078     *plow = ~ *plow;
3079     *phigh = ~ *phigh;
3080     add128(plow, phigh, 1, 0);
3081 }
3082
3083 static void mul64(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
3084 {
3085     uint32_t a0, a1, b0, b1;
3086     uint64_t v;
3087
3088     a0 = a;
3089     a1 = a >> 32;
3090
3091     b0 = b;
3092     b1 = b >> 32;
3093     
3094     v = (uint64_t)a0 * (uint64_t)b0;
3095     *plow = v;
3096     *phigh = 0;
3097
3098     v = (uint64_t)a0 * (uint64_t)b1;
3099     add128(plow, phigh, v << 32, v >> 32);
3100     
3101     v = (uint64_t)a1 * (uint64_t)b0;
3102     add128(plow, phigh, v << 32, v >> 32);
3103     
3104     v = (uint64_t)a1 * (uint64_t)b1;
3105     *phigh += v;
3106 #ifdef DEBUG_MULDIV
3107     printf("mul: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n",
3108            a, b, *phigh, *plow);
3109 #endif
3110 }
3111
3112 static void imul64(uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b)
3113 {
3114     int sa, sb;
3115     sa = (a < 0);
3116     if (sa)
3117         a = -a;
3118     sb = (b < 0);
3119     if (sb)
3120         b = -b;
3121     mul64(plow, phigh, a, b);
3122     if (sa ^ sb) {
3123         neg128(plow, phigh);
3124     }
3125 }
3126
3127 /* XXX: overflow support */
3128 static void div64(uint64_t *plow, uint64_t *phigh, uint64_t b)
3129 {
3130     uint64_t q, r, a1, a0;
3131     int i, qb;
3132
3133     a0 = *plow;
3134     a1 = *phigh;
3135     if (a1 == 0) {
3136         q = a0 / b;
3137         r = a0 % b;
3138         *plow = q;
3139         *phigh = r;
3140     } else {
3141         /* XXX: use a better algorithm */
3142         for(i = 0; i < 64; i++) {
3143             a1 = (a1 << 1) | (a0 >> 63);
3144             if (a1 >= b) {
3145                 a1 -= b;
3146                 qb = 1;
3147             } else {
3148                 qb = 0;
3149             }
3150             a0 = (a0 << 1) | qb;
3151         }
3152 #if defined(DEBUG_MULDIV)
3153         printf("div: 0x%016llx%016llx / 0x%016llx: q=0x%016llx r=0x%016llx\n",
3154                *phigh, *plow, b, a0, a1);
3155 #endif
3156         *plow = a0;
3157         *phigh = a1;
3158     }
3159 }
3160
3161 static void idiv64(uint64_t *plow, uint64_t *phigh, int64_t b)
3162 {
3163     int sa, sb;
3164     sa = ((int64_t)*phigh < 0);
3165     if (sa)
3166         neg128(plow, phigh);
3167     sb = (b < 0);
3168     if (sb)
3169         b = -b;
3170     div64(plow, phigh, b);
3171     if (sa ^ sb)
3172         *plow = - *plow;
3173     if (sa)
3174         *phigh = - *phigh;
3175 }
3176
3177 void helper_mulq_EAX_T0(void)
3178 {
3179     uint64_t r0, r1;
3180
3181     mul64(&r0, &r1, EAX, T0);
3182     EAX = r0;
3183     EDX = r1;
3184     CC_DST = r0;
3185     CC_SRC = r1;
3186 }
3187
3188 void helper_imulq_EAX_T0(void)
3189 {
3190     uint64_t r0, r1;
3191
3192     imul64(&r0, &r1, EAX, T0);
3193     EAX = r0;
3194     EDX = r1;
3195     CC_DST = r0;
3196     CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
3197 }
3198
3199 void helper_imulq_T0_T1(void)
3200 {
3201     uint64_t r0, r1;
3202
3203     imul64(&r0, &r1, T0, T1);
3204     T0 = r0;
3205     CC_DST = r0;
3206     CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
3207 }
3208
3209 void helper_divq_EAX_T0(void)
3210 {
3211     uint64_t r0, r1;
3212     if (T0 == 0) {
3213         raise_exception(EXCP00_DIVZ);
3214     }
3215     r0 = EAX;
3216     r1 = EDX;
3217     div64(&r0, &r1, T0);
3218     EAX = r0;
3219     EDX = r1;
3220 }
3221
3222 void helper_idivq_EAX_T0(void)
3223 {
3224     uint64_t r0, r1;
3225     if (T0 == 0) {
3226         raise_exception(EXCP00_DIVZ);
3227     }
3228     r0 = EAX;
3229     r1 = EDX;
3230     idiv64(&r0, &r1, T0);
3231     EAX = r0;
3232     EDX = r1;
3233 }
3234
3235 #endif
3236
3237 float approx_rsqrt(float a)
3238 {
3239     return 1.0 / sqrt(a);
3240 }
3241
3242 float approx_rcp(float a)
3243 {
3244     return 1.0 / a;
3245 }
3246
3247 void update_fp_status(void)
3248 {
3249     int rnd_type;
3250
3251     /* set rounding mode */
3252     switch(env->fpuc & RC_MASK) {
3253     default:
3254     case RC_NEAR:
3255         rnd_type = float_round_nearest_even;
3256         break;
3257     case RC_DOWN:
3258         rnd_type = float_round_down;
3259         break;
3260     case RC_UP:
3261         rnd_type = float_round_up;
3262         break;
3263     case RC_CHOP:
3264         rnd_type = float_round_to_zero;
3265         break;
3266     }
3267     set_float_rounding_mode(rnd_type, &env->fp_status);
3268 #ifdef FLOATX80
3269     switch((env->fpuc >> 8) & 3) {
3270     case 0:
3271         rnd_type = 32;
3272         break;
3273     case 2:
3274         rnd_type = 64;
3275         break;
3276     case 3:
3277     default:
3278         rnd_type = 80;
3279         break;
3280     }
3281     set_floatx80_rounding_precision(rnd_type, &env->fp_status);
3282 #endif
3283 }
3284
3285 #if !defined(CONFIG_USER_ONLY) 
3286
3287 #define MMUSUFFIX _mmu
3288 #define GETPC() (__builtin_return_address(0))
3289
3290 #define SHIFT 0
3291 #include "softmmu_template.h"
3292
3293 #define SHIFT 1
3294 #include "softmmu_template.h"
3295
3296 #define SHIFT 2
3297 #include "softmmu_template.h"
3298
3299 #define SHIFT 3
3300 #include "softmmu_template.h"
3301
3302 #endif
3303
3304 /* try to fill the TLB and return an exception if error. If retaddr is
3305    NULL, it means that the function was called in C code (i.e. not
3306    from generated code or from helper.c) */
3307 /* XXX: fix it to restore all registers */
3308 void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
3309 {
3310     TranslationBlock *tb;
3311     int ret;
3312     unsigned long pc;
3313     CPUX86State *saved_env;
3314
3315     /* XXX: hack to restore env in all cases, even if not called from
3316        generated code */
3317     saved_env = env;
3318     env = cpu_single_env;
3319
3320     ret = cpu_x86_handle_mmu_fault(env, addr, is_write, is_user, 1);
3321     if (ret) {
3322         if (retaddr) {
3323             /* now we have a real cpu fault */
3324             pc = (unsigned long)retaddr;
3325             tb = tb_find_pc(pc);
3326             if (tb) {
3327                 /* the PC is inside the translated code. It means that we have
3328                    a virtual CPU fault */
3329                 cpu_restore_state(tb, env, pc, NULL);
3330             }
3331         }
3332         if (retaddr)
3333             raise_exception_err(EXCP0E_PAGE, env->error_code);
3334         else
3335             raise_exception_err_norestore(EXCP0E_PAGE, env->error_code);
3336     }
3337     env = saved_env;
3338 }
This page took 0.2063 seconds and 4 git commands to generate.