#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <bfd.h>
#include <signal.h>
#include "gdb/callback.h"
#include "gdb/remote-sim.h"
#include "armdefs.h"
#include "armemu.h"
#include "dbg_rdi.h"
#include "ansidecl.h"
#include "sim-utils.h"
#include "run-sim.h"
#include "gdb/sim-arm.h"
host_callback *sim_callback;
static struct ARMul_State *state;
static SIM_OPEN_KIND sim_kind;
static char *myname;
static int mem_size = (1 << 21);
static int verbosity;
static int big_endian;
int stop_simulator;
static void
init ()
{
static int done;
if (!done)
{
ARMul_EmulateInit ();
state = ARMul_NewState ();
state->bigendSig = (big_endian ? HIGH : LOW);
ARMul_MemoryInit (state, mem_size);
ARMul_OSInit (state);
ARMul_CoProInit (state);
state->verbose = verbosity;
done = 1;
}
}
void
sim_set_verbose (v)
int v;
{
verbosity = v;
}
void
sim_size (size)
int size;
{
mem_size = size;
}
void
ARMul_ConsolePrint VPARAMS ((ARMul_State * state,
const char * format,
...))
{
va_list ap;
if (state->verbose)
{
va_start (ap, format);
vprintf (format, ap);
va_end (ap);
}
}
ARMword
ARMul_Debug (state, pc, instr)
ARMul_State * state ATTRIBUTE_UNUSED;
ARMword pc ATTRIBUTE_UNUSED;
ARMword instr ATTRIBUTE_UNUSED;
{
return 0;
}
int
sim_write (sd, addr, buffer, size)
SIM_DESC sd ATTRIBUTE_UNUSED;
SIM_ADDR addr;
unsigned char * buffer;
int size;
{
int i;
init ();
for (i = 0; i < size; i++)
ARMul_SafeWriteByte (state, addr + i, buffer[i]);
return size;
}
int
sim_read (sd, addr, buffer, size)
SIM_DESC sd ATTRIBUTE_UNUSED;
SIM_ADDR addr;
unsigned char * buffer;
int size;
{
int i;
init ();
for (i = 0; i < size; i++)
buffer[i] = ARMul_SafeReadByte (state, addr + i);
return size;
}
int
sim_trace (sd)
SIM_DESC sd ATTRIBUTE_UNUSED;
{
(*sim_callback->printf_filtered)
(sim_callback,
"This simulator does not support tracing\n");
return 1;
}
int
sim_stop (sd)
SIM_DESC sd ATTRIBUTE_UNUSED;
{
state->Emulate = STOP;
stop_simulator = 1;
return 1;
}
void
sim_resume (sd, step, siggnal)
SIM_DESC sd ATTRIBUTE_UNUSED;
int step;
int siggnal ATTRIBUTE_UNUSED;
{
state->EndCondition = 0;
stop_simulator = 0;
if (step)
{
state->Reg[15] = ARMul_DoInstr (state);
if (state->EndCondition == 0)
state->EndCondition = RDIError_BreakpointReached;
}
else
{
state->NextInstr = RESUME;
state->Reg[15] = ARMul_DoProg (state);
}
FLUSHPIPE;
}
SIM_RC
sim_create_inferior (sd, abfd, argv, env)
SIM_DESC sd ATTRIBUTE_UNUSED;
struct _bfd * abfd;
char ** argv;
char ** env;
{
int argvlen = 0;
int mach;
char **arg;
if (abfd != NULL)
ARMul_SetPC (state, bfd_get_start_address (abfd));
else
ARMul_SetPC (state, 0);
mach = bfd_get_mach (abfd);
switch (mach)
{
default:
(*sim_callback->printf_filtered)
(sim_callback,
"Unknown machine type '%d'; please update sim_create_inferior.\n",
mach);
case 0:
case bfd_mach_arm_XScale:
ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop | ARM_XScale_Prop);
break;
case bfd_mach_arm_5:
if (bfd_family_coff (abfd))
{
ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop | ARM_XScale_Prop);
break;
}
case bfd_mach_arm_5T:
ARMul_SelectProcessor (state, ARM_v5_Prop);
break;
case bfd_mach_arm_5TE:
ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop);
break;
case bfd_mach_arm_4:
case bfd_mach_arm_4T:
ARMul_SelectProcessor (state, ARM_v4_Prop);
break;
case bfd_mach_arm_3:
case bfd_mach_arm_3M:
ARMul_SelectProcessor (state, ARM_Lock_Prop);
break;
case bfd_mach_arm_2:
case bfd_mach_arm_2a:
ARMul_SelectProcessor (state, ARM_Fix26_Prop);
break;
}
if ( mach != bfd_mach_arm_3
&& mach != bfd_mach_arm_3M
&& mach != bfd_mach_arm_2
&& mach != bfd_mach_arm_2a)
{
ARMul_SetCPSR (state, SVC32MODE);
}
if (argv != NULL)
{
if (state->CommandLine != NULL)
{
free (state->CommandLine);
state->CommandLine = NULL;
}
for (arg = argv; *arg != NULL; arg++)
argvlen += strlen (*arg) + 1;
state->CommandLine = malloc (argvlen + 1);
if (state->CommandLine != NULL)
{
arg = argv;
state->CommandLine[0] = '\0';
for (arg = argv; *arg != NULL; arg++)
{
strcat (state->CommandLine, *arg);
strcat (state->CommandLine, " ");
}
}
}
if (env != NULL)
{
while (*env)
{
if (strncmp (*env, "MEMSIZE=", sizeof ("MEMSIZE=") - 1) == 0)
{
char *end_of_num;
state->MemSize =
strtoul (*env + sizeof ("MEMSIZE=") - 1, &end_of_num, 0);
}
env++;
}
}
return SIM_RC_OK;
}
void
sim_info (sd, verbose)
SIM_DESC sd ATTRIBUTE_UNUSED;
int verbose ATTRIBUTE_UNUSED;
{
}
static int
frommem (state, memory)
struct ARMul_State *state;
unsigned char *memory;
{
if (state->bigendSig == HIGH)
return (memory[0] << 24) | (memory[1] << 16)
| (memory[2] << 8) | (memory[3] << 0);
else
return (memory[3] << 24) | (memory[2] << 16)
| (memory[1] << 8) | (memory[0] << 0);
}
static void
tomem (state, memory, val)
struct ARMul_State *state;
unsigned char *memory;
int val;
{
if (state->bigendSig == HIGH)
{
memory[0] = val >> 24;
memory[1] = val >> 16;
memory[2] = val >> 8;
memory[3] = val >> 0;
}
else
{
memory[3] = val >> 24;
memory[2] = val >> 16;
memory[1] = val >> 8;
memory[0] = val >> 0;
}
}
int
sim_store_register (sd, rn, memory, length)
SIM_DESC sd ATTRIBUTE_UNUSED;
int rn;
unsigned char *memory;
int length ATTRIBUTE_UNUSED;
{
init ();
switch ((enum sim_arm_regs) rn)
{
case SIM_ARM_R0_REGNUM:
case SIM_ARM_R1_REGNUM:
case SIM_ARM_R2_REGNUM:
case SIM_ARM_R3_REGNUM:
case SIM_ARM_R4_REGNUM:
case SIM_ARM_R5_REGNUM:
case SIM_ARM_R6_REGNUM:
case SIM_ARM_R7_REGNUM:
case SIM_ARM_R8_REGNUM:
case SIM_ARM_R9_REGNUM:
case SIM_ARM_R10_REGNUM:
case SIM_ARM_R11_REGNUM:
case SIM_ARM_R12_REGNUM:
case SIM_ARM_R13_REGNUM:
case SIM_ARM_R14_REGNUM:
case SIM_ARM_R15_REGNUM:
case SIM_ARM_FP0_REGNUM:
case SIM_ARM_FP1_REGNUM:
case SIM_ARM_FP2_REGNUM:
case SIM_ARM_FP3_REGNUM:
case SIM_ARM_FP4_REGNUM:
case SIM_ARM_FP5_REGNUM:
case SIM_ARM_FP6_REGNUM:
case SIM_ARM_FP7_REGNUM:
case SIM_ARM_FPS_REGNUM:
ARMul_SetReg (state, state->Mode, rn, frommem (state, memory));
break;
case SIM_ARM_PS_REGNUM:
state->Cpsr = frommem (state, memory);
ARMul_CPSRAltered (state);
break;
default:
return 0;
}
return -1;
}
int
sim_fetch_register (sd, rn, memory, length)
SIM_DESC sd ATTRIBUTE_UNUSED;
int rn;
unsigned char *memory;
int length ATTRIBUTE_UNUSED;
{
ARMword regval;
init ();
switch ((enum sim_arm_regs) rn)
{
case SIM_ARM_R0_REGNUM:
case SIM_ARM_R1_REGNUM:
case SIM_ARM_R2_REGNUM:
case SIM_ARM_R3_REGNUM:
case SIM_ARM_R4_REGNUM:
case SIM_ARM_R5_REGNUM:
case SIM_ARM_R6_REGNUM:
case SIM_ARM_R7_REGNUM:
case SIM_ARM_R8_REGNUM:
case SIM_ARM_R9_REGNUM:
case SIM_ARM_R10_REGNUM:
case SIM_ARM_R11_REGNUM:
case SIM_ARM_R12_REGNUM:
case SIM_ARM_R13_REGNUM:
case SIM_ARM_R14_REGNUM:
case SIM_ARM_R15_REGNUM:
regval = ARMul_GetReg (state, state->Mode, rn);
break;
case SIM_ARM_FP0_REGNUM:
case SIM_ARM_FP1_REGNUM:
case SIM_ARM_FP2_REGNUM:
case SIM_ARM_FP3_REGNUM:
case SIM_ARM_FP4_REGNUM:
case SIM_ARM_FP5_REGNUM:
case SIM_ARM_FP6_REGNUM:
case SIM_ARM_FP7_REGNUM:
case SIM_ARM_FPS_REGNUM:
memset (memory, 0, length);
return 0;
case SIM_ARM_PS_REGNUM:
regval = ARMul_GetCPSR (state);
break;
default:
return 0;
}
while (length)
{
tomem (state, memory, regval);
length -= 4;
memory += 4;
regval = 0;
}
return -1;
}
#ifdef SIM_TARGET_SWITCHES
static void sim_target_parse_arg_array PARAMS ((char **));
typedef struct
{
char * swi_option;
unsigned int swi_mask;
} swi_options;
#define SWI_SWITCH "--swi-support"
static swi_options options[] =
{
{ "none", 0 },
{ "demon", SWI_MASK_DEMON },
{ "angel", SWI_MASK_ANGEL },
{ "redboot", SWI_MASK_REDBOOT },
{ "all", -1 },
{ "NONE", 0 },
{ "DEMON", SWI_MASK_DEMON },
{ "ANGEL", SWI_MASK_ANGEL },
{ "REDBOOT", SWI_MASK_REDBOOT },
{ "ALL", -1 }
};
int
sim_target_parse_command_line (argc, argv)
int argc;
char ** argv;
{
int i;
for (i = 1; i < argc; i++)
{
char * ptr = argv[i];
int arg;
if ((ptr == NULL) || (* ptr != '-'))
break;
if (strncmp (ptr, SWI_SWITCH, sizeof SWI_SWITCH - 1) != 0)
continue;
if (ptr[sizeof SWI_SWITCH - 1] == 0)
{
for (arg = i; arg < argc; arg ++)
argv[arg] = argv[arg + 1];
argc --;
ptr = argv[i];
}
else
ptr += sizeof SWI_SWITCH;
swi_mask = 0;
while (* ptr)
{
int i;
for (i = sizeof options / sizeof options[0]; i--;)
if (strncmp (ptr, options[i].swi_option,
strlen (options[i].swi_option)) == 0)
{
swi_mask |= options[i].swi_mask;
ptr += strlen (options[i].swi_option);
if (* ptr == ',')
++ ptr;
break;
}
if (i < 0)
break;
}
if (* ptr != 0)
fprintf (stderr, "Ignoring swi options: %s\n", ptr);
for (arg = i; arg < argc; arg ++)
argv[arg] = argv[arg + 1];
argc --;
i --;
}
return argc;
}
static void
sim_target_parse_arg_array (argv)
char ** argv;
{
int i;
for (i = 0; argv[i]; i++)
;
return (void) sim_target_parse_command_line (i, argv);
}
void
sim_target_display_usage ()
{
fprintf (stderr, "%s=<list> Comma seperated list of SWI protocols to supoport.\n\
This list can contain: NONE, DEMON, ANGEL, REDBOOT and/or ALL.\n",
SWI_SWITCH);
}
#endif
SIM_DESC
sim_open (kind, ptr, abfd, argv)
SIM_OPEN_KIND kind;
host_callback *ptr;
struct _bfd *abfd;
char **argv;
{
sim_kind = kind;
if (myname) free (myname);
myname = (char *) xstrdup (argv[0]);
sim_callback = ptr;
#ifdef SIM_TARGET_SWITCHES
sim_target_parse_arg_array (argv);
#endif
if (abfd != NULL)
big_endian = bfd_big_endian (abfd);
else if (argv[1] != NULL)
{
int i;
for (i = 0; (argv[i] != NULL) && (argv[i][0] != 0); i++)
if (argv[i][0] == '-' && argv[i][1] == 'E')
{
char c;
if ((c = argv[i][2]) == 0)
{
++i;
c = argv[i][0];
}
switch (c)
{
case 0:
sim_callback->printf_filtered
(sim_callback, "No argument to -E option provided\n");
break;
case 'b':
case 'B':
big_endian = 1;
break;
case 'l':
case 'L':
big_endian = 0;
break;
default:
sim_callback->printf_filtered
(sim_callback, "Unrecognised argument to -E option\n");
break;
}
}
else if (argv[i][0] == '-' && argv[i][1] == 'm')
{
if (argv[i][2] != '\0')
sim_size (atoi (&argv[i][2]));
else if (argv[i + 1] != NULL)
{
sim_size (atoi (argv[i + 1]));
i++;
}
else
{
sim_callback->printf_filtered (sim_callback,
"Missing argument to -m option\n");
return NULL;
}
}
}
return (SIM_DESC) 1;
}
void
sim_close (sd, quitting)
SIM_DESC sd ATTRIBUTE_UNUSED;
int quitting ATTRIBUTE_UNUSED;
{
if (myname)
free (myname);
myname = NULL;
}
SIM_RC
sim_load (sd, prog, abfd, from_tty)
SIM_DESC sd;
char *prog;
bfd *abfd;
int from_tty ATTRIBUTE_UNUSED;
{
bfd *prog_bfd;
prog_bfd = sim_load_file (sd, myname, sim_callback, prog, abfd,
sim_kind == SIM_OPEN_DEBUG, 0, sim_write);
if (prog_bfd == NULL)
return SIM_RC_FAIL;
ARMul_SetPC (state, bfd_get_start_address (prog_bfd));
if (abfd == NULL)
bfd_close (prog_bfd);
return SIM_RC_OK;
}
void
sim_stop_reason (sd, reason, sigrc)
SIM_DESC sd ATTRIBUTE_UNUSED;
enum sim_stop *reason;
int *sigrc;
{
if (stop_simulator)
{
*reason = sim_stopped;
*sigrc = SIGINT;
}
else if (state->EndCondition == 0)
{
*reason = sim_exited;
*sigrc = state->Reg[0] & 255;
}
else
{
*reason = sim_stopped;
if (state->EndCondition == RDIError_BreakpointReached)
*sigrc = SIGTRAP;
else
*sigrc = 0;
}
}
void
sim_do_command (sd, cmd)
SIM_DESC sd ATTRIBUTE_UNUSED;
char *cmd ATTRIBUTE_UNUSED;
{
(*sim_callback->printf_filtered)
(sim_callback,
"This simulator does not accept any commands.\n");
}
void
sim_set_callbacks (ptr)
host_callback *ptr;
{
sim_callback = ptr;
}