Index: /trunk/include/VBox/err.h
===================================================================
--- /trunk/include/VBox/err.h	(revision 35465)
+++ /trunk/include/VBox/err.h	(revision 35466)
@@ -267,6 +267,6 @@
 /** The OS was not detected. */
 #define VINF_DBGF_OS_NOT_DETCTED            1209
-/** Invalid register number. */
-#define VERR_DBGF_INVALID_REGISTER          (-1210)
+/** The specified register was not found. */
+#define VERR_DBGF_REGISTER_NOT_FOUND        (-1210)
 /** The value was truncated to fit.
  * For queries this means that the register is wider than the queried value.
Index: /trunk/include/VBox/vmm/dbgf.h
===================================================================
--- /trunk/include/VBox/vmm/dbgf.h	(revision 35465)
+++ /trunk/include/VBox/vmm/dbgf.h	(revision 35466)
@@ -1231,6 +1231,4 @@
     /** Unsigned 128-bit register value. */
     DBGFREGVALTYPE_U128,
-    /** 80-bit register value. */
-    DBGFREGVALTYPE_80,
     /** Long double register value. */
     DBGFREGVALTYPE_LRD,
@@ -1242,4 +1240,6 @@
     DBGFREGVALTYPE_32BIT_HACK = 0x7fffffff
 } DBGFREGVALTYPE;
+/** Pointer to a register value type. */
+typedef DBGFREGVALTYPE *PDBGFREGVALTYPE;
 
 /**
@@ -1282,9 +1282,10 @@
     /** The name of the sub-field.  NULL is used to terminate the array. */
     const char     *pszName;
-    /** The index of the first bit. */
+    /** The index of the first bit.  Ignored if pfnGet is set. */
     uint8_t         iFirstBit;
-    /** The number of bits. */
+    /** The number of bits.  Mandatory. */
     uint8_t         cBits;
-    /** The shift count. */
+    /** The shift count.  Not applied when pfnGet is set, but used to
+     * calculate the minimum type. */
     int8_t          cShift;
     /** Sub-field flags, DBGFREGSUBFIELD_FLAGS_XXX.  */
@@ -1389,5 +1390,5 @@
 VMMR3DECL(int) DBGFR3RegCpuSetBatch( PVM pVM, VMCPUID idCpu, PCDBGFREGENTRY paRegs, size_t cRegs);
 
-VMMR3DECL(const char *) DBGFR3RegCpuName(DBGFREG enmReg, DBGFREGVALTYPE enmType);
+VMMR3DECL(const char *) DBGFR3RegCpuName(PVM pVM, DBGFREG enmReg, DBGFREGVALTYPE enmType);
 
 /**
@@ -1408,23 +1409,25 @@
 typedef DBGFREGENTRYNM const *PCDBGFREGENTRYNM;
 
-VMMR3DECL(int) DBGFR3RegNmQueryU8(  PVM pVM, VMCPUID idCpu, const char *pszReg, uint8_t     *pu8);
-VMMR3DECL(int) DBGFR3RegNmQueryU16( PVM pVM, VMCPUID idCpu, const char *pszReg, uint16_t    *pu16);
-VMMR3DECL(int) DBGFR3RegNmQueryU32( PVM pVM, VMCPUID idCpu, const char *pszReg, uint32_t    *pu32);
-VMMR3DECL(int) DBGFR3RegNmQueryU64( PVM pVM, VMCPUID idCpu, const char *pszReg, uint64_t    *pu64);
-VMMR3DECL(int) DBGFR3RegNmQueryU128(PVM pVM, VMCPUID idCpu, const char *pszReg, uint128_t   *pu128);
-VMMR3DECL(int) DBGFR3RegNmQueryLrd( PVM pVM, VMCPUID idCpu, const char *pszReg, long double *plrd);
-VMMR3DECL(int) DBGFR3RegNmQueryXdtr(PVM pVM, VMCPUID idCpu, const char *pszReg, uint64_t *pu64Base, uint16_t *pu16Limit);
-VMMR3DECL(int) DBGFR3RegNmQueryBatch(PVM pVM,VMCPUID idCpu, DBGFREGENTRYNM paRegs, size_t cRegs);
-/** @todo VMMR3DECL(int) DBGFR3RegNmQueryAll( PVM pVM, VMCPUID idCpu, DBGFREGENTRYNM paRegs, size_t cRegs)? */
-VMMR3DECL(int) DBGFR3RegNmPrintf(   PVM pVM, VMCPUID idCpu, char pszBuf, size_t cbBuf, const char *pszFormat, ...);
-VMMR3DECL(int) DBGFR3RegNmPrintfV(  PVM pVM, VMCPUID idCpu, char pszBuf, size_t cbBuf, const char *pszFormat, ...);
-
-VMMR3DECL(int) DBGFR3RegNmSetU8(    PVM pVM, VMCPUID idCpu, const char *pszReg, uint8_t     u8);
-VMMR3DECL(int) DBGFR3RegNmSetU16(   PVM pVM, VMCPUID idCpu, const char *pszReg, uint16_t    u16);
-VMMR3DECL(int) DBGFR3RegNmSetU32(   PVM pVM, VMCPUID idCpu, const char *pszReg, uint32_t    u32);
-VMMR3DECL(int) DBGFR3RegNmSetU64(   PVM pVM, VMCPUID idCpu, const char *pszReg, uint64_t    u64);
-VMMR3DECL(int) DBGFR3RegNmSetU128(  PVM pVM, VMCPUID idCpu, const char *pszReg, uint128_t   u128);
-VMMR3DECL(int) DBGFR3RegNmSetLrd(   PVM pVM, VMCPUID idCpu, const char *pszReg, long double lrd);
-VMMR3DECL(int) DBGFR3RegNmSetBatch( PVM pVM, VMCPUID idCpu, DBGFREGENTRYNM paRegs, size_t cRegs);
+VMMR3DECL(int) DBGFR3RegNmQuery(    PVM pVM, VMCPUID idDefCpu, const char *pszReg, PDBGFREGVAL pValue, PDBGFREGVALTYPE penmType);
+VMMR3DECL(int) DBGFR3RegNmQueryU8(  PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint8_t     *pu8);
+VMMR3DECL(int) DBGFR3RegNmQueryU16( PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint16_t    *pu16);
+VMMR3DECL(int) DBGFR3RegNmQueryU32( PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint32_t    *pu32);
+VMMR3DECL(int) DBGFR3RegNmQueryU64( PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint64_t    *pu64);
+VMMR3DECL(int) DBGFR3RegNmQueryU128(PVM pVM, VMCPUID idDefCpu, const char *pszReg, PRTUINT128U  pu128);
+VMMR3DECL(int) DBGFR3RegNmQueryLrd( PVM pVM, VMCPUID idDefCpu, const char *pszReg, long double *plrd);
+VMMR3DECL(int) DBGFR3RegNmQueryXdtr(PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint64_t *pu64Base, uint16_t *pu16Limit);
+VMMR3DECL(int) DBGFR3RegNmQueryBatch(PVM pVM,VMCPUID idDefCpu, DBGFREGENTRYNM paRegs, size_t cRegs);
+VMMR3DECL(int) DBGFR3RegNmQueryAllCount(PVM pVM, size_t *pcRegs);
+VMMR3DECL(int) DBGFR3RegNmQueryAll( PVM pVM,                   DBGFREGENTRYNM paRegs, size_t cRegs);
+VMMR3DECL(int) DBGFR3RegNmPrintf(   PVM pVM, VMCPUID idDefCpu, char pszBuf, size_t cbBuf, const char *pszFormat, ...);
+VMMR3DECL(int) DBGFR3RegNmPrintfV(  PVM pVM, VMCPUID idDefCpu, char pszBuf, size_t cbBuf, const char *pszFormat, ...);
+
+VMMR3DECL(int) DBGFR3RegNmSetU8(    PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint8_t     u8);
+VMMR3DECL(int) DBGFR3RegNmSetU16(   PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint16_t    u16);
+VMMR3DECL(int) DBGFR3RegNmSetU32(   PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint32_t    u32);
+VMMR3DECL(int) DBGFR3RegNmSetU64(   PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint64_t    u64);
+VMMR3DECL(int) DBGFR3RegNmSetU128(  PVM pVM, VMCPUID idDefCpu, const char *pszReg, RTUINT128U  u128);
+VMMR3DECL(int) DBGFR3RegNmSetLrd(   PVM pVM, VMCPUID idDefCpu, const char *pszReg, long double lrd);
+VMMR3DECL(int) DBGFR3RegNmSetBatch( PVM pVM, VMCPUID idDefCpu, DBGFREGENTRYNM paRegs, size_t cRegs);
 
 /** @todo add enumeration methods.  */
