X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fmn10200-tdep.c;h=a8d7d72ef8ec45b3ce28589f522e08c9777b1f22;hb=e64f66d17121a4ce10bbd5eeadf8d4130c23e116;hp=11c03e9a0890615ed4285699893aaeb16a694579;hpb=a698d0d06fa53c237244835b97b5657f68a62add;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/mn10200-tdep.c b/gdb/mn10200-tdep.c index 11c03e9a08..a8d7d72ef8 100644 --- a/gdb/mn10200-tdep.c +++ b/gdb/mn10200-tdep.c @@ -1,33 +1,42 @@ /* Target-dependent code for the Matsushita MN10200 for GDB, the GNU debugger. - Copyright 1997 Free Software Foundation, Inc. + Copyright 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. -This file is part of GDB. + This file is part of GDB. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ #include "defs.h" #include "frame.h" #include "inferior.h" -#include "obstack.h" #include "target.h" #include "value.h" #include "bfd.h" #include "gdb_string.h" #include "gdbcore.h" #include "symfile.h" +#include "regcache.h" + +/* Should call_function allocate stack space for a struct return? */ +int +mn10200_use_struct_convention (int gcc_p, struct type *type) +{ + return (TYPE_NFIELDS (type) > 1 || TYPE_LENGTH (type) > 8); +} +/* *INDENT-OFF* */ /* The main purpose of this file is dealing with prologues to extract information about stack frames and saved registers. @@ -37,23 +46,27 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ mov fp,a0 mov sp,fp add ,sp - Register saves for d2, d3, a3 as needed. Saves start - at fp - and work towards higher addresses. Note - that the saves are actually done off the stack pointer - in the prologue! This makes for smaller code and easier - prologue scanning as the displacement fields will never + Register saves for d2, d3, a1, a2 as needed. Saves start + at fp - + and work towards higher + addresses. Note that the saves are actually done off the stack + pointer in the prologue! This makes for smaller code and easier + prologue scanning as the displacement fields will unlikely be more than 8 bits! Without frame pointer: add ,sp - Register saves for d2, d3, a3 as needed. Saves start - at sp and work towards higher addresses. + Register saves for d2, d3, a1, a2 as needed. Saves start + at sp + and work towards higher addresses. + Out of line prologue: + add ,sp -- optional + jsr __prologue + add ,sp -- optional + + The stack pointer remains constant throughout the life of most + functions. As a result the compiler will usually omit the + frame pointer, so we must handle frame pointerless functions. */ - One day we might keep the stack pointer constant, that won't - change the code for prologues, but it will make the frame - pointerless case much more common. */ - /* Analyze the prologue to determine where registers are saved, the end of the prologue, etc etc. Return the end of the prologue scanned. @@ -86,22 +99,25 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ NO_MORE_FRAMES: Set this if the current frame is "start" or if the first instruction looks like mov ,sp. This tells frame chain to not bother trying to unwind past this frame. */ +/* *INDENT-ON* */ + + + #define MY_FRAME_IN_SP 0x1 #define MY_FRAME_IN_FP 0x2 #define CALLER_A2_IN_A0 0x4 #define NO_MORE_FRAMES 0x8 - + static CORE_ADDR -mn10200_analyze_prologue (fi, pc) - struct frame_info *fi; - CORE_ADDR pc; +mn10200_analyze_prologue (struct frame_info *fi, CORE_ADDR pc) { CORE_ADDR func_addr, func_end, addr, stop; - CORE_ADDR stack_size; + CORE_ADDR stack_size = 0; unsigned char buf[4]; int status; char *name; + int out_of_line_prologue = 0; /* Use the PC in the frame if it's provided to look up the start of this function. */ @@ -118,7 +134,8 @@ mn10200_analyze_prologue (fi, pc) /* If we're in start, then give up. */ if (strcmp (name, "start") == 0) { - fi->status = NO_MORE_FRAMES; + if (fi) + fi->status = NO_MORE_FRAMES; return pc; } @@ -135,13 +152,15 @@ mn10200_analyze_prologue (fi, pc) status = target_read_memory (fi->pc, buf, 1); if (status != 0) { - fi->frame = read_sp (); + if (fi->next == NULL) + fi->frame = read_sp (); return fi->pc; } if (buf[0] == 0xfe) { - fi->frame = read_sp (); + if (fi->next == NULL) + fi->frame = read_sp (); return fi->pc; } } @@ -150,7 +169,8 @@ mn10200_analyze_prologue (fi, pc) frame hasn't been allocated yet. */ if (fi && fi->pc == func_addr) { - fi->frame = read_sp (); + if (fi->next == NULL) + fi->frame = read_sp (); return fi->pc; } @@ -166,7 +186,7 @@ mn10200_analyze_prologue (fi, pc) status = target_read_memory (addr, buf, 2); if (status != 0) { - if (fi && fi->status & MY_FRAME_IN_SP) + if (fi && fi->next == NULL && fi->status & MY_FRAME_IN_SP) fi->frame = read_sp (); return addr; } @@ -182,14 +202,14 @@ mn10200_analyze_prologue (fi, pc) } /* Now see if we have a frame pointer. - + Search for mov a2,a0 (0xf278) - then mov a3,a2 (0xf27e). */ + then mov a3,a2 (0xf27e). */ if (buf[0] == 0xf2 && buf[1] == 0x78) { /* Our caller's $a2 will be found in $a0 now. Note it for - our callers. */ + our callers. */ if (fi) fi->status |= CALLER_A2_IN_A0; addr += 2; @@ -197,7 +217,7 @@ mn10200_analyze_prologue (fi, pc) { /* We still haven't allocated our local stack. Handle this as if we stopped on the first or last insn of a function. */ - if (fi) + if (fi && fi->next == NULL) fi->frame = read_sp (); return addr; } @@ -205,7 +225,7 @@ mn10200_analyze_prologue (fi, pc) status = target_read_memory (addr, buf, 2); if (status != 0) { - if (fi) + if (fi && fi->next == NULL) fi->frame = read_sp (); return addr; } @@ -224,25 +244,25 @@ mn10200_analyze_prologue (fi, pc) } else { - if (fi) + if (fi && fi->next == NULL) fi->frame = read_sp (); return addr; } } /* Next we should allocate the local frame. - + Search for add imm8,a3 (0xd3XX) - or add imm16,a3 (0xf70bXXXX) - or add imm24,a3 (0xf467XXXXXX). - + or add imm16,a3 (0xf70bXXXX) + or add imm24,a3 (0xf467XXXXXX). + If none of the above was found, then this prologue has no stack, and therefore can't have any register saves, so quit now. */ status = target_read_memory (addr, buf, 2); if (status != 0) { - if (fi && (fi->status & MY_FRAME_IN_SP)) + if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP)) fi->frame = read_sp (); return addr; } @@ -254,8 +274,8 @@ mn10200_analyze_prologue (fi, pc) addr += 2; if (addr >= stop) { - if (fi && (fi->status & MY_FRAME_IN_SP)) - fi->frame = read_sp () + stack_size; + if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP)) + fi->frame = read_sp () - stack_size; return addr; } } @@ -264,7 +284,7 @@ mn10200_analyze_prologue (fi, pc) status = target_read_memory (addr + 2, buf, 2); if (status != 0) { - if (fi && (fi->status & MY_FRAME_IN_SP)) + if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP)) fi->frame = read_sp (); return addr; } @@ -274,8 +294,8 @@ mn10200_analyze_prologue (fi, pc) addr += 4; if (addr >= stop) { - if (fi && (fi->status & MY_FRAME_IN_SP)) - fi->frame = read_sp () + stack_size; + if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP)) + fi->frame = read_sp () - stack_size; return addr; } } @@ -284,7 +304,7 @@ mn10200_analyze_prologue (fi, pc) status = target_read_memory (addr + 2, buf, 3); if (status != 0) { - if (fi && (fi->status & MY_FRAME_IN_SP)) + if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP)) fi->frame = read_sp (); return addr; } @@ -294,23 +314,202 @@ mn10200_analyze_prologue (fi, pc) addr += 5; if (addr >= stop) { - if (fi && (fi->status & MY_FRAME_IN_SP)) - fi->frame = read_sp () + stack_size; + if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP)) + fi->frame = read_sp () - stack_size; return addr; } } - else + + /* Now see if we have a call to __prologue for an out of line + prologue. */ + status = target_read_memory (addr, buf, 2); + if (status != 0) + return addr; + + /* First check for 16bit pc-relative call to __prologue. */ + if (buf[0] == 0xfd) { - if (fi && (fi->status & MY_FRAME_IN_SP)) - fi->frame = read_sp (); + CORE_ADDR temp; + status = target_read_memory (addr + 1, buf, 2); + if (status != 0) + { + if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP)) + fi->frame = read_sp (); + return addr; + } + + /* Get the PC this instruction will branch to. */ + temp = (extract_signed_integer (buf, 2) + addr + 3) & 0xffffff; + + /* Get the name of the function at the target address. */ + status = find_pc_partial_function (temp, &name, NULL, NULL); + if (status == 0) + { + if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP)) + fi->frame = read_sp (); + return addr; + } + + /* Note if it is an out of line prologue. */ + out_of_line_prologue = (strcmp (name, "__prologue") == 0); + + /* This sucks up 3 bytes of instruction space. */ + if (out_of_line_prologue) + addr += 3; + + if (addr >= stop) + { + if (fi && fi->next == NULL) + { + fi->stack_size -= 16; + fi->frame = read_sp () - fi->stack_size; + } + return addr; + } + } + /* Now check for the 24bit pc-relative call to __prologue. */ + else if (buf[0] == 0xf4 && buf[1] == 0xe1) + { + CORE_ADDR temp; + status = target_read_memory (addr + 2, buf, 3); + if (status != 0) + { + if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP)) + fi->frame = read_sp (); + return addr; + } + + /* Get the PC this instruction will branch to. */ + temp = (extract_signed_integer (buf, 3) + addr + 5) & 0xffffff; + + /* Get the name of the function at the target address. */ + status = find_pc_partial_function (temp, &name, NULL, NULL); + if (status == 0) + { + if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP)) + fi->frame = read_sp (); + return addr; + } + + /* Note if it is an out of line prologue. */ + out_of_line_prologue = (strcmp (name, "__prologue") == 0); + + /* This sucks up 5 bytes of instruction space. */ + if (out_of_line_prologue) + addr += 5; + + if (addr >= stop) + { + if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP)) + { + fi->stack_size -= 16; + fi->frame = read_sp () - fi->stack_size; + } + return addr; + } + } + + /* Now actually handle the out of line prologue. */ + if (out_of_line_prologue) + { + int outgoing_args_size = 0; + + /* First adjust the stack size for this function. The out of + line prologue saves 4 registers (16bytes of data). */ + if (fi) + fi->stack_size -= 16; + + /* Update fi->frame if necessary. */ + if (fi && fi->next == NULL) + fi->frame = read_sp () - fi->stack_size; + + /* After the out of line prologue, there may be another + stack adjustment for the outgoing arguments. + + Search for add imm8,a3 (0xd3XX) + or add imm16,a3 (0xf70bXXXX) + or add imm24,a3 (0xf467XXXXXX). */ + + status = target_read_memory (addr, buf, 2); + if (status != 0) + { + if (fi) + { + fi->fsr.regs[2] = fi->frame + fi->stack_size + 4; + fi->fsr.regs[3] = fi->frame + fi->stack_size + 8; + fi->fsr.regs[5] = fi->frame + fi->stack_size + 12; + fi->fsr.regs[6] = fi->frame + fi->stack_size + 16; + } + return addr; + } + + if (buf[0] == 0xd3) + { + outgoing_args_size = extract_signed_integer (&buf[1], 1); + addr += 2; + } + else if (buf[0] == 0xf7 && buf[1] == 0x0b) + { + status = target_read_memory (addr + 2, buf, 2); + if (status != 0) + { + if (fi) + { + fi->fsr.regs[2] = fi->frame + fi->stack_size + 4; + fi->fsr.regs[3] = fi->frame + fi->stack_size + 8; + fi->fsr.regs[5] = fi->frame + fi->stack_size + 12; + fi->fsr.regs[6] = fi->frame + fi->stack_size + 16; + } + return addr; + } + outgoing_args_size = extract_signed_integer (buf, 2); + addr += 4; + } + else if (buf[0] == 0xf4 && buf[1] == 0x67) + { + status = target_read_memory (addr + 2, buf, 3); + if (status != 0) + { + if (fi && fi->next == NULL) + { + fi->fsr.regs[2] = fi->frame + fi->stack_size + 4; + fi->fsr.regs[3] = fi->frame + fi->stack_size + 8; + fi->fsr.regs[5] = fi->frame + fi->stack_size + 12; + fi->fsr.regs[6] = fi->frame + fi->stack_size + 16; + } + return addr; + } + outgoing_args_size = extract_signed_integer (buf, 3); + addr += 5; + } + else + outgoing_args_size = 0; + + /* Now that we know the size of the outgoing arguments, fix + fi->frame again if this is the innermost frame. */ + if (fi && fi->next == NULL) + fi->frame -= outgoing_args_size; + + /* Note the register save information and update the stack + size for this frame too. */ + if (fi) + { + fi->fsr.regs[2] = fi->frame + fi->stack_size + 4; + fi->fsr.regs[3] = fi->frame + fi->stack_size + 8; + fi->fsr.regs[5] = fi->frame + fi->stack_size + 12; + fi->fsr.regs[6] = fi->frame + fi->stack_size + 16; + fi->stack_size += outgoing_args_size; + } + /* There can be no more prologue insns, so return now. */ return addr; } /* At this point fi->frame needs to be correct. - If MY_FRAME_IN_SP is set, then we need to fix fi->frame so - that backtracing, find_frame_saved_regs, etc work correctly. */ - if (fi && (fi->status & MY_FRAME_IN_SP) != 0) + If MY_FRAME_IN_SP is set and we're the innermost frame, then we + need to fix fi->frame so that backtracing, find_frame_saved_regs, + etc work correctly. */ + if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP) != 0) fi->frame = read_sp () - fi->stack_size; /* And last we have the register saves. These are relatively @@ -318,11 +517,12 @@ mn10200_analyze_prologue (fi, pc) and thus the number of different instructions we need to check is greatly reduced because we know the displacements will be small. - + Search for movx d2,(X,a3) (0xf55eXX) - then movx d3,(X,a3) (0xf55fXX) - then mov a2,(X,a3) (0x5eXX) No frame pointer case - or mov a0,(X,a3) (0x5cXX) Frame pointer case. */ + then movx d3,(X,a3) (0xf55fXX) + then mov a1,(X,a3) (0x5dXX) No frame pointer case + then mov a2,(X,a3) (0x5eXX) No frame pointer case + or mov a0,(X,a3) (0x5cXX) Frame pointer case. */ status = target_read_memory (addr, buf, 2); if (status != 0) @@ -361,6 +561,23 @@ mn10200_analyze_prologue (fi, pc) if (status != 0) return addr; } + if (buf[0] == 0x5d) + { + if (fi) + { + status = target_read_memory (addr + 1, buf, 1); + if (status != 0) + return addr; + fi->fsr.regs[5] = (fi->frame + stack_size + + extract_signed_integer (buf, 1)); + } + addr += 2; + if (addr >= stop) + return addr; + status = target_read_memory (addr, buf, 2); + if (status != 0) + return addr; + } if (buf[0] == 0x5e || buf[0] == 0x5c) { if (fi) @@ -379,7 +596,7 @@ mn10200_analyze_prologue (fi, pc) } return addr; } - + /* Function: frame_chain Figure out and return the caller's frame pointer given current frame_info struct. @@ -388,15 +605,14 @@ mn10200_analyze_prologue (fi, pc) stack pointer that was in use at the time the function call was made? */ CORE_ADDR -mn10200_frame_chain (fi) - struct frame_info *fi; +mn10200_frame_chain (struct frame_info *fi) { struct frame_info dummy_frame; /* Walk through the prologue to determine the stack size, location of saved registers, end of the prologue, etc. */ if (fi->status == 0) - mn10200_analyze_prologue (fi, (CORE_ADDR)0); + mn10200_analyze_prologue (fi, (CORE_ADDR) 0); /* Quit now if mn10200_analyze_prologue set NO_MORE_FRAMES. */ if (fi->status & NO_MORE_FRAMES) @@ -405,19 +621,19 @@ mn10200_frame_chain (fi) /* Now that we've analyzed our prologue, determine the frame pointer for our caller. - If our caller has a frame pointer, then we need to - find the entry value of $a2 to our function. + If our caller has a frame pointer, then we need to + find the entry value of $a2 to our function. - If CALLER_A2_IN_A0, then the chain is in $a0. + If CALLER_A2_IN_A0, then the chain is in $a0. - If fsr.regs[6] is nonzero, then it's at the memory - location pointed to by fsr.regs[6]. + If fsr.regs[6] is nonzero, then it's at the memory + location pointed to by fsr.regs[6]. - Else it's still in $a2. + Else it's still in $a2. + + If our caller does not have a frame pointer, then his + frame base is fi->frame + -caller's stack size + 4. */ - If our caller does not have a frame pointer, then his - frame base is fi->frame + caller's stack size + 4. */ - /* The easiest way to get that info is to analyze our caller's frame. So we set up a dummy frame and call mn10200_analyze_prologue to @@ -427,12 +643,12 @@ mn10200_frame_chain (fi) memset (dummy_frame.fsr.regs, '\000', sizeof dummy_frame.fsr.regs); dummy_frame.status = 0; dummy_frame.stack_size = 0; - mn10200_analyze_prologue (&dummy_frame); + mn10200_analyze_prologue (&dummy_frame, 0); if (dummy_frame.status & MY_FRAME_IN_FP) { /* Our caller has a frame pointer. So find the frame in $a2, $a0, - or in the stack. */ + or in the stack. */ if (fi->fsr.regs[6]) return (read_memory_integer (fi->fsr.regs[FP_REGNUM], REGISTER_SIZE) & 0xffffff); @@ -444,8 +660,8 @@ mn10200_frame_chain (fi) else { /* Our caller does not have a frame pointer. So his frame starts - at the base of our frame (fi->frame) + + 4 (saved pc). */ - return fi->frame + dummy_frame.stack_size + 4; + at the base of our frame (fi->frame) + + 4 (saved pc). */ + return fi->frame + -dummy_frame.stack_size + 4; } } @@ -453,27 +669,11 @@ mn10200_frame_chain (fi) Return the address of the first inst past the prologue of the function. */ CORE_ADDR -mn10200_skip_prologue (pc) - CORE_ADDR pc; +mn10200_skip_prologue (CORE_ADDR pc) { - CORE_ADDR func_addr, func_end; - - /* First check the symbol table. That'll be faster than scanning - the prologue instructions if we have debug sybmols. */ - if (find_pc_partial_function (pc, NULL, &func_addr, &func_end)) - { - struct symtab_and_line sal; - - sal = find_pc_line (func_addr, 0); - - if (sal.line != 0 && sal.end < func_end) - return sal.end; - - return mn10200_analyze_prologue (NULL, pc); - } - - /* We couldn't find the start of this function, do nothing. */ - return pc; + /* We used to check the debug symbols, but that can lose if + we have a null prologue. */ + return mn10200_analyze_prologue (NULL, pc); } /* Function: pop_frame @@ -481,12 +681,11 @@ mn10200_skip_prologue (pc) command, or the call dummy breakpoint gets hit. */ void -mn10200_pop_frame (frame) - struct frame_info *frame; +mn10200_pop_frame (struct frame_info *frame) { int regnum; - if (PC_IN_CALL_DUMMY(frame->pc, frame->frame, frame->frame)) + if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame)) generic_pop_dummy_frame (); else { @@ -499,7 +698,7 @@ mn10200_pop_frame (frame) ULONGEST value; value = read_memory_unsigned_integer (frame->fsr.regs[regnum], - REGISTER_RAW_SIZE (regnum)); + REGISTER_RAW_SIZE (regnum)); write_register (regnum, value); } @@ -518,60 +717,99 @@ mn10200_pop_frame (frame) order on the stack. */ CORE_ADDR -mn10200_push_arguments (nargs, args, sp, struct_return, struct_addr) - int nargs; - value_ptr *args; - CORE_ADDR sp; - unsigned char struct_return; - CORE_ADDR struct_addr; +mn10200_push_arguments (int nargs, struct value **args, CORE_ADDR sp, + unsigned char struct_return, CORE_ADDR struct_addr) { int argnum = 0; int len = 0; int stack_offset = 0; + int regsused = struct_return ? 1 : 0; /* This should be a nop, but align the stack just in case something - went wrong. */ - sp &= ~3; + went wrong. Stacks are two byte aligned on the mn10200. */ + sp &= ~1; /* Now make space on the stack for the args. XXX This doesn't appear to handle pass-by-invisible reference arguments. */ for (argnum = 0; argnum < nargs; argnum++) - len += ((TYPE_LENGTH (VALUE_TYPE (args[argnum])) + 3) & ~3); + { + int arg_length = (TYPE_LENGTH (VALUE_TYPE (args[argnum])) + 1) & ~1; + + /* If we've used all argument registers, then this argument is + pushed. */ + if (regsused >= 2 || arg_length > 4) + { + regsused = 2; + len += arg_length; + } + /* We know we've got some arg register space left. If this argument + will fit entirely in regs, then put it there. */ + else if (arg_length <= 2 + || TYPE_CODE (VALUE_TYPE (args[argnum])) == TYPE_CODE_PTR) + { + regsused++; + } + else if (regsused == 0) + { + regsused = 2; + } + else + { + regsused = 2; + len += arg_length; + } + } /* Allocate stack space. */ sp -= len; + regsused = struct_return ? 1 : 0; /* Push all arguments onto the stack. */ for (argnum = 0; argnum < nargs; argnum++) { int len; char *val; - /* XXX Check this. What about UNIONS? Size check looks - wrong too. */ + /* XXX Check this. What about UNIONS? */ if (TYPE_CODE (VALUE_TYPE (*args)) == TYPE_CODE_STRUCT && TYPE_LENGTH (VALUE_TYPE (*args)) > 8) { /* XXX Wrong, we want a pointer to this argument. */ - len = TYPE_LENGTH (VALUE_TYPE (*args)); - val = (char *)VALUE_CONTENTS (*args); + len = TYPE_LENGTH (VALUE_TYPE (*args)); + val = (char *) VALUE_CONTENTS (*args); } else { len = TYPE_LENGTH (VALUE_TYPE (*args)); - val = (char *)VALUE_CONTENTS (*args); + val = (char *) VALUE_CONTENTS (*args); } - while (len > 0) + if (regsused < 2 + && (len <= 2 + || TYPE_CODE (VALUE_TYPE (*args)) == TYPE_CODE_PTR)) { - /* XXX This looks wrong; we can have one and two byte args. */ - write_memory (sp + stack_offset, val, 4); + write_register (regsused, extract_unsigned_integer (val, 4)); + regsused++; + } + else if (regsused == 0 && len == 4) + { + write_register (regsused, extract_unsigned_integer (val, 2)); + write_register (regsused + 1, extract_unsigned_integer (val + 2, 2)); + regsused = 2; + } + else + { + regsused = 2; + while (len > 0) + { + write_memory (sp + stack_offset, val, 2); - len -= 4; - val += 4; - stack_offset += 4; + len -= 2; + val += 2; + stack_offset += 2; + } } args++; } @@ -582,16 +820,29 @@ mn10200_push_arguments (nargs, args, sp, struct_return, struct_addr) /* Function: push_return_address (pc) Set up the return address for the inferior function call. Needed for targets where we don't actually execute a JSR/BSR instruction */ - + CORE_ADDR -mn10200_push_return_address (pc, sp) - CORE_ADDR pc; - CORE_ADDR sp; +mn10200_push_return_address (CORE_ADDR pc, CORE_ADDR sp) { + unsigned char buf[4]; + + store_unsigned_integer (buf, 4, CALL_DUMMY_ADDRESS ()); + write_memory (sp - 4, buf, 4); + return sp - 4; +} + +/* Function: store_struct_return (addr,sp) + Store the structure value return address for an inferior function + call. */ +CORE_ADDR +mn10200_store_struct_return (CORE_ADDR addr, CORE_ADDR sp) +{ + /* The structure return address is passed as the first argument. */ + write_register (0, addr); return sp; } - + /* Function: frame_saved_pc Find the caller of this frame. We do this by seeing if RP_REGNUM is saved in the stack anywhere, otherwise we get it from the @@ -600,26 +851,12 @@ mn10200_push_return_address (pc, sp) will be found. */ CORE_ADDR -mn10200_frame_saved_pc (fi) - struct frame_info *fi; +mn10200_frame_saved_pc (struct frame_info *fi) { /* The saved PC will always be at the base of the current frame. */ return (read_memory_integer (fi->frame, REGISTER_SIZE) & 0xffffff); } -void -get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval) - char *raw_buffer; - int *optimized; - CORE_ADDR *addrp; - struct frame_info *frame; - int regnum; - enum lval_type *lval; -{ - generic_get_saved_register (raw_buffer, optimized, addrp, - frame, regnum, lval); -} - /* Function: init_extra_frame_info Setup the frame's frame pointer, pc, and frame addresses for saved registers. Most of the work is done in mn10200_analyze_prologue(). @@ -635,8 +872,7 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval) pointer just prior to calling the target function (see run_stack_dummy). */ void -mn10200_init_extra_frame_info (fi) - struct frame_info *fi; +mn10200_init_extra_frame_info (struct frame_info *fi) { if (fi->next) fi->pc = FRAME_SAVED_PC (fi->next); @@ -649,8 +885,7 @@ mn10200_init_extra_frame_info (fi) } void -_initialize_mn10200_tdep () +_initialize_mn10200_tdep (void) { tm_print_insn = print_insn_mn10200; } -