set to protected mode
[qemu] / helper-i386.c
index f47252a..3f63704 100644 (file)
@@ -788,6 +788,37 @@ static inline void load_seg_vm(int seg, int selector)
     sc->limit = 0xffff;
 }
 
+/* real mode iret */
+void helper_iret_real(int shift)
+{
+    uint32_t sp, new_cs, new_eip, new_eflags, new_esp;
+    uint8_t *ssp;
+    int eflags_mask;
+    
+    sp = env->regs[R_ESP] & 0xffff;
+    ssp = env->segs[R_SS].base + sp;
+    if (shift == 1) {
+        /* 32 bits */
+        new_eflags = ldl(ssp + 8);
+        new_cs = ldl(ssp + 4) & 0xffff;
+        new_eip = ldl(ssp) & 0xffff;
+    } else {
+        /* 16 bits */
+        new_eflags = lduw(ssp + 4);
+        new_cs = lduw(ssp + 2);
+        new_eip = lduw(ssp);
+    }
+    new_esp = sp + (6 << shift);
+    env->regs[R_ESP] = (env->regs[R_ESP] & 0xffff0000) | 
+        (new_esp & 0xffff);
+    load_seg_vm(R_CS, new_cs);
+    env->eip = new_eip;
+    eflags_mask = FL_UPDATE_CPL0_MASK;
+    if (shift == 0)
+        eflags_mask &= 0xffff;
+    load_eflags(new_eflags, eflags_mask);
+}
+
 /* protected mode iret */
 void helper_iret_protected(int shift)
 {
@@ -947,6 +978,45 @@ void helper_rdtsc(void)
     EDX = val >> 32;
 }
 
+void helper_wrmsr(void)
+{
+    switch(ECX) {
+    case MSR_IA32_SYSENTER_CS:
+        env->sysenter_cs = EAX & 0xffff;
+        break;
+    case MSR_IA32_SYSENTER_ESP:
+        env->sysenter_esp = EAX;
+        break;
+    case MSR_IA32_SYSENTER_EIP:
+        env->sysenter_eip = EAX;
+        break;
+    default:
+        /* XXX: exception ? */
+        break; 
+    }
+}
+
+void helper_rdmsr(void)
+{
+    switch(ECX) {
+    case MSR_IA32_SYSENTER_CS:
+        EAX = env->sysenter_cs;
+        EDX = 0;
+        break;
+    case MSR_IA32_SYSENTER_ESP:
+        EAX = env->sysenter_esp;
+        EDX = 0;
+        break;
+    case MSR_IA32_SYSENTER_EIP:
+        EAX = env->sysenter_eip;
+        EDX = 0;
+        break;
+    default:
+        /* XXX: exception ? */
+        break; 
+    }
+}
+
 void helper_lsl(void)
 {
     unsigned int selector, limit;
@@ -981,7 +1051,11 @@ void helper_lar(void)
 #ifndef USE_X86LDOUBLE
 void helper_fldt_ST0_A0(void)
 {
-    ST0 = helper_fldt((uint8_t *)A0);
+    int new_fpstt;
+    new_fpstt = (env->fpstt - 1) & 7;
+    env->fpregs[new_fpstt] = helper_fldt((uint8_t *)A0);
+    env->fpstt = new_fpstt;
+    env->fptags[new_fpstt] = 0; /* validate stack entry */
 }
 
 void helper_fstt_ST0_A0(void)
@@ -996,81 +1070,47 @@ void helper_fstt_ST0_A0(void)
 
 void helper_fbld_ST0_A0(void)
 {
-    uint8_t *seg;
-    CPU86_LDouble fpsrcop;
-    int m32i;
+    CPU86_LDouble tmp;
+    uint64_t val;
     unsigned int v;
+    int i;
 
-    /* in this code, seg/m32i will be used as temporary ptr/int */
-    seg = (uint8_t *)A0 + 8;
-    v = ldub(seg--);
-    /* XXX: raise exception */
-    if (v != 0)
-        return;
-    v = ldub(seg--);
-    /* XXX: raise exception */
-    if ((v & 0xf0) != 0)
-        return;
-    m32i = v;  /* <-- d14 */
-    v = ldub(seg--);
-    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d13 */
-    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d12 */
-    v = ldub(seg--);
-    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d11 */
-    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d10 */
-    v = ldub(seg--);
-    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d9 */
-    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d8 */
-    fpsrcop = ((CPU86_LDouble)m32i) * 100000000.0;
-
-    v = ldub(seg--);
-    m32i = (v >> 4);  /* <-- d7 */
-    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d6 */
-    v = ldub(seg--);
-    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d5 */
-    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d4 */
-    v = ldub(seg--);
-    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d3 */
-    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d2 */
-    v = ldub(seg);
-    m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d1 */
-    m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d0 */
-    fpsrcop += ((CPU86_LDouble)m32i);
-    if ( ldub(seg+9) & 0x80 )
-        fpsrcop = -fpsrcop;
-    ST0 = fpsrcop;
+    val = 0;
+    for(i = 8; i >= 0; i--) {
+        v = ldub((uint8_t *)A0 + i);
+        val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
+    }
+    tmp = val;
+    if (ldub((uint8_t *)A0 + 9) & 0x80)
+        tmp = -tmp;
+    fpush();
+    ST0 = tmp;
 }
 
 void helper_fbst_ST0_A0(void)
 {
-    CPU86_LDouble fptemp;
-    CPU86_LDouble fpsrcop;
+    CPU86_LDouble tmp;
     int v;
     uint8_t *mem_ref, *mem_end;
+    int64_t val;
 
-    fpsrcop = rint(ST0);
+    tmp = rint(ST0);
+    val = (int64_t)tmp;
     mem_ref = (uint8_t *)A0;
-    mem_end = mem_ref + 8;
-    if ( fpsrcop < 0.0 ) {
-        stw(mem_end, 0x8000);
-        fpsrcop = -fpsrcop;
+    mem_end = mem_ref + 9;
+    if (val < 0) {
+        stb(mem_end, 0x80);
+        val = -val;
     } else {
-        stw(mem_end, 0x0000);
+        stb(mem_end, 0x00);
     }
     while (mem_ref < mem_end) {
-        if (fpsrcop == 0.0)
+        if (val == 0)
             break;
-        fptemp = floor(fpsrcop/10.0);
-        v = ((int)(fpsrcop - fptemp*10.0));
-        if  (fptemp == 0.0)  { 
-            stb(mem_ref++, v); 
-            break; 
-        }
-        fpsrcop = fptemp;
-        fptemp = floor(fpsrcop/10.0);
-        v |= (((int)(fpsrcop - fptemp*10.0)) << 4);
+        v = val % 100;
+        val = val / 100;
+        v = ((v / 10) << 4) | (v % 10);
         stb(mem_ref++, v);
-        fpsrcop = fptemp;
     }
     while (mem_ref < mem_end) {
         stb(mem_ref++, 0);