winedbg: Add display for floating point status.
authorJeff Latimer <lats@yless4u.com.au>
Tue, 21 Mar 2006 12:54:41 +0000 (23:54 +1100)
committerAlexandre Julliard <julliard@winehq.org>
Tue, 21 Mar 2006 15:30:47 +0000 (16:30 +0100)
Added code to examine and display floating point unit status into
be_i386.c as info all-regs command.

programs/winedbg/be_alpha.c
programs/winedbg/be_cpu.h
programs/winedbg/be_i386.c
programs/winedbg/be_ppc.c
programs/winedbg/dbg.y
programs/winedbg/debug.l
programs/winedbg/info.c
programs/winedbg/tgt_active.c
programs/winedbg/tgt_minidump.c
programs/winedbg/winedbg.man.in

index 221fd46..748e070 100644 (file)
@@ -34,7 +34,7 @@ static void be_alpha_single_step(CONTEXT* ctx, unsigned enable)
     dbg_printf("not done\n");
 }
 
-static void be_alpha_print_context(HANDLE hThread, const CONTEXT* ctx)
+static void be_alpha_print_context(HANDLE hThread, const CONTEXT* ctx, int all_regs)
 {
     dbg_printf("Context printing for Alpha not done yet\n");
 }
index 988a147..59333be 100644 (file)
@@ -49,7 +49,7 @@ struct backend_cpu
     /* Enables/disables CPU single step mode (depending on enable) */
     void                (*single_step)(CONTEXT* ctx, unsigned enable);
     /* Dumps out the content of the context */
-    void                (*print_context)(HANDLE hThread, const CONTEXT* ctx);
+    void                (*print_context)(HANDLE hThread, const CONTEXT* ctx, int all_regs);
     /* Prints information about segments. Non segmented CPU should leave this
      * function empty
      */
index 3f0fb6a..0b838f1 100644 (file)
@@ -116,7 +116,74 @@ static void be_i386_single_step(CONTEXT* ctx, unsigned enable)
     else ctx->EFlags &= ~STEP_FLAG;
 }
 
