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