X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gdb%2Fi386-tdep.c;h=c55757e76a69a318507fdb6e91852dfd612b9bcb;hb=56e2d25ab5b69584198204090fe049e920cd57db;hp=0e3e34057cefe6c913ccecd69bda196683080713;hpb=0d17c81d95377cc552092f5f92dc9221d562ef77;p=binutils-gdb.git diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index 0e3e34057ce..c55757e76a6 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -32,6 +32,9 @@ #include "command.h" #include "arch-utils.h" #include "regcache.h" +#include "doublest.h" + +#include "gdb_assert.h" /* i386_register_byte[i] is the offset into the register file of the start of register number i. We initialize this from @@ -57,6 +60,68 @@ int i386_register_raw_size[MAX_NUM_REGS] = { /* i386_register_virtual_size[i] is the size in bytes of the virtual type of register i. */ int i386_register_virtual_size[MAX_NUM_REGS]; + +/* Convert stabs register number REG to the appropriate register + number used by GDB. */ + +int +i386_stab_reg_to_regnum (int reg) +{ + /* This implements what GCC calls the "default" register map. */ + if (reg >= 0 && reg <= 7) + { + /* General registers. */ + return reg; + } + else if (reg >= 12 && reg <= 19) + { + /* Floating-point registers. */ + return reg - 12 + FP0_REGNUM; + } + else if (reg >= 21 && reg <= 28) + { + /* SSE registers. */ + return reg - 21 + XMM0_REGNUM; + } + else if (reg >= 29 && reg <= 36) + { + /* MMX registers. */ + /* FIXME: kettenis/2001-07-28: Should we have the MMX registers + as pseudo-registers? */ + return reg - 29 + FP0_REGNUM; + } + + /* This will hopefully provoke a warning. */ + return NUM_REGS + NUM_PSEUDO_REGS; +} + +/* Convert Dwarf register number REG to the appropriate register + number used by GDB. */ + +int +i386_dwarf_reg_to_regnum (int reg) +{ + /* The DWARF register numbering includes %eip and %eflags, and + numbers the floating point registers differently. */ + if (reg >= 0 && reg <= 9) + { + /* General registers. */ + return reg; + } + else if (reg >= 11 && reg <= 18) + { + /* Floating-point registers. */ + return reg - 11 + FP0_REGNUM; + } + else if (reg >= 21) + { + /* The SSE and MMX registers have identical numbers as in stabs. */ + return i386_stab_reg_to_regnum (reg); + } + + /* This will hopefully provoke a warning. */ + return NUM_REGS + NUM_PSEUDO_REGS; +} /* This is the variable that is set with "set disassembly-flavor", and @@ -669,7 +734,7 @@ i386_push_dummy_frame (void) void i386_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs, - value_ptr *args, struct type *type, int gcc_p) + struct value **args, struct type *type, int gcc_p) { int from, to, delta, loc; @@ -749,7 +814,7 @@ get_longjmp_target (CORE_ADDR *pc) CORE_ADDR -i386_push_arguments (int nargs, value_ptr *args, CORE_ADDR sp, +i386_push_arguments (int nargs, struct value **args, CORE_ADDR sp, int struct_return, CORE_ADDR struct_addr) { sp = default_push_arguments (nargs, args, sp, struct_return, struct_addr); @@ -861,13 +926,18 @@ i386_store_return_value (struct type *type, char *valbuf) if (TYPE_CODE (type) == TYPE_CODE_FLT) { + unsigned int fstat; + if (NUM_FREGS == 0) { warning ("Cannot set floating-point return value."); return; } - /* Floating-point return values can be found in %st(0). */ + /* Returning floating-point values is a bit tricky. Apart from + storing the return value in %st(0), we have to simulate the + state of the FPU at function return point. */ + if (len == TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT && TARGET_LONG_DOUBLE_FORMAT == &floatformat_i387_ext) { @@ -881,7 +951,7 @@ i386_store_return_value (struct type *type, char *valbuf) DOUBLEST val; /* Convert the value found in VALBUF to the extended - floating point format used by the FPU. This is probably + floating-point format used by the FPU. This is probably not exactly how it would happen on the target itself, but it is the best we can do. */ val = extract_floating (valbuf, TYPE_LENGTH (type)); @@ -889,6 +959,19 @@ i386_store_return_value (struct type *type, char *valbuf) write_register_bytes (REGISTER_BYTE (FP0_REGNUM), buf, FPU_REG_RAW_SIZE); } + + /* Set the top of the floating-point register stack to 7. The + actual value doesn't really matter, but 7 is what a normal + function return would end up with if the program started out + with a freshly initialized FPU. */ + fstat = read_register (FSTAT_REGNUM); + fstat |= (7 << 11); + write_register (FSTAT_REGNUM, fstat); + + /* Mark %st(1) through %st(7) as empty. Since we set the top of + the floating-point register stack to 7, the appropriate value + for the tag word is 0x3fff. */ + write_register (FTAG_REGNUM, 0x3fff); } else { @@ -954,27 +1037,45 @@ i386_register_convertible (int regnum) } /* Convert data from raw format for register REGNUM in buffer FROM to - virtual format with type TYPE in buffer TO. In principle both - formats are identical except that the virtual format has two extra - bytes appended that aren't used. We set these to zero. */ + virtual format with type TYPE in buffer TO. */ void i386_register_convert_to_virtual (int regnum, struct type *type, char *from, char *to) { - /* Copy straight over, but take care of the padding. */ - memcpy (to, from, FPU_REG_RAW_SIZE); - memset (to + FPU_REG_RAW_SIZE, 0, TYPE_LENGTH (type) - FPU_REG_RAW_SIZE); + char buf[12]; + DOUBLEST d; + + /* We only support floating-point values. */ + if (TYPE_CODE (type) != TYPE_CODE_FLT) + { + warning ("Cannot convert floating-point register value " + "to non-floating-point type."); + memset (to, 0, TYPE_LENGTH (type)); + return; + } + + /* First add the necessary padding. */ + memcpy (buf, from, FPU_REG_RAW_SIZE); + memset (buf + FPU_REG_RAW_SIZE, 0, sizeof buf - FPU_REG_RAW_SIZE); + + /* Convert to TYPE. This should be a no-op, if TYPE is equivalent + to the extended floating-point format used by the FPU. */ + d = extract_floating (buf, sizeof buf); + store_floating (to, TYPE_LENGTH (type), d); } /* Convert data from virtual format with type TYPE in buffer FROM to - raw format for register REGNUM in buffer TO. Simply omit the two - unused bytes. */ + raw format for register REGNUM in buffer TO. */ void i386_register_convert_to_raw (struct type *type, int regnum, char *from, char *to) { + gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT + && TYPE_LENGTH (type) == 12); + + /* Simply omit the two unused bytes. */ memcpy (to, from, FPU_REG_RAW_SIZE); }