-static void be_i386_print_context(HANDLE hThread, const CONTEXT* ctx)
+static void be_i386_all_print_context(HANDLE hThread, const CONTEXT* ctx)
+{
+    long double ST[8];                         /* These are for floating regs */
+    int         cnt;
+
+    /* Break out the FPU state and the floating point registers    */
+    dbg_printf("Floating Point Unit status:\n");
+    dbg_printf(" FLCW:%04x ", LOWORD(ctx->FloatSave.ControlWord));
+    dbg_printf(" FLTW:%04x ", LOWORD(ctx->FloatSave.TagWord));
+    dbg_printf(" FLEO:%08x ", (unsigned int) ctx->FloatSave.ErrorOffset);
+    dbg_printf(" FLSW:%04x", LOWORD(ctx->FloatSave.StatusWord));
+
+    /* Isolate the condition code bits - note they are not contiguous */
+    dbg_printf("(CC:%ld%ld%ld%ld", (ctx->FloatSave.StatusWord & 0x00004000) >> 14, 
+                                   (ctx->FloatSave.StatusWord & 0x00000400) >> 10,
+                                   (ctx->FloatSave.StatusWord & 0x00000200) >> 9,
+                                   (ctx->FloatSave.StatusWord & 0x00000100) >> 8);
+
+    /* Now pull out hte 3 bit of the TOP stack pointer */
+    dbg_printf(" TOP:%01x", (unsigned int) (ctx->FloatSave.StatusWord & 0x00003800) >> 11);
+
+    /* Lets analyse the error bits and indicate the status  
+     * the Invalid Op flag has sub status which is tested as follows */
+    if (ctx->FloatSave.StatusWord & 0x00000001) {     /* Invalid Fl OP   */
+       if (ctx->FloatSave.StatusWord & 0x00000040) {  /* Stack Fault     */
+          if (ctx->FloatSave.StatusWord & 0x00000200) /* C1 says Overflow */
+             dbg_printf(" #IE(Stack Overflow)");      
+          else
+             dbg_printf(" #IE(Stack Underflow)");     /* Underflow */
+       }
+       else  dbg_printf(" #IE(Arthimetic error)");    /* Invalid Fl OP   */
+    }
+
+    if (ctx->FloatSave.StatusWord & 0x00000002) dbg_printf(" #DE"); /* Denormalised OP */
+    if (ctx->FloatSave.StatusWord & 0x00000004) dbg_printf(" #ZE"); /* Zero Divide     */
+    if (ctx->FloatSave.StatusWord & 0x00000008) dbg_printf(" #OE"); /* Overflow        */
+    if (ctx->FloatSave.StatusWord & 0x00000010) dbg_printf(" #UE"); /* Underflow       */
+    if (ctx->FloatSave.StatusWord & 0x00000020) dbg_printf(" #PE"); /* Precision error */
+    if (ctx->FloatSave.StatusWord & 0x00000040)
+       if (!(ctx->FloatSave.StatusWord & 0x00000001))
+           dbg_printf(" #SE");                 /* Stack Fault (don't think this can occur) */
+    if (ctx->FloatSave.StatusWord & 0x00000080) dbg_printf(" #ES"); /* Error Summary   */
+    if (ctx->FloatSave.StatusWord & 0x00008000) dbg_printf(" #FB"); /* FPU Busy        */
+    dbg_printf(")\n");
+    
+    /* Here are the rest of the registers */
+    dbg_printf(" FLES:%08x ", (unsigned int) ctx->FloatSave.ErrorSelector);
+    dbg_printf(" FLDO:%08x ", (unsigned int) ctx->FloatSave.DataOffset);
+    dbg_printf(" FLDS:%08x ", (unsigned int) ctx->FloatSave.DataSelector);
+    dbg_printf(" FLCNS:%08x \n", (unsigned int) ctx->FloatSave.Cr0NpxState);
+
+    /* Now for the floating point registers */
+    dbg_printf("Floating Point Registers:\n");
+    for (cnt = 0; cnt < 4; cnt++) 
+    {
+        memcpy(&ST[cnt], &ctx->FloatSave.RegisterArea[cnt * 10], 10);
+        dbg_printf(" ST%d:%Lf ", cnt, ST[cnt]);
+    }
+    dbg_printf("\n");
+    for (cnt = 4; cnt < 8; cnt++) 
+    {
+        memcpy(&ST[cnt], &ctx->FloatSave.RegisterArea[cnt * 10], 10);
+        dbg_printf(" ST%d:%Lf ", cnt, ST[cnt]);
+    }
+    dbg_printf("\n");
+}
+
+static void be_i386_print_context(HANDLE hThread, const CONTEXT* ctx, int all_regs)
 {
     char        buf[33];
     char*       pt;
@@ -173,6 +240,9 @@ static void be_i386_print_context(HANDLE hThread, const CONTEXT* ctx)
                    ctx->Esi, ctx->Edi);
         break;
     }
+
+    if (all_regs) be_i386_all_print_context(hThread, ctx); /* print floating regs */
+
 }
 
 static void be_i386_print_segment_info(HANDLE hThread, const CONTEXT* ctx)
index 2ea7164..ea1653d 100644 (file)
@@ -47,7 +47,7 @@ static void be_ppc_single_step(CONTEXT* ctx, unsigned enable)
     else ctx->Msr &= ~MSR_SE;
 }
 
-static void be_ppc_print_context(HANDLE hThread, const CONTEXT* ctx)
+static void be_ppc_print_context(HANDLE hThread, const CONTEXT* ctx, int all_regs)
 {
     dbg_printf("Context printing for PPC not done yet\n");
 }
index 66145ee..ecbb3fa 100644 (file)
@@ -52,7 +52,7 @@ int yyerror(const char*);
 %token tCONT tPASS tSTEP tLIST tNEXT tQUIT tHELP tBACKTRACE tALL tINFO tUP tDOWN
 %token tENABLE tDISABLE tBREAK tHBREAK tWATCH tDELETE tSET tMODE tPRINT tEXAM
 %token tABORT tVM86 tECHO
-%token tCLASS tMAPS tSTACK tSEGMENTS tSYMBOL tREGS tWND tQUEUE tLOCAL tEXCEPTION
+%token tCLASS tMAPS tSTACK tSEGMENTS tSYMBOL tREGS tALLREGS tWND tQUEUE tLOCAL tEXCEPTION
 %token tPROCESS tTHREAD tMODREF tEOL tEOF
 %token tFRAME tSHARE tCOND tDISPLAY tUNDISPLAY tDISASSEMBLE
 %token tSTEPI tNEXTI tFINISH tSHOW tDIR tWHATIS tSOURCE
