This is just one file and working simulator.
I posted the work I've done so far. (attached again)
Actually, I'm planning to do this (unless someone will pick it up before me),
but hell busy now.

~d


> I don't have much time right now, but maybe you could commit a
> "gdb-current" tree with the bits you have done (and a big fat "DOES
> NOT WORK YET" disclaimer), and see if someone picks it up...
>
>
> Regards,

-- 
/********************************************************************
     ("`-''-/").___..--''"`-._     (\   Dimmy the Wild      UA1ACZ
      `6_ 6  )   `-.  (     ).`-.__.`)  Enterprise Information Sys 
      (_Y_.)'  ._   )  `._ `. ``-..-'   Nevsky prospekt,   20 / 44
    _..`--'_..-_/  /--'_.' ,'           Saint Petersburg,   Russia
   (il),-''  (li),'  ((!.-'             +7 (812)  3468202, 5585314
 ********************************************************************/
/* Target-dependent code for Atmel AVR, for GDB.
   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
   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 "gdbcmd.h"
#include "gdbcore.h"
#include "inferior.h"
#include "symfile.h"
#include "arch-utils.h"
#include "regcache.h"
#include "gdb_string.h"

#undef XMALLOC
#define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE)))

#undef EXTRACT_INSN
#define EXTRACT_INSN(addr) extract_unsigned_integer(addr,2)

#undef INSURE_ADDR
#define INSURE_ADDR(x)	((x)&0x00fffful)


#define MSP430_PC_REGNUM	0
#define MSP430_SP_REGNUM	1
#define MSP430_FP_REGNUM	1	/* is Ok for now. */
#define MSP430_FIRST_PSEUDO_REG	16
#define MSP430_NUM_REGS		16
#define MSP430_RETVAL_REGNUM	15
#define MSP430_LAST_ARGREG	12
#define MSP430_FIRST_ARGREG	15


/* The registers of the msp430 processors */
static const char *msp430_register_names[] =
    { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
};

/* 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 const char *
msp430_register_name (int regnum)
{
  if (regnum < 0)
    return NULL;
  if (regnum >= MSP430_FIRST_PSEUDO_REG)
    return NULL;
  return msp430_register_names[regnum];
}

static CORE_ADDR
msp430_read_pc (ptid_t ptid)
{
  return read_register_pid (MSP430_PC_REGNUM, ptid);
}

static void
msp430_write_pc (ptid_t ptid)
{
  write_register_pid (MSP430_PC_REGNUM, pc, ptid);
}

static CORE_ADDR
msp430_read_fp (void)
{
  /* I whish to have here something like:
     read_register (extra_frame_info->fp_regnum).
     However, right after prologue, even if r4 has been eliminated
     r4==r1:

     push       Rn
     sub        #XX, r1 ; adjust stack val.
     mov        r1, r4  ; load r4 (paradoxial frame pointer)

     So, if there is no call around current PC which 
     performs some pushes of long arg list, the following will 
     be correct.

     However this will be broken in two cases:
     1. va_arg, long arg list calls:
     call(arg1, arg2, arg3,...); =>

     push       argN    ; r1 now is broken!
     ...                        ; so, stepping though asm insn
     push       arg2    ; may result (if r1 being used as FP)
     push       arg1    ; wrong args list and everything else
     call       #call
     sub                #(2*N), r1      ; since FP will be just fine. 

     2. The same, but arg on stack:
     ...
     push X(r1) ; henceforth r1 is broken again
     push Y(r4) ; the same if r4 is a FP
   */
  return read_register (MSP430_SP_REGNUM);
}

static CORE_ADDR
msp430_read_sp (void)
{
  read_register (MSP430_SP_REGNUM);
}

static void
msp430_write_sp (CORE_ADDR val)
{
  write_register (MSP430_SP_REGNUM, INSURE_ADDR (val));
}

static int
msp430_register_byte (int regnum)
{
  if (regnum >= MSP430_FIRST_PSEUDO_REG)
    return 32;
  return regnum * 2;
}

static int
msp430_register_raw_size (int regnum)
{
  return 2;			/* all registers are 2 bytes wide. */
}

static int
msp430_register_virtual_size (int regnum)
{
  return return TYPE_LENGTH (REGISTER_VIRTUAL_TYPE (regnum));
}

static struct type *
msp430_register_virtual_type (int regnum)
{
  if (regnum >= MSP430_FIRST_PSEUDO_REG)
    return builtin_type_void;
  return builtin_type_unsigned_short;
}

static CORE_ADDR
msp430_call_dummy_address (void)
{
  return entry_point_address ();
}

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 (MSP430_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 (MSP430_RETVAL_REGNUM) + (return_size - value_size);
  zeros = alloca (return_size);
  memset (zeros, 0, return_size);

  write_register_bytes (REGISTER_BYTE (MSP430_RETVAL_REGNUM), zeros,
			return_size);
  write_register_bytes (offset, valbuf, value_size);
}

static void
msp430_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
{
  /* mspgcc stores struct ret addr at r15 */
  write_register (MSP430_RETVAL_REGNUM, addr);
}


