1/* IQ2000 simulator support code 2 Copyright (C) 2000, 2004, 2007 Free Software Foundation, Inc. 3 Contributed by Cygnus Support. 4 5 This file is part of the GNU simulators. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20#define WANT_CPU 21#define WANT_CPU_IQ2000BF 22 23#include "sim-main.h" 24#include "cgen-mem.h" 25#include "cgen-ops.h" 26 27enum 28{ 29 GPR0_REGNUM = 0, 30 NR_GPR = 32, 31 PC_REGNUM = 32 32}; 33 34enum libgloss_syscall 35{ 36 SYS_exit = 1, 37 SYS_open = 2, 38 SYS_close = 3, 39 SYS_read = 4, 40 SYS_write = 5, 41 SYS_lseek = 6, 42 SYS_unlink = 7, 43 SYS_getpid = 8, 44 SYS_kill = 9, 45 SYS_fstat = 10, 46 SYS_argvlen = 12, 47 SYS_argv = 13, 48 SYS_chdir = 14, 49 SYS_stat = 15, 50 SYS_chmod = 16, 51 SYS_utime = 17, 52 SYS_time = 18, 53 SYS_gettimeofday = 19, 54 SYS_times = 20 55}; 56 57/* Read a null terminated string from memory, return in a buffer */ 58static char * 59fetch_str (current_cpu, pc, addr) 60 SIM_CPU *current_cpu; 61 PCADDR pc; 62 DI addr; 63{ 64 char *buf; 65 int nr = 0; 66 while (sim_core_read_1 (current_cpu, 67 pc, read_map, CPU2DATA(addr + nr)) != 0) 68 nr++; 69 buf = NZALLOC (char, nr + 1); 70 sim_read (CPU_STATE (current_cpu), CPU2DATA(addr), buf, nr); 71 return buf; 72} 73 74void 75do_syscall (SIM_CPU *current_cpu, PCADDR pc) 76{ 77#if 0 78 int syscall = H2T_4 (iq2000bf_h_gr_get (current_cpu, 11)); 79#endif 80 int syscall_function = iq2000bf_h_gr_get (current_cpu, 4); 81 int i; 82 char *buf; 83 int PARM1 = iq2000bf_h_gr_get (current_cpu, 5); 84 int PARM2 = iq2000bf_h_gr_get (current_cpu, 6); 85 int PARM3 = iq2000bf_h_gr_get (current_cpu, 7); 86 const int ret_reg = 2; 87 88 switch (syscall_function) 89 { 90 case 0: 91 switch (H2T_4 (iq2000bf_h_gr_get (current_cpu, 11))) 92 { 93 case 0: 94 /* Pass. */ 95 puts ("pass"); 96 exit (0); 97 case 1: 98 /* Fail. */ 99 puts ("fail"); 100 exit (1); 101 } 102 103 case SYS_write: 104 buf = zalloc (PARM3); 105 sim_read (CPU_STATE (current_cpu), CPU2DATA(PARM2), buf, PARM3); 106 SET_H_GR (ret_reg, 107 sim_io_write (CPU_STATE (current_cpu), 108 PARM1, buf, PARM3)); 109 zfree (buf); 110 break; 111 112 case SYS_lseek: 113 SET_H_GR (ret_reg, 114 sim_io_lseek (CPU_STATE (current_cpu), 115 PARM1, PARM2, PARM3)); 116 break; 117 118 case SYS_exit: 119 sim_engine_halt (CPU_STATE (current_cpu), current_cpu, 120 NULL, pc, sim_exited, PARM1); 121 break; 122 123 case SYS_read: 124 buf = zalloc (PARM3); 125 SET_H_GR (ret_reg, 126 sim_io_read (CPU_STATE (current_cpu), 127 PARM1, buf, PARM3)); 128 sim_write (CPU_STATE (current_cpu), CPU2DATA(PARM2), buf, PARM3); 129 zfree (buf); 130 break; 131 132 case SYS_open: 133 buf = fetch_str (current_cpu, pc, PARM1); 134 SET_H_GR (ret_reg, 135 sim_io_open (CPU_STATE (current_cpu), 136 buf, PARM2)); 137 zfree (buf); 138 break; 139 140 case SYS_close: 141 SET_H_GR (ret_reg, 142 sim_io_close (CPU_STATE (current_cpu), PARM1)); 143 break; 144 145 case SYS_time: 146 SET_H_GR (ret_reg, time (0)); 147 break; 148 149 default: 150 SET_H_GR (ret_reg, -1); 151 } 152} 153 154void 155do_break (SIM_CPU *current_cpu, PCADDR pc) 156{ 157 SIM_DESC sd = CPU_STATE (current_cpu); 158 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP); 159} 160 161/* The semantic code invokes this for invalid (unrecognized) instructions. */ 162 163SEM_PC 164sim_engine_invalid_insn (SIM_CPU *current_cpu, IADDR cia, SEM_PC vpc) 165{ 166 SIM_DESC sd = CPU_STATE (current_cpu); 167 sim_engine_halt (sd, current_cpu, NULL, cia, sim_stopped, SIM_SIGILL); 168 169 return vpc; 170} 171 172 173/* Process an address exception. */ 174 175void 176iq2000_core_signal (SIM_DESC sd, SIM_CPU *current_cpu, sim_cia cia, 177 unsigned int map, int nr_bytes, address_word addr, 178 transfer_type transfer, sim_core_signals sig) 179{ 180 sim_core_signal (sd, current_cpu, cia, map, nr_bytes, addr, 181 transfer, sig); 182} 183 184 185/* Initialize cycle counting for an insn. 186 FIRST_P is non-zero if this is the first insn in a set of parallel 187 insns. */ 188 189void 190iq2000bf_model_insn_before (SIM_CPU *cpu, int first_p) 191{ 192 /* Do nothing. */ 193} 194 195 196/* Record the cycles computed for an insn. 197 LAST_P is non-zero if this is the last insn in a set of parallel insns, 198 and we update the total cycle count. 199 CYCLES is the cycle count of the insn. */ 200 201void 202iq2000bf_model_insn_after(SIM_CPU *cpu, int last_p, int cycles) 203{ 204 /* Do nothing. */ 205} 206 207 208int 209iq2000bf_model_iq2000_u_exec (SIM_CPU *cpu, const IDESC *idesc, 210 int unit_num, int referenced) 211{ 212 return idesc->timing->units[unit_num].done; 213} 214 215PCADDR 216get_h_pc (SIM_CPU *cpu) 217{ 218 return CPU_CGEN_HW(cpu)->h_pc; 219} 220 221void 222set_h_pc (SIM_CPU *cpu, PCADDR addr) 223{ 224 CPU_CGEN_HW(cpu)->h_pc = addr | IQ2000_INSN_MASK; 225} 226 227int 228iq2000bf_fetch_register (SIM_CPU *cpu, int nr, unsigned char *buf, int len) 229{ 230 if (nr >= GPR0_REGNUM 231 && nr < (GPR0_REGNUM + NR_GPR) 232 && len == 4) 233 { 234 *((unsigned32*)buf) = 235 H2T_4 (iq2000bf_h_gr_get (cpu, nr - GPR0_REGNUM)); 236 return 4; 237 } 238 else if (nr == PC_REGNUM 239 && len == 4) 240 { 241 *((unsigned32*)buf) = H2T_4 (get_h_pc (cpu)); 242 return 4; 243 } 244 else 245 return 0; 246} 247 248int 249iq2000bf_store_register (SIM_CPU *cpu, int nr, unsigned char *buf, int len) 250{ 251 if (nr >= GPR0_REGNUM 252 && nr < (GPR0_REGNUM + NR_GPR) 253 && len == 4) 254 { 255 iq2000bf_h_gr_set (cpu, nr - GPR0_REGNUM, T2H_4 (*((unsigned32*)buf))); 256 return 4; 257 } 258 else if (nr == PC_REGNUM 259 && len == 4) 260 { 261 set_h_pc (cpu, T2H_4 (*((unsigned32*)buf))); 262 return 4; 263 } 264 else 265 return 0; 266} 267