Improved support for vm86 mode.

diff --git a/debugger/break.c b/debugger/break.c
index e2ffe81..beabf4c 100644
--- a/debugger/break.c
+++ b/debugger/break.c
@@ -269,27 +269,27 @@
    {
       if (breakpoints[num].refcount == 0) 
       {
-	 breakpoints[num].refcount = 1;
-	 breakpoints[num].enabled = TRUE;
-	 breakpoints[num].type    = type;
-	 breakpoints[num].skipcount = 0;
-	 breakpoints[num].addr = *addr;
-	 breakpoints[num].is32 = 1;
-#ifdef __i386__
-	 if (addr->seg) 
-	 {
-	    switch (DEBUG_GetSelectorType( addr->seg )) 
-	    {
-	       case 32: break;
-	       case 16: breakpoints[num].is32 = 0; break;
-	       default: RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
-	    }
-	 }
-#endif
-	 return num;
+          breakpoints[num].refcount = 1;
+          breakpoints[num].enabled = TRUE;
+          breakpoints[num].type    = type;
+          breakpoints[num].skipcount = 0;
+          breakpoints[num].addr = *addr;
+          switch (DEBUG_GetSelectorType( addr->seg ))
+          {
+          case MODE_32:
+              breakpoints[num].is32 = 1;
+              break;
+          case MODE_VM86:
+          case MODE_16:
+              breakpoints[num].is32 = 0;
+              break;
+          default:
+              RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
+          }
+          return num;
       }
    }
-   
+
    DEBUG_Printf( DBG_CHN_MESG, "Too many breakpoints. Please delete some.\n" );
    return -1;
 }
@@ -360,7 +360,7 @@
     breakpoints[num].u.b.func = func;
 
     DEBUG_Printf( DBG_CHN_MESG, "Breakpoint %d at ", num );
-    DEBUG_PrintAddress( &breakpoints[num].addr, breakpoints[num].is32 ? 32 : 16,
+    DEBUG_PrintAddress( &breakpoints[num].addr, breakpoints[num].is32 ? MODE_32 : MODE_16,
 			TRUE );
     DEBUG_Printf( DBG_CHN_MESG, "\n" );
 }
@@ -472,7 +472,7 @@
       breakpoints[reg].u.w.reg = reg;
    
       DEBUG_Printf( DBG_CHN_MESG, "Watchpoint %d at ", num );
-      DEBUG_PrintAddress( &breakpoints[num].addr, breakpoints[num].is32 ? 32:16, TRUE );
+      DEBUG_PrintAddress( &breakpoints[num].addr, breakpoints[num].is32 ? MODE_32 : MODE_16, TRUE );
       DEBUG_Printf( DBG_CHN_MESG, "\n" );
    }
 }
@@ -623,7 +623,7 @@
         {
             DEBUG_Printf( DBG_CHN_MESG, "%d: %c ", i, breakpoints[i].enabled ? 'y' : 'n');
             DEBUG_PrintAddress( &breakpoints[i].addr, 
-				breakpoints[i].is32 ? 32 : 16, TRUE);
+				breakpoints[i].is32 ? MODE_32 : MODE_16, TRUE);
             DEBUG_Printf( DBG_CHN_MESG, " (%u)\n", breakpoints[i].refcount );
 	    if( breakpoints[i].condition != NULL )
 	    {
@@ -640,7 +640,7 @@
         {
             DEBUG_Printf( DBG_CHN_MESG, "%d: %c ", i, breakpoints[i].enabled ? 'y' : 'n');
             DEBUG_PrintAddress( &breakpoints[i].addr, 
-				breakpoints[i].is32 ? 32 : 16, TRUE);
+				breakpoints[i].is32 ? MODE_32 : MODE_16, TRUE);
             DEBUG_Printf( DBG_CHN_MESG, " on %d byte%s (%c)\n", 
 		     breakpoints[i].u.w.len + 1, 
 		     breakpoints[i].u.w.len > 0 ? "s" : "",
@@ -702,7 +702,7 @@
     int 	bpnum;
     DWORD	oldval;
     int 	wpnum;
-    int		addrlen = 32;
+    enum dbg_mode addr_mode;
     struct symbol_info syminfo;
 
 #ifdef __i386__
@@ -723,7 +723,7 @@
 
         DEBUG_Printf( DBG_CHN_MESG, "Stopped on breakpoint %d at ", bpnum );
         syminfo = DEBUG_PrintAddress( &breakpoints[bpnum].addr,
-				      breakpoints[bpnum].is32 ? 32 : 16, TRUE );
+				      breakpoints[bpnum].is32 ? MODE_32 : MODE_16, TRUE );
         DEBUG_Printf( DBG_CHN_MESG, "\n" );
 	
 	if( syminfo.list.sourcefile != NULL )
@@ -744,11 +744,9 @@
        }
        if (!DEBUG_ShallBreak(wpnum)) return TRUE;
        
