diff options
author | Andrew Cagney <cagney@redhat.com> | 2002-08-29 18:22:44 +0000 |
---|---|---|
committer | Andrew Cagney <cagney@redhat.com> | 2002-08-29 18:22:44 +0000 |
commit | 6e2f20b77871967fc0053abc19f93068fe3f59ba (patch) | |
tree | bb5ea89cad13955618eb7cb15cd1f530eff93356 | |
parent | 2cf491a821ae8239dd5af2c46755e34a91557945 (diff) | |
download | gdb-6e2f20b77871967fc0053abc19f93068fe3f59ba.tar.gz |
2002-08-28 Andrew Cagney <cagney@redhat.com>
* osabi.c (gdbarch_init_osabi): Allow a NULL abfd.
(gdb_osabi_names): Add "RedBoot".
* osabi.h (gdb_osabi): Add GDB_OSABI_REDBOOT.
* i386-tdep.c (i386_gdbarch_init): Force RedBoot OSABI.
* i386-tdep.h (i386_pseudo_register_read): Declare.
(i386_pseudo_register_write): Declare.
(i386_register_virtual_type): Declare.
(i386_register_reggroup_p): Declare.
* i386-tdep.c (i386_pseudo_register_read): Make global.
(i386_pseudo_register_write): Make global.
(i386_register_reggroup_p): Make global.
(i386_register_virtual_type): Make global.
* config/i386/embed.mt (TDEPFILES): Add i386-rb-tdep.c.
(TM_FILE): Set to tm-embed.h.
* config/i386/tm-embed.h: New file.
* i386-rb-tdep.c: New file. Based on code by Fernando Nasser.
* remote.c (remote_fetch_registers): Call fetch_register_using_p.
(fetch_register_using_p): New function.
(init_remote_state): If defined, use GPACKET_UPPER_BOUND_HACK to
identify a register that isn't in the G packet.
-rw-r--r-- | gdb/ChangeLog | 26 | ||||
-rw-r--r-- | gdb/config/i386/embed.mt | 4 | ||||
-rw-r--r-- | gdb/i386-rb-tdep.c | 862 | ||||
-rw-r--r-- | gdb/i386-tdep.c | 11 | ||||
-rw-r--r-- | gdb/i386-tdep.h | 13 | ||||
-rw-r--r-- | gdb/osabi.c | 4 | ||||
-rw-r--r-- | gdb/osabi.h | 2 | ||||
-rw-r--r-- | gdb/remote.c | 71 |
8 files changed, 986 insertions, 7 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 8641236569c..a7c224bc98d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,29 @@ +2002-08-28 Andrew Cagney <cagney@redhat.com> + + * osabi.c (gdbarch_init_osabi): Allow a NULL abfd. + (gdb_osabi_names): Add "RedBoot". + * osabi.h (gdb_osabi): Add GDB_OSABI_REDBOOT. + * i386-tdep.c (i386_gdbarch_init): Force RedBoot OSABI. + + * i386-tdep.h (i386_pseudo_register_read): Declare. + (i386_pseudo_register_write): Declare. + (i386_register_virtual_type): Declare. + (i386_register_reggroup_p): Declare. + * i386-tdep.c (i386_pseudo_register_read): Make global. + (i386_pseudo_register_write): Make global. + (i386_register_reggroup_p): Make global. + (i386_register_virtual_type): Make global. + + * config/i386/embed.mt (TDEPFILES): Add i386-rb-tdep.c. + (TM_FILE): Set to tm-embed.h. + * config/i386/tm-embed.h: New file. + * i386-rb-tdep.c: New file. Based on code by Fernando Nasser. + + * remote.c (remote_fetch_registers): Call fetch_register_using_p. + (fetch_register_using_p): New function. + (init_remote_state): If defined, use GPACKET_UPPER_BOUND_HACK to + identify a register that isn't in the G packet. + 2002-08-28 Andrew Cagney <ac131313@redhat.com> * infcmd.c (registers_info): Pass start, instead of addr_exp, to diff --git a/gdb/config/i386/embed.mt b/gdb/config/i386/embed.mt index 6925a83501d..76076cfc42d 100644 --- a/gdb/config/i386/embed.mt +++ b/gdb/config/i386/embed.mt @@ -1,3 +1,3 @@ # Target: Embedded Intel 386 -TDEPFILES= i386-tdep.o i387-tdep.o -TM_FILE= tm-i386.h +TDEPFILES= i386-tdep.o i387-tdep.o i386-rb-tdep.o +TM_FILE= tm-embed.h diff --git a/gdb/i386-rb-tdep.c b/gdb/i386-rb-tdep.c new file mode 100644 index 00000000000..451c0ef05a0 --- /dev/null +++ b/gdb/i386-rb-tdep.c @@ -0,0 +1,862 @@ +/* Intel 386 target-dependent stuff for the codetap target. + + Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, + 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "gdb_string.h" +#include "frame.h" +#include "inferior.h" +#include "gdbcore.h" +#include "objfiles.h" +#include "target.h" +#include "floatformat.h" +#include "symfile.h" +#include "symtab.h" +#include "gdbcmd.h" +#include "command.h" +#include "arch-utils.h" +#include "regcache.h" +#include "doublest.h" +#include "value.h" +#include "gdb_assert.h" +#include "reggroups.h" + +#include "i386-tdep.h" +#include "i387-tdep.h" + +#include <ctype.h> + +/* System registers. */ + +static struct type *builtin_type_i386_gdtr (void); +static struct type *builtin_type_i386_ldtr (void); +static struct type *builtin_type_i386_cr0 (void); +static struct type *builtin_type_i386_cr2 (void); +static struct type *builtin_type_i386_cr3 (void); +static struct type *builtin_type_i386_cr4 (void); +static struct type *builtin_type_i386_msr (void); + +struct i386_sys_reg +{ + const char *name; + struct type *(*type) (void); +}; + +struct i386_sys_reg i386_sys_regs[] = { + { "cr0", builtin_type_i386_cr0 }, + { "cr2", builtin_type_i386_cr2 }, + { "cr3", builtin_type_i386_cr3 }, + { "cr4", builtin_type_i386_cr4 }, + { "gdtr", builtin_type_i386_gdtr }, + { "idtr", builtin_type_i386_gdtr }, + { "ldtr", builtin_type_i386_ldtr }, + { "tr", builtin_type_i386_ldtr }, + { "", builtin_type_i386_msr } +}; +static const int num_sys_regs = (sizeof i386_sys_regs + / sizeof i386_sys_regs[0]); + +static int +regnum_to_sysnum (int regnum) +{ + return regnum - I386_SSE_NUM_REGS; +} + +static int +sys_regnum_p (int regnum) +{ + int sysnum = regnum_to_sysnum (regnum); + return (sysnum >= 0 && sysnum < num_sys_regs); +} + +static int +msr_regnum () +{ + /* The last SYSREG is special, it is used to access Red Boot's MSR + registers. Find the regnum of the first SYSREG by reversing the + effects of regnum_to_sysregnum. */ + return (-regnum_to_sysnum (0)) + num_sys_regs - 1; +} + +/* Red Boot's MSR registers. They are accessed using a single real + MSR register. */ + +struct i386_msr_reg +{ + const char *name; + long address; /* MSRs have a cardinal pnum. */ +}; + +struct i386_msr_reg i386_msr_regs[] = { + { "P5_MC_ADDR", 0 }, /* Machine-Check Error Address */ + { "P5_MC_TYPE", 1 }, /* Machine-Check Error Type */ + { "TSC", 16 }, /* Time Stamp Counter */ + { "BBL_CR_OVRD", 23 }, /* Platform type for microcode updates */ + { "APICBASE", 27 }, /* APIC Base Address */ + { "EBL_CR_POWERON", 42 }, /* Power On Configuration Register */ + { "TEST_CTL", 51 }, /* Test Control Register */ + { "BIOS_UPDT_TRIG", 121 }, /* BIOS Update Trigger Register */ + { "BBL_CR_D0", 136 }, /* L2 Chunk 0 data register D[63:0] */ + { "BBL_CR_D1", 137 }, /* L2 Chunk 1 data register D[63:0] */ + { "BBL_CR_D2", 138 }, /* L2 Chunk 2 data register D[63:0] */ + { "BBL_CR_D3", 139 }, /* L2 Chunk 3 data register D[63:0] */ + { "BIOS_SIGN", 139 }, /* BIOS Update Signature Register */ + { "PERFCT0", 193 }, /* Performance Counter 0 */ + { "PERFCT1", 194 }, /* Performance Counter 1 */ + { "MTRRcap", 254 }, /* MTR Information */ + { "BBL_CR_ADDR", 278 }, /* L2 Address Register */ + { "BBL_CR_DECC", 280 }, /* L2 Data ECC Register */ + { "BBL_CR_CTL", 281 }, /* L2 Control Register */ + { "BBL_CR_TRIG", 282 }, /* L2 Trigger Register */ + { "BBL_CR_BUSY", 283 }, /* L2 Busy Register */ + { "BBL_CR_CTL3", 286 }, /* L2 Control Register 3 */ + { "MCG_CAP", 377 }, /* Machine-Check Architecture Implementation */ + { "MCG_STATUS", 378 }, /* Machine-Check Status */ + { "MCG_CTL", 379 }, /* Machine-Check Control */ + { "EVNTSEL0", 390 }, /* Event Select 0 */ + { "EVNTSEL1", 391 }, /* Event Select 1 */ + { "DEBUGCTLMSR", 473 }, /* Debug Control */ + { "LASTBRANCHFROMIP", 475 }, /* LastBranchFromIP */ + { "LASTBRANCTOIP", 476 }, /* LastBranchToIP */ + { "LASTINTFROMIP", 477 }, /* LastExceptionFromIP */ + { "LASTINTTOIP", 478 }, /* LastExceptionToIP */ + { "ROB_CR_BKUPTMPDR6", 480 }, /* */ + { "MTRRphysBase0", 512 }, /* Variable Range MTRR Base Address and Type */ + { "MTRRphysMask0", 513 }, /* Variable Range MTRR Address Range Mask */ + { "MTRRphysBase1", 514 }, /* Variable Range MTRR Base Address and Type */ + { "MTRRphysMask1", 515 }, /* Variable Range MTRR Address Range Mask */ + { "MTRRphysBase2", 516 }, /* Variable Range MTRR Base Address and Type */ + { "MTRRphysMask2", 517 }, /* Variable Range MTRR Address Range Mask */ + { "MTRRphysBase3", 518 }, /* Variable Range MTRR Base Address and Type */ + { "MTRRphysMask3", 519 }, /* Variable Range MTRR Address Range Mask */ + { "MTRRphysBase4", 520 }, /* Variable Range MTRR Base Address and Type */ + { "MTRRphysMask4", 521 }, /* Variable Range MTRR Address Range Mask */ + { "MTRRphysBase5", 522 }, /* Variable Range MTRR Base Address and Type */ + { "MTRRphysMask5", 523 }, /* Variable Range MTRR Address Range Mask */ + { "MTRRphysBase6", 524 }, /* Variable Range MTRR Base Address and Type */ + { "MTRRphysMask6", 525 }, /* Variable Range MTRR Address Range Mask */ + { "MTRRphysBase7", 526 }, /* Variable Range MTRR Base Address and Type */ + { "MTRRphysMask7", 527 }, /* Variable Range MTRR Address Range Mask */ + { "MTRRfix64K_0000", 592 }, /* Fixed Range MTRR */ + { "MTRRfix16K_8000", 600 }, /* Fixed Range MTRR */ + { "MTRRfix16K_a000", 601 }, /* Fixed Range MTRR */ + { "MTRRfix4K_c000", 616 }, /* Fixed Range MTRR */ + { "MTRRfix4K_c800", 617 }, /* Fixed Range MTRR */ + { "MTRRfix4K_d000", 618 }, /* Fixed Range MTRR */ + { "MTRRfix4K_d800", 619 }, /* Fixed Range MTRR */ + { "MTRRfix4K_e000", 620 }, /* Fixed Range MTRR */ + { "MTRRfix4K_e800", 621 }, /* Fixed Range MTRR */ + { "MTRRfix4K_f000", 622 }, /* Fixed Range MTRR */ + { "MTRRfix4K_f800", 623 }, /* Fixed Range MTRR */ + { "MTRRdefType", 767 }, /* Default Properties of non-MTRR memory */ + { "MC0_CTL", 1024 }, /* Bank 0 Machine-Check Error Reporting Control */ + { "MC0_STATUS", 1025 }, /* Bank 0 Machine-Check Error Reporting Status */ + { "MC0_ADDR", 1026 }, /* Bank 0 Machine-Check Error Reporting Mask */ + { "MC1_CTL", 1028 }, /* Bank 1 Machine-Check Error Reporting Control */ + { "MC1_STATUS", 1029 }, /* Bank 1 Machine-Check Error Reporting Status */ + { "MC1_ADDR", 1030 }, /* Bank 1 Machine-Check Error Reporting Mask */ + { "MC2_CTL", 1032 }, /* Bank 2 Machine-Check Error Reporting Control */ + { "MC2_STATUS", 1033 }, /* Bank 2 Machine-Check Error Reporting Status */ + { "MC2_ADDR", 1034 }, /* Bank 2 Machine-Check Error Reporting Mask */ + { "MC4_CTL", 1036 }, /* Bank 4 Machine-Check Error Reporting Control */ + { "MC4_STATUS", 1037 }, /* Bank 4 Machine-Check Error Reporting Status */ + { "MC4_ADDR", 1038 }, /* Bank 4 Machine-Check Error Reporting Mask */ + { "MC3_CTL", 1040 }, /* Bank 3 Machine-Check Error Reporting Control */ + { "MC3_STATUS", 1041 }, /* Bank 3 Machine-Check Error Reporting Status */ + { "MC3_ADDR", 1042 } /* Bank 3 Machine-Check Error Reporting Mask */ +}; +static const long num_msr_regs = (sizeof i386_msr_regs + / sizeof i386_msr_regs[0]); +/* FIXME: cagney/2002-08-28: Just ``know'' that there are 8 MSR regs. */ +#define NUM_I386_MMX_REGS 8 /*MAGIC*/ + +static int +regnum_to_msrnum (int regnum) +{ + return regnum - (NUM_REGS + NUM_I386_MMX_REGS); +} + +static int +msr_regnum_p (int regnum) +{ + int msrnum = regnum_to_msrnum (regnum); + return (msrnum >= 0 && msrnum < num_msr_regs); +} + +/* Query the target for selected MSR, if available. This also tells + the target which MSR we are interested in. */ + +static int +i386_query_msr_regnum (int regnum) +{ + int size = 0; + char *buf; + char *rets; + char *qstr; + struct cleanup *saved_cleanups = make_cleanup (null_cleanup, NULL); + + gdb_assert (msr_regnum_p (regnum)); + + /* Get the current buffer size. */ + if (current_target.to_query == NULL) + return -1; + size = 0; + target_query ('M', "SR", NULL, &size); + + buf = xmalloc (size); + make_cleanup (xfree, buf); + + /* Now query the MSR info. */ + xasprintf (&qstr, "SR,%lx,%s", + i386_msr_regs[regnum_to_msrnum (regnum)].address, + i386_msr_regs[regnum_to_msrnum (regnum)].name); + make_cleanup (xfree, qstr); + + if (target_query ('M', qstr, buf, &size) < 0) + return -1; + + if ((strlen (buf) == 0) + || (strcmp (buf, "INVALID") == 0)) + { + do_cleanups (saved_cleanups); + return -1; + } + + do_cleanups (saved_cleanups); + return 0; +} + +/* Return the name of register REG. */ + +const char * +i386_rb_register_name (int regnum) +{ + if (sys_regnum_p (regnum)) + return i386_sys_regs[regnum_to_sysnum (regnum)].name; + if (msr_regnum_p (regnum)) + return i386_msr_regs[regnum_to_msrnum (regnum)].name; + return i386_register_name (regnum); +} + +static struct type * +builtin_type_i386_gdtr (void) +{ + /* Construct a type for the GDTR and IDTR MM registers. The type + we're building is this: */ +#if 0 + struct builtin_type_i386_gdtr + { + uint32_t base; + uint16_t lim; + }; +#endif + + static struct type *t; + struct field *f; + + if (t != NULL) + return t; + + f = (struct field *) xmalloc (sizeof (*f) * 2); + memset (f, 0, sizeof (*f) * 2); + + FIELD_TYPE (f[0])= builtin_type_uint32; + FIELD_NAME (f[0])= "base"; + FIELD_BITPOS (f[0]) = 0; + + FIELD_TYPE (f[1])= builtin_type_uint16; + FIELD_NAME (f[1])= "lim"; + FIELD_BITPOS (f[1]) = 32; + + /* Build a struct type with those fields. */ + t = init_type (TYPE_CODE_STRUCT, 6, 0, 0, 0); + TYPE_NFIELDS (t) = 2; + TYPE_FIELDS (t) = f; + TYPE_TAG_NAME (t) = "builtin_type_i386_gdtr"; + + return t; +} + +static struct type * +builtin_type_i386_ldtr (void) +{ + /* Construct a type for the LDTR and TR MM registers. The type + we're building is this: */ +#if 0 + struct builtin_type_i386_ldtr + { + uint32_t base; + uint16_t lim; + struct + { + unsigned int index:13; + unsigned int TI:1; + unsigned int RPL:2; + } sel; + }; */ +#endif + + static struct type *t; /* The type we are creating. */ + struct type *ts; /* The type of selector part. */ + struct field *f; /* Fields of the main type struct. */ + struct field *fs; /* Fields of the selector part. */ + + if (t != NULL) + return t; + + /* First, make a type for the selector part. */ + fs = (struct field *) xmalloc (sizeof (*fs) * 3); + memset (fs, 0, sizeof (*fs) * 3); + + /* Note that we reverse the order so we see the bit fields from + left to right, as in a manual figure. */ + + FIELD_TYPE (fs[0]) = builtin_type_unsigned_int; + FIELD_NAME (fs[0]) = "index"; + FIELD_BITPOS (fs[0]) = 3; + FIELD_BITSIZE (fs[0]) = 13; + + FIELD_TYPE (fs[1]) = builtin_type_unsigned_int; + FIELD_NAME (fs[1]) = "TI"; + FIELD_BITPOS (fs[1]) = 2; + FIELD_BITSIZE (fs[1]) = 1; + + FIELD_TYPE (fs[2]) = builtin_type_unsigned_int; + FIELD_NAME (fs[2]) = "RPL"; + FIELD_BITPOS (fs[2]) = 0; + FIELD_BITSIZE (fs[2]) = 2; + + /* Build a struct type with those fields. */ + ts = init_type (TYPE_CODE_STRUCT, 2, 0, 0, 0); + TYPE_NFIELDS (ts) = 3; + TYPE_FIELDS (ts) = fs; + TYPE_TAG_NAME (ts) = "builtin_type_i386_ldtr_selector"; + + /* Now build the main type. */ + f = (struct field *) xmalloc (sizeof (*f) * 3); + memset (f, 0, sizeof (*f) * 3); + + FIELD_TYPE (f[0])= builtin_type_uint32; + FIELD_NAME (f[0])= "base"; + FIELD_BITPOS (f[0]) = 0; + + FIELD_TYPE (f[1]) = builtin_type_uint16; + FIELD_NAME (f[1]) = "lim"; + FIELD_BITPOS (f[1]) = 32; + + FIELD_TYPE (f[2])= ts; + FIELD_NAME (f[2])= "sel"; + FIELD_BITPOS (f[2]) = 48; + + /* Build a struct type with those fields. */ + t = init_type (TYPE_CODE_STRUCT, 8, 0, 0, 0); + TYPE_NFIELDS (t) = 3; + TYPE_FIELDS (t) = f; + TYPE_TAG_NAME (t) = "builtin_type_i386_ldtr"; + + return t; +} + +static struct type * +builtin_type_i386_cr0 (void) +{ + /* Construct a type for the CR0 register. The type we're building + is this: */ +#if 0 + union builtin_type_i386_cr0 + { + void * cr0; + struct __builtin_i386_cr0_bits + { + unsigned PG:1; + unsigned CD:1; + unsigned NW:1; + /* We skip 10 reserved bits here. */ + unsigned AM:1; + /* We skip 1 reserved bit here. */ + unsigned WP:1; + /* We skip 10 reserved bits here. */ + unsigned NE:1; + unsigned ET:1; + unsigned TS:1; + unsigned EM:1; + unsigned MP:1; + unsigned PE:1; + } bits; + }; +#endif + /* Note that we cannot create a structure like that in C because we + could not skip the reserved bits and the order would be the + reverse of what we want (we want to see bit names from left to + right, as in a manual figure). */ + + static struct type *t; /* The type we are creating. */ + struct type *tp; /* The type of the pointer part. */ + struct type *tb; /* The type of the bitfields part. */ + struct field *fu; /* Fields of the union. */ + struct field *fs; /* Fields of the struct. */ + + if (t != NULL) + return t; + + /* Create fields for each group of bits. */ + fs = (struct field *) xmalloc (sizeof (*fs) * 11); + memset (fs, 0, sizeof (*fs) * 11); + + /* Note that we reverse the order of the fields so they are printed + as we would see then in a manual figure, left to right. */ + + FIELD_TYPE (fs[10]) = builtin_type_unsigned_int; + FIELD_NAME (fs[10]) = "PE"; + FIELD_BITPOS (fs[10]) = 0; + FIELD_BITSIZE (fs[10]) = 1; + + FIELD_TYPE (fs[9]) = builtin_type_unsigned_int; + FIELD_NAME (fs[9]) = "MP"; + FIELD_BITPOS (fs[9]) = 1; + FIELD_BITSIZE (fs[9]) = 1; + + FIELD_TYPE (fs[8]) = builtin_type_unsigned_int; + FIELD_NAME (fs[8]) = "EM"; + FIELD_BITPOS (fs[8]) = 2; + FIELD_BITSIZE (fs[8]) = 1; + + FIELD_TYPE (fs[7]) = builtin_type_unsigned_int; + FIELD_NAME (fs[7]) = "TS"; + FIELD_BITPOS (fs[7]) = 3; + FIELD_BITSIZE (fs[7]) = 1; + + FIELD_TYPE (fs[6]) = builtin_type_unsigned_int; + FIELD_NAME (fs[6]) = "ET"; + FIELD_BITPOS (fs[6]) = 4; + FIELD_BITSIZE (fs[6]) = 1; + + FIELD_TYPE (fs[5]) = builtin_type_unsigned_int; + FIELD_NAME (fs[5]) = "NE"; + FIELD_BITPOS (fs[5]) = 5; + FIELD_BITSIZE (fs[5]) = 1; + + FIELD_TYPE (fs[4]) = builtin_type_unsigned_int; + FIELD_NAME (fs[4]) = "WP"; + FIELD_BITPOS (fs[4]) = 16; + FIELD_BITSIZE (fs[4]) = 1; + + FIELD_TYPE (fs[3]) = builtin_type_unsigned_int; + FIELD_NAME (fs[3]) = "AM"; + FIELD_BITPOS (fs[3]) = 18; + FIELD_BITSIZE (fs[3]) = 1; + + FIELD_TYPE (fs[2]) = builtin_type_unsigned_int; + FIELD_NAME (fs[2]) = "NW"; + FIELD_BITPOS (fs[2]) = 29; + FIELD_BITSIZE (fs[2]) = 1; + + FIELD_TYPE (fs[1]) = builtin_type_unsigned_int; + FIELD_NAME (fs[1]) = "CD"; + FIELD_BITPOS (fs[1]) = 30; + FIELD_BITSIZE (fs[1]) = 1; + + FIELD_TYPE (fs[0]) = builtin_type_unsigned_int; + FIELD_NAME (fs[0]) = "PG"; + FIELD_BITPOS (fs[0]) = 31; + FIELD_BITSIZE (fs[0]) = 1; + + /* Build a struct type with these bitfields. */ + tb = init_type (TYPE_CODE_STRUCT, 4, 0, 0, 0); + TYPE_NFIELDS (tb) = 11; + TYPE_FIELDS (tb) = fs; + TYPE_TAG_NAME (tb) = "builtin_type_i386_cr0_bits"; + + /* Create the pointer part. */ + tp = make_pointer_type (builtin_type_void, NULL); + + /* Now make our type as the union of the pointer and the bitfield parts. */ + fu = (struct field *) xmalloc (sizeof (*fu) * 2); + memset (fu, 0, sizeof (*fu) * 2); + + FIELD_TYPE (fu[0]) = tp; + FIELD_NAME (fu[0]) = "cr0"; + + FIELD_TYPE (fu[1]) = tb; + FIELD_NAME (fu[1]) = "bits"; + + /* Build a union type with those fields. */ + t = init_type (TYPE_CODE_UNION, 4, 0, 0, 0); + TYPE_NFIELDS (t) = 2; + TYPE_FIELDS (t) = fu; + TYPE_TAG_NAME (t) = "builtin_type_i386_cr0"; + + return t; +} + +static struct type * +builtin_type_i386_cr2 (void) +{ + return builtin_type_uint32; +} + +static struct type * +builtin_type_i386_cr3 (void) +{ + /* Construct a type for the PDBR (CR3). The type we're building is + this: */ +#if 0 + union builtin_type_i386_cr3 + { + void * cr3; + struct builtin_type_i386_pdbr + { + unsigned int PDbase:20; + /* We skip 7 reserved bits here. */ + unsigned int PCD:1; + unsigned int PWT:1; + /* We ignore 3 reserved bits here. */ + }; + }; +#endif + + struct type *t; /* The type we are creating. */ + struct type *tp; /* The type of the pointer part. */ + struct type *tb; /* The type of the bitfields part. */ + struct field *fu; /* Fields of the union. */ + struct field *fs; /* Fields of the struct. */ + + fs = (struct field *) xmalloc (sizeof (*fs) * 3); + memset (fs, 0, sizeof (*fs) * 3); + + FIELD_TYPE (fs[0])= builtin_type_unsigned_int; + FIELD_NAME (fs[0])= "PDbase"; + FIELD_BITPOS (fs[0]) = 12; + FIELD_BITSIZE (fs[0]) = 20; + + FIELD_TYPE (fs[1])= builtin_type_unsigned_int; + FIELD_NAME (fs[1])= "PCD"; + FIELD_BITPOS (fs[1]) = 4; + FIELD_BITSIZE (fs[1]) = 1; + + FIELD_TYPE (fs[2])= builtin_type_unsigned_int; + FIELD_NAME (fs[2])= "PWT"; + FIELD_BITPOS (fs[2]) = 3; + FIELD_BITSIZE (fs[2]) = 1; + + /* Build a struct type with those fields. */ + tb = init_type (TYPE_CODE_STRUCT, 4, 0, 0, 0); + TYPE_NFIELDS (tb) = 3; + TYPE_FIELDS (tb) = fs; + TYPE_TAG_NAME (tb) = "builtin_type_i386_cr3_bits"; + + /* Create the pointer part. */ + tp = make_pointer_type (builtin_type_void, NULL); + + /* Now make our type as the union of the pointer and the bitfield parts. */ + fu = (struct field *) xmalloc (sizeof (*fu) * 2); + memset (fu, 0, sizeof (*fu) * 2); + + FIELD_TYPE (fu[0]) = tp; + FIELD_NAME (fu[0]) = "cr3"; + + FIELD_TYPE (fu[1]) = tb; + FIELD_NAME (fu[1]) = "bits"; + + /* Build a union type with those fields. */ + t = init_type (TYPE_CODE_UNION, 4, 0, 0, 0); + TYPE_NFIELDS (t) = 2; + TYPE_FIELDS (t) = fu; + TYPE_TAG_NAME (t) = "builtin_type_i386_cr3"; + + return t; +} + +static struct type * +builtin_type_i386_cr4 (void) +{ + /* Construct a type for the CR4 register. The type we're building + is this: */ +#if 0 + union builtin_type_i386_cr4 + { + void * cr0; + struct __builtin_i386_cr4_bits { + /* We skip the 21 reserved bits here. */ + unsigned OSXMMEXCPT:1; + unsigned OSFXSR:1; + unsigned PCE:1; + unsigned PGE:1; + unsigned MCE:1; + unsigned PAE:1; + unsigned PSE:1; + unsigned DE:1; + unsigned TSD:1; + unsigned PVI:1; + unsigned VME:1; + } bits; + }; +#endif + /* Note that we cannot create a structure like that in C because we + could not skip the reserved bits and the order would be the + reverse of what we want (we want to see bit names from left to + right, as in a manual figure). */ + + struct type *t; /* The type we are creating. */ + struct type *tp; /* The type of the pointer part. */ + struct type *tb; /* The type of the bitfields part. */ + struct field *fu; /* Fields of the union. */ + struct field *fs; /* Fields of the struct. */ + + /* Create fields for each group of bits. */ + fs = (struct field *) xmalloc (sizeof (*fs) * 11); + memset (fs, 0, sizeof (*fs) * 11); + + /* Note that we reverse the order of the fields so they are printed + as we would see then in a manual figure, left to right. */ + + FIELD_TYPE (fs[10]) = builtin_type_unsigned_int; + FIELD_NAME (fs[10]) = "VME"; + FIELD_BITPOS (fs[10]) = 0; + FIELD_BITSIZE (fs[10]) = 1; + + FIELD_TYPE (fs[9]) = builtin_type_unsigned_int; + FIELD_NAME (fs[9]) = "PVI"; + FIELD_BITPOS (fs[9]) = 1; + FIELD_BITSIZE (fs[9]) = 1; + + FIELD_TYPE (fs[8]) = builtin_type_unsigned_int; + FIELD_NAME (fs[8]) = "TSD"; + FIELD_BITPOS (fs[8]) = 2; + FIELD_BITSIZE (fs[8]) = 1; + + FIELD_TYPE (fs[7]) = builtin_type_unsigned_int; + FIELD_NAME (fs[7]) = "DE"; + FIELD_BITPOS (fs[7]) = 3; + FIELD_BITSIZE (fs[7]) = 1; + + FIELD_TYPE (fs[6]) = builtin_type_unsigned_int; + FIELD_NAME (fs[6]) = "PSE"; + FIELD_BITPOS (fs[6]) = 4; + FIELD_BITSIZE (fs[6]) = 1; + + FIELD_TYPE (fs[5]) = builtin_type_unsigned_int; + FIELD_NAME (fs[5]) = "PAE"; + FIELD_BITPOS (fs[5]) = 5; + FIELD_BITSIZE (fs[5]) = 1; + + FIELD_TYPE (fs[4]) = builtin_type_unsigned_int; + FIELD_NAME (fs[4]) = "MCE"; + FIELD_BITPOS (fs[4]) = 6; + FIELD_BITSIZE (fs[4]) = 1; + + FIELD_TYPE (fs[3]) = builtin_type_unsigned_int; + FIELD_NAME (fs[3]) = "PGE"; + FIELD_BITPOS (fs[3]) = 7; + FIELD_BITSIZE (fs[3]) = 1; + + FIELD_TYPE (fs[2]) = builtin_type_unsigned_int; + FIELD_NAME (fs[2]) = "PCE"; + FIELD_BITPOS (fs[2]) = 8; + FIELD_BITSIZE (fs[2]) = 1; + + FIELD_TYPE (fs[1]) = builtin_type_unsigned_int; + FIELD_NAME (fs[1]) = "OSFXSR"; + FIELD_BITPOS (fs[1]) = 9; + FIELD_BITSIZE (fs[1]) = 1; + + FIELD_TYPE (fs[0]) = builtin_type_unsigned_int; + FIELD_NAME (fs[0]) = "OSXMMEXCPT"; + FIELD_BITPOS (fs[0]) = 10; + FIELD_BITSIZE (fs[0]) = 1; + + /* Build a struct type with these bitfields. */ + tb = init_type (TYPE_CODE_STRUCT, 4, 0, 0, 0); + TYPE_NFIELDS (tb) = 11; + TYPE_FIELDS (tb) = fs; + TYPE_TAG_NAME (tb) = "builtin_type_i386_cr4_bits"; + + /* Create the pointer part. */ + tp = make_pointer_type (builtin_type_void, NULL); + + /* Now make our type as the union of the pointer and the bitfield parts. */ + fu = (struct field *) xmalloc (sizeof (*fu) * 2); + memset (fu, 0, sizeof (*fu) * 2); + + FIELD_TYPE (fu[0]) = tp; + FIELD_NAME (fu[0]) = "cr4"; + + FIELD_TYPE (fu[1]) = tb; + FIELD_NAME (fu[1]) = "bits"; + + /* Build a union type with those fields. */ + t = init_type (TYPE_CODE_UNION, 4, 0, 0, 0); + TYPE_NFIELDS (t) = 2; + TYPE_FIELDS (t) = fu; + TYPE_TAG_NAME (t) = "builtin_type_i386_cr4"; + + return t; +} + +static struct type * +builtin_type_i386_msr (void) +{ + return builtin_type_uint64; +} + +/* Return the GDB type object for the "standard" data type of data in + register REGNUM. Perhaps %esi and %edi should go here, but + potentially they could be used for things other than address. */ + +struct type * +i386_rb_register_virtual_type (int regnum) +{ + if (sys_regnum_p (regnum)) + return i386_sys_regs[regnum_to_sysnum (regnum)].type (); + if (msr_regnum_p (regnum)) + return builtin_type_i386_msr (); + return i386_register_virtual_type (regnum); +} + +static struct reggroup *msr_reggroup; + +static int +i386_rb_register_regroup_p (struct gdbarch *gdbarch, int regnum, + struct reggroup *group) +{ + if (group == system_reggroup) + return sys_regnum_p (regnum); + if (group == msr_reggroup) + return msr_regnum_p (regnum); + if (sys_regnum_p (regnum) || msr_regnum_p (regnum)) + return 0; + return i386_register_reggroup_p (gdbarch, regnum, group); +} + +int +i386_rb_gpacket_upper_bound_hack (void) +{ + return I386_SSE_NUM_REGS; +} + +int +i386_rb_next_abi_register (struct gdbarch *gdbarch, int regnum) +{ + if (regnum < 0) + return 0; + regnum++; + if (regnum >= I386_SSE_NUM_REGS) + return -1; + return regnum; +} + +/* Map registers onto their real counterparts. Note these functions + need sibling changes in the code that does the same thing for + registers on a frame. */ + +static void +i386_msr_register_read (struct gdbarch *gdbarch, struct regcache *regcache, + int regnum, void *buf) +{ + /* ULGH. */ + gdb_assert (msr_regnum_p (regnum)); + if (i386_query_msr_regnum (regnum) == 0) + { + /* Invalidate the MSR in the register cache forcing a re-read. */ + register_valid[msr_regnum ()] = 0; + regcache_raw_read (regcache, msr_regnum (), buf); + } +} + +static void +i386_rb_pseudo_register_read (struct gdbarch *gdbarch, + struct regcache *regcache, + int regnum, void *buf) +{ + if (msr_regnum_p (regnum)) + i386_msr_register_read (gdbarch, regcache, regnum, buf); + else + i386_pseudo_register_read (gdbarch, regcache, regnum, buf); +} + +static void +i386_msr_register_write (struct gdbarch *gdbarch, + struct regcache *regcache, int regnum, + const void *buf) +{ + /* ULGH. */ + gdb_assert (msr_regnum_p (regnum)); + if (i386_query_msr_regnum (regnum) == 0) + { + regcache_raw_write (regcache, msr_regnum (), buf); + } +} + +static void +i386_rb_pseudo_register_write (struct gdbarch *gdbarch, + struct regcache *regcache, + int regnum, const void *buf) +{ + if (msr_regnum_p (regnum)) + i386_msr_register_write (gdbarch, regcache, regnum, buf); + else + i386_pseudo_register_write (gdbarch, regcache, regnum, buf); +} + +static void +i386_rb_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* Red Boot uses ELF. */ + i386_elf_init_abi (info, gdbarch); + + /* We support the SSE registers on Red Boot */ + tdep->num_xmm_regs = I386_NUM_XREGS - 1; + + set_gdbarch_register_bytes (gdbarch, (I386_SSE_SIZEOF_REGS + + num_sys_regs * 4)); + + /* Since we have the extra system and MSR registers, we need to + adjust a few things. */ + + set_gdbarch_num_regs (gdbarch, I386_SSE_NUM_REGS + num_sys_regs); + set_gdbarch_register_name (gdbarch, i386_rb_register_name); + set_gdbarch_register_virtual_type (gdbarch, i386_rb_register_virtual_type); + + set_gdbarch_num_pseudo_regs (gdbarch, NUM_I386_MMX_REGS + num_msr_regs); + set_gdbarch_pseudo_register_read (gdbarch, i386_rb_pseudo_register_read); + set_gdbarch_pseudo_register_write (gdbarch, i386_rb_pseudo_register_write); + + set_gdbarch_next_cooked_register_to_save (gdbarch, i386_rb_next_abi_register); + set_gdbarch_next_cooked_register_to_restore (gdbarch, i386_rb_next_abi_register); + + set_gdbarch_register_reggroup_p (gdbarch, i386_rb_register_regroup_p); + reggroup_add (gdbarch, msr_reggroup); +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_i386_tdep (void); + +void +_initialize_i386_rb_tdep (void) +{ + /* Ulgh, claim the default. */ + gdbarch_register_osabi (bfd_arch_i386, GDB_OSABI_REDBOOT, + i386_rb_init_abi); + + msr_reggroup = reggroup_new ("msr"); +} diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index dd7a9e5c373..73cc6d56190 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -1097,7 +1097,7 @@ i386_use_struct_convention (int gcc_p, struct type *type) register REGNUM. Perhaps %esi and %edi should go here, but potentially they could be used for things other than address. */ -static struct type * +struct type * i386_register_virtual_type (int regnum) { if (regnum == PC_REGNUM || regnum == FP_REGNUM || regnum == SP_REGNUM) @@ -1132,7 +1132,7 @@ mmx_regnum_to_fp_regnum (struct regcache *regcache, int regnum) return (FP0_REGNUM + fpi); } -static void +void i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, int regnum, void *buf) { @@ -1148,7 +1148,7 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, regcache_raw_read (regcache, regnum, buf); } -static void +void i386_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, int regnum, const void *buf) { @@ -1439,7 +1439,7 @@ i386_add_reggroups (struct gdbarch *gdbarch) reggroup_add (gdbarch, system_reggroup); } -static int +int i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum, struct reggroup *group) { @@ -1467,6 +1467,9 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Try to determine the OS ABI of the object we're loading. */ if (info.abfd != NULL) osabi = gdbarch_lookup_osabi (info.abfd); + /* Hack, force redboot. */ + if (osabi == GDB_OSABI_UNKNOWN) + osabi = GDB_OSABI_REDBOOT; /* Find a candidate among extant architectures. */ for (arches = gdbarch_list_lookup_by_info (arches, &info); diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h index 30128d9341a..ca8d32904dc 100644 --- a/gdb/i386-tdep.h +++ b/gdb/i386-tdep.h @@ -166,6 +166,19 @@ extern CORE_ADDR i386_pe_skip_trampoline_code (CORE_ADDR pc, char *name); /* Return the name of register REG. */ extern char const *i386_register_name (int reg); +/* Return the type of the register REG. */ +extern struct type *i386_register_virtual_type (int reg); + +extern void i386_pseudo_register_write (struct gdbarch *gdbarch, + struct regcache *regcache, int regnum, + const void *buf); +extern void i386_pseudo_register_read (struct gdbarch *gdbarch, + struct regcache *regcache, + int regnum, void *buf); + +extern int i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum, + struct reggroup *group); + /* Initialize a basic ELF architecture variant. */ extern void i386_elf_init_abi (struct gdbarch_info, struct gdbarch *); diff --git a/gdb/osabi.c b/gdb/osabi.c index 83eb767c0b7..8239e3e37f7 100644 --- a/gdb/osabi.c +++ b/gdb/osabi.c @@ -49,6 +49,8 @@ static const char * const gdb_osabi_names[] = "ARM EABI v2", "ARM APCS", + "RedBoot", + "<invalid>" }; @@ -240,7 +242,7 @@ gdbarch_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch, for (handler = gdb_osabi_handler_list; handler != NULL; handler = handler->next) { - if (handler->arch == bfd_get_arch (abfd) + if ((abfd == NULL || handler->arch == bfd_get_arch (abfd)) && handler->osabi == osabi) { (*handler->init_osabi) (info, gdbarch); diff --git a/gdb/osabi.h b/gdb/osabi.h index f62bde71c4e..2769a77c40d 100644 --- a/gdb/osabi.h +++ b/gdb/osabi.h @@ -46,6 +46,8 @@ enum gdb_osabi GDB_OSABI_ARM_EABI_V2, GDB_OSABI_ARM_APCS, + GDB_OSABI_REDBOOT, + GDB_OSABI_INVALID /* keep this last */ }; diff --git a/gdb/remote.c b/gdb/remote.c index 1584d6bc7d4..06bff0f55e3 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -273,7 +273,11 @@ init_remote_state (struct gdbarch *gdbarch) r->pnum = regnum; r->regnum = regnum; r->offset = REGISTER_BYTE (regnum); +#ifdef GPACKET_UPPER_BOUND_HACK + r->in_g_packet = (regnum < GPACKET_UPPER_BOUND_HACK (gdbarch)); +#else r->in_g_packet = (regnum < NUM_REGS); +#endif /* ...size = REGISTER_RAW_SIZE (regnum); */ /* ...name = REGISTER_NAME (regnum); */ } @@ -3416,6 +3420,65 @@ got_status: static int register_bytes_found; +/* Helper for remote_fetch_registers. Fetch a register using the + ``p'' packet. */ + +static void +fetch_register_using_p (int regnum) +{ + struct remote_state *rs = get_remote_state (); + char *regs; + char *buf; + int i; + char *p; + + buf = alloca (rs->remote_packet_size); + sprintf (buf, "p%x", regnum); + remote_send (buf, rs->remote_packet_size); + + /* We can get out of synch in various cases. If the first character + in the buffer is not a hex character, assume that has happened + and try to fetch another packet to read. */ + while ((buf[0] < '0' || buf[0] > '9') + && (buf[0] < 'a' || buf[0] > 'f') + && buf[0] != 'x') /* New: unavailable register value */ + { + if (remote_debug) + fprintf_unfiltered (gdb_stdlog, + "Bad register packet; fetching a new packet\n"); + getpkt (buf, rs->remote_packet_size, 0); + } + + /* Reply describes registers byte by byte, each byte encoded as two + hex characters. Suck them all up, then supply them to the + register cacheing/storage mechanism. */ + + regs = alloca (REGISTER_RAW_SIZE (regnum)); + memset (regs, REGISTER_RAW_SIZE (regnum), 0); + p = buf; + for (i = 0; i < REGISTER_RAW_SIZE (regnum); i++) + { + if (p[0] == 0) + break; + if (p[1] == 0) + { + warning ("Remote reply is of odd length: %s", buf); + /* Don't change register_bytes_found in this case, and don't + print a second warning. */ + break; + } + if (p[0] == 'x' && p[1] == 'x') + regs[i] = 0; /* 'x' */ + else + regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]); + p += 2; + } + + supply_register (regnum, ®s[0]); + if (buf[0] == 'x') + register_valid[i] = -1; /* register value not available */ +} + /* Read the remote registers into the block REGS. */ /* Currently we just read all the registers, so we don't use regnum. */ @@ -3435,10 +3498,18 @@ remote_fetch_registers (int regnum) { struct packet_reg *reg = packet_reg_from_regnum (rs, regnum); gdb_assert (reg != NULL); +#if 1 + if (!reg->in_g_packet) + { + fetch_register_using_p (regnum); + return; + } +#else if (!reg->in_g_packet) internal_error (__FILE__, __LINE__, "Attempt to fetch a non G-packet register when this " "remote.c does not support the p-packet."); +#endif } sprintf (buf, "g"); |