1139749Simp/* This file is part of SIS (SPARC instruction simulator) 274429Sorion 374429Sorion Copyright (C) 1995-2023 Free Software Foundation, Inc. 474429Sorion Contributed by Jiri Gaisler, European Space Agency 574429Sorion 674429Sorion This program is free software; you can redistribute it and/or modify 774429Sorion it under the terms of the GNU General Public License as published by 874429Sorion the Free Software Foundation; either version 3 of the License, or 974429Sorion (at your option) any later version. 1074429Sorion 1174429Sorion This program is distributed in the hope that it will be useful, 1274429Sorion but WITHOUT ANY WARRANTY; without even the implied warranty of 1374429Sorion MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1474429Sorion GNU General Public License for more details. 1574429Sorion 1674429Sorion You should have received a copy of the GNU General Public License 1774429Sorion along with this program. If not, see <http://www.gnu.org/licenses/>. */ 1874429Sorion 1974429Sorion/* This must come before any other includes. */ 2074429Sorion#include "defs.h" 2174429Sorion 2274429Sorion#include <signal.h> 2374429Sorion#include <string.h> 2474429Sorion#include <stdlib.h> 25192919Sjoel#include <stdio.h> 26192919Sjoel#include <sys/fcntl.h> 27192919Sjoel#include "sis.h" 2874429Sorion#include <dis-asm.h> 2974429Sorion#include "sim-config.h" 3074429Sorion#include <inttypes.h> 3182180Scg 3274429Sorion#define VAL(x) strtol(x,(char **)NULL,0) 33193640Sariff 34193640Sariff/* Structures and functions from readline library */ 35193640Sariff 36193640Sariff#include "readline/readline.h" 3774429Sorion#include "readline/history.h" 3874429Sorion 3974429Sorion/* Command history buffer length - MUST be binary */ 40119287Simp#define HIST_LEN 64 41119287Simp 4274429Sorionextern struct disassemble_info dinfo; 4374429Sorionextern struct pstate sregs; 4474429Sorionextern struct estate ebase; 4582180Scg 4682180Scgextern int ctrl_c; 4774429Sorionextern int nfp; 4874429Sorionextern int ift; 4974429Sorionextern int wrp; 5074429Sorionextern int rom8; 5184771Sorionextern int uben; 5284771Sorionextern int sis_verbose; 5374429Sorionextern char *sis_version; 5474429Sorionextern struct estate ebase; 5574429Sorionextern struct evcell evbuf[]; 5674429Sorionextern struct irqcell irqarr[]; 5774429Sorionextern int irqpend, ext_irl; 5874429Sorionextern int termsave; 5974429Sorionextern int sparclite; 6074429Sorionextern int dumbio; 6174429Sorionextern char uart_dev1[]; 6274429Sorionextern char uart_dev2[]; 6374429Sorionextern uint32_t last_load_addr; 6474429Sorion 6574429Sorion#ifdef ERA 6674763Scgextern int era; 6774763Scg#endif 6874571Sorion 6974429Sorionint 7074429Sorionrun_sim(struct pstate *sregs, uint64_t icount, int dis) 7174429Sorion{ 7274429Sorion int irq, mexc, deb; 7374429Sorion 7474429Sorion sregs->starttime = get_time(); 7574429Sorion init_stdio(); 7674429Sorion if (sregs->err_mode) icount = 0; 7774429Sorion deb = dis || sregs->histlen || sregs->bptnum; 7874429Sorion irq = 0; 7974429Sorion while (icount > 0) { 8074429Sorion 8174429Sorion mexc = memory_iread (sregs->pc, &sregs->inst, &sregs->hold); 8274429Sorion sregs->icnt = 1; 8374429Sorion if (sregs->annul) { 8474429Sorion sregs->annul = 0; 8574429Sorion sregs->pc = sregs->npc; 8674429Sorion sregs->npc = sregs->npc + 4; 8774429Sorion } else { 8874429Sorion sregs->fhold = 0; 8974429Sorion if (ext_irl) irq = check_interrupts(sregs); 9074429Sorion if (!irq) { 9174429Sorion if (mexc) { 9274429Sorion sregs->trap = I_ACC_EXC; 9374429Sorion } else { 9474429Sorion if (deb) { 9574429Sorion if ((sregs->bphit = check_bpt(sregs)) != 0) { 9674429Sorion restore_stdio(); 9774429Sorion return BPT_HIT; 9884771Sorion } 9984771Sorion if (sregs->histlen) { 10084771Sorion sregs->histbuf[sregs->histind].addr = sregs->pc; 10174429Sorion sregs->histbuf[sregs->histind].time = ebase.simtime; 10274429Sorion sregs->histind++; 10374429Sorion if (sregs->histind >= sregs->histlen) 10474429Sorion sregs->histind = 0; 10574429Sorion } 106193640Sariff if (dis) { 107193640Sariff printf(" %8" PRIu64 " ", ebase.simtime); 108193640Sariff dis_mem(sregs->pc, 1, &dinfo); 109193640Sariff } 11074429Sorion } 11174429Sorion dispatch_instruction(sregs); 11274429Sorion icount--; 11374763Scg } 11474429Sorion } 11574429Sorion if (sregs->trap) { 11674429Sorion irq = 0; 11774429Sorion sregs->err_mode = execute_trap(sregs); 11874429Sorion if (sregs->err_mode) { 11974429Sorion error_mode(sregs->pc); 12074429Sorion icount = 0; 12174797Scg } 12274429Sorion } 12374429Sorion } 12474429Sorion advance_time(sregs); 12574429Sorion if (ctrl_c || (sregs->tlimit <= ebase.simtime)) { 12674429Sorion icount = 0; 12774797Scg if (sregs->tlimit <= ebase.simtime) sregs->tlimit = -1; 12874429Sorion } 12974429Sorion } 13074429Sorion sregs->tottime += get_time() - sregs->starttime; 13174429Sorion restore_stdio(); 13274429Sorion if (sregs->err_mode) 13374429Sorion return ERROR; 13474429Sorion if (ctrl_c) { 13574429Sorion ctrl_c = 0; 13674429Sorion return CTRL_C; 13774429Sorion } 13874429Sorion return TIME_OUT; 13974797Scg} 14074429Sorion 14174797Scgstatic int ATTRIBUTE_PRINTF (3, 4) 14274429Sorionfprintf_styled (void *stream, enum disassembler_style style, 14374429Sorion const char *fmt, ...) 14474429Sorion{ 14574429Sorion int ret; 14674429Sorion FILE *out = (FILE *) stream; 14774429Sorion va_list args; 14874429Sorion 14974429Sorion va_start (args, fmt); 15074429Sorion ret = vfprintf (out, fmt, args); 15174797Scg va_end (args); 15274429Sorion 15374797Scg return ret; 15474429Sorion} 15574429Sorion 15674429Sorionint 15774429Sorionmain(int argc, char **argv) 15874429Sorion{ 15974429Sorion 16074429Sorion int cont = 1; 16174429Sorion int stat = 1; 16274429Sorion int freq = 14; 16374429Sorion int copt = 0; 16474429Sorion 16574429Sorion char *cfile, *bacmd; 16674429Sorion char *cmdq[HIST_LEN]; 16774429Sorion int cmdi = 0; 16874429Sorion int i; 16974797Scg int lfile = 0; 17074797Scg 17174429Sorion cfile = 0; 17274429Sorion for (i = 0; i < 64; i++) 17374429Sorion cmdq[i] = 0; 17474429Sorion printf("\n SIS - SPARC instruction simulator %s, copyright Jiri Gaisler 1995\n", sis_version); 17574429Sorion printf(" Bug-reports to jgais@wd.estec.esa.nl\n\n"); 17674429Sorion while (stat < argc) { 17774429Sorion if (argv[stat][0] == '-') { 17874429Sorion if (strcmp(argv[stat], "-v") == 0) { 17974429Sorion sis_verbose += 1; 18074429Sorion } else if (strcmp(argv[stat], "-c") == 0) { 18174429Sorion if ((stat + 1) < argc) { 18274429Sorion copt = 1; 18374429Sorion cfile = argv[++stat]; 18474429Sorion } 18574429Sorion } else if (strcmp(argv[stat], "-nfp") == 0) 18674429Sorion nfp = 1; 18774429Sorion else if (strcmp(argv[stat], "-ift") == 0) 18874429Sorion ift = 1; 18974429Sorion else if (strcmp(argv[stat], "-wrp") == 0) 19074429Sorion wrp = 1; 19174763Scg else if (strcmp(argv[stat], "-rom8") == 0) 19274429Sorion rom8 = 1; 19374429Sorion else if (strcmp(argv[stat], "-uben") == 0) 19474429Sorion uben = 1; 19574797Scg else if (strcmp(argv[stat], "-uart1") == 0) { 19674429Sorion if ((stat + 1) < argc) 19774429Sorion strcpy(uart_dev1, argv[++stat]); 19874429Sorion } else if (strcmp(argv[stat], "-uart2") == 0) { 19974429Sorion if ((stat + 1) < argc) 20074429Sorion strcpy(uart_dev2, argv[++stat]); 201168847Sariff } else if (strcmp(argv[stat], "-freq") == 0) { 20274429Sorion if ((stat + 1) < argc) 20374429Sorion freq = VAL(argv[++stat]); 20474429Sorion } else if (strcmp(argv[stat], "-sparclite") == 0) { 20574429Sorion sparclite = 1; 206193640Sariff#ifdef ERA 20774429Sorion } else if (strcmp(argv[stat], "-era") == 0) { 20874429Sorion era = 1; 20974429Sorion#endif 21074429Sorion } else if (strcmp(argv[stat], "-dumbio") == 0) { 21174429Sorion dumbio = 1; 21274429Sorion } else { 21374763Scg printf("unknown option %s\n", argv[stat]); 21474429Sorion usage(); 21574429Sorion exit(1); 21674429Sorion } 21774429Sorion } else { 21874429Sorion lfile = stat; 219193640Sariff } 22074429Sorion stat++; 22174429Sorion } 22274429Sorion if (nfp) 22384771Sorion printf("FPU disabled\n"); 22474429Sorion#ifdef ERA 22574429Sorion if (era) 22684771Sorion printf("ERA ECC emulation enabled\n"); 22774429Sorion#endif 22874429Sorion sregs.freq = freq; 22982835Sorion 23074429Sorion INIT_DISASSEMBLE_INFO(dinfo, stdout, (fprintf_ftype) fprintf, 23174429Sorion (fprintf_styled_ftype) fprintf_styled); 23274429Sorion#ifdef HOST_LITTLE_ENDIAN 23374429Sorion dinfo.endian = BFD_ENDIAN_LITTLE; 23474429Sorion#else 23574429Sorion dinfo.endian = BFD_ENDIAN_BIG; 23674429Sorion#endif 23774429Sorion 238193640Sariff#ifdef F_GETFL 23974429Sorion termsave = fcntl(0, F_GETFL, 0); 24074429Sorion#endif 24174429Sorion using_history(); 24274429Sorion init_signals(); 243193640Sariff ebase.simtime = 0; 24474429Sorion reset_all(); 24574429Sorion init_bpt(&sregs); 24674429Sorion init_sim(); 24774429Sorion if (lfile) 24874429Sorion last_load_addr = bfd_load(argv[lfile]); 24974429Sorion#ifdef STAT 25074429Sorion reset_stat(&sregs); 25174429Sorion#endif 25274429Sorion 25374429Sorion if (copt) { 25474429Sorion bacmd = (char *) malloc(256); 25574797Scg strcpy(bacmd, "batch "); 25674429Sorion strcat(bacmd, cfile); 25774429Sorion exec_cmd(&sregs, bacmd); 25874429Sorion } 25974429Sorion while (cont) { 26074429Sorion 26174429Sorion if (cmdq[cmdi] != 0) { 26274429Sorion#if 0 26374429Sorion remove_history(cmdq[cmdi]); 26474429Sorion#else 26574429Sorion remove_history(cmdi); 26674429Sorion#endif 26774429Sorion free(cmdq[cmdi]); 26874429Sorion cmdq[cmdi] = 0; 26974429Sorion } 27074429Sorion cmdq[cmdi] = readline("sis> "); 27174429Sorion if (cmdq[cmdi] && *cmdq[cmdi]) 27274429Sorion add_history(cmdq[cmdi]); 27374429Sorion if (cmdq[cmdi]) 27474429Sorion stat = exec_cmd(&sregs, cmdq[cmdi]); 27574429Sorion else { 27674429Sorion puts("\n"); 27774429Sorion exit(0); 27874429Sorion } 27974429Sorion switch (stat) { 28074797Scg case OK: 28174429Sorion break; 28274429Sorion case CTRL_C: 28374429Sorion printf("\b\bInterrupt!\n"); 28474429Sorion case TIME_OUT: 28574797Scg printf(" Stopped at time %" PRIu64 " (%.3f ms)\n", ebase.simtime, 28674429Sorion ((double) ebase.simtime / (double) sregs.freq) / 1000.0); 28774429Sorion break; 28874429Sorion case BPT_HIT: 28974429Sorion printf("breakpoint at 0x%08x reached\n", sregs.pc); 29074429Sorion sregs.bphit = 1; 29174429Sorion break; 29274429Sorion case ERROR: 29374429Sorion printf("IU in error mode (%d)\n", sregs.trap); 29474429Sorion stat = 0; 29574429Sorion printf(" %8" PRIu64 " ", ebase.simtime); 29674429Sorion dis_mem(sregs.pc, 1, &dinfo); 29774429Sorion break; 29874429Sorion default: 29974429Sorion break; 30074429Sorion } 30174429Sorion ctrl_c = 0; 30274429Sorion stat = OK; 30374797Scg 30474429Sorion cmdi = (cmdi + 1) & (HIST_LEN - 1); 30574429Sorion 30674429Sorion } 30774429Sorion return 0; 30874429Sorion} 30974429Sorion 31074429Sorion