-#ifdef __i386__
-       if (addr->seg) addrlen = DEBUG_GetSelectorType( addr->seg );
-#endif
+       addr_mode = DEBUG_GetSelectorType( addr->seg );
        DEBUG_Printf(DBG_CHN_MESG, "Stopped on watchpoint %d at ", wpnum);
-       syminfo = DEBUG_PrintAddress( addr, addrlen, TRUE );
+       syminfo = DEBUG_PrintAddress( addr, addr_mode, TRUE );
        
        DEBUG_Printf(DBG_CHN_MESG, " values: old=%lu new=%lu\n", 
 	       oldval, breakpoints[wpnum].u.w.oldval);
diff --git a/debugger/db_disasm.c b/debugger/db_disasm.c
index ff54791..0fc9212 100644
--- a/debugger/db_disasm.c
+++ b/debugger/db_disasm.c
@@ -1033,7 +1033,7 @@
     address.seg = 0;
     address.off = addr;
 
-    DEBUG_PrintAddress( &address, db_disasm_16 ? 16 : 32, TRUE );
+    DEBUG_PrintAddress( &address, db_disasm_16 ? MODE_16 : MODE_32, TRUE );
 }
 
 void db_print_address(char *seg, int size, struct i_addr *addrp, int byref)
@@ -1189,10 +1189,12 @@
 	 * Set this so we get can supress the printout if we need to.
 	 */
 	db_display = display;
-        switch (DEBUG_GetSelectorType(addr->seg)) {
-	case 16: db_disasm_16 = 1; break;
-	case 32: db_disasm_16 = 0; break;
-	default: DEBUG_Printf(DBG_CHN_MESG, "Bad selector %ld\n", addr->seg); return;
+        switch (DEBUG_GetSelectorType(addr->seg))
+        {
+        case MODE_VM86:
+	case MODE_16: db_disasm_16 = 1; break;
+	case MODE_32: db_disasm_16 = 0; break;
+	default: DEBUG_Printf(DBG_CHN_MESG, "Bad selector %lx\n", addr->seg); return;
 	}
 
 	get_value_inc( inst, addr, 1, FALSE );
@@ -1625,8 +1627,7 @@
                                        2, FALSE );
 			if( db_display )
 			  {
-			    DEBUG_PrintAddress( &address, short_addr ? 16 : 32, 
-						TRUE );
+			    DEBUG_PrintAddress( &address, short_addr ? MODE_16 : MODE_32, TRUE );
 			  }
 		      
                     }
diff --git a/debugger/dbg.y b/debugger/dbg.y
index 7acfbce..12a2ded 100644
--- a/debugger/dbg.y
+++ b/debugger/dbg.y
@@ -40,7 +40,7 @@
 }
 
 %token tCONT tPASS tSTEP tLIST tNEXT tQUIT tHELP tBACKTRACE tINFO tWALK tUP tDOWN
-%token tENABLE tDISABLE tBREAK tWATCH tDELETE tSET tMODE tPRINT tEXAM tABORT
+%token tENABLE tDISABLE tBREAK tWATCH tDELETE tSET tMODE tPRINT tEXAM tABORT tVM86
 %token tCLASS tMAPS tMODULE tSTACK tSEGMENTS tREGS tWND tQUEUE tLOCAL
 %token tPROCESS tTHREAD tMODREF tEOL
 %token tFRAME tSHARE tCOND tDISPLAY tUNDISPLAY tDISASSEMBLE
