123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- /* IQ2000 simulator support code
- Copyright (C) 2000-2015 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 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/>. */
- #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));
- free (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);
- free (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));
- free (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;
- }
|