/* Copyright 2002 Free Software Foundation, Inc. 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 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. */ #include "defs.h" #include "frame.h" #include "symtab.h" #include "value.h" #include "gdbcmd.h" #include "regcache.h" #include "symfile.h" #include "gdbcore.h" #include "inferior.h" /* Functions declared and used only in this file */ static CORE_ADDR msp430_analyze_prologue (struct frame_info *fi, CORE_ADDR pc, int skip_prologue); static struct frame_info *analyze_dummy_frame (CORE_ADDR pc, CORE_ADDR frame); static int get_insn (CORE_ADDR pc); /* Functions exported from this file */ int msp430_use_struct_convention (int gcc_p, struct type *type); void _initialize_msp430 (void); void msp430_init_extra_frame_info (struct frame_info *fi); CORE_ADDR msp430_frame_saved_pc (struct frame_info *fi); CORE_ADDR msp430_find_callers_reg (struct frame_info *fi, int regnum); CORE_ADDR msp430_frame_args_address (struct frame_info *fi); CORE_ADDR msp430_frame_locals_address (struct frame_info *fi); void msp430_virtual_frame_pointer (CORE_ADDR pc, long *reg, long *offset); CORE_ADDR msp430_push_return_address (CORE_ADDR pc, CORE_ADDR sp); CORE_ADDR msp430_push_arguments (int nargs, struct value ** args, CORE_ADDR sp, unsigned char struct_return, CORE_ADDR struct_addr); void msp430_pop_frame (struct frame_info *fi); CORE_ADDR msp430_skip_prologue (CORE_ADDR pc); CORE_ADDR msp430_frame_chain (struct frame_info *fi); unsigned char *msp430_breakpoint_from_pc (CORE_ADDR * bp_addr, int *bp_size); int msp430_use_struct_convention (int gcc_p, struct type *type); void msp430_store_return_value (struct type *type, char *valbuf); CORE_ADDR msp430_extract_struct_value_address (char *regbuf); void msp430_extract_return_value (struct type *type, char *regbuf, char *valbuf); int msp430_real_fp = 0; #define MSP430_DEBUG 1 #ifdef MSP430_DEBUG int msp430_debug = 0; #endif /* The registers of the Motorola msp430 processors */ char *msp430_register_names[] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}; /* Additional info that we use for managing frames */ struct frame_extra_info { int status; int framesize; int fp_regnum; int num_saved_regs; CORE_ADDR entry_addr; int reti; }; /* The base of the current frame is actually in the stack pointer. This happens when there is no frame pointer (msp430 ABI does not require a frame pointer) or when we're stopped in the prologue or epilogue itself. In these cases, msp430_analyze_prologue will need to update fi->frame before returning or analyzing the register save instructions. */ #define MY_FRAME_IN_SP 0x1 /* The base of the current frame is in a frame pointer register. This register is noted in frame_extra_info->fp_regnum. Note that the existence of an FP might also indicate that the function has called alloca. */ #define MY_FRAME_IN_FP 0x2 /* This flag is set to indicate that this frame is the top-most frame. This tells frame chain not to bother trying to unwind beyond this frame. */ #define NO_MORE_FRAMES 0x4 #ifdef MSP430_DEBUG static void msp430_dump_insn (char *commnt, CORE_ADDR pc, int insn) { if (msp430_debug) { printf_filtered ("MSP430: %s %08x %08x ", commnt, (unsigned int) pc, (unsigned int) insn); (*tm_print_insn) (pc, &tm_print_insn_info); printf_filtered ("\n"); } } #define msp430_insn_debug(args) { if (msp430_debug) printf_filtered args; } #else /* !MSP430_DEBUG */ #define msp430_dump_insn(a,b,c) {} #define msp430_insn_debug(args) {} #endif unsigned char * msp430_breakpoint_from_pc (CORE_ADDR * bp_addr, int *bp_size) { static char breakpoint[] = {0x00, 0x00}; *bp_size = 2; return breakpoint; } /* Helper function for several routines below. This funtion simply sets up a fake, aka dummy, frame (not a _call_ dummy frame) that we can analyze with msp430_analyze_prologue. */ static struct frame_info * analyze_dummy_frame (CORE_ADDR pc, CORE_ADDR frame) { static struct frame_info *dummy = NULL; if (dummy == NULL) { dummy = (struct frame_info *) xmalloc (sizeof (struct frame_info)); dummy->saved_regs = (CORE_ADDR *) xmalloc (SIZEOF_FRAME_SAVED_REGS); dummy->extra_info = (struct frame_extra_info *) xmalloc (sizeof (struct frame_extra_info)); } dummy->next = NULL; dummy->prev = NULL; dummy->pc = pc; dummy->frame = frame; dummy->extra_info->status = 0; dummy->extra_info->reti = 0; dummy->extra_info->framesize = 0; dummy->extra_info->num_saved_regs = 0; memset (dummy->saved_regs, '\000', SIZEOF_FRAME_SAVED_REGS); msp430_analyze_prologue (dummy, 0, 0); return dummy; } /* our 'frame' member of 'fi' is a stack bottom after func. prologue. return address is located at 'frame' Scanning prologues. A typical msp430 function's prologue is one of the following: 1. some call push r4 <-- If used or fpn push rXX ... sub #[SIZE], r1 mov r1, r4 <-- If frame pointer needed 2. main() w/o -mno-stack-init mov #[SMTH], r1 mov r1, r4 <-- If frame pointer needed 3. with -mno-stack-init it looks like (1), but no regs saved. 4. No optimize, usual funct: push rXX mov r1, r5 add #[sizeofpushed+2], r5 sub #[framesize], r1 mov r1, r4 5. main does not look any different 6. any prologue may start from eint (0xd2, 0x32); */ /* patterns */ static unsigned short eint = 0xd232; static unsigned short push_rn = 0x1200; /* bitmask: push rX */ static unsigned short load_fp = 0x4104; /* match: mov r1, r4*/ static unsigned short sub_val = 0x8031; /* sub #VAL, r1 , VAL is not one of the consts. */ static unsigned short sub_2 = 0x8321; static unsigned short sub_4 = 0x8221; static unsigned short sub_8 = 0x8231; static unsigned short load_ap = 0x4105; /* match: mov r1, r5 */ static unsigned short add_val = 0x5035; /* followed by add value */ static unsigned short add_2 = 0x5325; static unsigned short add_4 = 0x5225; static unsigned short add_8 = 0x5235; static unsigned short init_sp = 0x4031; /* followed by value ... XXX assume no stupid things happen */ static CORE_ADDR current_sp; static CORE_ADDR msp430_analyze_prologue (struct frame_info *fi, CORE_ADDR pc, int skip_prologue) { CORE_ADDR func_addr, func_end, addr, stop; CORE_ADDR stack_size; CORE_ADDR stack_top; int insn, rn; int status; int fp_regnum = 0; /* dummy, valid when (flags & MY_FRAME_IN_FP) */ int flags; int framesize; int register_offsets[NUM_REGS]; int ro; char *name; int vpc = 0; CORE_ADDR start_addr ; int i; int reti = 0; msp430_real_fp = 1; /* Wild guess */ /* If provided, use the PC in the frame to look up the start of this function. */ pc = (fi == NULL ? pc : fi->pc); /* check if the frame has already been checked */ if(fi && fi->extra_info->status) return fi->extra_info->entry_addr; /* Find the start of this function. */ status = find_pc_partial_function (pc, &name, &func_addr, &func_end); /* If the start of this function could not be found or if the debbuger is stopped at the first instruction of the prologue, do nothing. */ if (status == 0) return 0xfffful&pc; /* If the debugger is entry function, give up. */ if (func_addr == entry_point_address ()) { if (fi != NULL) { fi->extra_info->status |= NO_MORE_FRAMES; fi->extra_info->entry_addr = 0xffff&pc; } return 0xffff&pc; } /* At the start of a function, our frame is in the stack pointer. */ flags = MY_FRAME_IN_SP; if(fi) { fi->extra_info->framesize = 0; fi->extra_info->status = flags; fi->extra_info->fp_regnum = SP_REGNUM; } /* Get the first insn from memory (all msp430 instructions are 16 bits) */ msp430_insn_debug (("MSP430: starting prologue decoding\n")); insn = get_insn (pc); msp430_dump_insn ("got 1: ", pc, insn); /* Check for return. */ if (fi != NULL && (insn == 0x1300 || insn == 0x4130)) { msp430_insn_debug (("MSP430: got immediate return.")); if (fi->next == NULL) fi->frame = read_sp () + (insn == 0x1300 ? 2:0); fi->extra_info->entry_addr = 0xffff&(func_addr); return 0xffff&(func_addr); } /* check if this an interrupt function */ if(fi && func_end != 0) { int rr = get_insn (func_end - 2); if(rr == 0x1300) reti = 2; } /* Check for first insn of prologue */ if (fi != NULL && fi->pc == func_addr) { if (fi->next == NULL) { fi->frame = read_sp () + reti; fi->saved_regs[0] = fi->frame; fi->extra_info->entry_addr = 0xffff&(func_addr); fi->extra_info->reti = reti; } return 0xffff&(func_addr); } if(func_addr) { pc = func_addr; } /* Figure out where to stop scanning */ stop = (fi ? fi->pc : func_end); /* Don't walk off the end of the function */ stop = (stop > func_end ? func_end : stop); /* REGISTER_OFFSETS will contain offsets, from the top of the frame (NOT the frame pointer), for the various saved registers or -1 if the register is not saved. */ for (rn = 0; rn < NUM_REGS; rn++) register_offsets[rn] = -1; stack_top = read_sp(); /* Analyze the prologue. Things we determine from analyzing the prologue include: * the size of the frame * where saved registers are located (and which are saved) * FP used? */ msp430_insn_debug (("MSP430: Scanning prologue: func_addr=0x%x, stop=0x%x\n", (unsigned int) func_addr, (unsigned int) stop)); framesize = 0; msp430_insn_debug (("MSP430: done analyzing prologue\n")); msp430_insn_debug (("MSP430: prologue end = 0x%x\n", (short)func_end)); if(name && strcmp ("main", name) == 0) { start_addr = func_addr; insn = get_insn(pc + vpc); if(insn == init_sp) { /* ok... will be a frame pointer adjustment? */ vpc += 2; insn = get_insn(pc + vpc); vpc += 2; /* skip this and value.*/ start_addr = func_addr + vpc; if(fi) fi->extra_info->fp_regnum = SP_REGNUM; } else if(insn == sub_val) /* -mno-stack-init */ { vpc += 2; insn = get_insn(pc + vpc); vpc += 2; start_addr = func_addr + vpc; if(fi) fi->extra_info->fp_regnum = SP_REGNUM; } else if(insn == sub_2) { vpc += 2; start_addr = func_addr + vpc; if(fi) fi->extra_info->fp_regnum = SP_REGNUM; } else if(insn == sub_4) { vpc += 2; start_addr = func_addr + vpc; if(fi) fi->extra_info->fp_regnum = SP_REGNUM; } else if(insn == sub_8) { vpc += 2; start_addr = func_addr + vpc; if(fi) fi->extra_info->fp_regnum = SP_REGNUM; } else { /* we're here cause no frame adjustment required and main main frame size is over any reasonable value... should never happen cause memory not less than 0x200*/ vpc += 2; start_addr = func_addr + vpc; } insn = get_insn(pc + vpc); /* check if fp being initialized */ if(insn == load_fp) { vpc += 2; start_addr = func_addr + vpc; if(fi) fi->extra_info->fp_regnum = 4; if(fi) fi->extra_info->status = MY_FRAME_IN_FP; msp430_real_fp = fi ? fi->extra_info->fp_regnum:1; } if(fi) fi->frame = read_sp(); if(fi) fi->extra_info->entry_addr = start_addr; return start_addr; } /* check eint Actually, there is only way to check if this is an interrupt is to check eint - enable nested. Ordinary interrupts cannot be caught */ insn = get_insn(pc + vpc); if(insn == eint) { vpc += 2; } /* check pushes */ i = 4; ro = 0; if(fi) fi->extra_info->num_saved_regs = 0; while(i < 12 ) { insn = get_insn(pc + vpc); if( (insn & 0xfff0) != push_rn ) break; /* no more pushes*/ if(fi) fi->extra_info->num_saved_regs += 1; vpc += 2; i++; ro++; register_offsets[i] = ro*2; } /* now check if there is an arg pointer */ insn = get_insn(pc + vpc); if(insn == load_ap) { vpc += 2; insn = get_insn(pc + vpc); if(insn == add_val) { vpc += 2; /* insn */ vpc += 2; /* actual value */ insn = get_insn(pc + vpc); } else if(insn == add_2 || insn == add_4 || insn == add_8) { vpc += 2; insn = get_insn(pc + vpc); } } /* check if stack pointer has been adjusted */ if(insn == sub_val) { vpc += 2; framesize = get_insn(pc + vpc); vpc += 2; insn = get_insn(pc + vpc); } else if(insn == sub_2) { framesize = 2; vpc += 2; insn = get_insn(pc + vpc); } else if(insn == sub_4) { framesize = 4; vpc += 2; insn = get_insn(pc + vpc); } else if(insn == sub_8) { framesize = 8; vpc += 2; insn = get_insn(pc + vpc); } if(fi) fi->extra_info->fp_regnum = SP_REGNUM; /* chec if fp loaded */ if(insn == load_fp) { if(fi) fi->extra_info->fp_regnum = 4; msp430_real_fp = fi ? fi->extra_info->fp_regnum:1; flags = MY_FRAME_IN_FP; vpc += 2; } /* Save everything we have learned about this frame into FI. */ if (fi != NULL) { fi->extra_info->framesize = framesize; fi->extra_info->status = flags; fi->extra_info->reti = reti; fi->saved_regs[0] = fi->frame + reti; if (fi->next == NULL) { fi->frame = (fi->extra_info->status == MY_FRAME_IN_SP) ? read_sp() : read_fp(); current_sp = fi->frame + reti; fi->frame += framesize + fi->extra_info->num_saved_regs * 2 + reti; fi->saved_regs[0] = fi->frame; /* this is only for 'info frame'*/ fi->saved_regs[1] = read_sp (); } else { fi->saved_regs[1] = fi->frame - reti - framesize - fi->extra_info->num_saved_regs * 2; } if(reti) fi->saved_regs[2] = fi->saved_regs[0] - 2; for (rn = 4; rn < NUM_REGS; rn++) { if (register_offsets[rn] >= 0) { fi->saved_regs[rn] = fi->saved_regs[0] - register_offsets[rn] - reti; } else { fi->saved_regs[rn] = 0; } } } /* Return addr of first non-prologue insn. */ if(fi) fi->extra_info->entry_addr = func_addr + vpc; return func_addr + vpc; } /* Given a GDB frame, determine the address of the calling function's frame. This will be used to create a new GDB frame struct, and then INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame. */ CORE_ADDR msp430_frame_chain (struct frame_info * fi) { struct frame_info *dummy; CORE_ADDR callers_addr; CORE_ADDR pc; if (fi->extra_info->status == 0) msp430_analyze_prologue (fi, 0, 0); if (fi->extra_info->status & NO_MORE_FRAMES) return 0; pc = 0xffffUL & (FRAME_SAVED_PC (fi)); dummy = analyze_dummy_frame (pc, fi->frame); callers_addr = fi->frame + dummy->extra_info->num_saved_regs * 2 + dummy->extra_info->framesize + 2 + dummy->extra_info->reti; return 0xffff&callers_addr; } /* Skip the prologue of the function at PC. */ CORE_ADDR msp430_skip_prologue (CORE_ADDR pc) { CORE_ADDR func_addr, func_end; struct symtab_and_line sal; /* If we have line debugging information, then the end of the prologue should be the first assembly instruction of the first source line */ /********* does not work somehow if (find_pc_partial_function (pc, NULL, &func_addr, &func_end)) { sal = find_pc_line (func_addr, 0); if (sal.end && sal.end < func_end) return sal.end; } ***************************************/ /* this will return right thing. */ return msp430_analyze_prologue (NULL, pc, 1); } /* Return the address at which function arguments are offset. */ CORE_ADDR msp430_frame_args_address (struct frame_info * fi) { return fi->frame + 2 + fi->extra_info->reti; } CORE_ADDR msp430_frame_locals_address (struct frame_info * fi) { return fi->frame - fi->extra_info->framesize - fi->extra_info->num_saved_regs * 2 - fi->extra_info->reti; } /* Return the frame pointer in use at address PC. */ void msp430_virtual_frame_pointer (CORE_ADDR pc, long *reg, long *offset) { struct frame_info *dummy = analyze_dummy_frame (pc, 0); if (dummy->extra_info->status & MY_FRAME_IN_SP) { *reg = SP_REGNUM; *offset = 0; } else { *reg = dummy->extra_info->fp_regnum; *offset = 0; } } /* Find the value of register REGNUM in frame FI. */ CORE_ADDR msp430_find_callers_reg (struct frame_info *fi, int regnum) { CORE_ADDR ret; for (; fi != NULL; fi = fi->next) { if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame)) { ret = 0xffff&generic_read_register_dummy (fi->pc, fi->frame, regnum); return ret; } else if (fi->saved_regs[regnum] != 0) { ret = 0xffff&read_memory_integer (fi->saved_regs[regnum], REGISTER_SIZE); return ret; } } ret = 0xffff&read_register (regnum); return ret; } /* Find the saved pc in frame FI. */ CORE_ADDR msp430_frame_saved_pc (struct frame_info * fi) { CORE_ADDR ret; if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame)) { ret = 0xffff&generic_read_register_dummy (fi->pc, fi->frame, PC_REGNUM); } else { ret = 0xffff&msp430_find_callers_reg (fi, PC_REGNUM); } return ret; } /* INFERIOR FUNCTION CALLS */ /* This routine gets called when either the user uses the "return" command, or the call dummy breakpoint gets hit. */ void msp430_pop_frame (struct frame_info *fi) { int rn; CORE_ADDR ret; if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame)) generic_pop_dummy_frame (); else { /* Write out the PC we saved. */ ret = FRAME_SAVED_PC (fi); write_register (PC_REGNUM, ret); /* Restore any saved registers. */ for (rn = 4; rn < NUM_REGS; rn++) { if (fi->saved_regs[rn] != 0) { ULONGEST value; value = read_memory_unsigned_integer (fi->saved_regs[rn], REGISTER_SIZE); write_register (rn, value); } } if(fi->extra_info->reti) { ULONGEST value; value = read_memory_unsigned_integer (fi->saved_regs[2], REGISTER_SIZE); write_register (2, value); } /* Actually cut back the stack. */ write_register (SP_REGNUM, (FRAME_FP(fi)) + 2); } /* Finally, throw away any cached frame information. */ flush_cached_frames (); } /* Setup arguments and PR for a call to the target. First four arguments go in FIRST_ARGREG -> LAST_ARGREG, subsequent args go on to the stack. * Types with lengths greater than REGISTER_SIZE may not be split between registers and the stack, and they must start in an even-numbered register. Subsequent args will go onto the stack. * If the function returns a struct which will not fit into registers (it's more than eight bytes), we must allocate for that, too. Gdb will tell us where this buffer is (STRUCT_ADDR), and we simply place it into FIRST_ARGREG, since the MSP430 treats struct returns (of less than eight bytes) as hidden first arguments. */ CORE_ADDR msp430_push_arguments (int nargs, struct value **args, CORE_ADDR sp, unsigned char struct_return, CORE_ADDR struct_addr) { int argreg; int argnum; struct stack_arg { int len; char *val; } *stack_args; int nstack_args = 0; stack_args = (struct stack_arg *) alloca (nargs * sizeof (struct stack_arg)); argreg = FIRST_ARGREG; sp &= ~1; if (struct_return) write_register (argreg--, struct_addr); for (argnum = 0; argnum < nargs; argnum++) { char *val = (char *) VALUE_CONTENTS (args[argnum]); int len = TYPE_LENGTH (VALUE_TYPE (args[argnum])); struct type *type = VALUE_TYPE (args[argnum]); int olen; msp430_insn_debug (("MSP430 PUSH: argreg=%d; len=%d; %s\n", argreg, len, TYPE_CODE (type) == TYPE_CODE_STRUCT ? "struct" : "not struct")); /* Arguments larger than a register must start in an even numbered register. */ olen = len; if (TYPE_CODE (type) != TYPE_CODE_STRUCT && len > REGISTER_SIZE && argreg % 2) { msp430_insn_debug (("MSP430 PUSH: %d > REGISTER_SIZE: and %s is not even\n", len, msp430_register_names[argreg])); argreg--; } if ((argreg >= LAST_ARGREG && len <= (-LAST_ARGREG + argreg + 1) * REGISTER_SIZE) || (TYPE_CODE (type) == TYPE_CODE_STRUCT)) { /* Something that will fit entirely into registers (or a struct which may be split between registers and stack). */ msp430_insn_debug (("MSP430 PUSH: arg %d going into regs\n", argnum)); if (TYPE_CODE (type) == TYPE_CODE_STRUCT && olen < REGISTER_SIZE) { /* Small structs must be right aligned within the register, the most significant bits are undefined. */ write_register (argreg, extract_unsigned_integer (val, len)); argreg--; len = 0; } while (len > 0 && argreg >= LAST_ARGREG) { write_register (argreg, extract_unsigned_integer (val, REGISTER_SIZE)); argreg--; val += REGISTER_SIZE; len -= REGISTER_SIZE; } /* Any remainder for the stack is noted below... */ } else if (TYPE_CODE (VALUE_TYPE (args[argnum])) != TYPE_CODE_STRUCT && len > REGISTER_SIZE) { /* All subsequent args go onto the stack. */ msp430_insn_debug (("MSP430 PUSH: does not fit into regs, going onto stack\n")); argnum = LAST_ARGREG - 1; } if (len > 0) { /* Note that this must be saved onto the stack */ msp430_insn_debug (("MSP430 PUSH: adding arg %d to stack\n", argnum)); stack_args[nstack_args].val = val; stack_args[nstack_args].len = len; nstack_args++; } } /* We're done with registers and stack allocation. Now do the actual stack pushes. */ while (nstack_args--) { sp -= stack_args[nstack_args].len; write_memory (sp, stack_args[nstack_args].val, stack_args[nstack_args].len); } /* Return adjusted stack pointer. */ return sp; } /* Store the return address for the call dummy. For msp430, we've opted to use generic call dummies, so we simply store the CALL_DUMMY_ADDRESS into the PR register (r15). */ CORE_ADDR msp430_push_return_address (CORE_ADDR pc, CORE_ADDR sp) { write_register (PC_REGNUM, CALL_DUMMY_ADDRESS ()); return sp; } /* Setting/getting return values from functions. If USE_STRUCT_CONVENTION retruns 0, then gdb uses STORE_RETURN_VALUE and EXTRACT_RETURN_VALUE to store/fetch the functions return value. */ /* Should we use EXTRACT_STRUCT_VALUE_ADDRESS instead of EXTRACT_RETURN_VALUE? GCC_P is true if compiled with gcc and TYPE is the type (which is known to be struct, union or array). */ int msp430_use_struct_convention (int gcc_p, struct type *type) { return (TYPE_LENGTH (type) > 8); } /* Where is the return value saved? For msp430, a pointer to this buffer was passed as a hidden first argument, so just return that address. */ CORE_ADDR msp430_extract_struct_value_address (char *regbuf) { return extract_address (regbuf + REGISTER_BYTE (FIRST_ARGREG), REGISTER_SIZE); } /* Given a function which returns a value of type TYPE, extract the the function's return value and place the result into VALBUF. REGBUF is the register contents of the target. */ void msp430_extract_return_value (struct type *type, char *regbuf, char *valbuf) { /* Copy the return value (starting) in RETVAL_REGNUM to VALBUF. */ /* Only getting the first byte! if len = 1, we need the last byte of the register, not the first. */ memcpy (valbuf, regbuf + REGISTER_BYTE (RETVAL_REGNUM) + (TYPE_LENGTH (type) < 8 ? 8 - TYPE_LENGTH (type) : 0), TYPE_LENGTH (type)); } void msp430_store_return_value (struct type *type, char *valbuf) { int value_size; int return_size; int offset; char *zeros; value_size = TYPE_LENGTH (type); /* Return value fits into registers. */ return_size = (value_size + REGISTER_SIZE - 1) & ~(REGISTER_SIZE - 1); offset = REGISTER_BYTE (RETVAL_REGNUM) + (return_size - value_size); zeros = alloca (return_size); memset (zeros, 0, return_size); write_register_bytes (REGISTER_BYTE (RETVAL_REGNUM), zeros, return_size); write_register_bytes (offset, valbuf, value_size); } /* Initialize our target-dependent "stuff" for this newly created frame. This includes allocating space for saved registers and analyzing the prologue of this frame. */ void msp430_init_extra_frame_info (struct frame_info *fi) { if (fi->next) fi->pc = FRAME_SAVED_PC (fi->next); frame_saved_regs_zalloc (fi); fi->extra_info = (struct frame_extra_info *) frame_obstack_alloc (sizeof (struct frame_extra_info)); fi->extra_info->status = 0; fi->extra_info->framesize = 0; fi->extra_info->num_saved_regs = 0; fi->extra_info->reti = 0; if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame)) { /* We need to setup fi->frame here because run_stack_dummy gets it wrong by assuming it's always FP. */ fi->frame = generic_read_register_dummy (fi->pc, fi->frame, SP_REGNUM); } else msp430_analyze_prologue (fi, 0, 0); } /* Get an insturction from memory. */ static int get_insn (CORE_ADDR pc) { char buf[4]; int status = read_memory_nobpt (0xfffful&pc, buf, 2); if (status != 0) return 0; return extract_unsigned_integer (buf, 2); } void _initialize_msp430_tdep (void) { extern int print_insn_msp430 (bfd_vma, disassemble_info *); tm_print_insn = print_insn_msp430; #ifdef MSP430_DEBUG add_show_from_set (add_set_cmd ("msp430debug", no_class, var_boolean, (char *) &msp430_debug, "Set msp430 debugging.\n", &setlist), &showlist); #endif } CORE_ADDR msp430_saved_pc_after_call (struct frame_info * frame) { unsigned char m1, m2; unsigned int sp = read_register (SP_REGNUM); m1 = 0xff & read_memory_unsigned_integer (sp + 0, 1); m2 = 0xff & read_memory_unsigned_integer (sp + 1, 1); return 0xffff & (m1 | ((unsigned long)m2 << 8)); }