Index: /trunk/src/VBox/Main/src-client/MachineDebuggerImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/MachineDebuggerImpl.cpp	(revision 35465)
+++ /trunk/src/VBox/Main/src-client/MachineDebuggerImpl.cpp	(revision 35466)
@@ -1098,5 +1098,6 @@
                                 RTStrFormatNumber(&szHex[2+16], aRegs[iReg].Val.au64[0], 16, 16, 0, RTSTR_F_ZEROPAD | RTSTR_F_64BIT);
                                 break;
-                            case DBGFREGVALTYPE_80:
+                            case DBGFREGVALTYPE_LRD:
+                                /** @todo long double -> string conversion. */
                                 RTStrFormatNumber(szHex, aRegs[iReg].Val.au16[5], 16, 2+4, 0, RTSTR_F_SPECIAL | RTSTR_F_ZEROPAD | RTSTR_F_16BIT);
                                 RTStrFormatNumber(&szHex[2+4], aRegs[iReg].Val.au64[0], 16, 16, 0, RTSTR_F_ZEROPAD | RTSTR_F_64BIT);
@@ -1108,5 +1109,4 @@
                                 break;
 
-                            case DBGFREGVALTYPE_LRD:
                             case DBGFREGVALTYPE_END:
                             case DBGFREGVALTYPE_INVALID:
@@ -1119,5 +1119,5 @@
                         bstrValue.detachTo(&abstrValues[iReg]);
 
-                        Bstr bstrName(DBGFR3RegCpuName(aRegs[iReg].enmReg, DBGFREGVALTYPE_INVALID));
+                        Bstr bstrName(DBGFR3RegCpuName(ptrVM.raw(), aRegs[iReg].enmReg, DBGFREGVALTYPE_INVALID));
                         bstrName.detachTo(&abstrNames[iReg]);
                     }
Index: /trunk/src/VBox/VMM/VMMR3/DBGF.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/DBGF.cpp	(revision 35465)
+++ /trunk/src/VBox/VMM/VMMR3/DBGF.cpp	(revision 35466)
@@ -135,4 +135,6 @@
 {
     int rc = dbgfR3InfoInit(pVM);
+    if (RT_SUCCESS(rc))
+        rc = dbgfR3RegInit(pVM);
     if (RT_SUCCESS(rc))
         rc = dbgfR3AsInit(pVM);
@@ -208,4 +210,5 @@
     dbgfR3OSTerm(pVM);
     dbgfR3AsTerm(pVM);
+    dbgfR3RegTerm(pVM);
     dbgfR3InfoTerm(pVM);
     return VINF_SUCCESS;
Index: /trunk/src/VBox/VMM/VMMR3/DBGFReg.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/DBGFReg.cpp	(revision 35465)
+++ /trunk/src/VBox/VMM/VMMR3/DBGFReg.cpp	(revision 35466)
@@ -64,4 +64,7 @@
 
 
+/** The max length of a set, register or sub-field name. */
+#define DBGF_REG_MAX_NAME       40
+
 
 /*******************************************************************************
@@ -92,5 +95,5 @@
     RTSTRSPACECORE          Core;
     /** The registration record type. */
-    DBGFREGSETTYPE       enmType;
+    DBGFREGSETTYPE          enmType;
     /** The user argument for the callbacks. */
     union
@@ -109,9 +112,62 @@
     size_t                  cDescs;
 
+    /** Array of lookup records. */
+    struct DBGFREGLOOKUP   *paLookupRecs;
+    /** The number of lookup records. */
+    size_t                  cLookupRecs;
+
     /** The register name prefix. */
-    char                    szPrefix[32];
+    char                    szPrefix[1];
 } DBGFREGSET;
 /** Pointer to a register registration record. */
 typedef DBGFREGSET *PDBGFREGSET;
+/** Pointer to a const register registration record. */
+typedef DBGFREGSET const *PCDBGFREGSET;
+
+
+/**
+ * Register lookup record.
+ */
+typedef struct DBGFREGLOOKUP
+{
+    /** The string space core. */
+    RTSTRSPACECORE      Core;
+    /** Pointer to the set. */
+    PCDBGFREGSET        pSet;
+    /** Pointer to the register descriptor. */
+    PCDBGFREGDESC       pDesc;
+    /** If an alias this points to the alias descriptor, NULL if not. */
+    PCDBGFREGALIAS      pAlias;
+    /** If a sub-field this points to the sub-field descriptor, NULL if not. */
+    PCDBGFREGSUBFIELD   pSubField;
+} DBGFREGLOOKUP;
+/** Pointer to a register lookup record. */
+typedef DBGFREGLOOKUP *PDBGFREGLOOKUP;
+/** Pointer to a const register lookup record. */
+typedef DBGFREGLOOKUP const *PCDBGFREGLOOKUP;
+
+
+/**
+ * Initializes the register database.
+ *
+ * @returns VBox status code.
+ * @param   pVM                 The VM handle.
+ */
+int dbgfR3RegInit(PVM pVM)
+{
+    return RTSemRWCreate(&pVM->dbgf.s.hRegDbLock);
+}
+
+
+/**
+ * Terminates the register database.
+ *
+ * @param   pVM                 The VM handle.
+ */
+void dbgfR3RegTerm(PVM pVM)
+{
+    RTSemRWDestroy(pVM->dbgf.s.hRegDbLock);
+    pVM->dbgf.s.hRegDbLock = NIL_RTSEMRW;
+}
 
 
@@ -126,12 +182,15 @@
 static bool dbgfR3RegIsNameValid(const char *pszName)
 {
-    if (!RT_C_IS_ALPHA(*pszName))
+    const char *psz = pszName;
+    if (!RT_C_IS_ALPHA(*psz))
         return false;
     char ch;
-    while ((ch = *++pszName))
+    while ((ch = *++psz))
         if (   !RT_C_IS_LOWER(ch)
             && !RT_C_IS_DIGIT(ch)
             && ch != '_')
             return false;
+    if (psz - pszName > DBGF_REG_MAX_NAME)
+        return false;
     return true;
 }
@@ -165,4 +224,5 @@
 
     /* The descriptors. */
+    uint32_t cLookupRecs = 0;
     uint32_t iDesc;
     for (iDesc = 0; paRegisters[iDesc].pszName != NULL; iDesc++)
@@ -184,56 +244,159 @@
         AssertPtrReturn(paRegisters[iDesc].pfnSet, VERR_INVALID_PARAMETER);
 
-        PCDBGFREGALIAS paAliases = paRegisters[iDesc].paAliases;
+        uint32_t        iAlias    = 0;
+        PCDBGFREGALIAS  paAliases = paRegisters[iDesc].paAliases;
         if (paAliases)
         {
             AssertPtrReturn(paAliases, VERR_INVALID_PARAMETER);
-            for (uint32_t j = 0; paAliases[j].pszName; j++)
+            for (; paAliases[iAlias].pszName; iAlias++)
             {
-                AssertMsgReturn(dbgfR3RegIsNameValid(paAliases[j].pszName), ("%s (%s)\n", paAliases[j].pszName, paRegisters[iDesc].pszName), VERR_INVALID_NAME);
-                AssertReturn(   paAliases[j].enmType > DBGFREGVALTYPE_INVALID
-                             && paAliases[j].enmType < DBGFREGVALTYPE_END, VERR_INVALID_PARAMETER);
+                AssertMsgReturn(dbgfR3RegIsNameValid(paAliases[iAlias].pszName), ("%s (%s)\n", paAliases[iAlias].pszName, paRegisters[iDesc].pszName), VERR_INVALID_NAME);
+                AssertReturn(   paAliases[iAlias].enmType > DBGFREGVALTYPE_INVALID
+                             && paAliases[iAlias].enmType < DBGFREGVALTYPE_END, VERR_INVALID_PARAMETER);
             }
         }
 
