summaryrefslogblamecommitdiffstats
path: root/interf.c
blob: 522f782388ad2ee567e5ece1155d1e5bc558e9c8 (plain) (tree)





































                                                                            


                         
 







                                                   


    
                        



                  
                  
                                        
                               




      
                      
 











                                             



     
                                                   
 
             
 

                              
                                                                 
     
                


   
                                            
 
             
 
                                                                



                                         

                              
                                                                
     
                


    
                      


                 
                          

 
                 

    
                     
 


                                 




                                                
 
                                              
                          









                      


































                                                        
                                                         
 










                                                          


          
                                     
 

            

                    








                                                         
     
           


          
                                                            
 










                                                                          


          
                                      
 

            

                    








                                                          
     
                   

 

                                                                         
 



                                                                          


 
   
                                                     



                     



                                                                            
 

               
           
                                                  

            
                                           

            





                                                    
                                                                       


                                                     

            
              
     



               
   
                                                       

          



              

               
           
                                                  

            
                                           

            





                                              
                                                                 
                                               
          
                                         

            
              
     


               

                                       
 


                                                           

 

                                    
 


                                                             


   
                                              


                   













                                                                            
                          



                                                                           
     
                                                          


   
                                              



                                 



                                    
     



                                                                  
                          





                                                                            
                                                




                                                          
 
/* This file is part of SIS (SPARC instruction simulator)

   Copyright (C) 1995-2017 Free Software Foundation, Inc.
   Contributed by Jiri Gaisler, European Space Agency

   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 3 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, see <http://www.gnu.org/licenses/>.  */

#include "config.h"
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#include "sis.h"

#define PSR_CWP 0x7
#define SIM_DESC int
#define SIM_ADDR uint32
#define SIM_RC int
#define SIM_RC_FAIL 0
#define SIM_RC_OK 1
#define EBREAK 0x00100073
#define CEBREAK 0x90002

static int
run_sim_gdb (icount, dis)
     uint64 icount;
     int dis;
{
  int res;

  if ((sregs[cpu].pc != 0) && (ebase.simtime == 0))
    ms->boot_init ();
  res = run_sim (icount, dis);
  ms->sim_halt ();
  clearerr (stdin);
  return res;
}

void
sim_close (sd, quitting)
     SIM_DESC sd;
     int quitting;
{

  ms->exit_sim ();
#if defined(F_GETFL) && defined(F_SETFL)
  fcntl (0, F_SETFL, termsave);
#endif

};

void
sim_create_inferior ()
{
  int i;

  if (sis_verbose)
    printf ("interf: sim_create_inferior()");
  ebase.simtime = 0;
  ebase.simstart = 0;
  reset_all ();
  reset_stat (sregs);
  for (i = 0; i < ncpu; i++)
    {
      sregs[i].pc = last_load_addr & ~1;
      sregs[i].npc = sregs[i].pc + 4;
    }
}

int
sim_write (uint32 mem, const char *buf, int length)
{
  int i, len;

  for (i = 0; i < length; i++)
    {
      ms->sis_memory_write ((mem + i) ^ arch->bswap, &buf[i], 1);
    }
  return length;
}

int
sim_read (uint32 mem, char *buf, int length)
{
  int i, len;

  if (sis_gdb_break && (archtype == CPU_SPARC) && (length >= 4))
    {
      if (gdb_sp_read (mem, buf, length))
	return length;
    }
  for (i = 0; i < length; i++)
    {
      ms->sis_memory_read ((mem + i) ^ arch->bswap, &buf[i], 1);
    }
  return length;
}

void
sim_info (sd, verbose)
     SIM_DESC sd;
     int verbose;
{
  show_stat (&sregs[cpu]);
}

int simstat = OK;

void
sim_resume (int step)
{
  if (step)
    simstat = run_sim_gdb (1, 0);
  else
    {
      socket_poll ();
      simstat = run_sim_gdb (UINT64_MAX / 2, 0);
      remove_event (socket_poll, -1);
    }

  if (sis_gdb_break && (cputype != CPU_RISCV))
    save_sp (&sregs[cpu]);
}

int
sim_stop (SIM_DESC sd)
{
  ctrl_c = 1;
  return 1;
}

static int
sis_insert_hw_breakpoint (int addr)
{
  if (ebase.wprnum < BPT_MAX)
    {
      ebase.bpts[ebase.bptnum] = addr;
      ebase.bptnum++;
      if (sis_verbose)
	printf ("inserted hw breakpoint at %x\n", addr);
      return SIM_RC_OK;
    }
  else
    return SIM_RC_FAIL;
}

static int
sis_remove_hw_breakpoint (int addr)
{
  int i = 0;

  if (!ebase.bptnum)
    return 1;
  while ((i < ebase.bptnum) && (ebase.bpts[i] != addr))
    i++;
  if (addr == ebase.bpts[i])
    {
      for (; i < ebase.bptnum - 1; i++)
	ebase.wprs[i] = ebase.bpts[i + 1];
      ebase.bptnum -= 1;
      if (sis_verbose)
	printf ("removed hw breakpoint at %x\n", addr);
    }
  return 1;
}

static int
sis_insert_watchpoint_read (int addr, unsigned char mask)
{
  if (ebase.wprnum < WPR_MAX)
    {
      ebase.wprs[ebase.wprnum] = addr;
      ebase.wprm[ebase.wprnum] = mask;
      ebase.wprnum++;
      if (sis_verbose)
	printf ("inserted read watchpoint at %x\n", addr);
      return SIM_RC_OK;
    }
  else
    return SIM_RC_FAIL;
}

