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:
Jim Blandy 2001-05-09 02:44:01 +00:00
parent bf4b70a5e8
commit ae83b20d8f
3 changed files with 101 additions and 35 deletions

View File

@ -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.

View File

@ -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 */

View File

@ -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));
}