@@ -256,7 +256,8 @@ info_command:
       tINFO tBREAK              { break_info(); }
     | tINFO tSHARE                     { info_win32_module(0); }
     | tINFO tSHARE expr_rvalue  { info_win32_module($3); }
-    | tINFO tREGS               { be_cpu->print_context(dbg_curr_thread->handle, &dbg_context); }
+    | tINFO tREGS               { be_cpu->print_context(dbg_curr_thread->handle, &dbg_context, 0); }
+    | tINFO tALLREGS            { be_cpu->print_context(dbg_curr_thread->handle, &dbg_context, 1); }
     | tINFO tSEGMENTS expr_rvalue { info_win32_segments($3 >> 3, 1); }
     | tINFO tSEGMENTS           { info_win32_segments(0, -1); }
     | tINFO tSTACK              { stack_info(); }
index 71d10f0..dd18a89 100644 (file)
@@ -189,6 +189,8 @@ STRING     \"[^\n"]+\"
 <INFO_CMD>threads|thread|threa|thre|thr|th { return tTHREAD; }
 <INFO_CMD>exception|except|exc|ex      { return tEXCEPTION; }
 <INFO_CMD>registers|regs|reg|re                { return tREGS; }
+<INFO_CMD>allregs|allreg|allre          { return tALLREGS; }
+<INFO_CMD>"all-registers"|"all-regs"|"all-reg"|"all-re" { return tALLREGS; }
 <INFO_CMD>segments|segment|segm|seg|se { return tSEGMENTS; }
 <INFO_CMD>stack|stac|sta|st            { return tSTACK; }
 <INFO_CMD>symbol|symbo|symb|sym         { BEGIN(ASTRING_EXPECTED); return tSYMBOL; }
index c58b3e7..7799af8 100644 (file)
@@ -101,7 +101,8 @@ void info_help(void)
             "  info locals          Displays values of all local vars for current frame",
             "  info maps <pid>      Shows virtual mappings (in a given process)",
             "  info process         Shows all running processes",
-            "  info reg             Displays values in all registers at top of stack",
+            "  info reg             Displays values of the general registers at top of stack",
+            "  info all-reg         Displays the general and floating point registers",
             "  info segments <pid>  Displays information about all known segments",
             "  info share           Displays all loaded modules",
             "  info share <addr>    Displays internal module state",
index 7c83d85..cdd50ad 100644 (file)
@@ -171,7 +171,7 @@ static unsigned dbg_exception_prolog(BOOL is_debug, const EXCEPTION_RECORD* rec)
     if (!is_debug)
     {
        /* This is a real crash, dump some info */
-       be_cpu->print_context(dbg_curr_thread->handle, &dbg_context);
+       be_cpu->print_context(dbg_curr_thread->handle, &dbg_context, 0);
        stack_info();
         be_cpu->print_segment_info(dbg_curr_thread->handle, &dbg_context);
        stack_backtrace(dbg_curr_tid);
index 750efe4..d067470 100644 (file)
@@ -348,7 +348,7 @@ static enum dbg_start minidump_do_reload(struct tgt_process_minidump_data* data)
                    min(sizeof(dbg_context), mes->ThreadContext.DataSize));
             memory_get_current_pc(&addr);
             stack_fetch_frames();
-            be_cpu->print_context(dbg_curr_thread->handle, &dbg_context);
+            be_cpu->print_context(dbg_curr_thread->handle, &dbg_context, 0);
             stack_info();
             be_cpu->print_segment_info(dbg_curr_thread->handle, &dbg_context);
             stack_backtrace(mes->ThreadId);
index a064b5c..c9922c7 100644 (file)
@@ -348,6 +348,8 @@ Lists all the dynamic libraries loaded in the debugged program
 Prints information on module at address \fBN\fR
 .IP \fBinfo\ regs\fR
 Prints the value of the CPU registers
+.IP \fBinfo\ all-regs\fR
+Prints the value of the CPU and Floating Point registers
 .IP \fBinfo\ segment\fR
 Lists all allocated segments (i386 only)
 .IP \fBinfo\ segment\ N\fR