@@ -117,6 +117,7 @@
                                   DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_OVER; return TRUE; }
     | tABORT tEOL              	{ kill(getpid(), SIGABRT); }
     | tMODE tNUM tEOL          	{ mode_command($2); }
+    | tMODE tVM86 tEOL         	{ DEBUG_CurrThread->dbg_mode = MODE_VM86; }
     | tENABLE tNUM tEOL        	{ DEBUG_EnableBreakpoint( $2, TRUE ); }
     | tDISABLE tNUM tEOL       	{ DEBUG_EnableBreakpoint( $2, FALSE ); }
     | tDELETE tBREAK tNUM tEOL 	{ DEBUG_DelBreakpoint( $3 ); }
@@ -346,8 +347,12 @@
 
 static void mode_command(int newmode)
 {
-    if ((newmode == 16) || (newmode == 32)) DEBUG_CurrThread->dbg_mode = newmode;
-    else DEBUG_Printf(DBG_CHN_MESG,"Invalid mode (use 16 or 32)\n");
+    switch(newmode)
+    {
+    case 16: DEBUG_CurrThread->dbg_mode = MODE_16; break;
+    case 32: DEBUG_CurrThread->dbg_mode = MODE_32; break;
+    default: DEBUG_Printf(DBG_CHN_MESG,"Invalid mode (use 16, 32 or vm86)\n");
+    }
 }
 
 void DEBUG_Exit(DWORD ec)
diff --git a/debugger/debug.l b/debugger/debug.l
index cb8dc64..855f5e2 100644
--- a/debugger/debug.l
+++ b/debugger/debug.l
@@ -41,6 +41,7 @@
 %s DEL_CMD
 %s WALK_CMD
 %s SHOW_CMD
+%s MODE_CMD
 %s NOCMD
 
 %x ASTRING_EXPECTED
@@ -111,7 +112,7 @@
 <INITIAL>abort|abor|abo         	{ BEGIN(NOCMD); return tABORT; }
 <INITIAL>print|prin|pri|pr|p		{ BEGIN(FORMAT_EXPECTED); return tPRINT; }
 
-<INITIAL>mode				{ BEGIN(NOCMD); return tMODE; }
+<INITIAL>mode				{ BEGIN(MODE_CMD); return tMODE; }
 <INITIAL>show|sho|sh			{ BEGIN(SHOW_CMD); return tSHOW; }
 <INITIAL>symbolfile|symbols|symbol|sf   { BEGIN(PATH_EXPECTED); return tSYMBOLFILE; }
 
@@ -134,6 +135,7 @@
 <INFO_CMD>maps|map			{ return tMAPS; }
 <INFO_CMD,WALK_CMD>window|windo|wind|win|wnd	{ return tWND; }
 <HELP_CMD>info|inf|in                   { return tINFO; }
+<MODE_CMD>vm86                          { return tVM86; }
 
 <INITIAL,SHOW_CMD>directories|directorie|directori|director|directo|direct|direc|direc|dir { 
 			                  BEGIN(PATH_EXPECTED); return tDIR; }
diff --git a/debugger/debugger.h b/debugger/debugger.h
index b5c021e..bf860a7 100644
--- a/debugger/debugger.h
+++ b/debugger/debugger.h
@@ -144,6 +144,11 @@
     struct expr * condition;
 } DBG_BREAKPOINT;
 