+        uint32_t          iSubField   = 0;
         PCDBGFREGSUBFIELD paSubFields = paRegisters[iDesc].paSubFields;
         if (paSubFields)
         {
             AssertPtrReturn(paSubFields, VERR_INVALID_PARAMETER);
-            for (uint32_t j = 0; paSubFields[j].pszName; j++)
+            for (; paSubFields[iSubField].pszName; iSubField++)
             {
-                AssertMsgReturn(dbgfR3RegIsNameValid(paSubFields[j].pszName), ("%s (%s)\n", paSubFields[j].pszName, paRegisters[iDesc].pszName), VERR_INVALID_NAME);
-                AssertReturn(paSubFields[j].iFirstBit + paSubFields[j].cBits <= 128, VERR_INVALID_PARAMETER);
-                AssertReturn(paSubFields[j].cBits + paSubFields[j].cShift <= 128, VERR_INVALID_PARAMETER);
-                AssertPtrNullReturn(paSubFields[j].pfnGet, VERR_INVALID_POINTER);
-                AssertPtrNullReturn(paSubFields[j].pfnSet, VERR_INVALID_POINTER);
+                AssertMsgReturn(dbgfR3RegIsNameValid(paSubFields[iSubField].pszName), ("%s (%s)\n", paSubFields[iSubField].pszName, paRegisters[iDesc].pszName), VERR_INVALID_NAME);
+                AssertReturn(paSubFields[iSubField].iFirstBit + paSubFields[iSubField].cBits <= 128, VERR_INVALID_PARAMETER);
+                AssertReturn(paSubFields[iSubField].cBits + paSubFields[iSubField].cShift <= 128, VERR_INVALID_PARAMETER);
+                AssertPtrNullReturn(paSubFields[iSubField].pfnGet, VERR_INVALID_POINTER);
+                AssertPtrNullReturn(paSubFields[iSubField].pfnSet, VERR_INVALID_POINTER);
             }
         }
-    }
+
+        cLookupRecs += (1 + iAlias) * (1 + iSubField);
+    }
+
+    /* Check the instance number of the CPUs. */
+    AssertReturn(enmType != DBGFREGSETTYPE_CPU || iInstance < pVM->cCpus, VERR_INVALID_CPU_ID);
 
     /*
-     * Allocate a new record.
+     * Allocate a new record and all associated lookup records.
      */
-    PDBGFREGSET pRegRec = (PDBGFREGSET)MMR3HeapAlloc(pVM, MM_TAG_DBGF_REG, RT_OFFSETOF(DBGFREGSET, szPrefix[cchPrefix + 4 + 1]));
-    if (!pRegRec)
+    size_t cbRegSet = RT_OFFSETOF(DBGFREGSET, szPrefix[cchPrefix + 4 + 1]);
+    cbRegSet = RT_ALIGN_Z(cbRegSet, 32);
+    size_t const offLookupRecArray = cbRegSet;
+    cbRegSet += cLookupRecs * sizeof(DBGFREGLOOKUP);
+
+    PDBGFREGSET pRegSet = (PDBGFREGSET)MMR3HeapAllocZ(pVM, MM_TAG_DBGF_REG, cbRegSet);
+    if (!pRegSet)
         return VERR_NO_MEMORY;
 
-    pRegRec->Core.pszString = pRegRec->szPrefix;
-    pRegRec->enmType        = enmType;
-    pRegRec->uUserArg.pv    = pvUserArg;
-    pRegRec->paDescs        = paRegisters;
-    pRegRec->cDescs         = iDesc;
+    /*
+     * Initialize the new record.
+     */
+    pRegSet->Core.pszString = pRegSet->szPrefix;
+    pRegSet->enmType        = enmType;
+    pRegSet->uUserArg.pv    = pvUserArg;
+    pRegSet->paDescs        = paRegisters;
+    pRegSet->cDescs         = iDesc;
+    pRegSet->cLookupRecs    = cLookupRecs;
+    pRegSet->paLookupRecs   = (PDBGFREGLOOKUP)((uintptr_t)pRegSet + offLookupRecArray);
     if (fNeedUnderscore)
-        RTStrPrintf(pRegRec->szPrefix, cchPrefix + 4 + 1, "%s_%u", pszPrefix, iInstance);
+        RTStrPrintf(pRegSet->szPrefix, cchPrefix + 4 + 1, "%s_%u", pszPrefix, iInstance);
     else
-        RTStrPrintf(pRegRec->szPrefix, cchPrefix + 4 + 1, "%s%u", pszPrefix, iInstance);
-
-    DBGF_REG_DB_LOCK_WRITE(pVM);
-    bool fInserted = RTStrSpaceInsert(&pVM->dbgf.s.RegSetSpace, &pRegRec->Core);
-    DBGF_REG_DB_UNLOCK_WRITE(pVM);
-    if (fInserted)
-        return VINF_SUCCESS;
-
-    MMR3HeapFree(pRegRec);
-    return VERR_DUPLICATE;
+        RTStrPrintf(pRegSet->szPrefix, cchPrefix + 4 + 1, "%s%u", pszPrefix, iInstance);
+
+
+    /*
+     * Initialize the lookup records.
+     */
+    char szName[DBGF_REG_MAX_NAME * 3 + 16];
+    strcpy(szName, pRegSet->szPrefix);
+    char *pszReg = strchr(szName, '\0');
+    *pszReg++ = '.';
+
+    int             rc = VINF_SUCCESS;
+    PDBGFREGLOOKUP  pLookupRec = &pRegSet->paLookupRecs[0];
+    for (iDesc = 0; paRegisters[iDesc].pszName != NULL && RT_SUCCESS(rc); iDesc++)
+    {
+        PCDBGFREGALIAS  pCurAlias  = NULL;
+        PCDBGFREGALIAS  pNextAlias = paRegisters[iDesc].paAliases;
+        const char     *pszRegName = paRegisters[iDesc].pszName;
+        while (RT_SUCCESS(rc))
+        {
+            size_t cchReg = strlen(paRegisters[iDesc].pszName);
+            memcpy(pszReg, paRegisters[iDesc].pszName, cchReg + 1);
+            pLookupRec->Core.pszString = MMR3HeapStrDup(pVM, MM_TAG_DBGF_REG, szName);
+            if (!pLookupRec->Core.pszString)
+                rc = VERR_NO_STR_MEMORY;
+            pLookupRec->pSet      = pRegSet;
+            pLookupRec->pDesc     = &paRegisters[iDesc];
+            pLookupRec->pAlias    = pCurAlias;
+            pLookupRec->pSubField = NULL;
+
+            PCDBGFREGSUBFIELD paSubFields = paRegisters[iDesc].paSubFields;
+            if (paSubFields)
+            {
+                char *pszSub = &pszReg[cchReg];
+                *pszSub++ = '.';
+                for (uint32_t iSubField = 0; paSubFields[iSubField].pszName && RT_SUCCESS(rc); iSubField++)
+                {
+                    strcpy(pszSub, paSubFields[iSubField].pszName);
+                    pLookupRec->Core.pszString = MMR3HeapStrDup(pVM, MM_TAG_DBGF_REG, szName);
+                    if (!pLookupRec->Core.pszString)
+                        rc = VERR_NO_STR_MEMORY;
+                    pLookupRec->pSet      = pRegSet;
+                    pLookupRec->pDesc     = &paRegisters[iDesc];
+                    pLookupRec->pAlias    = pCurAlias;
+                    pLookupRec->pSubField = &paSubFields[iSubField];
+                }
+            }
+
+            /* next */
+            pCurAlias = pNextAlias++;
+            if (   !pCurAlias
+                || !pCurAlias->pszName)
+                break;
+            pszRegName = pCurAlias->pszName;
+        }
+    }
+
+    if (RT_SUCCESS(rc))
+    {
+        /*
+         * Insert the record into the register set string space and optionally into
+         * the CPU register set cache.
+         */
+        DBGF_REG_DB_LOCK_WRITE(pVM);
+
+        bool fInserted = RTStrSpaceInsert(&pVM->dbgf.s.RegSetSpace, &pRegSet->Core);
+        if (fInserted)
+        {
+            if (enmType == DBGFREGSETTYPE_CPU)
+                pVM->aCpus[iInstance].dbgf.s.pRegSet = pRegSet;
+            pVM->dbgf.s.cRegs += pRegSet->cDescs;
+
+            PDBGFREGLOOKUP  paLookupRecs = pRegSet->paLookupRecs;
+            uint32_t        iLookupRec   = pRegSet->cLookupRecs;
+            while (iLookupRec-- > 0)
+            {
+                bool fInserted2 = RTStrSpaceInsert(&pVM->dbgf.s.RegSpace, &paLookupRecs[iLookupRec].Core);
+                AssertMsg(fInserted2, ("'%s'", paLookupRecs[iLookupRec].Core.pszString));
+            }
+
+            DBGF_REG_DB_UNLOCK_WRITE(pVM);
+            return VINF_SUCCESS;
+        }
+
+        DBGF_REG_DB_UNLOCK_WRITE(pVM);
+        rc = VERR_DUPLICATE;
+    }
+
+    /*
+     * Bail out.
+     */
+    for (uint32_t i = 0; i < pRegSet->cLookupRecs; i++)
+        MMR3HeapFree((char *)pRegSet->paLookupRecs[i].Core.pszString);
+    MMR3HeapFree(pRegSet);
+
+    return rc;
 }
 
