aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sim/sh/ChangeLog11
-rw-r--r--sim/sh/interp.c48
-rw-r--r--sim/sh/syscall.h5
3 files changed, 59 insertions, 5 deletions
diff --git a/sim/sh/ChangeLog b/sim/sh/ChangeLog
index 9839e8d..541ed1f 100644
--- a/sim/sh/ChangeLog
+++ b/sim/sh/ChangeLog
@@ -1,3 +1,14 @@
+2001-01-30 Ben Elliston <bje@redhat.com>
+
+ * interp.c (sim_create_inferior): Record program arguments for
+ later inspection by the trap handler.
+ (count_argc): New function.
+ (prog_argv): Declare static.
+ (sim_write): Declare.
+ (trap): Implement argc, argnlen and argn system calls. Do not
+ abort on unknown system calls--simply return -1.
+ * syscall.h (SYS_argc, SYS_argnlen, SYS_argn): Define.
+
2001-01-24 Alexandre Oliva <aoliva@redhat.com>
* interp.c (trap): Implement time.
diff --git a/sim/sh/interp.c b/sim/sh/interp.c
index 7f7ffab..99f51d1 100644
--- a/sim/sh/interp.c
+++ b/sim/sh/interp.c
@@ -54,6 +54,8 @@
extern unsigned char sh_jump_table[], sh_dsp_table[0x1000], ppi_table[];
+int sim_write (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size);
+
#define O_RECOMPILE 85
#define DEFINE_TABLE
#define DISASSEMBLER_TABLE
@@ -162,6 +164,7 @@ static int target_little_endian;
static int global_endianw, endianb;
static int target_dsp;
static int host_little_endian;
+static char **prog_argv;
#if 1
static int maskw = 0;
@@ -264,6 +267,20 @@ do { \
#define FPSCR_SZ ((GET_FPSCR() & FPSCR_MASK_SZ) != 0)
#define FPSCR_PR ((GET_FPSCR() & FPSCR_MASK_PR) != 0)
+/* Count the number of arguments in an argv. */
+static int
+count_argc (char **argv)
+{
+ int i;
+
+ if (! argv)
+ return -1;
+
+ for (i = 0; argv[i] != NULL; ++i)
+ continue;
+ return i;
+}
+
static void
set_fpscr1 (x)
int x;
@@ -1102,11 +1119,31 @@ trap (i, regs, memory, maskl, maskw, endianw)
strnswap (regs[5], len);
break;
}
+ case SYS_argc:
+ regs[0] = count_argc (prog_argv);
+ break;
+ case SYS_argnlen:
+ if (regs[5] < count_argc (prog_argv))
+ regs[0] = strlen (prog_argv[regs[5]]);
+ else
+ regs[0] = -1;
+ break;
+ case SYS_argn:
+ if (regs[5] < count_argc (prog_argv))
+ {
+ /* Include the termination byte. */
+ int i = strlen (prog_argv[regs[5]]) + 1;
+ regs[0] = sim_write (0, regs[6], prog_argv[regs[5]], i);
+ }
+ else
+ regs[0] = -1;
+ break;
case SYS_time:
regs[0] = get_now ();
break;
default:
- abort ();
+ regs[0] = -1;
+ break;
}
regs[1] = callback->get_errno (callback);
errno = perrno;
@@ -2146,12 +2183,17 @@ sim_create_inferior (sd, prog_bfd, argv, env)
char **argv;
char **env;
{
- /* clear the registers */
+ /* Clear the registers. */
memset (&saved_state, 0,
(char*)&saved_state.asregs.end_of_registers - (char*)&saved_state);
- /* set the PC */
+
+ /* Set the PC. */
if (prog_bfd != NULL)
saved_state.asregs.pc = bfd_get_start_address (prog_bfd);
+
+ /* Record the program's arguments. */
+ prog_argv = argv;
+
return SIM_RC_OK;
}
diff --git a/sim/sh/syscall.h b/sim/sh/syscall.h
index 2c15447..9b818f9 100644
--- a/sim/sh/syscall.h
+++ b/sim/sh/syscall.h
@@ -27,7 +27,8 @@
#define SYS_stat 38
#define SYS_pipe 42
#define SYS_execve 59
+#define SYS_argc 172
+#define SYS_argnlen 173
+#define SYS_argn 174
#define SYS_utime 201 /* not really a system call */
#define SYS_wait 202 /* nor is this */
-
-