+enum dbg_mode
+{
+    MODE_INVALID, MODE_16, MODE_32, MODE_VM86
+};
+
 typedef struct tagDBG_THREAD {
     struct tagDBG_PROCESS*	process;
     HANDLE			handle;
@@ -151,7 +156,7 @@
     LPVOID			start;
     LPVOID			teb;
     int				wait_for_first_exception;
-    int				dbg_mode;
+    enum dbg_mode		dbg_mode;
     enum exec_mode 		dbg_exec_mode;
     int 			dbg_exec_count;
     DBG_BREAKPOINT		stepOverBP;
@@ -326,12 +331,11 @@
 
   /* debugger/info.c */
 extern void DEBUG_PrintBasic( const DBG_VALUE* value, int count, char format );
-extern struct symbol_info DEBUG_PrintAddress( const DBG_ADDR *addr, 
-					      int addrlen, int flag );
+extern struct symbol_info DEBUG_PrintAddress( const DBG_ADDR *addr, enum dbg_mode mode, int flag );
 extern void DEBUG_Help(void);
 extern void DEBUG_HelpInfo(void);
 extern struct symbol_info DEBUG_PrintAddressAndArgs( const DBG_ADDR *addr, 
-						     int addrlen, 
+						     enum dbg_mode mode,
 						     unsigned int ebp, 
 						     int flag );
 extern void DEBUG_InfoClass(const char* clsName);
@@ -357,10 +361,9 @@
 extern DWORD DEBUG_ToLinear( const DBG_ADDR *address );
 extern void DEBUG_GetCurrentAddress( DBG_ADDR * );
 extern BOOL DEBUG_GrabAddress( DBG_VALUE* value, BOOL fromCode );
+extern enum dbg_mode DEBUG_GetSelectorType( WORD sel );
 #ifdef __i386__
 extern void DEBUG_FixAddress( DBG_ADDR *address, DWORD def );
-extern BOOL DEBUG_FixSegment( DBG_ADDR* addr );
-extern int  DEBUG_GetSelectorType( WORD sel );
 extern int  DEBUG_IsSelectorSystem( WORD sel );
 #endif
 
diff --git a/debugger/expr.c b/debugger/expr.c
index 29262ef..7466dc8 100644
--- a/debugger/expr.c
+++ b/debugger/expr.c
@@ -513,9 +513,6 @@
 	  rtn.type = NULL;
 	  rtn.addr.seg = VAL(exp1);
 	  rtn.addr.off = VAL(exp2);
-#ifdef __i386__
-	  DEBUG_FixSegment(&rtn.addr);
-#endif
 	  break;
 	case EXP_OP_LOR:
 	  exp->un.binop.result = (VAL(exp1) || VAL(exp2));
diff --git a/debugger/info.c b/debugger/info.c
index 2df7ac8..f11f68e 100644
--- a/debugger/info.c
+++ b/debugger/info.c
@@ -120,7 +120,7 @@
  * Print an 16- or 32-bit address, with the nearest symbol if any.
  */
 struct symbol_info
-DEBUG_PrintAddress( const DBG_ADDR *addr, int addrlen, int flag )
+DEBUG_PrintAddress( const DBG_ADDR *addr, enum dbg_mode mode, int flag )
 {
     struct symbol_info rtn;
 
@@ -128,7 +128,7 @@
 						&rtn.list );
 
     if (addr->seg) DEBUG_Printf( DBG_CHN_MESG, "0x%04lx:", addr->seg&0xFFFF );
-    if (addrlen == 16) DEBUG_Printf( DBG_CHN_MESG, "0x%04lx", addr->off );
+    if (mode != MODE_32) DEBUG_Printf( DBG_CHN_MESG, "0x%04lx", addr->off );
     else DEBUG_Printf( DBG_CHN_MESG, "0x%08lx", addr->off );
     if (name) DEBUG_Printf( DBG_CHN_MESG, " (%s)", name );
     return rtn;
@@ -141,7 +141,7 @@
  * each function (if known).  This is useful in a backtrace.
  */
 struct symbol_info
-DEBUG_PrintAddressAndArgs( const DBG_ADDR *addr, int addrlen, 
+DEBUG_PrintAddressAndArgs( const DBG_ADDR *addr, enum dbg_mode mode,
 			   unsigned int ebp, int flag )
 {
     struct symbol_info rtn;
@@ -150,7 +150,7 @@
 						&rtn.list );
 
     if (addr->seg) DEBUG_Printf( DBG_CHN_MESG, "0x%04lx:", addr->seg );
-    if (addrlen == 16) DEBUG_Printf( DBG_CHN_MESG, "0x%04lx", addr->off );
+    if (mode != MODE_32) DEBUG_Printf( DBG_CHN_MESG, "0x%04lx", addr->off );
     else DEBUG_Printf( DBG_CHN_MESG, "0x%08lx", addr->off );
     if (name) DEBUG_Printf( DBG_CHN_MESG, " (%s)", name );
 
@@ -186,7 +186,7 @@
 "  show dir                               dir <path>",
 "  display <expr>                         undisplay <disnum>",
 "  delete display <disnum>                debugmsg <class>[-+]<type>\n",
-"  mode [16,32]                           walk [wnd,class,queue,module,",
+"  mode [16,32,vm86]                      walk [wnd,class,queue,module,",
 "  whatis                                       process,modref <pid>]",
 "  info (see 'help info' for options)\n",
 
diff --git a/debugger/memory.c b/debugger/memory.c
index 6f7083c..416788d 100644
--- a/debugger/memory.c
+++ b/debugger/memory.c
@@ -15,10 +15,7 @@
 #include "winbase.h"
 
 #ifdef __i386__
-#include "wine/winbase16.h"
-
-#define DBG_V86_MODULE(seg) ((seg)>>16)
-#define IS_SELECTOR_V86(seg) DBG_V86_MODULE(seg)
+#define IS_VM86_MODE() (DEBUG_context.EFlags & V86_FLAG)
 #endif
 
 static	void	DEBUG_Die(const char* msg)
@@ -52,41 +49,33 @@
    return res;
 }
 
+enum dbg_mode DEBUG_GetSelectorType( WORD sel )
+{
+#ifdef __i386__
+    LDT_ENTRY	le;
+
+    if (IS_VM86_MODE()) return MODE_VM86;
+    if (sel == 0) return MODE_32;
+    if (GetThreadSelectorEntry( DEBUG_CurrThread->handle, sel, &le)) 
+        return le.HighWord.Bits.Default_Big ? MODE_32 : MODE_16;
+    /* selector doesn't exist */
+    return MODE_INVALID;
+#else
+    return MODE_32;
+#endif
+}
 #ifdef __i386__
 void DEBUG_FixAddress( DBG_ADDR *addr, DWORD def) 
 {
    if (addr->seg == 0xffffffff) addr->seg = def;
-   if (!IS_SELECTOR_V86(addr->seg) && DEBUG_IsSelectorSystem(addr->seg)) addr->seg = 0;
-}
-
-BOOL  DEBUG_FixSegment( DBG_ADDR* addr )
-{
-   /* V86 mode ? */
-   if (DEBUG_context.EFlags & V86_FLAG) {
-      addr->seg |= (DWORD)(GetExePtr(GetCurrentTask())) << 16;
-      return TRUE;
-   }
-   return FALSE;
-}
-
-int	DEBUG_GetSelectorType( WORD sel )
-{
-    LDT_ENTRY	le;
-
-    if (sel == 0)
-        return 32;
-    if (IS_SELECTOR_V86(sel))
-        return 16;
-    if (GetThreadSelectorEntry( DEBUG_CurrThread->handle, sel, &le)) 
-        return le.HighWord.Bits.Default_Big ? 32 : 16;
-	 /* selector doesn't exist */
-    return 0;
+   if (DEBUG_IsSelectorSystem(addr->seg)) addr->seg = 0;
 }
 
 /* Determine if sel is a system selector (i.e. not managed by Wine) */
 BOOL	DEBUG_IsSelectorSystem(WORD sel)
 {
-   return !(sel & 4) || (((sel & 0xFFFF) >> 3) < 17);
+    if (IS_VM86_MODE()) return FALSE;  /* no system selectors in vm86 mode */
+    return !(sel & 4) || ((sel >> 3) < 17);
 }
 #endif /* __i386__ */
 
@@ -95,10 +84,8 @@
 #ifdef __i386__
    LDT_ENTRY	le;
    
-#if 0
-   if (IS_SELECTOR_V86(addr->seg))
-      return (DWORD) DOSMEM_MemoryBase(DBG_V86_MODULE(addr->seg)) + (((addr->seg)&0xFFFF)<<4) + addr->off;
-#endif
+   if (IS_VM86_MODE()) return (DWORD)(LOWORD(addr->seg) << 4) + addr->off;
+
    if (DEBUG_IsSelectorSystem(addr->seg))
       return addr->off;
    
@@ -116,7 +103,7 @@
 #ifdef __i386__
     addr->seg  = DEBUG_context.SegCs;
 
-    if (!DEBUG_FixSegment( addr ) && DEBUG_IsSelectorSystem(addr->seg)) 
+    if (DEBUG_IsSelectorSystem(addr->seg))
        addr->seg = 0;
     addr->off  = DEBUG_context.Eip;
 #elif defined(__sparc__)
diff --git a/debugger/registers.c b/debugger/registers.c
index 4ff5952..d5a2747 100644
--- a/debugger/registers.c
+++ b/debugger/registers.c
@@ -82,7 +82,7 @@
 		  (WORD)DEBUG_context.SegCs, (WORD)DEBUG_context.SegSs,
 		  (WORD)DEBUG_context.SegDs, (WORD)DEBUG_context.SegEs,
 		  (WORD)DEBUG_context.SegFs, (WORD)DEBUG_context.SegGs );
