ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

cpu_i386.c
Go to the documentation of this file.
00001 /*
00002  * File cpu_i386.c
00003  *
00004  * Copyright (C) 2009-2009, Eric Pouech.
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 
00021 #include <assert.h>
00022 
00023 #include "ntstatus.h"
00024 #define WIN32_NO_STATUS
00025 #include "dbghelp_private.h"
00026 #include "wine/winbase16.h"
00027 #include "winternl.h"
00028 #include "wine/debug.h"
00029 
00030 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
00031 
00032 #define STEP_FLAG 0x00000100 /* single step flag */
00033 #define V86_FLAG  0x00020000
00034 
00035 #define IS_VM86_MODE(ctx) (ctx->EFlags & V86_FLAG)
00036 
00037 #ifdef __i386__
00038 static ADDRESS_MODE get_selector_type(HANDLE hThread, const CONTEXT* ctx, WORD sel)
00039 {
00040     LDT_ENTRY   le;
00041 
00042     if (IS_VM86_MODE(ctx)) return AddrModeReal;
00043     /* null or system selector */
00044     if (!(sel & 4) || ((sel >> 3) < 17)) return AddrModeFlat;
00045     if (hThread && GetThreadSelectorEntry(hThread, sel, &le))
00046         return le.HighWord.Bits.Default_Big ? AddrMode1632 : AddrMode1616;
00047     /* selector doesn't exist */
00048     return -1;
00049 }
00050 
00051 static unsigned i386_build_addr(HANDLE hThread, const CONTEXT* ctx, ADDRESS64* addr,
00052                                 unsigned seg, unsigned long offset)
00053 {
00054     addr->Mode    = AddrModeFlat;
00055     addr->Segment = seg;
00056     addr->Offset  = offset;
00057     if (seg)
00058     {
00059         switch (addr->Mode = get_selector_type(hThread, ctx, seg))
00060         {
00061         case AddrModeReal:
00062         case AddrMode1616:
00063             addr->Offset &= 0xffff;
00064             break;
00065         case AddrModeFlat:
00066         case AddrMode1632:
00067             break;
00068         default:
00069             return FALSE;
00070         }
00071     }
00072     return TRUE;
00073 }
00074 #endif
00075 
00076 static unsigned i386_get_addr(HANDLE hThread, const CONTEXT* ctx,
00077                               enum cpu_addr ca, ADDRESS64* addr)
00078 {
00079 #ifdef __i386__
00080     switch (ca)
00081     {
00082     case cpu_addr_pc:    return i386_build_addr(hThread, ctx, addr, ctx->SegCs, ctx->Eip);
00083     case cpu_addr_stack: return i386_build_addr(hThread, ctx, addr, ctx->SegSs, ctx->Esp);
00084     case cpu_addr_frame: return i386_build_addr(hThread, ctx, addr, ctx->SegSs, ctx->Ebp);
00085     }
00086 #endif
00087     return FALSE;
00088 }
00089 
00090 #ifdef __i386__
00091 /* fetch_next_frame32()
00092  *
00093  * modify (at least) context.{eip, esp, ebp} using unwind information
00094  * either out of debug info (dwarf, pdb), or simple stack unwind
00095  */
00096 static BOOL fetch_next_frame32(struct cpu_stack_walk* csw,
00097                                CONTEXT* context, DWORD_PTR curr_pc)
00098 {
00099     DWORD_PTR               xframe;
00100     struct pdb_cmd_pair     cpair[4];
00101     DWORD                   val32;
00102 
00103     if (dwarf2_virtual_unwind(csw, curr_pc, context, &xframe))
00104     {
00105         context->Esp = xframe;
00106         return TRUE;
00107     }
00108     cpair[0].name = "$ebp";      cpair[0].pvalue = &context->Ebp;
00109     cpair[1].name = "$esp";      cpair[1].pvalue = &context->Esp;
00110     cpair[2].name = "$eip";      cpair[2].pvalue = &context->Eip;
00111     cpair[3].name = NULL;        cpair[3].pvalue = NULL;
00112 
00113     if (!pdb_virtual_unwind(csw, curr_pc, context, cpair))
00114     {
00115         /* do a simple unwind using ebp
00116          * we assume a "regular" prologue in the function has been used
00117          */
00118         context->Esp = context->Ebp + 2 * sizeof(DWORD);
00119         if (!sw_read_mem(csw, context->Ebp + sizeof(DWORD), &val32, sizeof(DWORD)))
00120         {
00121             WARN("Cannot read new frame offset %p\n",
00122                  (void*)(DWORD_PTR)(context->Ebp + (int)sizeof(DWORD)));
00123             return FALSE;
00124         }
00125         context->Eip = val32;
00126         /* "pop up" previous EBP value */
00127         if (!sw_read_mem(csw, context->Ebp, &val32, sizeof(DWORD)))
00128             return FALSE;
00129         context->Ebp = val32;
00130     }
00131     return TRUE;
00132 }
00133 #endif
00134 
00135 enum st_mode {stm_start, stm_32bit, stm_16bit, stm_done};
00136 
00137 /* indexes in Reserved array */
00138 #define __CurrentModeCount      0
00139 #define __CurrentSwitch         1
00140 #define __NextSwitch            2
00141 
00142 #define curr_mode   (frame->Reserved[__CurrentModeCount] & 0x0F)
00143 #define curr_count  (frame->Reserved[__CurrentModeCount] >> 4)
00144 #define curr_switch (frame->Reserved[__CurrentSwitch])
00145 #define next_switch (frame->Reserved[__NextSwitch])
00146 
00147 #define set_curr_mode(m) {frame->Reserved[__CurrentModeCount] &= ~0x0F; frame->Reserved[__CurrentModeCount] |= (m & 0x0F);}
00148 #define inc_curr_count() (frame->Reserved[__CurrentModeCount] += 0x10)
00149 
00150 static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CONTEXT* context)
00151 {
00152     STACK32FRAME        frame32;
00153     STACK16FRAME        frame16;
00154     char                ch;
00155     ADDRESS64           tmp;
00156     DWORD               p;
00157     WORD                val16;
00158     DWORD               val32;
00159     BOOL                do_switch;
00160 #ifdef __i386__
00161     unsigned            deltapc;
00162     CONTEXT             _context;
00163 #endif
00164 
00165     /* sanity check */
00166     if (curr_mode >= stm_done) return FALSE;
00167 
00168     TRACE("Enter: PC=%s Frame=%s Return=%s Stack=%s Mode=%s Count=%s cSwitch=%p nSwitch=%p\n",
00169           wine_dbgstr_addr(&frame->AddrPC),
00170           wine_dbgstr_addr(&frame->AddrFrame),
00171           wine_dbgstr_addr(&frame->AddrReturn),
00172           wine_dbgstr_addr(&frame->AddrStack),
00173           curr_mode == stm_start ? "start" : (curr_mode == stm_16bit ? "16bit" : "32bit"),
00174           wine_dbgstr_longlong(curr_count),
00175           (void*)(DWORD_PTR)curr_switch, (void*)(DWORD_PTR)next_switch);
00176 
00177 #ifdef __i386__
00178     /* if we're at first call (which doesn't actually unwind, it just computes ReturnPC,
00179      * or if we're doing the first real unwind (count == 1), then we can directly use
00180      * eip. otherwise, eip is *after* the insn that actually made the call to
00181      * previous frame, so decrease eip by delta pc (1!) so that we're inside previous
00182      * insn.
00183      * Doing so, we ensure that the pc used for unwinding is always inside the function
00184      * we want to use for next frame
00185      */
00186     deltapc = curr_count <= 1 ? 0 : 1;
00187 
00188     if (!context)
00189     {
00190         /* setup a pseudo context for the rest of the code (esp. unwinding) */
00191         context = &_context;
00192         memset(context, 0, sizeof(*context));
00193         context->ContextFlags = CONTEXT_CONTROL | CONTEXT_SEGMENTS;
00194         if (frame->AddrPC.Mode != AddrModeFlat)    context->SegCs = frame->AddrPC.Segment;
00195         context->Eip = frame->AddrPC.Offset;
00196         if (frame->AddrFrame.Mode != AddrModeFlat) context->SegSs = frame->AddrFrame.Segment;
00197         context->Ebp = frame->AddrFrame.Offset;
00198         if (frame->AddrStack.Mode != AddrModeFlat) context->SegSs = frame->AddrStack.Segment;
00199         context->Esp = frame->AddrStack.Offset;
00200     }
00201 #endif
00202     if (curr_mode == stm_start)
00203     {
00204         THREAD_BASIC_INFORMATION info;
00205 
00206         if ((frame->AddrPC.Mode == AddrModeFlat) &&
00207             (frame->AddrFrame.Mode != AddrModeFlat))
00208         {
00209             WARN("Bad AddrPC.Mode / AddrFrame.Mode combination\n");
00210             goto done_err;
00211         }
00212 
00213         /* Init done */
00214         set_curr_mode((frame->AddrPC.Mode == AddrModeFlat) ? stm_32bit : stm_16bit);
00215 
00216         /* cur_switch holds address of WOW32Reserved field in TEB in debuggee
00217          * address space
00218          */
00219         if (NtQueryInformationThread(csw->hThread, ThreadBasicInformation, &info,
00220                                      sizeof(info), NULL) == STATUS_SUCCESS)
00221         {
00222             curr_switch = (unsigned long)info.TebBaseAddress + FIELD_OFFSET(TEB, WOW32Reserved);
00223             if (!sw_read_mem(csw, curr_switch, &p, sizeof(p)))
00224             {
00225                 WARN("Can't read TEB:WOW32Reserved\n");
00226                 goto done_err;
00227             }
00228             next_switch = p;
00229             if (!next_switch)  /* no 16-bit stack */
00230             {
00231                 curr_switch = 0;
00232             }
00233             else if (curr_mode == stm_16bit)
00234             {
00235                 if (!sw_read_mem(csw, next_switch, &frame32, sizeof(frame32)))
00236                 {
00237                     WARN("Bad stack frame %p\n", (void*)(DWORD_PTR)next_switch);
00238                     goto done_err;
00239                 }
00240                 curr_switch = (DWORD)frame32.frame16;
00241                 tmp.Mode    = AddrMode1616;
00242                 tmp.Segment = SELECTOROF(curr_switch);
00243                 tmp.Offset  = OFFSETOF(curr_switch);
00244                 if (!sw_read_mem(csw, sw_xlat_addr(csw, &tmp), &ch, sizeof(ch)))
00245                     curr_switch = 0xFFFFFFFF;
00246             }
00247             else
00248             {
00249                 tmp.Mode    = AddrMode1616;
00250                 tmp.Segment = SELECTOROF(next_switch);
00251                 tmp.Offset  = OFFSETOF(next_switch);
00252                 p = sw_xlat_addr(csw, &tmp);
00253                 if (!sw_read_mem(csw, p, &frame16, sizeof(frame16)))
00254                 {
00255                     WARN("Bad stack frame 0x%08x\n", p);
00256                     goto done_err;
00257                 }
00258                 curr_switch = (DWORD_PTR)frame16.frame32;
00259                 if (!sw_read_mem(csw, curr_switch, &ch, sizeof(ch)))
00260                     curr_switch = 0xFFFFFFFF;
00261             }
00262         }
00263         else
00264             /* FIXME: this will allow to work when we're not attached to a live target,
00265              * but the 16 <=> 32 switch facility won't be available.
00266              */
00267             curr_switch = 0;
00268         frame->AddrReturn.Mode = frame->AddrStack.Mode = (curr_mode == stm_16bit) ? AddrMode1616 : AddrModeFlat;
00269         /* don't set up AddrStack on first call. Either the caller has set it up, or
00270          * we will get it in the next frame
00271          */
00272         memset(&frame->AddrBStore, 0, sizeof(frame->AddrBStore));
00273     }
00274     else
00275     {
00276         if (frame->AddrFrame.Offset == 0) goto done_err;
00277         if (frame->AddrFrame.Mode == AddrModeFlat)
00278         {
00279             assert(curr_mode == stm_32bit);
00280             do_switch = curr_switch && frame->AddrFrame.Offset >= curr_switch;
00281         }
00282         else
00283         {
00284             assert(curr_mode == stm_16bit);
00285             do_switch = curr_switch &&
00286                 frame->AddrFrame.Segment == SELECTOROF(curr_switch) &&
00287                 frame->AddrFrame.Offset >= OFFSETOF(curr_switch);
00288         }
00289 
00290         if (do_switch)
00291         {
00292             if (curr_mode == stm_16bit)
00293             {
00294                 if (!sw_read_mem(csw, next_switch, &frame32, sizeof(frame32)))
00295                 {
00296                     WARN("Bad stack frame %p\n", (void*)(DWORD_PTR)next_switch);
00297                     goto done_err;
00298                 }
00299 
00300                 frame->AddrPC.Mode        = AddrModeFlat;
00301                 frame->AddrPC.Segment     = 0;
00302                 frame->AddrPC.Offset      = frame32.retaddr;
00303                 frame->AddrFrame.Mode     = AddrModeFlat;
00304                 frame->AddrFrame.Segment  = 0;
00305                 frame->AddrFrame.Offset   = frame32.ebp;
00306 
00307                 frame->AddrStack.Mode     = AddrModeFlat;
00308                 frame->AddrStack.Segment  = 0;
00309                 frame->AddrReturn.Mode    = AddrModeFlat;
00310                 frame->AddrReturn.Segment = 0;
00311 
00312                 next_switch = curr_switch;
00313                 tmp.Mode    = AddrMode1616;
00314                 tmp.Segment = SELECTOROF(next_switch);
00315                 tmp.Offset  = OFFSETOF(next_switch);
00316                 p = sw_xlat_addr(csw, &tmp);
00317 
00318                 if (!sw_read_mem(csw, p, &frame16, sizeof(frame16)))
00319                 {
00320                     WARN("Bad stack frame 0x%08x\n", p);
00321                     goto done_err;
00322                 }
00323                 curr_switch = (DWORD_PTR)frame16.frame32;
00324                 set_curr_mode(stm_32bit);
00325                 if (!sw_read_mem(csw, curr_switch, &ch, sizeof(ch)))
00326                     curr_switch = 0;
00327             }
00328             else
00329             {
00330                 tmp.Mode    = AddrMode1616;
00331                 tmp.Segment = SELECTOROF(next_switch);
00332                 tmp.Offset  = OFFSETOF(next_switch);
00333                 p = sw_xlat_addr(csw, &tmp);
00334 
00335                 if (!sw_read_mem(csw, p, &frame16, sizeof(frame16)))
00336                 {
00337                     WARN("Bad stack frame 0x%08x\n", p);
00338                     goto done_err;
00339                 }
00340 
00341                 TRACE("Got a 16 bit stack switch:"
00342                       "\n\tframe32: %08lx"
00343                       "\n\tedx:%08x ecx:%08x ebp:%08x"
00344                       "\n\tds:%04x es:%04x fs:%04x gs:%04x"
00345                       "\n\tcall_from_ip:%08x module_cs:%04x relay=%08x"
00346                       "\n\tentry_ip:%04x entry_point:%08x"
00347                       "\n\tbp:%04x ip:%04x cs:%04x\n",
00348                       (unsigned long)frame16.frame32,
00349                       frame16.edx, frame16.ecx, frame16.ebp,
00350                       frame16.ds, frame16.es, frame16.fs, frame16.gs,
00351                       frame16.callfrom_ip, frame16.module_cs, frame16.relay,
00352                       frame16.entry_ip, frame16.entry_point,
00353                       frame16.bp, frame16.ip, frame16.cs);
00354 
00355                 frame->AddrPC.Mode       = AddrMode1616;
00356                 frame->AddrPC.Segment    = frame16.cs;
00357                 frame->AddrPC.Offset     = frame16.ip;
00358 
00359                 frame->AddrFrame.Mode    = AddrMode1616;
00360                 frame->AddrFrame.Segment = SELECTOROF(next_switch);
00361                 frame->AddrFrame.Offset  = frame16.bp;
00362 
00363                 frame->AddrStack.Mode    = AddrMode1616;
00364                 frame->AddrStack.Segment = SELECTOROF(next_switch);
00365 
00366                 frame->AddrReturn.Mode    = AddrMode1616;
00367                 frame->AddrReturn.Segment = frame16.cs;
00368 
00369                 next_switch = curr_switch;
00370                 if (!sw_read_mem(csw, next_switch, &frame32, sizeof(frame32)))
00371                 {
00372                     WARN("Bad stack frame %p\n", (void*)(DWORD_PTR)next_switch);
00373                     goto done_err;
00374                 }
00375                 curr_switch = (DWORD)frame32.frame16;
00376                 tmp.Mode    = AddrMode1616;
00377                 tmp.Segment = SELECTOROF(curr_switch);
00378                 tmp.Offset  = OFFSETOF(curr_switch);
00379 
00380                 if (!sw_read_mem(csw, sw_xlat_addr(csw, &tmp), &ch, sizeof(ch)))
00381                     curr_switch = 0;
00382                 set_curr_mode(stm_16bit);
00383             }
00384         }
00385         else
00386         {
00387             if (curr_mode == stm_16bit)
00388             {
00389                 frame->AddrPC = frame->AddrReturn;
00390                 frame->AddrStack.Offset = frame->AddrFrame.Offset + 2 * sizeof(WORD);
00391                 /* "pop up" previous BP value */
00392                 if (!sw_read_mem(csw, sw_xlat_addr(csw, &frame->AddrFrame),
00393                                  &val16, sizeof(WORD)))
00394                     goto done_err;
00395                 frame->AddrFrame.Offset = val16;
00396             }
00397             else
00398             {
00399 #ifdef __i386__
00400                 if (!fetch_next_frame32(csw, context, sw_xlat_addr(csw, &frame->AddrPC) - deltapc))
00401                     goto done_err;
00402 
00403                 frame->AddrStack.Mode = frame->AddrFrame.Mode = frame->AddrPC.Mode = AddrModeFlat;
00404                 frame->AddrStack.Offset = context->Esp;
00405                 frame->AddrFrame.Offset = context->Ebp;
00406                 if (frame->AddrReturn.Offset != context->Eip)
00407                     FIXME("new PC=%s different from Eip=%x\n",
00408                           wine_dbgstr_longlong(frame->AddrReturn.Offset), context->Eip);
00409                 frame->AddrPC.Offset = context->Eip;
00410 #endif
00411             }
00412         }
00413     }
00414 
00415     if (curr_mode == stm_16bit)
00416     {
00417         unsigned int     i;
00418 
00419         p = sw_xlat_addr(csw, &frame->AddrFrame);
00420         if (!sw_read_mem(csw, p + sizeof(WORD), &val16, sizeof(WORD)))
00421             goto done_err;
00422         frame->AddrReturn.Offset = val16;
00423         /* get potential cs if a far call was used */
00424         if (!sw_read_mem(csw, p + 2 * sizeof(WORD), &val16, sizeof(WORD)))
00425             goto done_err;
00426         if (frame->AddrFrame.Offset & 1)
00427             frame->AddrReturn.Segment = val16; /* far call assumed */
00428         else
00429         {
00430             /* not explicitly marked as far call,
00431              * but check whether it could be anyway
00432              */
00433             if ((val16 & 7) == 7 && val16 != frame->AddrReturn.Segment)
00434             {
00435                 LDT_ENTRY   le;
00436 
00437                 if (GetThreadSelectorEntry(csw->hThread, val16, &le) &&
00438                     (le.HighWord.Bits.Type & 0x08)) /* code segment */
00439                 {
00440                     /* it is very uncommon to push a code segment cs as
00441                      * a parameter, so this should work in most cases
00442                      */
00443                     frame->AddrReturn.Segment = val16;
00444                 }
00445         }
00446     }
00447         frame->AddrFrame.Offset &= ~1;
00448         /* we "pop" parameters as 16 bit entities... of course, this won't
00449          * work if the parameter is in fact bigger than 16bit, but
00450          * there's no way to know that here
00451          */
00452         for (i = 0; i < sizeof(frame->Params) / sizeof(frame->Params[0]); i++)
00453         {
00454             sw_read_mem(csw, p + (2 + i) * sizeof(WORD), &val16, sizeof(val16));
00455             frame->Params[i] = val16;
00456         }
00457 #ifdef __i386__
00458         if (context)
00459         {
00460 #define SET(field, seg, reg) \
00461             switch (frame->field.Mode) \
00462             { \
00463             case AddrModeFlat: context->reg = frame->field.Offset; break; \
00464             case AddrMode1616: context->seg = frame->field.Segment; context->reg = frame->field.Offset; break; \
00465             default: assert(0); \
00466             }
00467             SET(AddrStack,  SegSs, Esp);
00468             SET(AddrFrame,  SegSs, Ebp);
00469             SET(AddrReturn, SegCs, Eip);
00470 #undef SET
00471         }
00472 #endif
00473     }
00474     else
00475     {
00476         unsigned int    i;
00477 #ifdef __i386__
00478         CONTEXT         newctx = *context;
00479 
00480         if (!fetch_next_frame32(csw, &newctx, frame->AddrPC.Offset - deltapc))
00481             goto done_err;
00482         frame->AddrReturn.Mode = AddrModeFlat;
00483         frame->AddrReturn.Offset = newctx.Eip;
00484 #endif
00485         for (i = 0; i < sizeof(frame->Params) / sizeof(frame->Params[0]); i++)
00486         {
00487             sw_read_mem(csw, frame->AddrFrame.Offset + (2 + i) * sizeof(DWORD), &val32, sizeof(val32));
00488             frame->Params[i] = val32;
00489         }
00490     }
00491 
00492     frame->Far = TRUE;
00493     frame->Virtual = TRUE;
00494     p = sw_xlat_addr(csw, &frame->AddrPC);
00495     if (p && sw_module_base(csw, p))
00496         frame->FuncTableEntry = sw_table_access(csw, p);
00497     else
00498         frame->FuncTableEntry = NULL;
00499 
00500     inc_curr_count();
00501     TRACE("Leave: PC=%s Frame=%s Return=%s Stack=%s Mode=%s Count=%s cSwitch=%p nSwitch=%p FuncTable=%p\n",
00502           wine_dbgstr_addr(&frame->AddrPC),
00503           wine_dbgstr_addr(&frame->AddrFrame),
00504           wine_dbgstr_addr(&frame->AddrReturn),
00505           wine_dbgstr_addr(&frame->AddrStack),
00506           curr_mode == stm_start ? "start" : (curr_mode == stm_16bit ? "16bit" : "32bit"),
00507           wine_dbgstr_longlong(curr_count),
00508           (void*)(DWORD_PTR)curr_switch, (void*)(DWORD_PTR)next_switch, frame->FuncTableEntry);
00509 
00510     return TRUE;
00511 done_err:
00512     set_curr_mode(stm_done);
00513     return FALSE;
00514 }
00515 
00516 static unsigned i386_map_dwarf_register(unsigned regno)
00517 {
00518     unsigned    reg;
00519 
00520     switch (regno)
00521     {
00522     case  0: reg = CV_REG_EAX; break;
00523     case  1: reg = CV_REG_ECX; break;
00524     case  2: reg = CV_REG_EDX; break;
00525     case  3: reg = CV_REG_EBX; break;
00526     case  4: reg = CV_REG_ESP; break;
00527     case  5: reg = CV_REG_EBP; break;
00528     case  6: reg = CV_REG_ESI; break;
00529     case  7: reg = CV_REG_EDI; break;
00530     case  8: reg = CV_REG_EIP; break;
00531     case  9: reg = CV_REG_EFLAGS; break;
00532     case 10: reg = CV_REG_CS;  break;
00533     case 11: reg = CV_REG_SS;  break;
00534     case 12: reg = CV_REG_DS;  break;
00535     case 13: reg = CV_REG_ES;  break;
00536     case 14: reg = CV_REG_FS;  break;
00537     case 15: reg = CV_REG_GS;  break;
00538     case 16: case 17: case 18: case 19:
00539     case 20: case 21: case 22: case 23:
00540         reg = CV_REG_ST0 + regno - 16; break;
00541     case 24: reg = CV_REG_CTRL; break;
00542     case 25: reg = CV_REG_STAT; break;
00543     case 26: reg = CV_REG_TAG; break;
00544     case 27: reg = CV_REG_FPCS; break;
00545     case 28: reg = CV_REG_FPIP; break;
00546     case 29: reg = CV_REG_FPDS; break;
00547     case 30: reg = CV_REG_FPDO; break;
00548 /*
00549 reg: fop   31
00550 */
00551     case 32: case 33: case 34: case 35:
00552     case 36: case 37: case 38: case 39:
00553         reg = CV_REG_XMM0 + regno - 32; break;
00554     case 40: reg = CV_REG_MXCSR; break;
00555     default:
00556         FIXME("Don't know how to map register %d\n", regno);
00557         return 0;
00558     }
00559     return reg;
00560 }
00561 
00562 static void* i386_fetch_context_reg(CONTEXT* ctx, unsigned regno, unsigned* size)
00563 {
00564 #ifdef __i386__
00565     switch (regno)
00566     {
00567     case CV_REG_EAX: *size = sizeof(ctx->Eax); return &ctx->Eax;
00568     case CV_REG_EDX: *size = sizeof(ctx->Edx); return &ctx->Edx;
00569     case CV_REG_ECX: *size = sizeof(ctx->Ecx); return &ctx->Ecx;
00570     case CV_REG_EBX: *size = sizeof(ctx->Ebx); return &ctx->Ebx;
00571     case CV_REG_ESI: *size = sizeof(ctx->Esi); return &ctx->Esi;
00572     case CV_REG_EDI: *size = sizeof(ctx->Edi); return &ctx->Edi;
00573     case CV_REG_EBP: *size = sizeof(ctx->Ebp); return &ctx->Ebp;
00574     case CV_REG_ESP: *size = sizeof(ctx->Esp); return &ctx->Esp;
00575     case CV_REG_EIP: *size = sizeof(ctx->Eip); return &ctx->Eip;
00576 
00577     case CV_REG_ST0 + 0: *size = sizeof(long double); return &ctx->FloatSave.RegisterArea[0*sizeof(long double)];
00578     case CV_REG_ST0 + 1: *size = sizeof(long double); return &ctx->FloatSave.RegisterArea[1*sizeof(long double)];
00579     case CV_REG_ST0 + 2: *size = sizeof(long double); return &ctx->FloatSave.RegisterArea[2*sizeof(long double)];
00580     case CV_REG_ST0 + 3: *size = sizeof(long double); return &ctx->FloatSave.RegisterArea[3*sizeof(long double)];
00581     case CV_REG_ST0 + 4: *size = sizeof(long double); return &ctx->FloatSave.RegisterArea[4*sizeof(long double)];
00582     case CV_REG_ST0 + 5: *size = sizeof(long double); return &ctx->FloatSave.RegisterArea[5*sizeof(long double)];
00583     case CV_REG_ST0 + 6: *size = sizeof(long double); return &ctx->FloatSave.RegisterArea[6*sizeof(long double)];
00584     case CV_REG_ST0 + 7: *size = sizeof(long double); return &ctx->FloatSave.RegisterArea[7*sizeof(long double)];
00585 
00586     case CV_REG_CTRL: *size = sizeof(DWORD); return &ctx->FloatSave.ControlWord;
00587     case CV_REG_STAT: *size = sizeof(DWORD); return &ctx->FloatSave.StatusWord;
00588     case CV_REG_TAG:  *size = sizeof(DWORD); return &ctx->FloatSave.TagWord;
00589     case CV_REG_FPCS: *size = sizeof(DWORD); return &ctx->FloatSave.ErrorSelector;
00590     case CV_REG_FPIP: *size = sizeof(DWORD); return &ctx->FloatSave.ErrorOffset;
00591     case CV_REG_FPDS: *size = sizeof(DWORD); return &ctx->FloatSave.DataSelector;
00592     case CV_REG_FPDO: *size = sizeof(DWORD); return &ctx->FloatSave.DataOffset;
00593 
00594     case CV_REG_EFLAGS: *size = sizeof(ctx->EFlags); return &ctx->EFlags;
00595     case CV_REG_ES: *size = sizeof(ctx->SegEs); return &ctx->SegEs;
00596     case CV_REG_CS: *size = sizeof(ctx->SegCs); return &ctx->SegCs;
00597     case CV_REG_SS: *size = sizeof(ctx->SegSs); return &ctx->SegSs;
00598     case CV_REG_DS: *size = sizeof(ctx->SegDs); return &ctx->SegDs;
00599     case CV_REG_FS: *size = sizeof(ctx->SegFs); return &ctx->SegFs;
00600     case CV_REG_GS: *size = sizeof(ctx->SegGs); return &ctx->SegGs;
00601 
00602     }
00603 #endif
00604     FIXME("Unknown register %x\n", regno);
00605     return NULL;
00606 }
00607 
00608 static const char* i386_fetch_regname(unsigned regno)
00609 {
00610     switch (regno)
00611     {
00612     case CV_REG_EAX: return "eax";
00613     case CV_REG_EDX: return "edx";
00614     case CV_REG_ECX: return "ecx";
00615     case CV_REG_EBX: return "ebx";
00616     case CV_REG_ESI: return "esi";
00617     case CV_REG_EDI: return "edi";
00618     case CV_REG_EBP: return "ebp";
00619     case CV_REG_ESP: return "esp";
00620     case CV_REG_EIP: return "eip";
00621 
00622     case CV_REG_ST0 + 0: return "st0";
00623     case CV_REG_ST0 + 1: return "st1";
00624     case CV_REG_ST0 + 2: return "st2";
00625     case CV_REG_ST0 + 3: return "st3";
00626     case CV_REG_ST0 + 4: return "st4";
00627     case CV_REG_ST0 + 5: return "st5";
00628     case CV_REG_ST0 + 6: return "st6";
00629     case CV_REG_ST0 + 7: return "st7";
00630 
00631     case CV_REG_EFLAGS: return "eflags";
00632     case CV_REG_ES: return "es";
00633     case CV_REG_CS: return "cs";
00634     case CV_REG_SS: return "ss";
00635     case CV_REG_DS: return "ds";
00636     case CV_REG_FS: return "fs";
00637     case CV_REG_GS: return "gs";
00638 
00639     case CV_REG_CTRL: return "fpControl";
00640     case CV_REG_STAT: return "fpStatus";
00641     case CV_REG_TAG:  return "fpTag";
00642     case CV_REG_FPCS: return "fpCS";
00643     case CV_REG_FPIP: return "fpIP";
00644     case CV_REG_FPDS: return "fpDS";
00645     case CV_REG_FPDO: return "fpData";
00646 
00647     case CV_REG_XMM0 + 0: return "xmm0";
00648     case CV_REG_XMM0 + 1: return "xmm1";
00649     case CV_REG_XMM0 + 2: return "xmm2";
00650     case CV_REG_XMM0 + 3: return "xmm3";
00651     case CV_REG_XMM0 + 4: return "xmm4";
00652     case CV_REG_XMM0 + 5: return "xmm5";
00653     case CV_REG_XMM0 + 6: return "xmm6";
00654     case CV_REG_XMM0 + 7: return "xmm7";
00655 
00656     case CV_REG_MXCSR: return "MxCSR";
00657     }
00658     FIXME("Unknown register %x\n", regno);
00659     return NULL;
00660 }
00661 
00662 DECLSPEC_HIDDEN struct cpu cpu_i386 = {
00663     IMAGE_FILE_MACHINE_I386,
00664     4,
00665     CV_REG_EBP,
00666     i386_get_addr,
00667     i386_stack_walk,
00668     NULL,
00669     i386_map_dwarf_register,
00670     i386_fetch_context_reg,
00671     i386_fetch_regname,
00672 };

Generated on Sun May 27 2012 04:23:20 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.