summary refs log tree commit diff stats
path: root/op-i386.c
diff options
context:
space:
mode:
Diffstat (limited to 'op-i386.c')
-rw-r--r--op-i386.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/op-i386.c b/op-i386.c
index 6d695ff90d..503fb88ede 100644
--- a/op-i386.c
+++ b/op-i386.c
@@ -858,6 +858,60 @@ void OPPROTO op_das(void)
     CC_SRC = eflags;
 }
 
+/* segment handling */
+
+void load_seg(int seg_reg, int selector)
+{
+    SegmentCache *sc;
+    SegmentDescriptorTable *dt;
+    int index;
+    uint32_t e1, e2;
+    uint8_t *ptr;
+
+    env->segs[seg_reg] = selector;
+    sc = &env->seg_cache[seg_reg];
+    if (env->vm86) {
+        sc->base = (void *)(selector << 4);
+        sc->limit = 0xffff;
+        sc->seg_32bit = 0;
+    } else {
+        if (selector & 0x4)
+            dt = &env->ldt;
+        else
+            dt = &env->gdt;
+        index = selector & ~7;
+        if ((index + 7) > dt->limit)
+            raise_exception(EXCP0D_GPF);
+        ptr = dt->base + index;
+        e1 = ldl(ptr);
+        e2 = ldl(ptr + 4);
+        sc->base = (void *)((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
+        sc->limit = (e1 & 0xffff) | (e2 & 0x000f0000);
+        if (e2 & (1 << 23))
+            sc->limit = (sc->limit << 12) | 0xfff;
+        sc->seg_32bit = (e2 >> 22) & 1;
+#if 0
+        fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx seg_32bit=%d\n", 
+                selector, (unsigned long)sc->base, sc->limit, sc->seg_32bit);
+#endif
+    }
+}
+
+void OPPROTO op_movl_seg_T0(void)
+{
+    load_seg(PARAM1, T0 & 0xffff);
+}
+
+void OPPROTO op_movl_T0_seg(void)
+{
+    T0 = env->segs[PARAM1];
+}
+
+void OPPROTO op_addl_A0_seg(void)
+{
+    A0 += *(unsigned long *)((char *)env + PARAM1);
+}
+
 /* flags handling */
 
 /* slow jumps cases (compute x86 flags) */