Correct and expand handling of `movm' instruction, and register
saves in general. * config/mn10300/tm-mn10300.h (D0_REGNUM, A0_REGNUM, MDRQ_REGNUM, MCRH_REGNUM, MCRL_REGNUM, MCVF_REGNUM): New definitions. (enum movm_register_bits): New enum. * mn10300-tdep.c (set_movm_offsets): Use symbolic names for the bits, not hex literals. Handle the `other', `exreg0', and `exother' bits. Correct handling of `exreg1': it saves r4, r5, r6, and r7, not r2, r3, r4, and r5. (saved_regs_size): New function. (mn10300_frame_chain, mn10300_frame_saved_pc): Use it, instead of computing the same thing inline, incorrectly.
This commit is contained in:
parent
bf4b70a5e8
commit
ae83b20d8f
|
@ -1,5 +1,18 @@
|
|||
2001-05-08 Jim Blandy <jimb@redhat.com>
|
||||
|
||||
Correct and expand handling of `movm' instruction, and register
|
||||
saves in general.
|
||||
* config/mn10300/tm-mn10300.h (D0_REGNUM, A0_REGNUM, MDRQ_REGNUM,
|
||||
MCRH_REGNUM, MCRL_REGNUM, MCVF_REGNUM): New definitions.
|
||||
(enum movm_register_bits): New enum.
|
||||
* mn10300-tdep.c (set_movm_offsets): Use symbolic names for the
|
||||
bits, not hex literals. Handle the `other', `exreg0', and
|
||||
`exother' bits. Correct handling of `exreg1': it saves r4, r5,
|
||||
r6, and r7, not r2, r3, r4, and r5.
|
||||
(saved_regs_size): New function.
|
||||
(mn10300_frame_chain, mn10300_frame_saved_pc): Use it, instead
|
||||
of computing the same thing inline, incorrectly.
|
||||
|
||||
* mn10300-tdep.c (mn10300_gdbarch_init): We do have a
|
||||
dummy_breakpoint_offset; it's zero.
|
||||
|
||||
|
|
|
@ -43,8 +43,10 @@
|
|||
#define REGISTER_RAW_SIZE(REG) 4
|
||||
#endif
|
||||
|
||||
#define D0_REGNUM 0
|
||||
#define D2_REGNUM 2
|
||||
#define D3_REGNUM 3
|
||||
#define A0_REGNUM 4
|
||||
#define A2_REGNUM 6
|
||||
#define A3_REGNUM 7
|
||||
#define SP_REGNUM 8
|
||||
|
@ -53,7 +55,22 @@
|
|||
#define PSW_REGNUM 11
|
||||
#define LIR_REGNUM 12
|
||||
#define LAR_REGNUM 13
|
||||
#define MDRQ_REGNUM 14
|
||||
#define E0_REGNUM 15
|
||||
#define MCRH_REGNUM 26
|
||||
#define MCRL_REGNUM 27
|
||||
#define MCVF_REGNUM 28
|
||||
|
||||
enum movm_register_bits {
|
||||
movm_exother_bit = 0x01,
|
||||
movm_exreg1_bit = 0x02,
|
||||
movm_exreg0_bit = 0x04,
|
||||
movm_other_bit = 0x08,
|
||||
movm_a3_bit = 0x10,
|
||||
movm_a2_bit = 0x20,
|
||||
movm_d3_bit = 0x40,
|
||||
movm_d2_bit = 0x80
|
||||
};
|
||||
|
||||
#define INIT_FRAME_PC /* Not necessary */
|
||||
|
||||
|
|
|
@ -197,32 +197,66 @@ set_movm_offsets (struct frame_info *fi, int movm_args)
|
|||
if (fi == NULL || movm_args == 0)
|
||||
return;
|
||||
|
||||
if (movm_args & 0x10)
|
||||
if (movm_args & movm_other_bit)
|
||||
{
|
||||
/* The `other' bit leaves a blank area of four bytes at the
|
||||
beginning of its block of saved registers, making it 32 bytes
|
||||
long in total. */
|
||||
fi->saved_regs[LAR_REGNUM] = fi->frame + offset + 4;
|
||||
fi->saved_regs[LIR_REGNUM] = fi->frame + offset + 8;
|
||||
fi->saved_regs[MDR_REGNUM] = fi->frame + offset + 12;
|
||||
fi->saved_regs[A0_REGNUM + 1] = fi->frame + offset + 16;
|
||||
fi->saved_regs[A0_REGNUM] = fi->frame + offset + 20;
|
||||
fi->saved_regs[D0_REGNUM + 1] = fi->frame + offset + 24;
|
||||
fi->saved_regs[D0_REGNUM] = fi->frame + offset + 28;
|
||||
offset += 32;
|
||||
}
|
||||
if (movm_args & movm_a3_bit)
|
||||
{
|
||||
fi->saved_regs[A3_REGNUM] = fi->frame + offset;
|
||||
offset += 4;
|
||||
}
|
||||
if (movm_args & 0x20)
|
||||
if (movm_args & movm_a2_bit)
|
||||
{
|
||||
fi->saved_regs[A2_REGNUM] = fi->frame + offset;
|
||||
offset += 4;
|
||||
}
|
||||
if (movm_args & 0x40)
|
||||
if (movm_args & movm_d3_bit)
|
||||
{
|
||||
fi->saved_regs[D3_REGNUM] = fi->frame + offset;
|
||||
offset += 4;
|
||||
}
|
||||
if (movm_args & 0x80)
|
||||
if (movm_args & movm_d2_bit)
|
||||
{
|
||||
fi->saved_regs[D2_REGNUM] = fi->frame + offset;
|
||||
offset += 4;
|
||||
}
|
||||
if (AM33_MODE && movm_args & 0x02)
|
||||
if (AM33_MODE)
|
||||
{
|
||||
fi->saved_regs[E0_REGNUM + 5] = fi->frame + offset;
|
||||
fi->saved_regs[E0_REGNUM + 4] = fi->frame + offset + 4;
|
||||
fi->saved_regs[E0_REGNUM + 3] = fi->frame + offset + 8;
|
||||
fi->saved_regs[E0_REGNUM + 2] = fi->frame + offset + 12;
|
||||
if (movm_args & movm_exother_bit)
|
||||
{
|
||||
fi->saved_regs[MCVF_REGNUM] = fi->frame + offset;
|
||||
fi->saved_regs[MCRL_REGNUM] = fi->frame + offset + 4;
|
||||
fi->saved_regs[MCRH_REGNUM] = fi->frame + offset + 8;
|
||||
fi->saved_regs[MDRQ_REGNUM] = fi->frame + offset + 12;
|
||||
fi->saved_regs[E0_REGNUM + 1] = fi->frame + offset + 16;
|
||||
fi->saved_regs[E0_REGNUM + 0] = fi->frame + offset + 20;
|
||||
offset += 24;
|
||||
}
|
||||
if (movm_args & movm_exreg1_bit)
|
||||
{
|
||||
fi->saved_regs[E0_REGNUM + 7] = fi->frame + offset;
|
||||
fi->saved_regs[E0_REGNUM + 6] = fi->frame + offset + 4;
|
||||
fi->saved_regs[E0_REGNUM + 5] = fi->frame + offset + 8;
|
||||
fi->saved_regs[E0_REGNUM + 4] = fi->frame + offset + 12;
|
||||
offset += 16;
|
||||
}
|
||||
if (movm_args & movm_exreg0_bit)
|
||||
{
|
||||
fi->saved_regs[E0_REGNUM + 3] = fi->frame + offset;
|
||||
fi->saved_regs[E0_REGNUM + 2] = fi->frame + offset + 4;
|
||||
offset += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -510,6 +544,32 @@ mn10300_analyze_prologue (struct frame_info *fi, CORE_ADDR pc)
|
|||
return addr;
|
||||
}
|
||||
|
||||
|
||||
/* Function: saved_regs_size
|
||||
Return the size in bytes of the register save area, based on the
|
||||
saved_regs array in FI. */
|
||||
static int
|
||||
saved_regs_size (struct frame_info *fi)
|
||||
{
|
||||
int adjust = 0;
|
||||
int i;
|
||||
|
||||
/* Reserve four bytes for every register saved. */
|
||||
for (i = 0; i < NUM_REGS; i++)
|
||||
if (fi->saved_regs[i])
|
||||
adjust += 4;
|
||||
|
||||
/* If we saved LIR, then it's most likely we used a `movm'
|
||||
instruction with the `other' bit set, in which case the SP is
|
||||
decremented by an extra four bytes, "to simplify calculation
|
||||
of the transfer area", according to the processor manual. */
|
||||
if (fi->saved_regs[LIR_REGNUM])
|
||||
adjust += 4;
|
||||
|
||||
return adjust;
|
||||
}
|
||||
|
||||
|
||||
/* Function: frame_chain
|
||||
Figure out and return the caller's frame pointer given current
|
||||
frame_info struct.
|
||||
|
@ -560,19 +620,7 @@ mn10300_frame_chain (struct frame_info *fi)
|
|||
}
|
||||
else
|
||||
{
|
||||
int adjust = 0;
|
||||
|
||||
adjust += (fi->saved_regs[D2_REGNUM] ? 4 : 0);
|
||||
adjust += (fi->saved_regs[D3_REGNUM] ? 4 : 0);
|
||||
adjust += (fi->saved_regs[A2_REGNUM] ? 4 : 0);
|
||||
adjust += (fi->saved_regs[A3_REGNUM] ? 4 : 0);
|
||||
if (AM33_MODE)
|
||||
{
|
||||
adjust += (fi->saved_regs[E0_REGNUM + 5] ? 4 : 0);
|
||||
adjust += (fi->saved_regs[E0_REGNUM + 4] ? 4 : 0);
|
||||
adjust += (fi->saved_regs[E0_REGNUM + 3] ? 4 : 0);
|
||||
adjust += (fi->saved_regs[E0_REGNUM + 2] ? 4 : 0);
|
||||
}
|
||||
int adjust = saved_regs_size (fi);
|
||||
|
||||
/* Our caller does not have a frame pointer. So his frame starts
|
||||
at the base of our frame (fi->frame) + register save space
|
||||
|
@ -748,19 +796,7 @@ mn10300_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
|
|||
static CORE_ADDR
|
||||
mn10300_frame_saved_pc (struct frame_info *fi)
|
||||
{
|
||||
int adjust = 0;
|
||||
|
||||
adjust += (fi->saved_regs[D2_REGNUM] ? 4 : 0);
|
||||
adjust += (fi->saved_regs[D3_REGNUM] ? 4 : 0);
|
||||
adjust += (fi->saved_regs[A2_REGNUM] ? 4 : 0);
|
||||
adjust += (fi->saved_regs[A3_REGNUM] ? 4 : 0);
|
||||
if (AM33_MODE)
|
||||
{
|
||||
adjust += (fi->saved_regs[E0_REGNUM + 5] ? 4 : 0);
|
||||
adjust += (fi->saved_regs[E0_REGNUM + 4] ? 4 : 0);
|
||||
adjust += (fi->saved_regs[E0_REGNUM + 3] ? 4 : 0);
|
||||
adjust += (fi->saved_regs[E0_REGNUM + 2] ? 4 : 0);
|
||||
}
|
||||
int adjust = saved_regs_size (fi);
|
||||
|
||||
return (read_memory_integer (fi->frame + adjust, REGISTER_SIZE));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue