void _initialize_i386_tdep PARAMS ((void));
+/* i386_register_byte[i] is the offset into the register file of the
+ start of register number i. We initialize this from
+ i386_register_raw_size. */
+int i386_register_byte[MAX_NUM_REGS];
+
+/* i386_register_raw_size[i] is the number of bytes of storage in
+ GDB's register array occupied by register i. */
+int i386_register_raw_size[MAX_NUM_REGS] = {
+ 4, 4, 4, 4,
+ 4, 4, 4, 4,
+ 4, 4, 4, 4,
+ 4, 4, 4, 4,
+ 10, 10, 10, 10,
+ 10, 10, 10, 10,
+ 4, 4, 4, 4,
+ 4, 4, 4, 4,
+ 16, 16, 16, 16,
+ 16, 16, 16, 16,
+ 4
+};
+
+/* 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];
+
+
/* This is the variable the is set with "set disassembly-flavor",
and its legitimate values. */
static char att_flavor[] = "att";
};
static char *disassembly_flavor = att_flavor;
+static void i386_print_register PARAMS ((char *, int, int));
+
/* This is used to keep the bfd arch_info in sync with the disassembly flavor. */
static void set_disassembly_flavor_sfunc PARAMS ((char *, int, struct cmd_list_element *));
-static void set_disassembly_flavor ();
+static void set_disassembly_flavor PARAMS ((void));
/* Stdio style buffering was used to minimize calls to ptrace, but this
buffering did not take into account that the code section being accessed
*/
void
-i386_frame_find_saved_regs (fip, fsrp)
+i386_frame_init_saved_regs (fip)
struct frame_info *fip;
- struct frame_saved_regs *fsrp;
{
long locals = -1;
unsigned char op;
CORE_ADDR pc;
int i;
- memset (fsrp, 0, sizeof *fsrp);
+ if (fip->saved_regs)
+ return;
+
+ frame_saved_regs_zalloc (fip);
/* if frame is the end of a dummy, compute where the
* beginning would be
for (i = 0; i < NUM_REGS; i++)
{
adr -= REGISTER_RAW_SIZE (i);
- fsrp->regs[i] = adr;
+ fip->saved_regs[i] = adr;
}
return;
}
break;
#ifdef I386_REGNO_TO_SYMMETRY
/* Dynix uses different internal numbering. Ick. */
- fsrp->regs[I386_REGNO_TO_SYMMETRY (op - 0x50)] = adr;
+ fip->saved_regs[I386_REGNO_TO_SYMMETRY (op - 0x50)] = adr;
#else
- fsrp->regs[op - 0x50] = adr;
+ fip->saved_regs[op - 0x50] = adr;
#endif
adr -= 4;
}
}
- fsrp->regs[PC_REGNUM] = fip->frame + 4;
- fsrp->regs[FP_REGNUM] = fip->frame;
+ fip->saved_regs[PC_REGNUM] = fip->frame + 4;
+ fip->saved_regs[FP_REGNUM] = fip->frame;
}
/* return pc of first real instruction */
struct frame_info *frame = get_current_frame ();
CORE_ADDR fp;
int regnum;
- struct frame_saved_regs fsr;
char regbuf[MAX_REGISTER_RAW_SIZE];
fp = FRAME_FP (frame);
- get_frame_saved_regs (frame, &fsr);
+ i386_frame_init_saved_regs (frame);
+
for (regnum = 0; regnum < NUM_REGS; regnum++)
{
CORE_ADDR adr;
- adr = fsr.regs[regnum];
+ adr = frame->saved_regs[regnum];
if (adr)
{
read_memory (adr, regbuf, REGISTER_RAW_SIZE (regnum));
#endif /* GET_LONGJMP_TARGET */
+/* These registers are used for returning integers (and on some
+ targets also for returning `struct' and `union' values when their
+ size and alignment match an integer type. */
+#define LOW_RETURN_REGNUM 0 /* %eax */
+#define HIGH_RETURN_REGNUM 2 /* %edx */
+
+/* Extract from an array REGBUF containing the (raw) register state, a
+ function return value of TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
void
-i386_extract_return_value (type, regbuf, valbuf)
- struct type *type;
- char regbuf[REGISTER_BYTES];
- char *valbuf;
+i386_extract_return_value (struct type *type, char *regbuf, char *valbuf)
{
-/* On AIX, floating point values are returned in floating point registers. */
-#ifdef I386_AIX_TARGET
+ int len = TYPE_LENGTH (type);
+
if (TYPE_CODE_FLT == TYPE_CODE (type))
{
- double d;
- /* 387 %st(0), gcc uses this */
- floatformat_to_double (&floatformat_i387_ext,
- ®buf[REGISTER_BYTE (FP0_REGNUM)],
- &d);
- store_floating (valbuf, TYPE_LENGTH (type), d);
+ if (NUM_FREGS == 0)
+ {
+ warning ("Cannot find floating-point return value.");
+ memset (valbuf, 0, len);
+ }
+
+ /* Floating-point return values can be found in %st(0). */
+ if (len == TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT
+ && TARGET_LONG_DOUBLE_FORMAT == &floatformat_i387_ext)
+ {
+ /* Copy straight over, but take care of the padding. */
+ memcpy (valbuf, ®buf[REGISTER_BYTE (FP0_REGNUM)],
+ FPU_REG_RAW_SIZE);
+ memset (valbuf + FPU_REG_RAW_SIZE, 0, len - FPU_REG_RAW_SIZE);
+ }
+ else
+ {
+ /* Convert the extended floating-point number found in
+ %st(0) to the desired type. This is probably not exactly
+ how it would happen on the target itself, but it is the
+ best we can do. */
+ DOUBLEST val;
+ floatformat_to_doublest (&floatformat_i387_ext,
+ ®buf[REGISTER_BYTE (FP0_REGNUM)], &val);
+ store_floating (valbuf, TYPE_LENGTH (type), val);
+ }
}
else
-#endif /* I386_AIX_TARGET */
{
- memcpy (valbuf, regbuf, TYPE_LENGTH (type));
+ int low_size = REGISTER_RAW_SIZE (LOW_RETURN_REGNUM);
+ int high_size = REGISTER_RAW_SIZE (HIGH_RETURN_REGNUM);
+
+ if (len <= low_size)
+ memcpy (valbuf, ®buf[REGISTER_BYTE (LOW_RETURN_REGNUM)], len);
+ else if (len <= (low_size + high_size))
+ {
+ memcpy (valbuf,
+ ®buf[REGISTER_BYTE (LOW_RETURN_REGNUM)], low_size);
+ memcpy (valbuf + low_size,
+ ®buf[REGISTER_BYTE (HIGH_RETURN_REGNUM)], len - low_size);
+ }
+ else
+ internal_error ("Cannot extract return value of %d bytes long.", len);
}
}
+/* 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. */
+
+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);
+}
+
+/* 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. */
+
+void
+i386_register_convert_to_raw (struct type *type, int regnum,
+ char *from, char *to)
+{
+ memcpy (to, from, FPU_REG_RAW_SIZE);
+}
+
+\f
#ifdef I386V4_SIGTRAMP_SAVED_PC
/* Get saved user PC for sigtramp from the pushed ucontext on the stack
for all three variants of SVR4 sigtramps. */
}
#endif /* I386V4_SIGTRAMP_SAVED_PC */
-#ifdef I386_LINUX_SIGTRAMP
-
-/* When the i386 Linux kernel calls a signal handler, the return
- address points to a bit of code on the stack. This function
- returns whether the PC appears to be within this bit of code.
-
- The instruction sequence is
- pop %eax
- mov $0x77,%eax
- int $0x80
- or 0x58 0xb8 0x77 0x00 0x00 0x00 0xcd 0x80.
-
- Checking for the code sequence should be somewhat reliable, because
- the effect is to call the system call sigreturn. This is unlikely
- to occur anywhere other than a signal trampoline.
-
- It kind of sucks that we have to read memory from the process in
- order to identify a signal trampoline, but there doesn't seem to be
- any other way. The IN_SIGTRAMP macro in tm-linux.h arranges to
- only call us if no function name could be identified, which should
- be the case since the code is on the stack. */
-
-#define LINUX_SIGTRAMP_INSN0 (0x58) /* pop %eax */
-#define LINUX_SIGTRAMP_OFFSET0 (0)
-#define LINUX_SIGTRAMP_INSN1 (0xb8) /* mov $NNNN,%eax */
-#define LINUX_SIGTRAMP_OFFSET1 (1)
-#define LINUX_SIGTRAMP_INSN2 (0xcd) /* int */
-#define LINUX_SIGTRAMP_OFFSET2 (6)
-
-static const unsigned char linux_sigtramp_code[] =
-{
- LINUX_SIGTRAMP_INSN0, /* pop %eax */
- LINUX_SIGTRAMP_INSN1, 0x77, 0x00, 0x00, 0x00, /* mov $0x77,%eax */
- LINUX_SIGTRAMP_INSN2, 0x80 /* int $0x80 */
-};
-
-#define LINUX_SIGTRAMP_LEN (sizeof linux_sigtramp_code)
-
-/* If PC is in a sigtramp routine, return the address of the start of
- the routine. Otherwise, return 0. */
-
-static CORE_ADDR
-i386_linux_sigtramp_start (pc)
- CORE_ADDR pc;
-{
- unsigned char buf[LINUX_SIGTRAMP_LEN];
-
- /* We only recognize a signal trampoline if PC is at the start of
- one of the three instructions. We optimize for finding the PC at
- the start, as will be the case when the trampoline is not the
- first frame on the stack. We assume that in the case where the
- PC is not at the start of the instruction sequence, there will be
- a few trailing readable bytes on the stack. */
-
- if (read_memory_nobpt (pc, (char *) buf, LINUX_SIGTRAMP_LEN) != 0)
- return 0;
-
- if (buf[0] != LINUX_SIGTRAMP_INSN0)
- {
- int adjust;
-
- switch (buf[0])
- {
- case LINUX_SIGTRAMP_INSN1:
- adjust = LINUX_SIGTRAMP_OFFSET1;
- break;
- case LINUX_SIGTRAMP_INSN2:
- adjust = LINUX_SIGTRAMP_OFFSET2;
- break;
- default:
- return 0;
- }
-
- pc -= adjust;
-
- if (read_memory_nobpt (pc, (char *) buf, LINUX_SIGTRAMP_LEN) != 0)
- return 0;
- }
-
- if (memcmp (buf, linux_sigtramp_code, LINUX_SIGTRAMP_LEN) != 0)
- return 0;
-
- return pc;
-}
-
-/* Return whether PC is in a Linux sigtramp routine. */
-
-int
-i386_linux_sigtramp (pc)
- CORE_ADDR pc;
-{
- return i386_linux_sigtramp_start (pc) != 0;
-}
-
-/* Assuming FRAME is for a Linux sigtramp routine, return the saved
- program counter. The Linux kernel will set up a sigcontext
- structure immediately before the sigtramp routine on the stack. */
-
-CORE_ADDR
-i386_linux_sigtramp_saved_pc (frame)
- struct frame_info *frame;
-{
- CORE_ADDR pc;
-
- pc = i386_linux_sigtramp_start (frame->pc);
- if (pc == 0)
- error ("i386_linux_sigtramp_saved_pc called when no sigtramp");
- return read_memory_integer ((pc
- - LINUX_SIGCONTEXT_SIZE
- + LINUX_SIGCONTEXT_PC_OFFSET),
- 4);
-}
-
-/* Assuming FRAME is for a Linux sigtramp routine, return the saved
- stack pointer. The Linux kernel will set up a sigcontext structure
- immediately before the sigtramp routine on the stack. */
-
-CORE_ADDR
-i386_linux_sigtramp_saved_sp (frame)
- struct frame_info *frame;
-{
- CORE_ADDR pc;
-
- pc = i386_linux_sigtramp_start (frame->pc);
- if (pc == 0)
- error ("i386_linux_sigtramp_saved_sp called when no sigtramp");
- return read_memory_integer ((pc
- - LINUX_SIGCONTEXT_SIZE
- + LINUX_SIGCONTEXT_SP_OFFSET),
- 4);
-}
-
-#endif /* I386_LINUX_SIGTRAMP */
#ifdef STATIC_TRANSFORM_NAME
/* SunPRO encodes the static variables. This is not related to C++ mangling,
struct cmd_list_element *c;
{
set_disassembly_flavor ();
-
- if (disassembly_flavor_hook != NULL)
- disassembly_flavor_hook (args, from_tty);
}
static void
set_architecture_from_arch_mach (bfd_arch_i386, bfd_mach_i386_i386_intel_syntax);
}
+
void
_initialize_i386_tdep ()
{
- struct cmd_list_element *new_cmd;
+ /* Initialize the table saying where each register starts in the
+ register file. */
+ {
+ int i, offset;
+
+ offset = 0;
+ for (i = 0; i < MAX_NUM_REGS; i++)
+ {
+ i386_register_byte[i] = offset;
+ offset += i386_register_raw_size[i];
+ }
+ }
+
+ /* Initialize the table of virtual register sizes. */
+ {
+ int i;
+
+ for (i = 0; i < MAX_NUM_REGS; i++)
+ i386_register_virtual_size[i] = TYPE_LENGTH (REGISTER_VIRTUAL_TYPE (i));
+ }
tm_print_insn = gdb_print_insn_i386;
tm_print_insn_info.mach = bfd_lookup_arch (bfd_arch_i386, 0)->mach;
/* Add the variable that controls the disassembly flavor */
+ {
+ struct cmd_list_element *new_cmd;
- new_cmd = add_set_enum_cmd ("disassembly-flavor", no_class,
- valid_flavors,
- (char *) &disassembly_flavor,
- "Set the disassembly flavor, the valid values are \"att\" and \"intel\", \
+ new_cmd = add_set_enum_cmd ("disassembly-flavor", no_class,
+ valid_flavors,
+ &disassembly_flavor,
+ "Set the disassembly flavor, the valid values are \"att\" and \"intel\", \
and the default value is \"att\".",
- &setlist);
- new_cmd->function.sfunc = set_disassembly_flavor_sfunc;
- add_show_from_set (new_cmd, &showlist);
+ &setlist);
+ new_cmd->function.sfunc = set_disassembly_flavor_sfunc;
+ add_show_from_set (new_cmd, &showlist);
+ }
/* Finally, initialize the disassembly flavor to the default given
in the disassembly_flavor variable */
set_disassembly_flavor ();
-
}