@@ -301,4 +464,6 @@
     dbgfR3RegValClear(pValue);
 
+    /* Note! No default cases here as gcc warnings about missing enum values
+             are desired. */
     switch (enmFromType)
     {
@@ -311,5 +476,4 @@
                 case DBGFREGVALTYPE_U64:    pValue->u64       = InVal.u8; return VINF_DBGF_ZERO_EXTENDED_REGISTER;
                 case DBGFREGVALTYPE_U128:   pValue->u128.s.Lo = InVal.u8; return VINF_DBGF_ZERO_EXTENDED_REGISTER;
-                case DBGFREGVALTYPE_80:                                   return VERR_DBGF_UNSUPPORTED_CAST;
                 case DBGFREGVALTYPE_LRD:    pValue->lrd       = InVal.u8; return VINF_DBGF_ZERO_EXTENDED_REGISTER;
                 case DBGFREGVALTYPE_DTR:                                  return VERR_DBGF_UNSUPPORTED_CAST;
@@ -330,5 +494,4 @@
                 case DBGFREGVALTYPE_U64:    pValue->u64       = InVal.u16;  return VINF_DBGF_ZERO_EXTENDED_REGISTER;
                 case DBGFREGVALTYPE_U128:   pValue->u128.s.Lo = InVal.u16;  return VINF_DBGF_ZERO_EXTENDED_REGISTER;
-                case DBGFREGVALTYPE_80:                                     return VERR_DBGF_UNSUPPORTED_CAST;
                 case DBGFREGVALTYPE_LRD:    pValue->lrd       = InVal.u16;  return VINF_DBGF_ZERO_EXTENDED_REGISTER;
                 case DBGFREGVALTYPE_DTR:                                    return VERR_DBGF_UNSUPPORTED_CAST;
@@ -349,5 +512,4 @@
                 case DBGFREGVALTYPE_U64:    pValue->u64       = InVal.u32;  return VINF_DBGF_ZERO_EXTENDED_REGISTER;
                 case DBGFREGVALTYPE_U128:   pValue->u128.s.Lo = InVal.u32;  return VINF_DBGF_ZERO_EXTENDED_REGISTER;
-                case DBGFREGVALTYPE_80:                                     return VERR_DBGF_UNSUPPORTED_CAST;
                 case DBGFREGVALTYPE_LRD:    pValue->lrd       = InVal.u32;  return VINF_DBGF_ZERO_EXTENDED_REGISTER;
                 case DBGFREGVALTYPE_DTR:                                    return VERR_DBGF_UNSUPPORTED_CAST;
@@ -368,5 +530,4 @@
                 case DBGFREGVALTYPE_U64:    pValue->u64       = InVal.u64;  return VINF_SUCCESS;
                 case DBGFREGVALTYPE_U128:   pValue->u128.s.Lo = InVal.u64;  return VINF_DBGF_TRUNCATED_REGISTER;
-                case DBGFREGVALTYPE_80:                                     return VERR_DBGF_UNSUPPORTED_CAST;
                 case DBGFREGVALTYPE_LRD:    pValue->lrd       = InVal.u64;  return VINF_DBGF_ZERO_EXTENDED_REGISTER;
                 case DBGFREGVALTYPE_DTR:                                    return VERR_DBGF_UNSUPPORTED_CAST;
@@ -387,5 +548,4 @@
                 case DBGFREGVALTYPE_U64:    pValue->u64       = InVal.u128.s.Lo;  return VINF_DBGF_TRUNCATED_REGISTER;
                 case DBGFREGVALTYPE_U128:   pValue->u128      = InVal.u128;       return VINF_SUCCESS;
-                case DBGFREGVALTYPE_80:                                           return VERR_DBGF_UNSUPPORTED_CAST;
                 case DBGFREGVALTYPE_LRD:    pValue->lrd       = InVal.u64;        return VINF_DBGF_TRUNCATED_REGISTER;
                 case DBGFREGVALTYPE_DTR:                                          return VERR_DBGF_UNSUPPORTED_CAST;
@@ -397,7 +557,4 @@
             }
             break;
-
-        case DBGFREGVALTYPE_80:
-            return VERR_DBGF_UNSUPPORTED_CAST;
 
         case DBGFREGVALTYPE_LRD:
@@ -412,5 +569,4 @@
                     pValue->u128.s.Hi = (uint64_t)InVal.lrd / _4G / _4G;
                     return VINF_DBGF_TRUNCATED_REGISTER;
-                case DBGFREGVALTYPE_80:                                     return VERR_DBGF_UNSUPPORTED_CAST;
                 case DBGFREGVALTYPE_LRD:    pValue->lrd       = InVal.lrd;  return VINF_SUCCESS;
                 case DBGFREGVALTYPE_DTR:                                    return VERR_DBGF_UNSUPPORTED_CAST;
@@ -431,5 +587,4 @@
                 case DBGFREGVALTYPE_U64:    pValue->u64       = InVal.dtr.u64Base;  return VINF_DBGF_TRUNCATED_REGISTER;
                 case DBGFREGVALTYPE_U128:   pValue->u128.s.Lo = InVal.dtr.u64Base;  return VINF_DBGF_TRUNCATED_REGISTER;
-                case DBGFREGVALTYPE_80:                                             return VERR_DBGF_UNSUPPORTED_CAST;
                 case DBGFREGVALTYPE_LRD:    pValue->lrd       = InVal.dtr.u64Base;  return VINF_DBGF_TRUNCATED_REGISTER;
                 case DBGFREGVALTYPE_DTR:    pValue->dtr       = InVal.dtr;          return VINF_SUCCESS;
@@ -460,5 +615,5 @@
  * @retval  VERR_INVALID_VM_HANDLE
  * @retval  VERR_INVALID_CPU_ID
- * @retval  VERR_DBGF_INVALID_REGISTER
+ * @retval  VERR_DBGF_REGISTER_NOT_FOUND
  * @retval  VERR_DBGF_UNSUPPORTED_CAST
  * @retval  VINF_DBGF_TRUNCATED_REGISTER
@@ -469,7 +624,7 @@
  * @param   enmReg              The register to query.
  * @param   enmType             The desired return type.
