Bug 574668 - unexpected DWARF Register Number for fctrl and fstat in i386
diff --git a/agent/machine/i386/tcf/cpu-regs-gdb.h b/agent/machine/i386/tcf/cpu-regs-gdb.h
index d5fa9b8..02d4a37 100644
--- a/agent/machine/i386/tcf/cpu-regs-gdb.h
+++ b/agent/machine/i386/tcf/cpu-regs-gdb.h
@@ -45,8 +45,8 @@
 "  <reg name='st5' bitsize='80' type='i387_ext'/>\n"
 "  <reg name='st6' bitsize='80' type='i387_ext'/>\n"
 "  <reg name='st7' bitsize='80' type='i387_ext'/>\n"
-"  <reg name='fctrl' bitsize='32' type='int' group='float' id='65'/>\n"
-"  <reg name='fstat' bitsize='32' type='int' group='float' id='66'/>\n"
+"  <reg name='fctrl' bitsize='32' type='int' group='float'/>\n"
+"  <reg name='fstat' bitsize='32' type='int' group='float'/>\n"
 "  <reg name='ftag' bitsize='32' type='int' group='float'/>\n"
 "  <reg name='fiseg' bitsize='32' type='int' group='float'/>\n"
 "  <reg name='fioff' bitsize='32' type='int' group='float'/>\n"
diff --git a/agent/machine/x86_64/tcf/cpu-regs-gdb.h b/agent/machine/x86_64/tcf/cpu-regs-gdb.h
index c569008..6ef3ee8 100644
--- a/agent/machine/x86_64/tcf/cpu-regs-gdb.h
+++ b/agent/machine/x86_64/tcf/cpu-regs-gdb.h
@@ -76,9 +76,9 @@
 "  <reg name='fstat' bitsize='32' type='int' group='float' id='66'/>\n"
 "  <reg name='ftag' bitsize='32' type='int' group='float'/>\n"
 "  <reg name='fiseg' bitsize='32' type='int' group='float'/>\n"
-"  <reg name='fioff' bitsize='32' type='int' group='float'/>\n"
+"  <reg name='fioff' bitsize='64' type='int' group='float'/>\n"
 "  <reg name='foseg' bitsize='32' type='int' group='float'/>\n"
-"  <reg name='fooff' bitsize='32' type='int' group='float'/>\n"
+"  <reg name='fooff' bitsize='64' type='int' group='float'/>\n"
 "  <reg name='fop' bitsize='32' type='int' group='float'/>\n"
 "</feature>\n"
 "<feature name='org.gnu.gdb.i386.sse'>\n"
diff --git a/agent/machine/x86_64/tcf/cpudefs-mdep.c b/agent/machine/x86_64/tcf/cpudefs-mdep.c
index 5583828..abed12d 100644
--- a/agent/machine/x86_64/tcf/cpudefs-mdep.c
+++ b/agent/machine/x86_64/tcf/cpudefs-mdep.c
@@ -81,8 +81,8 @@
     { "st6", REG_OFFSET(FloatSave.RegisterArea) + 60, 10, 39, 39, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 24 },
     { "st7", REG_OFFSET(FloatSave.RegisterArea) + 70, 10, 40, 40, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 24 },
 
-    { "control", REG_OFFSET(FloatSave.ControlWord),  2, 65, 65, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 24 },
-    { "status",  REG_OFFSET(FloatSave.StatusWord),   2, 66, 66, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 24 },
+    { "control", REG_OFFSET(FloatSave.ControlWord),  2, -1, -1, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 24 },
+    { "status",  REG_OFFSET(FloatSave.StatusWord),   2, -1, -1, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 24 },
     { "tag",     REG_OFFSET(FloatSave.TagWord),      1, -1, -1, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 24 },
 
     { "xmm",    0, 0, -1, -1, 0, 0, 1, 1 }, /* 36 */
@@ -455,39 +455,41 @@
     { "swd",    REG_OFFSET(fp.swd),  2, 66, 66, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 26 },
     { "ftw",    REG_OFFSET(fp.ftw),  2, -1, -1, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 26 },
     { "fop",    REG_OFFSET(fp.fop),  2, -1, -1, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 26 },
-    { "rip",    REG_OFFSET(fp.rip),  8, -1, -1, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 26 },
-    { "rdp",    REG_OFFSET(fp.rdp),  8, -1, -1, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 26 },
+    { "fip",    REG_OFFSET(fp.rip),  8, -1, -1, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 26 },
+    { "fcs",    REG_OFFSET(user.regs.cs),  4, -1, -1, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 26 },
+    { "foo",    REG_OFFSET(fp.rdp),  8, -1, -1, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 26 },
+    { "fos",    REG_OFFSET(user.regs.ds),  4, -1, -1, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 26 },
 
     { "mxcsr",      REG_OFFSET(fp.mxcsr),       4, 64, 64, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 26 },
     { "mxcr_mask",  REG_OFFSET(fp.mxcr_mask),   4, -1, -1, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 26 },
 
     { "xmm",    0, 0, -1, -1, 0, 0, 1, 1 },
 
