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