- * @param   puValue             Where to return the register value.
- */
-static DECLCALLBACK(int) dbgfR3RegCpuQueryWorker(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, DBGFREGVALTYPE enmType, PDBGFREGVAL puValue)
+ * @param   pValue              Where to return the register value.
+ */
+static DECLCALLBACK(int) dbgfR3RegCpuQueryWorker(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, DBGFREGVALTYPE enmType, PDBGFREGVAL pValue)
 {
     int rc = VINF_SUCCESS;
@@ -477,10 +632,7 @@
 
     /*
-     * Look up the register set of the CPU.
+     * Look up the register set of the specified CPU.
      */
-    /** @todo optimize this by adding a cpu register set array to DBGF. */
-    char szSetName[16];
-    RTStrPrintf(szSetName, sizeof(szSetName), "cpu%u", idCpu);
-    PDBGFREGSET pSet = (PDBGFREGSET)RTStrSpaceGet(&pVM->dbgf.s.RegSetSpace, szSetName);
+    PDBGFREGSET pSet = pVM->aCpus[idCpu].dbgf.s.pRegSet;
     if (RT_LIKELY(pSet))
     {
@@ -492,6 +644,6 @@
             PCDBGFREGDESC pDesc = &pSet->paDescs[enmReg];
 
-            puValue->au64[0] = puValue->au64[1] = 0;
-            rc = pDesc->pfnGet(pSet->uUserArg.pv, pDesc, puValue);
+            pValue->au64[0] = pValue->au64[1] = 0;
+            rc = pDesc->pfnGet(pSet->uUserArg.pv, pDesc, pValue);
             if (RT_SUCCESS(rc))
             {
@@ -503,9 +655,9 @@
                     rc = VINF_SUCCESS;
                 else
-                    rc = dbgfR3RegValCast(puValue, pDesc->enmType, enmType);
+                    rc = dbgfR3RegValCast(pValue, pDesc->enmType, enmType);
             }
         }
         else
-            rc = VERR_DBGF_INVALID_REGISTER;
+            rc = VERR_DBGF_REGISTER_NOT_FOUND;
     }
     else
@@ -523,5 +675,5 @@
  * @retval  VERR_INVALID_VM_HANDLE
  * @retval  VERR_INVALID_CPU_ID
- * @retval  VERR_DBGF_INVALID_REGISTER
+ * @retval  VERR_DBGF_REGISTER_NOT_FOUND
  * @retval  VERR_DBGF_UNSUPPORTED_CAST
  * @retval  VINF_DBGF_TRUNCATED_REGISTER
@@ -554,5 +706,5 @@
  * @retval  VERR_INVALID_VM_HANDLE
  * @retval  VERR_INVALID_CPU_ID
- * @retval  VERR_DBGF_INVALID_REGISTER
+ * @retval  VERR_DBGF_REGISTER_NOT_FOUND
  * @retval  VERR_DBGF_UNSUPPORTED_CAST
  * @retval  VINF_DBGF_TRUNCATED_REGISTER
@@ -586,5 +738,5 @@
  * @retval  VERR_INVALID_VM_HANDLE
  * @retval  VERR_INVALID_CPU_ID
- * @retval  VERR_DBGF_INVALID_REGISTER
+ * @retval  VERR_DBGF_REGISTER_NOT_FOUND
  * @retval  VERR_DBGF_UNSUPPORTED_CAST
  * @retval  VINF_DBGF_TRUNCATED_REGISTER
@@ -618,5 +770,5 @@
  * @retval  VERR_INVALID_VM_HANDLE
  * @retval  VERR_INVALID_CPU_ID
- * @retval  VERR_DBGF_INVALID_REGISTER
+ * @retval  VERR_DBGF_REGISTER_NOT_FOUND
  * @retval  VERR_DBGF_UNSUPPORTED_CAST
  * @retval  VINF_DBGF_TRUNCATED_REGISTER
@@ -648,5 +800,5 @@
  *
  * @retval  VINF_SUCCESS
- * @retval  VERR_DBGF_INVALID_REGISTER
+ * @retval  VERR_DBGF_REGISTER_NOT_FOUND
  *
  * @param   pVCpu               The current CPU.
@@ -681,5 +833,5 @@
 
         DBGFREG const enmReg = pReg->enmReg;
