From ae83b20d8f8eff60f8bd9d7a131f7f60b06db772 Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Wed, 9 May 2001 02:44:01 +0000 Subject: 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. --- gdb/mn10300-tdep.c | 106 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 71 insertions(+), 35 deletions(-) (limited to 'gdb/mn10300-tdep.c') diff --git a/gdb/mn10300-tdep.c b/gdb/mn10300-tdep.c index ca73a06..ae7d2f5 100644 --- a/gdb/mn10300-tdep.c +++ b/gdb/mn10300-tdep.c @@ -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)); } -- cgit v1.1