-    if (DEBUG_CurrThread->dbg_mode == 16)
+    if (DEBUG_CurrThread->dbg_mode != MODE_32)
     {
         char flag[33];
 
diff --git a/debugger/stack.c b/debugger/stack.c
index 0c59389..5cdff62 100644
--- a/debugger/stack.c
+++ b/debugger/stack.c
@@ -63,11 +63,13 @@
     value.addr.off = DEBUG_context.Esp;
 
     DEBUG_Printf(DBG_CHN_MESG,"Stack dump:\n");
-    switch (DEBUG_GetSelectorType(value.addr.seg)) {
-    case 32: /* 32-bit mode */
+    switch (DEBUG_GetSelectorType(value.addr.seg))
+    {
+    case MODE_32: /* 32-bit mode */
        DEBUG_ExamineMemory( &value, 24, 'x' );
        break;
-    case 16:  /* 16-bit mode */
+    case MODE_16:  /* 16-bit mode */
+    case MODE_VM86:
         value.addr.off &= 0xffff;
         DEBUG_ExamineMemory( &value, 24, 'w' );
 	break;
@@ -79,7 +81,8 @@
 }
 
 #ifdef __i386__
-static void DEBUG_ForceFrame(DBG_ADDR *stack, DBG_ADDR *code, int frameno, int bits, int noisy, const char *caveat)
+static void DEBUG_ForceFrame(DBG_ADDR *stack, DBG_ADDR *code, int frameno, enum dbg_mode mode,
+                             int noisy, const char *caveat)
 {
     int theframe = nframe++;
     frames = (struct bt_info *)DBG_realloc(frames,
@@ -90,8 +93,7 @@
     frames[theframe].cs = code->seg;
     frames[theframe].eip = code->off;
     if (noisy)
-      frames[theframe].frame = DEBUG_PrintAddressAndArgs( code, bits, 
-							  stack->off, TRUE );
+        frames[theframe].frame = DEBUG_PrintAddressAndArgs( code, mode, stack->off, TRUE );
     else
       DEBUG_FindNearestSymbol( code, TRUE, 
 			       &frames[theframe].frame.sym, stack->off, 
@@ -99,7 +101,8 @@
     frames[theframe].ss = stack->seg;
     frames[theframe].ebp = stack->off;
     if (noisy) {
-      DEBUG_Printf( DBG_CHN_MESG, (bits == 16) ? " (bp=%04lx%s)\n" : " (ebp=%08lx%s)\n", stack->off, caveat?caveat:"" );
+      DEBUG_Printf( DBG_CHN_MESG, (mode != MODE_32) ? " (bp=%04lx%s)\n" : " (ebp=%08lx%s)\n",
+                    stack->off, caveat?caveat:"" );
     }
 }
 
@@ -136,7 +139,8 @@
     code.seg = *cs;
     code.off = frame.ip;
     addr->off = frame.bp & ~1;
-    DEBUG_ForceFrame(addr, &code, frameno, 16, noisy, possible_cs ? ", far call assumed" : NULL );
+    DEBUG_ForceFrame(addr, &code, frameno, MODE_16, noisy,
+                     possible_cs ? ", far call assumed" : NULL );
     return TRUE;
 }
 
@@ -158,7 +162,7 @@
     code.seg = *cs;
     code.off = frame.ip;
     addr->off = frame.bp;
-    DEBUG_ForceFrame(addr, &code, frameno, 32, noisy, NULL);
+    DEBUG_ForceFrame(addr, &code, frameno, MODE_32, noisy, NULL);
     if (addr->off == old_bp) return FALSE;
     return TRUE;
 }
@@ -195,12 +199,12 @@
     /* first stack frame from registers */
     switch (DEBUG_GetSelectorType(ss))
     {
-    case 32:
+    case MODE_32:
         code.seg = cs;
         code.off = DEBUG_context.Eip;
         addr.seg = ss;
 	addr.off = DEBUG_context.Ebp;
-        DEBUG_ForceFrame( &addr, &code, frameno, 32, noisy, NULL );
+        DEBUG_ForceFrame( &addr, &code, frameno, MODE_32, noisy, NULL );
         if (!(code.seg || code.off)) {
             /* trying to execute a null pointer... yuck...
              * if it was a call to null, the return EIP should be
@@ -208,21 +212,22 @@
             tmp.seg = ss;
             tmp.off = DEBUG_context.Esp;
             if (DEBUG_READ_MEM((void *)DEBUG_ToLinear(&tmp), &code.off, sizeof(code.off))) {
-                DEBUG_ForceFrame( &addr, &code, ++frameno, 32, noisy, ", null call assumed" );
+                DEBUG_ForceFrame( &addr, &code, ++frameno, MODE_32, noisy, ", null call assumed" );
             }
         }
         is16 = FALSE;
 	break;
-    case 16:
+    case MODE_16:
+    case MODE_VM86:
         code.seg = cs;
         code.off = LOWORD(DEBUG_context.Eip);
         addr.seg = ss;
 	addr.off = LOWORD(DEBUG_context.Ebp);
-        DEBUG_ForceFrame( &addr, &code, frameno, 16, noisy, NULL );
+        DEBUG_ForceFrame( &addr, &code, frameno, MODE_16, noisy, NULL );
         is16 = TRUE;
 	break;
     default:
-        if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Bad segment '%u'\n", ss);
+        if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Bad segment '%x'\n", ss);
 	return;
     }
 
@@ -282,7 +287,7 @@
 	       cs = 0;
 	       addr.seg = 0;
 	       addr.off = frame32.ebp;
-	       DEBUG_ForceFrame( &addr, &code, ++frameno, 32, noisy, NULL );
+	       DEBUG_ForceFrame( &addr, &code, ++frameno, MODE_32, noisy, NULL );
 	       
 	       next_switch = cur_switch;
 	       tmp.seg = SELECTOROF(next_switch);
@@ -316,7 +321,7 @@
 	      cs = frame16.cs;
 	      addr.seg = SELECTOROF(next_switch);
 	      addr.off = frame16.bp;
-	      DEBUG_ForceFrame( &addr, &code, ++frameno, 16, noisy, NULL );
+	      DEBUG_ForceFrame( &addr, &code, ++frameno, MODE_16, noisy, NULL );
 	      
 	      next_switch = cur_switch;
 	      if (!DEBUG_READ_MEM((void*)next_switch, &frame32, sizeof(STACK32FRAME))) {
diff --git a/debugger/winedbg.c b/debugger/winedbg.c
index 1b78279..45dde5c 100644
--- a/debugger/winedbg.c
+++ b/debugger/winedbg.c
@@ -282,15 +282,24 @@
     DEBUG_SuspendExecution();
 
     if (!is_debug) {
-#ifdef __i386__
-        if (DEBUG_IsSelectorSystem(DEBUG_context.SegCs))
+        if (!addr.seg)
             DEBUG_Printf(DBG_CHN_MESG, " in 32-bit code (0x%08lx).\n", addr.off);
         else
-            DEBUG_Printf(DBG_CHN_MESG, " in 16-bit code (%04x:%04lx).\n",
-			 LOWORD(addr.seg), addr.off);
-#else
-        DEBUG_Printf(DBG_CHN_MESG, " (0x%08lx).\n", addr.off);
-#endif
+            switch(DEBUG_GetSelectorType(addr.seg))
+            {
+            case MODE_32:
+                DEBUG_Printf(DBG_CHN_MESG, " in 32-bit code (%04lx:%08lx).\n", addr.seg, addr.off);
+                break;
+            case MODE_16:
+                DEBUG_Printf(DBG_CHN_MESG, " in 16-bit code (%04lx:%04lx).\n", addr.seg, addr.off);
+                break;
+            case MODE_VM86:
+                DEBUG_Printf(DBG_CHN_MESG, " in vm86 code (%04lx:%04lx).\n", addr.seg, addr.off);
+                break;
+            case MODE_INVALID:
+                DEBUG_Printf(DBG_CHN_MESG, "bad CS (%lx)\n", addr.seg);
+                break;
+        }
     }
 
     DEBUG_LoadEntryPoints("Loading new modules symbols:\n");
@@ -302,16 +311,13 @@
 			     &DEBUG_CurrThread->dbg_exec_count))
 	return FALSE;
 
-#ifdef __i386__
-    switch (newmode = DEBUG_GetSelectorType(addr.seg)) {
-    case 16: case 32: break;
-    default: DEBUG_Printf(DBG_CHN_MESG, "Bad CS (%ld)\n", addr.seg); newmode = 32;
-    }
-#else
-    newmode = 32;
-#endif
+    if ((newmode = DEBUG_GetSelectorType(addr.seg)) == MODE_INVALID) newmode = MODE_32;
     if (newmode != DEBUG_CurrThread->dbg_mode)
-	DEBUG_Printf(DBG_CHN_MESG,"In %d bit mode.\n", DEBUG_CurrThread->dbg_mode = newmode);
+    {
+        static const char * const names[] = { "???", "16-bit", "32-bit", "vm86" };
+        DEBUG_Printf(DBG_CHN_MESG,"In %s mode.\n", names[newmode] );
+        DEBUG_CurrThread->dbg_mode = newmode;
+    }
 
     DEBUG_DoDisplay();
 
@@ -326,7 +332,7 @@
 	DEBUG_InfoRegisters();
 	DEBUG_InfoStack();
 #ifdef __i386__
-	if (DEBUG_CurrThread->dbg_mode == 16) {
+	if (DEBUG_CurrThread->dbg_mode == MODE_16) {
 	    DEBUG_InfoSegments(DEBUG_context.SegDs >> 3, 1);
 	    if (DEBUG_context.SegEs != DEBUG_context.SegDs)
 		DEBUG_InfoSegments(DEBUG_context.SegEs >> 3, 1);
@@ -374,7 +380,6 @@
     BOOL	ret = TRUE;
 
     *cont = DBG_CONTINUE;
-    if (first_chance && !force && !DBG_IVAR(BreakOnFirstChance)) return TRUE;
 
     switch (rec->ExceptionCode)
     {
@@ -384,6 +389,13 @@
         break;
     }
 
+    if (first_chance && !force && !DBG_IVAR(BreakOnFirstChance))
+    {
+        /* pass exception to program except for debug exceptions */
+        *cont = is_debug ? DBG_CONTINUE : DBG_EXCEPTION_NOT_HANDLED;
+        return TRUE;
+    }
+
     if (!is_debug)
     {
         /* print some infos */
@@ -432,6 +444,16 @@
 		return TRUE;
 	    }
             break;
+        case EXCEPTION_VM86_INTx:
+            DEBUG_Printf(DBG_CHN_MESG, "interrupt %02lx in vm86 mode",
+                         rec->ExceptionInformation[0]);
+            break;
+        case EXCEPTION_VM86_STI:
+            DEBUG_Printf(DBG_CHN_MESG, "sti in vm86 mode");
+            break;
+        case EXCEPTION_VM86_PICRETURN:
+            DEBUG_Printf(DBG_CHN_MESG, "PIC return in vm86 mode");
+            break;
         default:
             DEBUG_Printf(DBG_CHN_MESG, "%08lx", rec->ExceptionCode);
             break;
@@ -728,7 +750,7 @@
     DWORD		cont;
     BOOL		ret;
 
-    DEBUG_Printf(DBG_CHN_MESG, " on pid %ld\n", DEBUG_CurrPid);
+    DEBUG_Printf(DBG_CHN_MESG, " on pid %lx\n", DEBUG_CurrPid);
     
     for (ret = TRUE; ret; ) {
 	/* wait until we get at least one loaded process */
@@ -741,7 +763,7 @@
 	}
     };
     
-    DEBUG_Printf(DBG_CHN_MESG, "WineDbg terminated on pid %ld\n", DEBUG_CurrPid);
+    DEBUG_Printf(DBG_CHN_MESG, "WineDbg terminated on pid %lx\n", DEBUG_CurrPid);
 
     return 0;
 }