op = read_memory_unsigned_integer (pc + 1, 1);
- /* Check for some special instructions that might be migrated
- by GCC into the prologue. We check for
+ /* Check for some special instructions that might be migrated by
+ GCC into the prologue. At this point in the prologue, code
+ should only touch the scratch registers %eax, %ecx and %edx,
+ so we check for
- xorl %ebx, %ebx
+ movl $XXX, %eax
+ movl $XXX, %ecx
+ movl $XXX, %edx
+
+ These instructions have opcodes 0xb8, 0xb9 and 0xba.
+
+ We also check for
+
+ xorl %eax, %eax
xorl %ecx, %ecx
xorl %edx, %edx
- xorl %eax, %eax
and the equivalent
- subl %ebx, %ebx
+ subl %eax, %eax
subl %ecx, %ecx
subl %edx, %edx
- subl %eax, %eax
Because of the symmetry, there are actually two ways to
encode these instructions; with opcode bytes 0x29 and 0x2b
Make sure we only skip these instructions if we later see the
`movl %esp, %ebp' that actually sets up the frame. */
- while (op == 0x29 || op == 0x2b || op == 0x31 || op == 0x33)
+ while ((op >= 0xb8 && op <= 0xba)
+ || op == 0x29 || op == 0x2b
+ || op == 0x31 || op == 0x33)
{
- op = read_memory_unsigned_integer (pc + skip + 2, 1);
- switch (op)
+ if (op >= 0xb8 && op <= 0xba)
+ {
+ /* Skip the `movl' instructions cited above. */
+ skip += 5;
+ }
+ else
{
- case 0xdb: /* %ebx */
- case 0xc9: /* %ecx */
- case 0xd2: /* %edx */
- case 0xc0: /* %eax */
- skip += 2;
- break;
- default:
- return pc + 1;
+ /* Skip the `subl' and `xorl' instructions cited above. */
+ op = read_memory_unsigned_integer (pc + skip + 2, 1);
+ switch (op)
+ {
+ case 0xc0: /* %eax */
+ case 0xc9: /* %ecx */
+ case 0xd2: /* %edx */
+ skip += 2;
+ break;
+ default:
+ return pc + 1;
+ }
}
+ /* If that's all, return now. */
+ if (current_pc <= pc + skip + 1)
+ return current_pc;
+
op = read_memory_unsigned_integer (pc + skip + 1, 1);
}
\f
static CORE_ADDR
-i386_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
+i386_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
struct regcache *regcache, CORE_ADDR bp_addr, int nargs,
struct value **args, CORE_ADDR sp, int struct_return,
CORE_ADDR struct_addr)
}
}
\f
-/* Supply register REGNUM from the general-purpose register set REGSET
- to register cache REGCACHE. If REGNUM is -1, do this for all
- registers in REGSET. */
+/* Supply register REGNUM from the buffer specified by GREGS and LEN
+ in the general-purpose register set REGSET to register cache
+ REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
void
i386_supply_gregset (const struct regset *regset, struct regcache *regcache,
int regnum, const void *gregs, size_t len)
{
- const struct gdbarch_tdep *tdep = regset->descr;
+ const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
const char *regs = gregs;
int i;
}
}
-/* Supply register REGNUM from the floating-point register set REGSET
- to register cache REGCACHE. If REGNUM is -1, do this for all
- registers in REGSET. */
+/* Collect register REGNUM from the register cache REGCACHE and store
+ it in the buffer specified by GREGS and LEN as described by the
+ general-purpose register set REGSET. If REGNUM is -1, do this for
+ all registers in REGSET. */
+
+void
+i386_collect_gregset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *gregs, size_t len)
+{
+ const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
+ char *regs = gregs;
+ int i;
+
+ gdb_assert (len == tdep->sizeof_gregset);
+
+ for (i = 0; i < tdep->gregset_num_regs; i++)
+ {
+ if ((regnum == i || regnum == -1)
+ && tdep->gregset_reg_offset[i] != -1)
+ regcache_raw_collect (regcache, i, regs + tdep->gregset_reg_offset[i]);
+ }
+}
+
+/* Supply register REGNUM from the buffer specified by FPREGS and LEN
+ in the floating-point register set REGSET to register cache
+ REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
static void
i386_supply_fpregset (const struct regset *regset, struct regcache *regcache,
int regnum, const void *fpregs, size_t len)
{
- const struct gdbarch_tdep *tdep = regset->descr;
+ const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
if (len == I387_SIZEOF_FXSAVE)
{
i387_supply_fsave (regcache, regnum, fpregs);
}
+/* Collect register REGNUM from the register cache REGCACHE and store
+ it in the buffer specified by FPREGS and LEN as described by the
+ floating-point register set REGSET. If REGNUM is -1, do this for
+ all registers in REGSET. */
+
+static void
+i386_collect_fpregset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *fpregs, size_t len)
+{
+ const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
+
+ if (len == I387_SIZEOF_FXSAVE)
+ {
+ i387_collect_fxsave (regcache, regnum, fpregs);
+ return;
+ }
+
+ gdb_assert (len == tdep->sizeof_fpregset);
+ i387_collect_fsave (regcache, regnum, fpregs);
+}
+
/* Return the appropriate register set for the core section identified
by SECT_NAME and SECT_SIZE. */
if (strcmp (sect_name, ".reg") == 0 && sect_size == tdep->sizeof_gregset)
{
if (tdep->gregset == NULL)
- tdep->gregset = regset_alloc (gdbarch, tdep,
- i386_supply_gregset, NULL);
+ tdep->gregset = regset_alloc (gdbarch, i386_supply_gregset,
+ i386_collect_gregset);
return tdep->gregset;
}
&& sect_size == I387_SIZEOF_FXSAVE))
{
if (tdep->fpregset == NULL)
- tdep->fpregset = regset_alloc (gdbarch, tdep,
- i386_supply_fpregset, NULL);
+ tdep->fpregset = regset_alloc (gdbarch, i386_supply_fpregset,
+ i386_collect_fpregset);
return tdep->fpregset;
}