-    { "xmm0",   REG_OFFSET(fp.xmm_space) +   0, 16, 17, 17, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 43 },
-    { "xmm1",   REG_OFFSET(fp.xmm_space) +  16, 16, 18, 18, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 43 },
-    { "xmm2",   REG_OFFSET(fp.xmm_space) +  32, 16, 19, 19, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 43 },
-    { "xmm3",   REG_OFFSET(fp.xmm_space) +  48, 16, 20, 20, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 43 },
-    { "xmm4",   REG_OFFSET(fp.xmm_space) +  64, 16, 21, 21, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 43 },
-    { "xmm5",   REG_OFFSET(fp.xmm_space) +  80, 16, 22, 22, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 43 },
-    { "xmm6",   REG_OFFSET(fp.xmm_space) +  96, 16, 23, 23, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 43 },
-    { "xmm7",   REG_OFFSET(fp.xmm_space) + 112, 16, 24, 24, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 43 },
-    { "xmm8",   REG_OFFSET(fp.xmm_space) + 128, 16, 25, 25, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 43 },
-    { "xmm9",   REG_OFFSET(fp.xmm_space) + 144, 16, 26, 26, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 43 },
-    { "xmm10",  REG_OFFSET(fp.xmm_space) + 160, 16, 27, 27, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 43 },
-    { "xmm11",  REG_OFFSET(fp.xmm_space) + 176, 16, 28, 28, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 43 },
-    { "xmm12",  REG_OFFSET(fp.xmm_space) + 192, 16, 29, 29, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 43 },
-    { "xmm13",  REG_OFFSET(fp.xmm_space) + 208, 16, 30, 30, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 43 },
-    { "xmm14",  REG_OFFSET(fp.xmm_space) + 224, 16, 31, 31, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 43 },
-    { "xmm15",  REG_OFFSET(fp.xmm_space) + 240, 16, 32, 32, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 43 },
+    { "xmm0",   REG_OFFSET(fp.xmm_space) +   0, 16, 17, 17, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 45 },
+    { "xmm1",   REG_OFFSET(fp.xmm_space) +  16, 16, 18, 18, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 45 },
+    { "xmm2",   REG_OFFSET(fp.xmm_space) +  32, 16, 19, 19, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 45 },
+    { "xmm3",   REG_OFFSET(fp.xmm_space) +  48, 16, 20, 20, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 45 },
+    { "xmm4",   REG_OFFSET(fp.xmm_space) +  64, 16, 21, 21, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 45 },
+    { "xmm5",   REG_OFFSET(fp.xmm_space) +  80, 16, 22, 22, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 45 },
+    { "xmm6",   REG_OFFSET(fp.xmm_space) +  96, 16, 23, 23, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 45 },
+    { "xmm7",   REG_OFFSET(fp.xmm_space) + 112, 16, 24, 24, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 45 },
+    { "xmm8",   REG_OFFSET(fp.xmm_space) + 128, 16, 25, 25, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 45 },
+    { "xmm9",   REG_OFFSET(fp.xmm_space) + 144, 16, 26, 26, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 45 },
+    { "xmm10",  REG_OFFSET(fp.xmm_space) + 160, 16, 27, 27, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 45 },
+    { "xmm11",  REG_OFFSET(fp.xmm_space) + 176, 16, 28, 28, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 45 },
+    { "xmm12",  REG_OFFSET(fp.xmm_space) + 192, 16, 29, 29, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 45 },
+    { "xmm13",  REG_OFFSET(fp.xmm_space) + 208, 16, 30, 30, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 45 },
+    { "xmm14",  REG_OFFSET(fp.xmm_space) + 224, 16, 31, 31, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 45 },
+    { "xmm15",  REG_OFFSET(fp.xmm_space) + 240, 16, 32, 32, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 45 },
 
-    { "debug",    0, 0, -1, -1, 0, 0, 1, 1 }, /* 60 */
+    { "debug",    0, 0, -1, -1, 0, 0, 1, 1 }, /* 62 */
 