-        AssertMsgReturn(enmReg >= 0 && enmReg <= DBGFREG_END, ("%d (%#x)\n", enmReg, enmReg), VERR_DBGF_INVALID_REGISTER);
+        AssertMsgReturn(enmReg >= 0 && enmReg <= DBGFREG_END, ("%d (%#x)\n", enmReg, enmReg), VERR_DBGF_REGISTER_NOT_FOUND);
         if (enmReg != DBGFREG_END)
         {
@@ -728,5 +880,5 @@
  * @retval  VERR_INVALID_VM_HANDLE
  * @retval  VERR_INVALID_CPU_ID
- * @retval  VERR_DBGF_INVALID_REGISTER
+ * @retval  VERR_DBGF_REGISTER_NOT_FOUND
  *
  * @param   pVM                 The VM handle.
@@ -751,5 +903,5 @@
     {
         DBGFREG enmReg = paRegs[iReg].enmReg;
-        AssertMsgReturn(enmReg < DBGFREG_END && enmReg >= DBGFREG_AL, ("%d (%#x)", enmReg, enmReg), VERR_DBGF_INVALID_REGISTER);
+        AssertMsgReturn(enmReg < DBGFREG_END && enmReg >= DBGFREG_AL, ("%d (%#x)", enmReg, enmReg), VERR_DBGF_REGISTER_NOT_FOUND);
     }
 
@@ -809,4 +961,6 @@
  * @returns Pointer to read-only register name (lower case).  NULL if the
  *          parameters are invalid.
+ *
+ * @param   pVM                 The VM handle.
  * @param   enmReg              The register identifier.
  * @param   enmType             The register type.  This is for sort out
@@ -814,12 +968,16 @@
  *                              the standard name.
  */
-VMMR3DECL(const char *) DBGFR3RegCpuName(DBGFREG enmReg, DBGFREGVALTYPE enmType)
+VMMR3DECL(const char *) DBGFR3RegCpuName(PVM pVM, DBGFREG enmReg, DBGFREGVALTYPE enmType)
 {
     AssertReturn(enmReg >= DBGFREG_AL && enmReg < DBGFREG_END, NULL);
     AssertReturn(enmType >= DBGFREGVALTYPE_INVALID && enmType < DBGFREGVALTYPE_END, NULL);
-
-#if 0 /** @todo need the optimization */
-    PCDBGFREGDESC   pDesc  = &g_aDbgfRegDescs[enmReg];
-    PCDBGFREGALIAS  pAlias = pDesc->paAliases;
+    VM_ASSERT_VALID_EXT_RETURN(pVM, NULL);
+
+    PCDBGFREGSET    pSet    = pVM->aCpus[0].dbgf.s.pRegSet;
+    if (RT_UNLIKELY(!pSet))
+        return NULL;
+
+    PCDBGFREGDESC   pDesc   = &pSet->paDescs[enmReg];
+    PCDBGFREGALIAS  pAlias  = pDesc->paAliases;
     if (   pAlias
         && pDesc->enmType != enmType
@@ -835,8 +993,555 @@
 
     return pDesc->pszName;
-#else
-    return NULL;
-#endif
-}
-
-/** @todo Implementing missing APIs. */
+}
+
+
+/**
+ * Fold the string to lower case and copy it into the destination buffer.
+ *
+ * @returns Number of folder characters, -1 on overflow.
+ * @param   pszSrc              The source string.
+ * @param   cchSrc              How much to fold and copy.
+ * @param   pszDst              The output buffer.
+ * @param   cbDst               The size of the output buffer.
+ */
+static ssize_t dbgfR3RegCopyToLower(const char *pszSrc, size_t cchSrc, char *pszDst, size_t cbDst)
+{
+    ssize_t cchFolded = 0;
+    char    ch;
+    while (cchSrc-- > 0 && (ch = *pszSrc++))
+    {
+        if (RT_UNLIKELY(cbDst <= 1))
+            return -1;
+        cbDst--;
+
+        char chLower = RT_C_TO_LOWER(ch);
+        cchFolded += chLower != ch;
+        *pszDst++ = chLower;
+    }
+    if (RT_UNLIKELY(!cbDst))
+        return -1;
+    *pszDst = '\0';
+    return cchFolded;
+}
+
+
+/**
+ * Resolves the register name.
+ *
+ * @returns Lookup record.
+ * @param   pVM                 The VM handle.
+ * @param   idDefCpu            The default CPU ID set.
+ * @param   pszReg              The register name.
+ */
+static PCDBGFREGLOOKUP dbgfR3RegResolve(PVM pVM, VMCPUID idDefCpu, const char *pszReg)
+{
+    DBGF_REG_DB_LOCK_READ(pVM);
+
+    /* Try looking up the name without any case folding or cpu prefixing. */
+    PCDBGFREGLOOKUP pLookupRec = (PCDBGFREGLOOKUP)RTStrSpaceGet(&pVM->dbgf.s.RegSpace, pszReg);
+    if (!pLookupRec)
+    {
+        char szName[DBGF_REG_MAX_NAME * 4 + 16];
+
+        /* Lower case it and try again. */
+        ssize_t cchFolded = dbgfR3RegCopyToLower(pszReg, RTSTR_MAX, szName, sizeof(szName) - DBGF_REG_MAX_NAME);
+        if (cchFolded > 0)
+            pLookupRec = (PCDBGFREGLOOKUP)RTStrSpaceGet(&pVM->dbgf.s.RegSpace, szName);
+        if (   !pLookupRec
+            && cchFolded >= 0
+            && idDefCpu != VMCPUID_ANY)
+        {
+            /* Prefix it with the specified CPU set. */
+            size_t cchCpuSet = RTStrPrintf(szName, sizeof(szName), "cpu%u.", idDefCpu);
+            dbgfR3RegCopyToLower(pszReg, RTSTR_MAX, &szName[cchCpuSet], sizeof(szName) - cchCpuSet);
+            pLookupRec = (PCDBGFREGLOOKUP)RTStrSpaceGet(&pVM->dbgf.s.RegSpace, szName);
+        }
+    }
+
+    DBGF_REG_DB_UNLOCK_READ(pVM);
+    return pLookupRec;
+}
+
+
+/**
+ * Performs a left shift on a RTUINT128U value.
+ *
+ * @returns pVal.
+ * @param   pVal                The value to shift (input/output).
+ * @param   cBits               The number of bits to shift it.  Negative
+ *                              numbers are treated as right shifts.
+ */
+static PRTUINT128U dbgfR3RegU128_ShiftLeft(PRTUINT128U pVal, int cBits)
+{
+    RTUINT128U const InVal = *pVal;
+
+    if (cBits >= 0)
+    {
+        if (cBits >= 128)
+            pVal->s.Lo  = pVal->s.Hi = 0;
+        else if (cBits >= 64)
+        {
+            pVal->s.Lo  = 0;
+            pVal->s.Hi  = InVal.s.Lo << (cBits - 64);
+        }
+        else
+        {
+            pVal->s.Hi  = InVal.s.Hi << cBits;
+            pVal->s.Hi |= InVal.s.Lo >> (64 - cBits);
+            pVal->s.Lo  = InVal.s.Lo << cBits;
+        }
+    }
+    else
+    {
+        /* (right shift) */
+        cBits = -cBits;
+        if (cBits >= 128)
+            pVal->s.Lo  = pVal->s.Hi = 0;
+        else if (cBits >= 64)
+        {
+            pVal->s.Hi  = 0;
+            pVal->s.Lo  = InVal.s.Hi >> (cBits - 64);
+        }
+        else
+        {
+            pVal->s.Lo  = InVal.s.Lo >> cBits;
+            pVal->s.Lo |= InVal.s.Hi << (64 - cBits);
+            pVal->s.Hi  = InVal.s.Hi >> cBits;
+        }
+    }
+    return pVal;
+}
+
+
+/**
+ * ANDs the RTUINT128U value against a bitmask made up of the first @a cBits
+ * bits.
+ *
+ * @returns pVal.
+ * @param   pVal                The value to shift (input/output).
+ * @param   cBits               The number of bits in the AND mask.
+ */
+static PRTUINT128U dbgfR3RegU128_AndNFirstBits(PRTUINT128U pVal, unsigned cBits)
+{
+    if (cBits <= 64)
+    {
+        pVal->s.Hi  = 0;
+        pVal->s.Lo &= RT_BIT_64(cBits) - 1;
+    }
+    else if (cBits < 128)
+        pVal->s.Hi &= RT_BIT_64(cBits - 64) - 1;
+    return pVal;
+}
+
+
+/**
+ * On CPU worker for the register queries, used by dbgfR3RegNmQueryWorker.
+ *
+ * @returns VBox status code.
+ *
+ * @param   pVM                 The VM handle.
+ * @param   pLookupRec          The register lookup record.
+ * @param   enmType             The desired return type.
+ * @param   pValue              Where to return the register value.
+ * @param   penmType            Where to store the register value type.
+ *                              Optional.
+ */
+static DECLCALLBACK(int) dbgfR3RegNmQueryWorkerOnCpu(PVM pVM, PCDBGFREGLOOKUP pLookupRec, DBGFREGVALTYPE enmType,
+                                                     PDBGFREGVAL pValue, PDBGFREGVALTYPE penmType)
+{
+    PCDBGFREGDESC       pDesc        = pLookupRec->pDesc;
+    PCDBGFREGSET        pSet         = pLookupRec->pSet;
+    PCDBGFREGSUBFIELD   pSubField    = pLookupRec->pSubField;
+    DBGFREGVALTYPE      enmValueType = pDesc->enmType;
+    int                 rc;
+
+    /*
+     * Get the register or sub-field value.
+     */
+    dbgfR3RegValClear(pValue);
+    if (!pSubField)
+        rc = pDesc->pfnGet(pSet->uUserArg.pv, pDesc, pValue);
+    else
+    {
+        if (pSubField->pfnGet)
+        {
+            rc = pSubField->pfnGet(pSet->uUserArg.pv, pSubField, &pValue->u128);
+            enmValueType = DBGFREGVALTYPE_U128;
+        }
+        else
+        {
+            rc = pDesc->pfnGet(pSet->uUserArg.pv, pDesc, pValue);
+            if (RT_SUCCESS(rc))
+            {
+                rc = dbgfR3RegValCast(pValue, enmValueType, DBGFREGVALTYPE_U128);
+                if (RT_SUCCESS(rc))
+                {
+                    dbgfR3RegU128_ShiftLeft(&pValue->u128, -pSubField->iFirstBit);
+                    dbgfR3RegU128_AndNFirstBits(&pValue->u128, pSubField->cBits);
+                    if (pSubField->cShift)
+                        dbgfR3RegU128_ShiftLeft(&pValue->u128, pSubField->cShift);
+                }
+            }
+        }
+        if (RT_SUCCESS(rc))
+        {
+            unsigned const cBits = pSubField->cBits + pSubField->cShift;
+            if (cBits <= 8)
+                enmValueType = DBGFREGVALTYPE_U8;
+            else if (cBits <= 16)
+                enmValueType = DBGFREGVALTYPE_U16;
+            else if (cBits <= 32)
+                enmValueType = DBGFREGVALTYPE_U32;
+            else if (cBits <= 64)
+                enmValueType = DBGFREGVALTYPE_U64;
+            else
+                enmValueType = DBGFREGVALTYPE_U128;
+            rc = dbgfR3RegValCast(pValue, DBGFREGVALTYPE_U128, enmValueType);
+        }
+    }
+    if (RT_SUCCESS(rc))
+    {
+        /*
+         * Do the cast if the desired return type doesn't match what
+         * the getter returned.
+         */
+        if (   enmValueType == enmType
+            || enmType == DBGFREGVALTYPE_END)
+        {
+            rc = VINF_SUCCESS;
+            if (penmType)
+                *penmType = enmValueType;
+        }
+        else
+        {
+            rc = dbgfR3RegValCast(pValue, enmValueType, enmType);
+            if (penmType)
+                *penmType = RT_SUCCESS(rc) ? enmType : enmValueType;
+        }
+    }
+
+    return rc;
+}
+
+
+/**
+ * Worker for the register queries.
+ *
+ * @returns VBox status code.
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_INVALID_VM_HANDLE
+ * @retval  VERR_INVALID_CPU_ID
+ * @retval  VERR_DBGF_REGISTER_NOT_FOUND
+ * @retval  VERR_DBGF_UNSUPPORTED_CAST
+ * @retval  VINF_DBGF_TRUNCATED_REGISTER
+ * @retval  VINF_DBGF_ZERO_EXTENDED_REGISTER
+ *
+ * @param   pVM                 The VM handle.
+ * @param   idDefCpu            The virtual CPU ID for the default CPU register
+ *                              set.
+ * @param   pszReg              The register to query.
+ * @param   enmType             The desired return type.
+ * @param   pValue              Where to return the register value.
+ * @param   penmType            Where to store the register value type.
+ *                              Optional.
+ */
+static DECLCALLBACK(int) dbgfR3RegNmQueryWorker(PVM pVM, VMCPUID idDefCpu, const char *pszReg, DBGFREGVALTYPE enmType,
+                                                PDBGFREGVAL pValue, PDBGFREGVALTYPE penmType)
+{
+    /*
+     * Validate input.
+     */
+    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
+    AssertReturn(idDefCpu < pVM->cCpus || idDefCpu == VMCPUID_ANY, VERR_INVALID_CPU_ID);
+    AssertPtrReturn(pszReg, VERR_INVALID_POINTER);
+
+    Assert(enmType > DBGFREGVALTYPE_INVALID && enmType <= DBGFREGVALTYPE_END);
+    AssertPtr(pValue);
+
+    /*
+     * Resolve the register and call the getter on the relevant CPU.
+     */
+    PCDBGFREGLOOKUP pLookupRec = dbgfR3RegResolve(pVM, idDefCpu, pszReg);
+    if (pLookupRec)
+    {
+        if (pLookupRec->pSet->enmType == DBGFREGSETTYPE_CPU)
+            idDefCpu = pLookupRec->pSet->uUserArg.pVCpu->idCpu;
+        return VMR3ReqCallWait(pVM, idDefCpu, (PFNRT)dbgfR3RegNmQueryWorkerOnCpu, 5, pVM, pLookupRec, enmType, pValue, penmType);
+    }
+    return VERR_DBGF_REGISTER_NOT_FOUND;
+}
+
+
+/**
+ * Queries a descriptor table register value.
+ *
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_INVALID_VM_HANDLE
+ * @retval  VERR_INVALID_CPU_ID
+ * @retval  VERR_DBGF_REGISTER_NOT_FOUND
+ *
+ * @param   pVM                 The VM handle.
+ * @param   idDefCpu            The default target CPU ID, VMCPUID_ANY if not
+ *                              applicable.
+ * @param   pszReg              The register that's being queried.  Except for
+ *                              CPU registers, this must be on the form
+ *                              "set.reg[.sub]".
+ * @param   pValue              Where to store the register value.
+ * @param   penmType            Where to store the register value type.
+ */
+VMMR3DECL(int) DBGFR3RegNmQuery(PVM pVM, VMCPUID idDefCpu, const char *pszReg, PDBGFREGVAL pValue, PDBGFREGVALTYPE penmType)
+{
+    return dbgfR3RegNmQueryWorker(pVM, idDefCpu, pszReg, DBGFREGVALTYPE_END, pValue, penmType);
+}
+
+
+/**
+ * Queries a 8-bit register value.
+ *
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_INVALID_VM_HANDLE
+ * @retval  VERR_INVALID_CPU_ID
+ * @retval  VERR_DBGF_REGISTER_NOT_FOUND
+ * @retval  VERR_DBGF_UNSUPPORTED_CAST
+ * @retval  VINF_DBGF_TRUNCATED_REGISTER
+ *
+ * @param   pVM                 The VM handle.
+ * @param   idDefCpu            The default target CPU ID, VMCPUID_ANY if not
+ *                              applicable.
+ * @param   pszReg              The register that's being queried.  Except for
+ *                              CPU registers, this must be on the form
+ *                              "set.reg[.sub]".
+ * @param   pu8                 Where to store the register value.
+ */
+VMMR3DECL(int) DBGFR3RegNmQueryU8(PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint8_t *pu8)
+{
+    DBGFREGVAL Value;
+    int rc = dbgfR3RegNmQueryWorker(pVM, idDefCpu, pszReg, DBGFREGVALTYPE_U8, &Value, NULL);
+    if (RT_SUCCESS(rc))
+        *pu8 = Value.u8;
+    else
+        *pu8 = 0;
+    return rc;
+}
+
+
+/**
+ * Queries a 16-bit register value.
+ *
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_INVALID_VM_HANDLE
+ * @retval  VERR_INVALID_CPU_ID
+ * @retval  VERR_DBGF_REGISTER_NOT_FOUND
+ * @retval  VERR_DBGF_UNSUPPORTED_CAST
+ * @retval  VINF_DBGF_TRUNCATED_REGISTER
+ * @retval  VINF_DBGF_ZERO_EXTENDED_REGISTER
+ *
+ * @param   pVM                 The VM handle.
+ * @param   idDefCpu            The default target CPU ID, VMCPUID_ANY if not
+ *                              applicable.
+ * @param   pszReg              The register that's being queried.  Except for
+ *                              CPU registers, this must be on the form
+ *                              "set.reg[.sub]".
+ * @param   pu16                Where to store the register value.
+ */
+VMMR3DECL(int) DBGFR3RegNmQueryU16(PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint16_t *pu16)
+{
+    DBGFREGVAL Value;
+    int rc = dbgfR3RegNmQueryWorker(pVM, idDefCpu, pszReg, DBGFREGVALTYPE_U16, &Value, NULL);
+    if (RT_SUCCESS(rc))
+        *pu16 = Value.u16;
+    else
+        *pu16 = 0;
+    return rc;
+}
+
+
+/**
+ * Queries a 32-bit register value.
+ *
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_INVALID_VM_HANDLE
+ * @retval  VERR_INVALID_CPU_ID
+ * @retval  VERR_DBGF_REGISTER_NOT_FOUND
+ * @retval  VERR_DBGF_UNSUPPORTED_CAST
+ * @retval  VINF_DBGF_TRUNCATED_REGISTER
+ * @retval  VINF_DBGF_ZERO_EXTENDED_REGISTER
+ *
+ * @param   pVM                 The VM handle.
+ * @param   idDefCpu            The default target CPU ID, VMCPUID_ANY if not
+ *                              applicable.
+ * @param   pszReg              The register that's being queried.  Except for
+ *                              CPU registers, this must be on the form
+ *                              "set.reg[.sub]".
+ * @param   pu32                Where to store the register value.
+ */
+VMMR3DECL(int) DBGFR3RegNmQueryU32(PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint32_t *pu32)
+{
+    DBGFREGVAL Value;
+    int rc = dbgfR3RegNmQueryWorker(pVM, idDefCpu, pszReg, DBGFREGVALTYPE_U32, &Value, NULL);
+    if (RT_SUCCESS(rc))
+        *pu32 = Value.u32;
+    else
+        *pu32 = 0;
+    return rc;
+}
+
+
+/**
+ * Queries a 64-bit register value.
+ *
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_INVALID_VM_HANDLE
+ * @retval  VERR_INVALID_CPU_ID
+ * @retval  VERR_DBGF_REGISTER_NOT_FOUND
+ * @retval  VERR_DBGF_UNSUPPORTED_CAST
+ * @retval  VINF_DBGF_TRUNCATED_REGISTER
+ * @retval  VINF_DBGF_ZERO_EXTENDED_REGISTER
+ *
+ * @param   pVM                 The VM handle.
+ * @param   idDefCpu            The default target CPU ID, VMCPUID_ANY if not
+ *                              applicable.
+ * @param   pszReg              The register that's being queried.  Except for
+ *                              CPU registers, this must be on the form
+ *                              "set.reg[.sub]".
+ * @param   pu64                Where to store the register value.
+ */
+VMMR3DECL(int) DBGFR3RegNmQueryU64(PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint64_t *pu64)
+{
+    DBGFREGVAL Value;
+    int rc = dbgfR3RegNmQueryWorker(pVM, idDefCpu, pszReg, DBGFREGVALTYPE_U64, &Value, NULL);
+    if (RT_SUCCESS(rc))
+        *pu64 = Value.u64;
+    else
+        *pu64 = 0;
+    return rc;
+}
+
+
+/**
+ * Queries a 128-bit register value.
+ *
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_INVALID_VM_HANDLE
+ * @retval  VERR_INVALID_CPU_ID
+ * @retval  VERR_DBGF_REGISTER_NOT_FOUND
+ * @retval  VERR_DBGF_UNSUPPORTED_CAST
+ * @retval  VINF_DBGF_TRUNCATED_REGISTER
+ * @retval  VINF_DBGF_ZERO_EXTENDED_REGISTER
+ *
+ * @param   pVM                 The VM handle.
+ * @param   idDefCpu            The default target CPU ID, VMCPUID_ANY if not
+ *                              applicable.
+ * @param   pszReg              The register that's being queried.  Except for
+ *                              CPU registers, this must be on the form
+ *                              "set.reg[.sub]".
+ * @param   pu128               Where to store the register value.
+ */
+VMMR3DECL(int) DBGFR3RegNmQueryU128(PVM pVM, VMCPUID idDefCpu, const char *pszReg, PRTUINT128U pu128)
+{
+    DBGFREGVAL Value;
+    int rc = dbgfR3RegNmQueryWorker(pVM, idDefCpu, pszReg, DBGFREGVALTYPE_U128, &Value, NULL);
+    if (RT_SUCCESS(rc))
+        *pu128 = Value.u128;
+    else
+        pu128->s.Hi = pu128->s.Lo = 0;
+    return rc;
+}
+
+
+/**
+ * Queries a long double register value.
+ *
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_INVALID_VM_HANDLE
+ * @retval  VERR_INVALID_CPU_ID
+ * @retval  VERR_DBGF_REGISTER_NOT_FOUND
+ * @retval  VERR_DBGF_UNSUPPORTED_CAST
+ * @retval  VINF_DBGF_TRUNCATED_REGISTER
+ * @retval  VINF_DBGF_ZERO_EXTENDED_REGISTER
+ *
+ * @param   pVM                 The VM handle.
+ * @param   idDefCpu            The default target CPU ID, VMCPUID_ANY if not
+ *                              applicable.
+ * @param   pszReg              The register that's being queried.  Except for
+ *                              CPU registers, this must be on the form
+ *                              "set.reg[.sub]".
+ * @param   plrd                Where to store the register value.
+ */
+VMMR3DECL(int) DBGFR3RegNmQueryLrd(PVM pVM, VMCPUID idDefCpu, const char *pszReg, long double *plrd)
+{
+    DBGFREGVAL Value;
+    int rc = dbgfR3RegNmQueryWorker(pVM, idDefCpu, pszReg, DBGFREGVALTYPE_LRD, &Value, NULL);
+    if (RT_SUCCESS(rc))
+        *plrd = Value.lrd;
+    else
+        *plrd = 0;
+    return rc;
+}
+
+
+/**
+ * Queries a descriptor table register value.
+ *
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_INVALID_VM_HANDLE
+ * @retval  VERR_INVALID_CPU_ID
+ * @retval  VERR_DBGF_REGISTER_NOT_FOUND
+ * @retval  VERR_DBGF_UNSUPPORTED_CAST
+ * @retval  VINF_DBGF_TRUNCATED_REGISTER
+ * @retval  VINF_DBGF_ZERO_EXTENDED_REGISTER
+ *
+ * @param   pVM                 The VM handle.
+ * @param   idDefCpu            The default target CPU ID, VMCPUID_ANY if not
+ *                              applicable.
+ * @param   pszReg              The register that's being queried.  Except for
+ *                              CPU registers, this must be on the form
+ *                              "set.reg[.sub]".
+ * @param   pu64Base            Where to store the register base value.
+ * @param   pu32Limit           Where to store the register limit value.
+ */
+VMMR3DECL(int) DBGFR3RegNmQueryXdtr(PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint64_t *pu64Base, uint32_t *pu32Limit)
+{
+    DBGFREGVAL Value;
+    int rc = dbgfR3RegNmQueryWorker(pVM, idDefCpu, pszReg, DBGFREGVALTYPE_DTR, &Value, NULL);
+    if (RT_SUCCESS(rc))
+    {
+        *pu64Base  = Value.dtr.u64Base;
+        *pu32Limit = Value.dtr.u32Limit;
+    }
+    else
+    {
+        *pu64Base  = 0;
+        *pu32Limit = 0;
+    }
+    return rc;
+}
+
+
+/// @todo VMMR3DECL(int) DBGFR3RegNmQueryBatch(PVM pVM,VMCPUID idDefCpu, DBGFREGENTRYNM paRegs, size_t cRegs);
+
+
+/**
+ * Gets the number of registers returned by DBGFR3RegNmQueryAll.
+ *
+ * @returns VBox status code.
+ * @param   pVM                 The VM handle.
+ * @param   pcRegs              Where to return the register count.
+ */
+VMMR3DECL(int) DBGFR3RegNmQueryAllCount(PVM pVM, size_t *pcRegs)
+{
+    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
+    *pcRegs = pVM->dbgf.s.cRegs;
+    return VINF_SUCCESS;
+}
+
+
+VMMR3DECL(int) DBGFR3RegNmQueryAll(PVM pVM, DBGFREGENTRYNM paRegs, size_t cRegs)
+{
+    return VERR_NOT_IMPLEMENTED;
+}
+
+
+/// @todo VMMR3DECL(int) DBGFR3RegNmPrintf(PVM pVM, VMCPUID idDefCpu, char pszBuf, size_t cbBuf, const char *pszFormat, ...);
+/// @todo VMMR3DECL(int) DBGFR3RegNmPrintfV(PVM pVM, VMCPUID idDefCpu, char pszBuf, size_t cbBuf, const char *pszFormat, ...);
+
Index: /trunk/src/VBox/VMM/include/DBGFInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/DBGFInternal.h	(revision 35465)
+++ /trunk/src/VBox/VMM/include/DBGFInternal.h	(revision 35466)
@@ -275,6 +275,12 @@
     /** The register database lock. */
     RTSEMRW                     hRegDbLock;
+    /** String space for looking up registers.  (Protected by hRegDbLock.) */
+    R3PTRTYPE(RTSTRSPACE)       RegSpace;
     /** String space holding the register sets. (Protected by hRegDbLock.)  */
     R3PTRTYPE(RTSTRSPACE)       RegSetSpace;
+    /** The number of registers (aliases and sub-fields not counted). */
+    uint32_t                    cRegs;
+    /** Alignment padding. */
+    uint32_t                    Alignment2;
 
     /** The current Guest OS digger. */
@@ -310,5 +316,8 @@
 
     /** Padding the structure to 16 bytes. */
-    uint8_t                 abReserved[3];
+    bool                    afReserved[7];
+
+    /** The register set for this CPU.  Can be NULL. */
+    R3PTRTYPE(struct DBGFREGSET *) pRegSet;
 } DBGFCPU;
 /** Pointer to DBGFCPU data. */
@@ -322,4 +331,6 @@
 int  dbgfR3InfoTerm(PVM pVM);
 void dbgfR3OSTerm(PVM pVM);
+int  dbgfR3RegInit(PVM pVM);
+void dbgfR3RegTerm(PVM pVM);
 int  dbgfR3SymInit(PVM pVM);
 int  dbgfR3SymTerm(PVM pVM);
Index: /trunk/src/VBox/VMM/testcase/tstVMStructRC.cpp
===================================================================
--- /trunk/src/VBox/VMM/testcase/tstVMStructRC.cpp	(revision 35465)
+++ /trunk/src/VBox/VMM/testcase/tstVMStructRC.cpp	(revision 35466)
@@ -134,4 +134,5 @@
     GEN_CHECK_OFF(DBGFCPU, iActiveBp);
     GEN_CHECK_OFF(DBGFCPU, fSingleSteppingRaw);
+    GEN_CHECK_OFF(DBGFCPU, pRegSet);
 
     GEN_CHECK_SIZE(EM);
