aboutsummaryrefslogtreecommitdiff
path: root/sim/iq2000/iq2000.c
diff options
context:
space:
mode:
Diffstat (limited to 'sim/iq2000/iq2000.c')
-rw-r--r--sim/iq2000/iq2000.c267
1 files changed, 267 insertions, 0 deletions
diff --git a/sim/iq2000/iq2000.c b/sim/iq2000/iq2000.c
new file mode 100644
index 0000000..afe8429
--- /dev/null
+++ b/sim/iq2000/iq2000.c
@@ -0,0 +1,267 @@
+/* IQ2000 simulator support code
+ Copyright (C) 2000, 2004 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+ This file is part of the GNU simulators.
+
+ 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, 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. */
+
+#define WANT_CPU
+#define WANT_CPU_IQ2000BF
+
+#include "sim-main.h"
+#include "cgen-mem.h"
+#include "cgen-ops.h"
+
+enum
+{
+ GPR0_REGNUM = 0,
+ NR_GPR = 32,
+ PC_REGNUM = 32
+};
+
+enum libgloss_syscall
+{
+ SYS_exit = 1,
+ SYS_open = 2,
+ SYS_close = 3,
+ SYS_read = 4,
+ SYS_write = 5,
+ SYS_lseek = 6,
+ SYS_unlink = 7,
+ SYS_getpid = 8,
+ SYS_kill = 9,
+ SYS_fstat = 10,
+ SYS_argvlen = 12,
+ SYS_argv = 13,
+ SYS_chdir = 14,
+ SYS_stat = 15,
+ SYS_chmod = 16,
+ SYS_utime = 17,
+ SYS_time = 18,
+ SYS_gettimeofday = 19,
+ SYS_times = 20
+};
+
+/* Read a null terminated string from memory, return in a buffer */
+static char *
+fetch_str (current_cpu, pc, addr)
+ SIM_CPU *current_cpu;
+ PCADDR pc;
+ DI addr;
+{
+ char *buf;
+ int nr = 0;
+ while (sim_core_read_1 (current_cpu,
+ pc, read_map, CPU2DATA(addr + nr)) != 0)
+ nr++;
+ buf = NZALLOC (char, nr + 1);
+ sim_read (CPU_STATE (current_cpu), CPU2DATA(addr), buf, nr);
+ return buf;
+}
+
+void
+do_syscall (SIM_CPU *current_cpu, PCADDR pc)
+{
+#if 0
+ int syscall = H2T_4 (iq2000bf_h_gr_get (current_cpu, 11));
+#endif
+ int syscall_function = iq2000bf_h_gr_get (current_cpu, 4);
+ int i;
+ char *buf;
+ int PARM1 = iq2000bf_h_gr_get (current_cpu, 5);
+ int PARM2 = iq2000bf_h_gr_get (current_cpu, 6);
+ int PARM3 = iq2000bf_h_gr_get (current_cpu, 7);
+ const int ret_reg = 2;
+
+ switch (syscall_function)
+ {
+ case 0:
+ switch (H2T_4 (iq2000bf_h_gr_get (current_cpu, 11)))
+ {
+ case 0:
+ /* Pass. */
+ puts ("pass");
+ exit (0);
+ case 1:
+ /* Fail. */
+ puts ("fail");
+ exit (1);
+ }
+
+ case SYS_write:
+ buf = zalloc (PARM3);
+ sim_read (CPU_STATE (current_cpu), CPU2DATA(PARM2), buf, PARM3);
+ SET_H_GR (ret_reg,
+ sim_io_write (CPU_STATE (current_cpu),
+ PARM1, buf, PARM3));
+ zfree (buf);
+ break;
+
+ case SYS_lseek:
+ SET_H_GR (ret_reg,
+ sim_io_lseek (CPU_STATE (current_cpu),
+ PARM1, PARM2, PARM3));
+ break;
+
+ case SYS_exit:
+ sim_engine_halt (CPU_STATE (current_cpu), current_cpu,
+ NULL, pc, sim_exited, PARM1);
+ break;
+
+ case SYS_read:
+ buf = zalloc (PARM3);
+ SET_H_GR (ret_reg,
+ sim_io_read (CPU_STATE (current_cpu),
+ PARM1, buf, PARM3));
+ sim_write (CPU_STATE (current_cpu), CPU2DATA(PARM2), buf, PARM3);
+ zfree (buf);
+ break;
+
+ case SYS_open:
+ buf = fetch_str (current_cpu, pc, PARM1);
+ SET_H_GR (ret_reg,
+ sim_io_open (CPU_STATE (current_cpu),
+ buf, PARM2));
+ zfree (buf);
+ break;
+
+ case SYS_close:
+ SET_H_GR (ret_reg,
+ sim_io_close (CPU_STATE (current_cpu), PARM1));
+ break;
+
+ case SYS_time:
+ SET_H_GR (ret_reg, time (0));
+ break;
+
+ default:
+ SET_H_GR (ret_reg, -1);
+ }
+}
+
+void
+do_break (SIM_CPU *current_cpu, PCADDR pc)
+{
+ SIM_DESC sd = CPU_STATE (current_cpu);
+ sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
+}
+
+/* The semantic code invokes this for invalid (unrecognized) instructions. */
+
+SEM_PC
+sim_engine_invalid_insn (SIM_CPU *current_cpu, IADDR cia, SEM_PC vpc)
+{
+ SIM_DESC sd = CPU_STATE (current_cpu);
+ sim_engine_halt (sd, current_cpu, NULL, cia, sim_stopped, SIM_SIGILL);
+
+ return vpc;
+}
+
+
+/* Process an address exception. */
+
+void
+iq2000_core_signal (SIM_DESC sd, SIM_CPU *current_cpu, sim_cia cia,
+ unsigned int map, int nr_bytes, address_word addr,
+ transfer_type transfer, sim_core_signals sig)
+{
+ sim_core_signal (sd, current_cpu, cia, map, nr_bytes, addr,
+ transfer, sig);
+}
+
+
+/* Initialize cycle counting for an insn.
+ FIRST_P is non-zero if this is the first insn in a set of parallel
+ insns. */
+
+void
+iq2000bf_model_insn_before (SIM_CPU *cpu, int first_p)
+{
+ /* Do nothing. */
+}
+
+
+/* Record the cycles computed for an insn.
+ LAST_P is non-zero if this is the last insn in a set of parallel insns,
+ and we update the total cycle count.
+ CYCLES is the cycle count of the insn. */
+
+void
+iq2000bf_model_insn_after(SIM_CPU *cpu, int last_p, int cycles)
+{
+ /* Do nothing. */
+}
+
+
+int
+iq2000bf_model_iq2000_u_exec (SIM_CPU *cpu, const IDESC *idesc,
+ int unit_num, int referenced)
+{
+ return idesc->timing->units[unit_num].done;
+}
+
+PCADDR
+get_h_pc (SIM_CPU *cpu)
+{
+ return CPU_CGEN_HW(cpu)->h_pc;
+}
+
+void
+set_h_pc (SIM_CPU *cpu, PCADDR addr)
+{
+ CPU_CGEN_HW(cpu)->h_pc = addr | IQ2000_INSN_MASK;
+}
+
+int
+iq2000bf_fetch_register (SIM_CPU *cpu, int nr, unsigned char *buf, int len)
+{
+ if (nr >= GPR0_REGNUM
+ && nr < (GPR0_REGNUM + NR_GPR)
+ && len == 4)
+ {
+ *((unsigned32*)buf) =
+ H2T_4 (iq2000bf_h_gr_get (cpu, nr - GPR0_REGNUM));
+ return 4;
+ }
+ else if (nr == PC_REGNUM
+ && len == 4)
+ {
+ *((unsigned32*)buf) = H2T_4 (get_h_pc (cpu));
+ return 4;
+ }
+ else
+ return 0;
+}
+
+int
+iq2000bf_store_register (SIM_CPU *cpu, int nr, unsigned char *buf, int len)
+{
+ if (nr >= GPR0_REGNUM
+ && nr < (GPR0_REGNUM + NR_GPR)
+ && len == 4)
+ {
+ iq2000bf_h_gr_set (cpu, nr - GPR0_REGNUM, T2H_4 (*((unsigned32*)buf)));
+ return 4;
+ }
+ else if (nr == PC_REGNUM
+ && len == 4)
+ {
+ set_h_pc (cpu, T2H_4 (*((unsigned32*)buf)));
+ return 4;
+ }
+ else
+ return 0;
+}