CORE_ADDR
msp430_extract_struct_value_address (char *regbuf)
{
  return extract_address (regbuf + REGISTER_BYTE (MSP430_FIRST_ARGREG),
			  REGISTER_SIZE);
}


/* Find the value of register REGNUM in frame FI. */
CORE_ADDR
msp430_find_callers_reg (struct frame_info * fi, int regnum)
{
  for (; fi != NULL; fi = get_next_frame (fi))
    {
      if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), get_frame_base (fi),
				       get_frame_base (fi)))
	return INSURE_ADDR (deprecated_read_register_dummy (get_frame_pc (fi),
							    get_frame_base
							    (fi), regnum));
      else if (get_frame_saved_regs (fi)[regnum] != 0)
	return
	    INSURE_ADDR (read_memory_integer
			 (get_frame_saved_regs (fi)[regnum], REGISTER_SIZE));
    }

  return read_register (regnum);
}


/* Find the saved pc in frame FI. */
CORE_ADDR
msp430_frame_saved_pc (struct frame_info * fi)
{

  if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), get_frame_base (fi),
				   get_frame_base (fi)))
    return deprecated_read_register_dummy (get_frame_pc (fi),
					   get_frame_base (fi),
					   MSP430_PC_REGNUM);
  else
    return INSURE_ADDR (msp430_find_callers_reg (fi, MSP430_PR_REGNUM));
}


/* 
   SCAN prologue. 
 */

/* Additional info that we use for managing frames */
struct frame_extra_info
{
  CORE_ADDR entry_addr;
  int framesize;
  int fp_regnum;
  int num_saved_regs;
  int reti;
};

  /*
   *   THIS SHOULD BE WRITTEN!!!!!!!!!!!!!!!!!!!!!!!!
   */
static void
msp430_scan_prologue (struct frame_info *fi)
{ 
  CORE_ADDR func_start, func_end, addr, stop;
  int status;
  int pc;
  char *name;
  
  if(fi)
  {
    pc = get_frame_pc (fi);
    get_frame_extra_info (fi)->framereg = MSP430_FP_REGNUM;
    status = find_pc_partial_function(pc, &name, &func_start, &func_end);

    if(status)
    {
      
    }
  }
  

}



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 = MSP430_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 >= MSP430_LAST_ARGREG
	   && len <= (-MSP430_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 >= MSP430_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 = MSP430_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;
}

void
msp430_pop_frame (void)
{
  int rn;
  CORE_ADDR ret;
  struct frame_info *fi = get_current_frame ();

  if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), get_frame_base (fi),
				   get_frame_base (fi)))
    generic_pop_dummy_frame ();
  else
    {
      /* Write out the PC we saved. */
      ret = FRAME_SAVED_PC (fi);
      write_register (MSP430_PC_REGNUM, ret);

      /* Restore any saved registers. */
      for (rn = 4; rn < MSP430_NUM_REGS; rn++)
	{
	  if (get_frame_saved_regs (fi)[rn] != 0)
	    {
	      ULONGEST value;

	      value =
		  read_memory_unsigned_integer (get_frame_saved_regs (fi)[rn],
						REGISTER_SIZE);
	      write_register (rn, value);
	    }
	}

      if (get_frame_extra_info (fi)->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 (MSP430_SP_REGNUM, (FRAME_FP (fi)) + 2);
    }

  /* Finally, throw away any cached frame information. */
  flush_cached_frames ();
}


  CORE_ADDR
msp430_saved_pc_after_call (struct frame_info * frame)
{
  unsigned char m1, m2;
  unsigned int sp = read_register (MSP430_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));
}



CORE_ADDR
msp430_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
{
  write_register (PC_REGNUM, CALL_DUMMY_ADDRESS ());
  return sp;
}

unsigned char *
msp430_breakpoint_from_pc (CORE_ADDR * bp_addr, int *bp_size)
{
  static char breakpoint[] = { 0x00, 0x00 };
  *bp_size = 2;
  return breakpoint;
}

CORE_ADDR
msp430_frame_args_address (struct frame_info * fi)
{
  return INSURE_ADDR(get_frame_base (fi) + 2 + get_frame_extra_info (fi)->reti);
}

CORE_ADDR
msp430_frame_locals_address (struct frame_info * fi)
{
  return INSURE_ADDR(get_frame_base (fi) - get_frame_extra_info (fi)->framesize);
}