static int
sis_remove_watchpoint_read (int addr)
{
  int i = 0;

  if (!ebase.wprnum)
    return 1;
  while ((i < ebase.wprnum) && (ebase.wprs[i] != addr))
    i++;
  if (addr == ebase.wprs[i])
    {
      for (; i < ebase.wprnum - 1; i++)
	ebase.wprs[i] = ebase.wprs[i + 1];
      ebase.wprnum -= 1;
      if (sis_verbose)
	printf ("removed read watchpoint at %x\n", addr);
    }
  return 1;
}

static int
sis_insert_watchpoint_write (int32 addr, unsigned char mask)
{
  if (ebase.wpwnum < WPR_MAX)
    {
      ebase.wpws[ebase.wpwnum] = addr;
      ebase.wpwm[ebase.wpwnum] = mask;
      ebase.wpwnum++;
      if (sis_verbose)
	printf ("sim_insert_watchpoint_write: 0x%08x : %x\n", addr, mask);
      return SIM_RC_OK;
    }
  else
    return SIM_RC_FAIL;
}

static int
sis_remove_watchpoint_write (int addr)
{
  int i = 0;

  if (!ebase.wpwnum)
    return 1;
  while ((i < ebase.wpwnum) && (ebase.wpws[i] != addr))
    i++;
  if (addr == ebase.wpws[i])
    {
      for (; i < ebase.wpwnum - 1; i++)
	ebase.wpws[i] = ebase.wpws[i + 1];
      ebase.wpwnum -= 1;
      if (sis_verbose)
	printf ("removed write watchpoint at %x\n", addr);
    }
  return SIM_RC_OK;
}

int
sim_can_use_hw_breakpoint (SIM_DESC sd, int type, int cnt, int othertype)
{
  if (type == 2)		/* bp_hardware_breakpoint not supported */
    return 0;
  else
    return 1;
}


int
sim_set_watchpoint (uint32 mem, int length, int type)
{
  int res;
  unsigned char mask;

  if (!length)
    return 1;			/* used by gdb for probing of watchpoints */

  mask = length - 1;

  switch (type)
    {
    case 0:
      res = sim_insert_swbreakpoint (mem, length);
      break;
    case 1:
      res = sis_insert_hw_breakpoint (mem);
      break;
    case 2:
      res = sis_insert_watchpoint_write (mem, mask);
      break;
    case 3:
      res = sis_insert_watchpoint_read (mem, mask);
      break;
    case 4:
      if ((res = sis_insert_watchpoint_write (mem, mask)) == SIM_RC_OK)
	res = sis_insert_watchpoint_read (mem, mask);
      if (res == SIM_RC_FAIL)
	sis_remove_watchpoint_read (mem);
      break;
    default:
      res = 0;
    }
  return (res);
}


int
sim_clear_watchpoint (uint32 mem, int length, int type)
{
  int res;

  if (!length)
    return 1;

  switch (type)
    {
    case 0:
      res = sim_remove_swbreakpoint (mem, length);
      break;
    case 1:
      res = sis_remove_hw_breakpoint (mem);
      break;
    case 2:
      res = sis_remove_watchpoint_write (mem);
      break;
    case 3:
      res = sis_remove_watchpoint_read (mem);
      break;
    case 4:
      if ((res = sis_remove_watchpoint_write (mem)) == SIM_RC_OK)
	res = sis_remove_watchpoint_read (mem);
      else
	sis_remove_watchpoint_read (mem);
      break;
    default:
      res = 0;
    }
  return (res);
}

int
sim_stopped_by_watchpoint (SIM_DESC sd)
{
  if (sis_verbose)
    printf ("sim_stopped_by_watchpoint %x\n", ebase.wphit);
  return ((ebase.wphit != 0));
}

int
sim_watchpoint_address (SIM_DESC sd)
{
  if (sis_verbose)
    printf ("sim__watchpoint_address %x\n", ebase.wpaddress);
  return (ebase.wpaddress);
}

int
sim_insert_swbreakpoint (uint32 addr, int len)
{
  uint32 breakinsn;

  if (ebase.bptnum < BPT_MAX)
    {
      ebase.bpts[ebase.bptnum] = addr;
      ms->sis_memory_read (addr, (char *) &ebase.bpsave[ebase.bptnum], len);
      if (len == 4)
	{
	  breakinsn = EBREAK;
	  ms->sis_memory_write (addr, (char *) &breakinsn, 4);
	}
      else
	{
	  breakinsn = CEBREAK;
	  ms->sis_memory_write (addr, (char *) &breakinsn, 2);
	}
      if (sis_verbose > 1)
	printf ("sim_insert_swbreakpoint: added breakpoint %d at 0x%08x\n",
		ebase.bptnum + 1, addr);
      ebase.bptnum += 1;
      return 1;
    }
  return 0;			/* Too many breakpoints */
}

int
sim_remove_swbreakpoint (uint32 addr, int len)
{
  int i;

  /* find breakpoint to remove */
  for (i = 0; i < ebase.bptnum; i++)
    {
      if (ebase.bpts[i] == addr)
	break;
    }
  if (ebase.bpts[i] == addr)
    {
      /* write back saved opcode */
      ms->sis_memory_write (addr, (char *) &ebase.bpsave[i], len);
      if (sis_verbose > 1)
	printf ("sim_remove_swbreakpoint: remove breakpoint %d at 0x%08x\n",
		i, addr);
      /* shift down remaining breakpoints */
      for (; i < ebase.bptnum; i++)
	{
	  ebase.bpts[i] = ebase.bpts[i + 1];
	  ebase.bpsave[i] = ebase.bpsave[i + 1];
	}
      ebase.bptnum -= 1;
      return 1;
    }
  return 0;			/* breakpoint not found */
}