-    { "dr0",    REG_OFFSET(user.u_debugreg[0]), 8, -1, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, regs_def + 60 },
-    { "dr1",    REG_OFFSET(user.u_debugreg[1]), 8, -1, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, regs_def + 60 },
-    { "dr2",    REG_OFFSET(user.u_debugreg[2]), 8, -1, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, regs_def + 60 },
-    { "dr3",    REG_OFFSET(user.u_debugreg[3]), 8, -1, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, regs_def + 60 },
-    { "dr6",    REG_OFFSET(user.u_debugreg[6]), 8, -1, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, regs_def + 60 },
-    { "dr7",    REG_OFFSET(user.u_debugreg[7]), 8, -1, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, regs_def + 60 },
+    { "dr0",    REG_OFFSET(user.u_debugreg[0]), 8, -1, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, regs_def + 62 },
+    { "dr1",    REG_OFFSET(user.u_debugreg[1]), 8, -1, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, regs_def + 62 },
+    { "dr2",    REG_OFFSET(user.u_debugreg[2]), 8, -1, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, regs_def + 62 },
+    { "dr3",    REG_OFFSET(user.u_debugreg[3]), 8, -1, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, regs_def + 62 },
+    { "dr6",    REG_OFFSET(user.u_debugreg[6]), 8, -1, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, regs_def + 62 },
+    { "dr7",    REG_OFFSET(user.u_debugreg[7]), 8, -1, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, regs_def + 62 },
 
     { "fs_base32", REG_OFFSET(other.fs.base), 4, 158, 158, 0, 0, 0, 1 },
     { "gs_base32", REG_OFFSET(other.gs.base), 4, 159, 159, 0, 0, 0, 1 },
@@ -540,8 +542,8 @@
     { "st6",    REG_OFFSET(other.fpx.st_space) +  96, 10, 39, 39, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 28 },
     { "st7",    REG_OFFSET(other.fpx.st_space) + 112, 10, 40, 40, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 28 },
 
-    { "cwd",    REG_OFFSET(other.fpx.cwd),  2, 65, 65, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 28 },
-    { "swd",    REG_OFFSET(other.fpx.swd),  2, 66, 66, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 28 },
+    { "cwd",    REG_OFFSET(other.fpx.cwd),  2, -1, -1, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 28 },
+    { "swd",    REG_OFFSET(other.fpx.swd),  2, -1, -1, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 28 },
     { "twd",    REG_OFFSET(other.fpx.twd),  2, -1, -1, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 28 },
     { "fop",    REG_OFFSET(other.fpx.fop),  2, -1, -1, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 28 },
     { "fip",    REG_OFFSET(other.fpx.fip),  4, -1, -1, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 28 },
diff --git a/agent/tcf/main/gdb-rsp.c b/agent/tcf/main/gdb-rsp.c
index c4e2dbc..6a2c8ed 100644
--- a/agent/tcf/main/gdb-rsp.c
+++ b/agent/tcf/main/gdb-rsp.c
@@ -321,9 +321,18 @@
     return h;
 }
 
-static RegisterDefinition * find_register(GdbThread * t, GdbRegister * r) {
+static RegisterDefinition * find_register_by_name(GdbThread * t, const char * name) {
     RegisterDefinition ** map = t->regs_nm_map;
-    unsigned n = 0;
+    unsigned n = reg_name_hash(name) & t->regs_nm_map_index_mask;
+    while (map[n] != NULL) {
+        if (strcmp(map[n]->name, name) == 0) return map[n];
+        n = (n + 1) & t->regs_nm_map_index_mask;
+    }
+    return NULL;
+}
+
+static RegisterDefinition * find_register(GdbThread * t, GdbRegister * r) {
+    RegisterDefinition * res = NULL;
 
     if (r->id >= 0) {
         RegisterDefinition * def = get_reg_definitions(t->ctx);
@@ -334,9 +343,10 @@
         }
         return NULL;
     }
-    if (map == NULL) {
+    if (t->regs_nm_map == NULL) {
         unsigned map_len = 0;
         unsigned map_len_p2 = 1;
+        RegisterDefinition ** map = NULL;
         RegisterDefinition * def = get_reg_definitions(t->ctx);
         if (def == NULL) return NULL;
         while (def->name != NULL) {
@@ -356,12 +366,31 @@
         }
         t->regs_nm_map = map;
     }
-    n = reg_name_hash(r->name) & t->regs_nm_map_index_mask;
-    while (map[n] != NULL) {
-        if (strcmp(map[n]->name, r->name) == 0) return map[n];
-        n = (n + 1) & t->regs_nm_map_index_mask;
+    res = find_register_by_name(t, r->name);
+    if (res == NULL) {
+        const char * regs = get_regs(t->process->client);
+        /* Try alternative register names */
+        if (regs == cpu_regs_gdb_i386 || regs == cpu_regs_gdb_x86_64) {
+            static const char * alt_names[] = {
+                "fctrl", "control", "fpcr", "cwd", NULL,
+                "fstat", "status", "fpsr", "swd", NULL,
+                "ftag",  "tag", "fptag", "twd", NULL,
+                "fiseg", "fcs", NULL,
+                "fioff", "fip", NULL,
+                "foseg", "fos", NULL,
+                "fooff", "foo", NULL,
+                NULL
+            };
+            unsigned i = 0;
+            for (; alt_names[i] != NULL && res == NULL; i++) {
+                int b = strcmp(alt_names[i++], r->name) == 0;
+                for (; alt_names[i] != NULL && res == NULL; i++) {
+                    if (b) res = find_register_by_name(t, alt_names[i]);
+                }
+            }
+        }
     }
-    return NULL;
+    return res;
 }
 
 static int open_server(const char * port) {