static struct gdbarch *
msp430_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
  struct gdbarch *gdbarch;
  struct gdbarch_tdep *tdep;
  static LONGEST msp430_call_dummy_words[] = { 0 };

  /* Find a candidate among the list of pre-declared architectures. */
  arches = gdbarch_list_lookup_by_info (arches, &info);
  if (arches != NULL)
    return arches->gdbarch;

  /* None found, create a new architecture from the information provided. */
  tdep = XMALLOC (struct gdbarch_tdep);
  gdbarch = gdbarch_alloc (&info, tdep);

  set_gdbarch_deprecated_init_frame_pc (gdbarch, init_frame_pc_default);

  /* If we ever need to differentiate the device types, do it here.
     Currently, all targets are equial */
  switch (info.bfd_arch_info->mach)
    {
    default:
      break;
    }

  set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
  set_gdbarch_int_bit (gdbarch, 2 * TARGET_CHAR_BIT);
  set_gdbarch_long_bit (gdbarch, 4 * TARGET_CHAR_BIT);
  set_gdbarch_long_long_bit (gdbarch, 8 * TARGET_CHAR_BIT);
  set_gdbarch_ptr_bit (gdbarch, 2 * TARGET_CHAR_BIT);
  set_gdbarch_addr_bit (gdbarch, 32);
  set_gdbarch_bfd_vma_bit (gdbarch, 32);	/* FIXME: TRoth/2002-02-18: Is this needed? */

  set_gdbarch_float_bit (gdbarch, 4 * TARGET_CHAR_BIT);
  set_gdbarch_double_bit (gdbarch, 4 * TARGET_CHAR_BIT);
  set_gdbarch_long_double_bit (gdbarch, 4 * TARGET_CHAR_BIT);

  set_gdbarch_float_format (gdbarch, &floatformat_ieee_single_little);
  set_gdbarch_double_format (gdbarch, &floatformat_ieee_single_little);
  set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_single_little);

  set_gdbarch_read_pc (gdbarch, msp430_read_pc);
  set_gdbarch_write_pc (gdbarch, msp430_write_pc);
  set_gdbarch_read_fp (gdbarch, msp430_read_fp);
  set_gdbarch_read_sp (gdbarch, msp430_read_sp);
  set_gdbarch_write_sp (gdbarch, msp430_write_sp);

  set_gdbarch_num_regs (gdbarch, MSP430_NUM_REGS);

  set_gdbarch_sp_regnum (gdbarch, MSP430_SP_REGNUM);
  set_gdbarch_fp_regnum (gdbarch, MSP430_FP_REGNUM);
  set_gdbarch_pc_regnum (gdbarch, MSP430_PC_REGNUM);

  set_gdbarch_register_name (gdbarch, msp430_register_name);
  set_gdbarch_register_size (gdbarch, 2);
  set_gdbarch_register_bytes (gdbarch, MSP430_NUM_REGS * 2);
  set_gdbarch_register_byte (gdbarch, msp430_register_byte);
  set_gdbarch_register_raw_size (gdbarch, msp430_register_raw_size);
  set_gdbarch_max_register_raw_size (gdbarch, 2);
  set_gdbarch_register_virtual_size (gdbarch, msp430_register_virtual_size);
  set_gdbarch_max_register_virtual_size (gdbarch, 2);
  set_gdbarch_register_virtual_type (gdbarch, msp430_register_virtual_type);

  set_gdbarch_print_insn (gdbarch, print_insn_msp430);

  set_gdbarch_call_dummy_address (gdbarch, msp430_call_dummy_address);
  set_gdbarch_call_dummy_start_offset (gdbarch, 0);
  set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 1);
  set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
  set_gdbarch_call_dummy_length (gdbarch, 0);
  set_gdbarch_call_dummy_p (gdbarch, 1);
  set_gdbarch_call_dummy_words (gdbarch, msp430_call_dummy_words);
  set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
  set_gdbarch_fix_call_dummy (gdbarch, generic_fix_call_dummy);

  set_gdbarch_deprecated_extract_return_value (gdbarch,
					       msp430_extract_return_value);
  set_gdbarch_push_arguments (gdbarch, msp430_push_arguments);
  set_gdbarch_push_dummy_frame (gdbarch, generic_push_dummy_frame);
  set_gdbarch_push_return_address (gdbarch, msp430_push_return_address);
  set_gdbarch_pop_frame (gdbarch, msp430_pop_frame);

  set_gdbarch_deprecated_store_return_value (gdbarch,
					     msp430_store_return_value);

  set_gdbarch_use_struct_convention (gdbarch, generic_use_struct_convention);
  set_gdbarch_store_struct_return (gdbarch, msp430_store_struct_return);
  set_gdbarch_deprecated_extract_struct_value_address
      (gdbarch, msp430_extract_struct_value_address);

  set_gdbarch_breakpoint_from_pc (gdbarch, msp430_breakpoint_from_pc);
  
  /******************************************/
  /*** ?????? PROBABLY INCORRECT ***/
  
  set_gdbarch_frame_init_saved_regs (gdbarch, msp430_scan_prologue);
  set_gdbarch_init_extra_frame_info (gdbarch, msp430_init_extra_frame_info);
  
  
  set_gdbarch_frame_saved_pc (gdbarch, msp430_frame_saved_pc);
  set_gdbarch_frame_args_address (gdbarch, msp430_frame_args_address);
  set_gdbarch_frame_locals_address (gdbarch, msp430_frame_locals_address);
  
  set_gdbarch_saved_pc_after_call (gdbarch, msp430_saved_pc_after_call);
  
  set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);


  return gdbarch;
}

Reply via email to