1 1.1.1.4 christos /* This file is part of SIS (SPARC instruction simulator) 2 1.1.1.4 christos 3 1.1.1.11 christos Copyright (C) 1995-2025 Free Software Foundation, Inc. 4 1.1.1.4 christos Contributed by Jiri Gaisler, European Space Agency 5 1.1.1.4 christos 6 1.1.1.4 christos This program is free software; you can redistribute it and/or modify 7 1.1.1.4 christos it under the terms of the GNU General Public License as published by 8 1.1.1.4 christos the Free Software Foundation; either version 3 of the License, or 9 1.1.1.4 christos (at your option) any later version. 10 1.1.1.4 christos 11 1.1.1.4 christos This program is distributed in the hope that it will be useful, 12 1.1.1.4 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 13 1.1.1.4 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 1.1.1.4 christos GNU General Public License for more details. 15 1.1.1.4 christos 16 1.1.1.4 christos You should have received a copy of the GNU General Public License 17 1.1.1.4 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 18 1.1 christos 19 1.1.1.9 christos /* This must come before any other includes. */ 20 1.1.1.9 christos #include "defs.h" 21 1.1.1.9 christos 22 1.1 christos #include <signal.h> 23 1.1 christos #include <string.h> 24 1.1 christos #include <stdlib.h> 25 1.1 christos #include <stdio.h> 26 1.1 christos #include <sys/fcntl.h> 27 1.1 christos #include "sis.h" 28 1.1 christos #include <dis-asm.h> 29 1.1 christos #include "sim-config.h" 30 1.1.1.4 christos #include <inttypes.h> 31 1.1 christos 32 1.1 christos #define VAL(x) strtol(x,(char **)NULL,0) 33 1.1 christos 34 1.1 christos /* Structures and functions from readline library */ 35 1.1 christos 36 1.1.1.4 christos #include "readline/readline.h" 37 1.1.1.4 christos #include "readline/history.h" 38 1.1 christos 39 1.1 christos /* Command history buffer length - MUST be binary */ 40 1.1 christos #define HIST_LEN 64 41 1.1 christos 42 1.1 christos extern struct disassemble_info dinfo; 43 1.1 christos extern struct pstate sregs; 44 1.1 christos extern struct estate ebase; 45 1.1 christos 46 1.1 christos extern int ctrl_c; 47 1.1 christos extern int nfp; 48 1.1 christos extern int ift; 49 1.1 christos extern int wrp; 50 1.1 christos extern int rom8; 51 1.1 christos extern int uben; 52 1.1 christos extern int sis_verbose; 53 1.1 christos extern char *sis_version; 54 1.1 christos extern struct estate ebase; 55 1.1 christos extern struct evcell evbuf[]; 56 1.1 christos extern struct irqcell irqarr[]; 57 1.1 christos extern int irqpend, ext_irl; 58 1.1 christos extern int termsave; 59 1.1 christos extern int sparclite; 60 1.1 christos extern int dumbio; 61 1.1 christos extern char uart_dev1[]; 62 1.1 christos extern char uart_dev2[]; 63 1.1.1.9 christos extern uint32_t last_load_addr; 64 1.1 christos 65 1.1 christos #ifdef ERA 66 1.1 christos extern int era; 67 1.1 christos #endif 68 1.1 christos 69 1.1 christos int 70 1.1.1.9 christos run_sim(struct pstate *sregs, uint64_t icount, int dis) 71 1.1 christos { 72 1.1.1.4 christos int irq, mexc, deb; 73 1.1 christos 74 1.1.1.4 christos sregs->starttime = get_time(); 75 1.1 christos init_stdio(); 76 1.1 christos if (sregs->err_mode) icount = 0; 77 1.1 christos deb = dis || sregs->histlen || sregs->bptnum; 78 1.1 christos irq = 0; 79 1.1 christos while (icount > 0) { 80 1.1 christos 81 1.1.1.4 christos mexc = memory_iread (sregs->pc, &sregs->inst, &sregs->hold); 82 1.1 christos sregs->icnt = 1; 83 1.1 christos if (sregs->annul) { 84 1.1 christos sregs->annul = 0; 85 1.1 christos sregs->pc = sregs->npc; 86 1.1 christos sregs->npc = sregs->npc + 4; 87 1.1 christos } else { 88 1.1 christos sregs->fhold = 0; 89 1.1 christos if (ext_irl) irq = check_interrupts(sregs); 90 1.1 christos if (!irq) { 91 1.1 christos if (mexc) { 92 1.1 christos sregs->trap = I_ACC_EXC; 93 1.1 christos } else { 94 1.1 christos if (deb) { 95 1.1 christos if ((sregs->bphit = check_bpt(sregs)) != 0) { 96 1.1 christos restore_stdio(); 97 1.1.1.4 christos return BPT_HIT; 98 1.1 christos } 99 1.1 christos if (sregs->histlen) { 100 1.1 christos sregs->histbuf[sregs->histind].addr = sregs->pc; 101 1.1 christos sregs->histbuf[sregs->histind].time = ebase.simtime; 102 1.1 christos sregs->histind++; 103 1.1 christos if (sregs->histind >= sregs->histlen) 104 1.1 christos sregs->histind = 0; 105 1.1 christos } 106 1.1 christos if (dis) { 107 1.1.1.4 christos printf(" %8" PRIu64 " ", ebase.simtime); 108 1.1 christos dis_mem(sregs->pc, 1, &dinfo); 109 1.1 christos } 110 1.1 christos } 111 1.1 christos dispatch_instruction(sregs); 112 1.1 christos icount--; 113 1.1 christos } 114 1.1 christos } 115 1.1 christos if (sregs->trap) { 116 1.1 christos irq = 0; 117 1.1 christos sregs->err_mode = execute_trap(sregs); 118 1.1 christos if (sregs->err_mode) { 119 1.1 christos error_mode(sregs->pc); 120 1.1 christos icount = 0; 121 1.1 christos } 122 1.1 christos } 123 1.1 christos } 124 1.1 christos advance_time(sregs); 125 1.1 christos if (ctrl_c || (sregs->tlimit <= ebase.simtime)) { 126 1.1 christos icount = 0; 127 1.1 christos if (sregs->tlimit <= ebase.simtime) sregs->tlimit = -1; 128 1.1 christos } 129 1.1 christos } 130 1.1.1.4 christos sregs->tottime += get_time() - sregs->starttime; 131 1.1 christos restore_stdio(); 132 1.1 christos if (sregs->err_mode) 133 1.1.1.4 christos return ERROR; 134 1.1 christos if (ctrl_c) { 135 1.1 christos ctrl_c = 0; 136 1.1.1.4 christos return CTRL_C; 137 1.1 christos } 138 1.1.1.4 christos return TIME_OUT; 139 1.1 christos } 140 1.1 christos 141 1.1.1.9 christos static int ATTRIBUTE_PRINTF (3, 4) 142 1.1.1.9 christos fprintf_styled (void *stream, enum disassembler_style style, 143 1.1.1.9 christos const char *fmt, ...) 144 1.1.1.9 christos { 145 1.1.1.9 christos int ret; 146 1.1.1.9 christos FILE *out = (FILE *) stream; 147 1.1.1.9 christos va_list args; 148 1.1.1.9 christos 149 1.1.1.9 christos va_start (args, fmt); 150 1.1.1.9 christos ret = vfprintf (out, fmt, args); 151 1.1.1.9 christos va_end (args); 152 1.1.1.9 christos 153 1.1.1.9 christos return ret; 154 1.1.1.9 christos } 155 1.1.1.9 christos 156 1.1 christos int 157 1.1.1.9 christos main(int argc, char **argv) 158 1.1 christos { 159 1.1 christos 160 1.1 christos int cont = 1; 161 1.1 christos int stat = 1; 162 1.1 christos int freq = 14; 163 1.1 christos int copt = 0; 164 1.1 christos 165 1.1 christos char *cfile, *bacmd; 166 1.1 christos char *cmdq[HIST_LEN]; 167 1.1 christos int cmdi = 0; 168 1.1 christos int i; 169 1.1.1.4 christos int lfile = 0; 170 1.1 christos 171 1.1 christos cfile = 0; 172 1.1 christos for (i = 0; i < 64; i++) 173 1.1 christos cmdq[i] = 0; 174 1.1 christos printf("\n SIS - SPARC instruction simulator %s, copyright Jiri Gaisler 1995\n", sis_version); 175 1.1 christos printf(" Bug-reports to jgais (at) wd.estec.esa.nl\n\n"); 176 1.1 christos while (stat < argc) { 177 1.1 christos if (argv[stat][0] == '-') { 178 1.1 christos if (strcmp(argv[stat], "-v") == 0) { 179 1.1.1.4 christos sis_verbose += 1; 180 1.1 christos } else if (strcmp(argv[stat], "-c") == 0) { 181 1.1 christos if ((stat + 1) < argc) { 182 1.1 christos copt = 1; 183 1.1 christos cfile = argv[++stat]; 184 1.1 christos } 185 1.1 christos } else if (strcmp(argv[stat], "-nfp") == 0) 186 1.1 christos nfp = 1; 187 1.1 christos else if (strcmp(argv[stat], "-ift") == 0) 188 1.1 christos ift = 1; 189 1.1 christos else if (strcmp(argv[stat], "-wrp") == 0) 190 1.1 christos wrp = 1; 191 1.1 christos else if (strcmp(argv[stat], "-rom8") == 0) 192 1.1 christos rom8 = 1; 193 1.1 christos else if (strcmp(argv[stat], "-uben") == 0) 194 1.1 christos uben = 1; 195 1.1 christos else if (strcmp(argv[stat], "-uart1") == 0) { 196 1.1 christos if ((stat + 1) < argc) 197 1.1 christos strcpy(uart_dev1, argv[++stat]); 198 1.1 christos } else if (strcmp(argv[stat], "-uart2") == 0) { 199 1.1 christos if ((stat + 1) < argc) 200 1.1 christos strcpy(uart_dev2, argv[++stat]); 201 1.1 christos } else if (strcmp(argv[stat], "-freq") == 0) { 202 1.1 christos if ((stat + 1) < argc) 203 1.1 christos freq = VAL(argv[++stat]); 204 1.1 christos } else if (strcmp(argv[stat], "-sparclite") == 0) { 205 1.1 christos sparclite = 1; 206 1.1 christos #ifdef ERA 207 1.1 christos } else if (strcmp(argv[stat], "-era") == 0) { 208 1.1 christos era = 1; 209 1.1 christos #endif 210 1.1 christos } else if (strcmp(argv[stat], "-dumbio") == 0) { 211 1.1 christos dumbio = 1; 212 1.1 christos } else { 213 1.1 christos printf("unknown option %s\n", argv[stat]); 214 1.1 christos usage(); 215 1.1 christos exit(1); 216 1.1 christos } 217 1.1 christos } else { 218 1.1.1.4 christos lfile = stat; 219 1.1 christos } 220 1.1 christos stat++; 221 1.1 christos } 222 1.1 christos if (nfp) 223 1.1 christos printf("FPU disabled\n"); 224 1.1 christos #ifdef ERA 225 1.1 christos if (era) 226 1.1 christos printf("ERA ECC emulation enabled\n"); 227 1.1 christos #endif 228 1.1 christos sregs.freq = freq; 229 1.1 christos 230 1.1.1.9 christos INIT_DISASSEMBLE_INFO(dinfo, stdout, (fprintf_ftype) fprintf, 231 1.1.1.9 christos (fprintf_styled_ftype) fprintf_styled); 232 1.1.1.4 christos #ifdef HOST_LITTLE_ENDIAN 233 1.1.1.4 christos dinfo.endian = BFD_ENDIAN_LITTLE; 234 1.1.1.4 christos #else 235 1.1 christos dinfo.endian = BFD_ENDIAN_BIG; 236 1.1.1.4 christos #endif 237 1.1 christos 238 1.1.1.9 christos #ifdef F_GETFL 239 1.1 christos termsave = fcntl(0, F_GETFL, 0); 240 1.1.1.9 christos #endif 241 1.1 christos using_history(); 242 1.1 christos init_signals(); 243 1.1 christos ebase.simtime = 0; 244 1.1 christos reset_all(); 245 1.1 christos init_bpt(&sregs); 246 1.1 christos init_sim(); 247 1.1.1.4 christos if (lfile) 248 1.1.1.4 christos last_load_addr = bfd_load(argv[lfile]); 249 1.1 christos #ifdef STAT 250 1.1 christos reset_stat(&sregs); 251 1.1 christos #endif 252 1.1 christos 253 1.1 christos if (copt) { 254 1.1 christos bacmd = (char *) malloc(256); 255 1.1 christos strcpy(bacmd, "batch "); 256 1.1 christos strcat(bacmd, cfile); 257 1.1 christos exec_cmd(&sregs, bacmd); 258 1.1 christos } 259 1.1 christos while (cont) { 260 1.1 christos 261 1.1 christos if (cmdq[cmdi] != 0) { 262 1.1 christos #if 0 263 1.1 christos remove_history(cmdq[cmdi]); 264 1.1 christos #else 265 1.1 christos remove_history(cmdi); 266 1.1 christos #endif 267 1.1 christos free(cmdq[cmdi]); 268 1.1 christos cmdq[cmdi] = 0; 269 1.1 christos } 270 1.1 christos cmdq[cmdi] = readline("sis> "); 271 1.1 christos if (cmdq[cmdi] && *cmdq[cmdi]) 272 1.1 christos add_history(cmdq[cmdi]); 273 1.1 christos if (cmdq[cmdi]) 274 1.1 christos stat = exec_cmd(&sregs, cmdq[cmdi]); 275 1.1 christos else { 276 1.1 christos puts("\n"); 277 1.1 christos exit(0); 278 1.1 christos } 279 1.1 christos switch (stat) { 280 1.1 christos case OK: 281 1.1 christos break; 282 1.1 christos case CTRL_C: 283 1.1 christos printf("\b\bInterrupt!\n"); 284 1.1.1.10 christos ATTRIBUTE_FALLTHROUGH; 285 1.1 christos case TIME_OUT: 286 1.1.1.4 christos printf(" Stopped at time %" PRIu64 " (%.3f ms)\n", ebase.simtime, 287 1.1 christos ((double) ebase.simtime / (double) sregs.freq) / 1000.0); 288 1.1 christos break; 289 1.1 christos case BPT_HIT: 290 1.1 christos printf("breakpoint at 0x%08x reached\n", sregs.pc); 291 1.1 christos sregs.bphit = 1; 292 1.1 christos break; 293 1.1 christos case ERROR: 294 1.1 christos printf("IU in error mode (%d)\n", sregs.trap); 295 1.1 christos stat = 0; 296 1.1.1.4 christos printf(" %8" PRIu64 " ", ebase.simtime); 297 1.1 christos dis_mem(sregs.pc, 1, &dinfo); 298 1.1 christos break; 299 1.1 christos default: 300 1.1 christos break; 301 1.1 christos } 302 1.1 christos ctrl_c = 0; 303 1.1 christos stat = OK; 304 1.1 christos 305 1.1 christos cmdi = (cmdi + 1) & (HIST_LEN - 1); 306 1.1 christos 307 1.1 christos } 308 1.1 christos return 0; 309 1.1 christos } 310 1.1 christos 311