1 /* IQ2000 simulator support code 2 Copyright (C) 2000-2023 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 /* This must come before any other includes. */ 21 #include "defs.h" 22 23 #define WANT_CPU 24 #define WANT_CPU_IQ2000BF 25 26 #include "sim-main.h" 27 #include "sim-signal.h" 28 #include "cgen-mem.h" 29 #include "cgen-ops.h" 30 #include "target-newlib-syscall.h" 31 #include <stdlib.h> 32 33 enum 34 { 35 GPR0_REGNUM = 0, 36 NR_GPR = 32, 37 PC_REGNUM = 32 38 }; 39 40 /* Read a null terminated string from memory, return in a buffer */ 41 static char * 42 fetch_str (SIM_CPU *current_cpu, PCADDR pc, DI addr) 43 { 44 char *buf; 45 int nr = 0; 46 while (sim_core_read_1 (current_cpu, 47 pc, read_map, CPU2DATA(addr + nr)) != 0) 48 nr++; 49 buf = NZALLOC (char, nr + 1); 50 sim_read (CPU_STATE (current_cpu), CPU2DATA(addr), buf, nr); 51 return buf; 52 } 53 54 void 55 do_syscall (SIM_CPU *current_cpu, PCADDR pc) 56 { 57 #if 0 58 int syscall = H2T_4 (iq2000bf_h_gr_get (current_cpu, 11)); 59 #endif 60 int syscall_function = iq2000bf_h_gr_get (current_cpu, 4); 61 int i; 62 char *buf; 63 int PARM1 = iq2000bf_h_gr_get (current_cpu, 5); 64 int PARM2 = iq2000bf_h_gr_get (current_cpu, 6); 65 int PARM3 = iq2000bf_h_gr_get (current_cpu, 7); 66 const int ret_reg = 2; 67 68 switch (syscall_function) 69 { 70 case 0: 71 switch (H2T_4 (iq2000bf_h_gr_get (current_cpu, 11))) 72 { 73 case 0: 74 /* Pass. */ 75 puts ("pass"); 76 exit (0); 77 case 1: 78 /* Fail. */ 79 puts ("fail"); 80 exit (1); 81 } 82 83 case TARGET_NEWLIB_SYS_write: 84 buf = zalloc (PARM3); 85 sim_read (CPU_STATE (current_cpu), CPU2DATA(PARM2), buf, PARM3); 86 SET_H_GR (ret_reg, 87 sim_io_write (CPU_STATE (current_cpu), 88 PARM1, buf, PARM3)); 89 free (buf); 90 break; 91 92 case TARGET_NEWLIB_SYS_lseek: 93 SET_H_GR (ret_reg, 94 sim_io_lseek (CPU_STATE (current_cpu), 95 PARM1, PARM2, PARM3)); 96 break; 97 98 case TARGET_NEWLIB_SYS_exit: 99 sim_engine_halt (CPU_STATE (current_cpu), current_cpu, 100 NULL, pc, sim_exited, PARM1); 101 break; 102 103 case TARGET_NEWLIB_SYS_read: 104 buf = zalloc (PARM3); 105 SET_H_GR (ret_reg, 106 sim_io_read (CPU_STATE (current_cpu), 107 PARM1, buf, PARM3)); 108 sim_write (CPU_STATE (current_cpu), CPU2DATA(PARM2), 109 (unsigned char *) buf, PARM3); 110 free (buf); 111 break; 112 113 case TARGET_NEWLIB_SYS_open: 114 buf = fetch_str (current_cpu, pc, PARM1); 115 SET_H_GR (ret_reg, 116 sim_io_open (CPU_STATE (current_cpu), 117 buf, PARM2)); 118 free (buf); 119 break; 120 121 case TARGET_NEWLIB_SYS_close: 122 SET_H_GR (ret_reg, 123 sim_io_close (CPU_STATE (current_cpu), PARM1)); 124 break; 125 126 case TARGET_NEWLIB_SYS_time: 127 SET_H_GR (ret_reg, time (0)); 128 break; 129 130 default: 131 SET_H_GR (ret_reg, -1); 132 } 133 } 134 135 void 136 do_break (SIM_CPU *current_cpu, PCADDR pc) 137 { 138 SIM_DESC sd = CPU_STATE (current_cpu); 139 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP); 140 } 141 142 /* The semantic code invokes this for invalid (unrecognized) instructions. */ 143 144 SEM_PC 145 sim_engine_invalid_insn (SIM_CPU *current_cpu, IADDR cia, SEM_PC vpc) 146 { 147 SIM_DESC sd = CPU_STATE (current_cpu); 148 sim_engine_halt (sd, current_cpu, NULL, cia, sim_stopped, SIM_SIGILL); 149 150 return vpc; 151 } 152 153 154 /* Process an address exception. */ 155 156 void 157 iq2000_core_signal (SIM_DESC sd, SIM_CPU *current_cpu, sim_cia cia, 158 unsigned int map, int nr_bytes, address_word addr, 159 transfer_type transfer, sim_core_signals sig) 160 { 161 sim_core_signal (sd, current_cpu, cia, map, nr_bytes, addr, 162 transfer, sig); 163 } 164 165 166 /* Initialize cycle counting for an insn. 167 FIRST_P is non-zero if this is the first insn in a set of parallel 168 insns. */ 169 170 void 171 iq2000bf_model_insn_before (SIM_CPU *cpu, int first_p) 172 { 173 /* Do nothing. */ 174 } 175 176 177 /* Record the cycles computed for an insn. 178 LAST_P is non-zero if this is the last insn in a set of parallel insns, 179 and we update the total cycle count. 180 CYCLES is the cycle count of the insn. */ 181 182 void 183 iq2000bf_model_insn_after(SIM_CPU *cpu, int last_p, int cycles) 184 { 185 /* Do nothing. */ 186 } 187 188 189 int 190 iq2000bf_model_iq2000_u_exec (SIM_CPU *cpu, const IDESC *idesc, 191 int unit_num, int referenced) 192 { 193 return idesc->timing->units[unit_num].done; 194 } 195 196 PCADDR 197 get_h_pc (SIM_CPU *cpu) 198 { 199 return CPU_CGEN_HW(cpu)->h_pc; 200 } 201 202 void 203 set_h_pc (SIM_CPU *cpu, PCADDR addr) 204 { 205 CPU_CGEN_HW(cpu)->h_pc = addr | IQ2000_INSN_MASK; 206 } 207 208 int 209 iq2000bf_fetch_register (SIM_CPU *cpu, int nr, void *buf, int len) 210 { 211 if (nr >= GPR0_REGNUM 212 && nr < (GPR0_REGNUM + NR_GPR) 213 && len == 4) 214 { 215 *((uint32_t*)buf) = 216 H2T_4 (iq2000bf_h_gr_get (cpu, nr - GPR0_REGNUM)); 217 return 4; 218 } 219 else if (nr == PC_REGNUM 220 && len == 4) 221 { 222 *((uint32_t*)buf) = H2T_4 (get_h_pc (cpu)); 223 return 4; 224 } 225 else 226 return 0; 227 } 228 229 int 230 iq2000bf_store_register (SIM_CPU *cpu, int nr, const void *buf, int len) 231 { 232 if (nr >= GPR0_REGNUM 233 && nr < (GPR0_REGNUM + NR_GPR) 234 && len == 4) 235 { 236 iq2000bf_h_gr_set (cpu, nr - GPR0_REGNUM, T2H_4 (*((uint32_t*)buf))); 237 return 4; 238 } 239 else if (nr == PC_REGNUM 240 && len == 4) 241 { 242 set_h_pc (cpu, T2H_4 (*((uint32_t*)buf))); 243 return 4; 244 } 245 else 246 return 0; 247 } 248