diff options
Diffstat (limited to 'sim/iq2000/iq2000.c')
-rw-r--r-- | sim/iq2000/iq2000.c | 267 |
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; +} |