📄 spim.c
字号:
return (0); case REDO_CMD: return (1); case NOP_CMD: prev_cmd = NOP_CMD; return (0); case HELP_CMD: if (!redo) flush_to_newline (); write_output (message_out, "\nSPIM is a MIPS R2000 simulator.\n"); write_output (message_out, "Its top-level commands are:\n"); write_output (message_out, "exit -- Exit the simulator\n"); write_output (message_out, "quit -- Exit the simulator\n"); write_output (message_out, "read \"FILE\" -- Read FILE of assembly code into memory\n"); write_output (message_out, "load \"FILE\" -- Same as read\n"); write_output (message_out, "run <ADDR> -- Start the program at optional ADDRESS\n"); write_output (message_out, "step <N> -- Step the program for N instructions\n"); write_output (message_out, "continue -- Continue program execution without stepping\n"); write_output (message_out, "print $N -- Print register N\n"); write_output (message_out, "print $fN -- Print floating point register N\n"); write_output (message_out, "print ADDR -- Print contents of memory at ADDRESS\n"); write_output (message_out, "print_symbols -- Print all global symbols\n"); write_output (message_out, "print_all_regs -- Print all MIPS registers\n"); write_output (message_out, "print_all_regs hex -- Print all MIPS registers in hex\n"); write_output (message_out, "reinitialize -- Clear the memory and registers\n"); write_output (message_out, "breakpoint <ADDR> -- Set a breakpoint at address\n"); write_output (message_out, "delete <ADDR> -- Delete all breakpoints at address\n"); write_output (message_out, "list -- List all breakpoints\n"); write_output (message_out, "dump [ \"FILE\" ] -- Dump binary code to spim.dump or FILE in network byte order\n"); write_output (message_out, "dumpnative [ \"FILE\" ] -- Dump binary code to spim.dump or FILE in host byte order\n"); write_output (message_out, ". -- Rest of line is assembly instruction to put in memory\n"); write_output (message_out, "<cr> -- Newline reexecutes previous command\n"); write_output (message_out, "? -- Print this message\n"); write_output (message_out, "\nMost commands can be abbreviated to their unique prefix\n"); write_output (message_out, "e.g., ex(it), re(ad), l(oad), ru(n), s(tep), p(rint)\n\n"); prev_cmd = HELP_CMD; return (0); case SET_BKPT_CMD: case DELETE_BKPT_CMD: { int token = (redo ? prev_token : read_token ()); static mem_addr addr; if (!redo) flush_to_newline (); if (token == Y_INT) addr = redo ? addr + 4 : (mem_addr)yylval.i; else if (token == Y_ID) addr = redo ? addr + 4 : find_symbol_address ((char *) yylval.p); else error ("Must supply an address for breakpoint\n"); if (cmd == SET_BKPT_CMD) add_breakpoint (addr); else delete_breakpoint (addr); prev_cmd = cmd; return (0); } case LIST_BKPT_CMD: if (!redo) flush_to_newline (); list_breakpoints (); prev_cmd = LIST_BKPT_CMD; return (0); case DUMPNATIVE_TEXT_CMD: case DUMP_TEXT_CMD: { FILE *fp = NULL; char *filename = NULL; int token = (redo ? prev_token : read_token ()); int i; int words = 0; int dump_start; int dump_limit; if (token == Y_STR) filename = (char *) yylval.p; else if (token == Y_NL) filename = "spim.dump"; else { fprintf (stderr, "usage: %s [ \"filename\" ]\n", (cmd == DUMP_TEXT_CMD ? "dump" : "dumpnative")); return (0); } fp = fopen (filename, "wb"); if (fp == NULL) { perror (filename); return (0); } dump_start = find_symbol_address (END_OF_TRAP_HANDLER_SYMBOL); if (dump_start != 0) dump_start -= TEXT_BOT; dump_start = dump_start >> 2; user_kernel_text_segment (0); dump_limit = (current_text_pc() - TEXT_BOT) >> 2; for (i = dump_start; i < dump_limit; i++) { int32 code = inst_encode (text_seg[i]); if (cmd == DUMP_TEXT_CMD) code = (int32)htonl ((unsigned long)code); /* dump in network byte order */ (void)fwrite (&code, 1, sizeof(code), fp); words++; } fclose (fp); fprintf (stderr, "Dumped %d words starting at 0x%08x to file %s\n", words, (unsigned int)((dump_start << 2) + TEXT_BOT), filename); } prev_cmd = cmd; return (0); default: while (read_token () != Y_NL) ; error ("Unknown spim command\n"); return (0); }}/* Read a SPIM command with the scanner and return its ennuemerated value. */static intread_assembly_command (){ int token = read_token (); if (token == Y_NL) /* Blank line means redo */ return (REDO_CMD); else if (token != Y_ID) /* Better be a string */ return (UNKNOWN_CMD); else if (str_prefix ((char *) yylval.p, "exit", 2)) return (EXIT_CMD); else if (str_prefix ((char *) yylval.p, "quit", 2)) return (EXIT_CMD); else if (str_prefix ((char *) yylval.p, "print", 1)) return (PRINT_CMD); else if (str_prefix ((char *) yylval.p, "print_symbols", 7)) return (PRINT_SYM_CMD); else if (str_prefix ((char *) yylval.p, "print_all_regs", 7)) return (PRINT_ALL_REGS_CMD); else if (str_prefix ((char *) yylval.p, "run", 2)) return (RUN_CMD); else if (str_prefix ((char *) yylval.p, "read", 2)) return (READ_CMD); else if (str_prefix ((char *) yylval.p, "load", 2)) return (READ_CMD); else if (str_prefix ((char *) yylval.p, "reinitialize", 6)) return (REINITIALIZE_CMD); else if (str_prefix ((char *) yylval.p, "step", 1)) return (STEP_CMD); else if (str_prefix ((char *) yylval.p, "help", 1)) return (HELP_CMD); else if (str_prefix ((char *) yylval.p, "continue", 1)) return (CONTINUE_CMD); else if (str_prefix ((char *) yylval.p, "breakpoint", 2)) return (SET_BKPT_CMD); else if (str_prefix ((char *) yylval.p, "delete", 1)) return (DELETE_BKPT_CMD); else if (str_prefix ((char *) yylval.p, "list", 2)) return (LIST_BKPT_CMD); else if (str_prefix ((char *) yylval.p, "dumpnative", 5)) return (DUMPNATIVE_TEXT_CMD); else if (str_prefix ((char *) yylval.p, "dump", 4)) return (DUMP_TEXT_CMD); else if (*(char *) yylval.p == '?') return (HELP_CMD); else if (*(char *) yylval.p == '.') return (ASM_CMD); else return (UNKNOWN_CMD);}/* Return non-nil if STRING1 is a (proper) prefix of STRING2. */static intstr_prefix (char *s1, char *s2, int min_match){ for ( ; *s1 == *s2 && *s1 != '\0'; s1 ++, s2 ++) min_match --; return (*s1 == '\0' && min_match <= 0);}/* Read and return an integer from the current line of input. If the line doesn't contain an integer, return 0. In either case, flush the rest of the line, including the newline. */static intget_opt_int (){ int token; if ((token = read_token ()) == Y_INT) { flush_to_newline (); return (yylval.i); } else if (token == Y_NL) return (0); else { flush_to_newline (); return (0); }}/* Flush the rest of the input line up to and including the next newline. */static voidflush_to_newline (){ while (read_token () != Y_NL) ;}/* Print register number N. Return non-zero if register N was valid register string. */static intprint_reg (int reg_no){ write_output (message_out, "Reg %d = 0x%08x (%d)\n", reg_no, R[reg_no], R[reg_no]); return (1);}static intprint_fp_reg (int reg_no){ if ((reg_no & 1) == 0) write_output (message_out, "FP reg %d = %g (double)\n", reg_no, FPR_D (reg_no)); write_output (message_out, "FP reg %d = %g (single)\n", reg_no, FPR_S (reg_no)); return (1);}static intprint_reg_from_string (char* reg_num){ char s[100]; char *s1 = s; /* Conver to lower case */ while (*reg_num != '\0' && s1 - s < 100) *s1++ = tolower (*reg_num++); *s1 = '\0'; /* Drop leading $ */ if (s[0] == '$') s1 = s + 1; else s1 = s; if (streq (s1, "pc")) write_output (message_out, "PC = 0x%08x (%d)\n", PC, PC); else if (streq (s1, "hi")) write_output (message_out, "HI = 0x%08x (%d)\n", HI, HI); else if (streq (s1, "lo")) write_output (message_out, "LO = 0x%08x (%d)\n", LO, LO); else if (streq (s1, "fpcond")) write_output (message_out, "FCSR = 0x%08x (%d)\n", FCSR, FCSR); else if (streq (s1, "cause")) write_output (message_out, "Cause = 0x%08x (%d)\n", CP0_Cause, CP0_Cause); else if (streq (s1, "epc")) write_output (message_out, "EPC = 0x%08x (%d)\n", CP0_EPC, CP0_EPC); else if (streq (s1, "status")) write_output (message_out, "Status = 0x%08x (%d)\n", CP0_Status, CP0_Status); else if (streq (s1, "badvaddr")) write_output (message_out, "BadVAddr = 0x%08x (%d)\n", CP0_BadVAddr, CP0_BadVAddr); else return (0); return (1);}static voidprint_all_regs (int hex_flag){ static str_stream ss; ss_clear (&ss); format_registers (&ss, hex_flag, hex_flag); write_output (message_out, "%s\n", ss_to_string (&ss));}/* Print an error message. */voiderror (char *fmt, ...){ va_list args; va_start (args, fmt);#ifdef NO_VFPRINTF _doprnt (fmt, args, stderr);#else vfprintf (stderr, fmt, args);#endif va_end (args);}/* Print the error message then exit. */voidfatal_error (char *fmt, ...){ va_list args; va_start (args, fmt); fmt = va_arg (args, char *);#ifdef NO_VFPRINTF _doprnt (fmt, args, stderr);#else vfprintf (stderr, fmt, args);#endif exit (-1);}/* Print an error message and return to top level. */voidrun_error (char *fmt, ...){ va_list args; va_start (args, fmt); console_to_spim ();#ifdef NO_VFPRINTF _doprnt (fmt, args, stderr);#else vfprintf (stderr, fmt, args);#endif va_end (args); longjmp (spim_top_level_env, 1);}/* IO facilities: */voidwrite_output (port fp, char *fmt, ...){ va_list args; FILE *f; int restore_console_to_program = 0; va_start (args, fmt); f = fp.f; if (console_state_saved) { restore_console_to_program = 1; console_to_spim (); } if (f != 0) {#ifdef NO_VFPRINTF _doprnt (fmt, args, f);#else vfprintf (f, fmt, args);#endif fflush (f); } else {#ifdef NO_VFPRINTF _doprnt (fmt, args, stdout);#else vfprintf (stdout, fmt, args);#endif fflush (stdout); } va_end (args); if (restore_console_to_program) console_to_program ();}/* Simulate the semantics of fgets (not gets) on Unix file. */voidread_input (char *str, int str_size){ char *ptr; int restore_console_to_program = 0; if (console_state_saved) { restore_console_to_program = 1; console_to_spim (); } ptr = str; while (1 < str_size) /* Reserve space for null */ { char buf[1]; read ((int) console_in.i, buf, 1); /* Not in raw mode! */ *ptr ++ = buf[0]; str_size -= 1; if (buf[0] == '\n') break; } if (0 < str_size) *ptr = '\0'; /* Null terminate input */ if (restore_console_to_program) console_to_program ();}/* Give the console to the program for IO. */static voidconsole_to_program (){ if (mapped_io && !console_state_saved) {#ifdef USE_TERMIOS struct termios params; tcgetattr (console_in.i, &saved_console_state); params = saved_console_state; params.c_iflag &= ~(ISTRIP|INLCR|ICRNL|IGNCR|IXON|IXOFF|INPCK|BRKINT|PARMRK); /* Translate CR -> NL to canonicalize input. */ params.c_iflag |= IGNBRK|IGNPAR|ICRNL; params.c_oflag = OPOST|ONLCR; params.c_cflag &= ~PARENB; params.c_cflag |= CREAD|CS8; params.c_lflag = 0; params.c_cc[VMIN] = 1; params.c_cc[VTIME] = 1; tcsetattr (console_in.i, TCSANOW, ¶ms);#else int flags; ioctl ((int) console_in.i, TIOCGETP, (char *) &saved_console_state); flags = saved_console_state.sg_flags; saved_console_state.sg_flags = (flags | RAW) & ~(CRMOD|ECHO); ioctl ((int) console_in.i, TIOCSETP, (char *) &saved_console_state); saved_console_state.sg_flags = flags;#endif console_state_saved = 1; }}/* Return the console to SPIM. */static voidconsole_to_spim (){ if (mapped_io && console_state_saved)#ifdef USE_TERMIOS tcsetattr (console_in.i, TCSANOW, &saved_console_state);#else ioctl ((int) console_in.i, TIOCSETP, (char *) &saved_console_state);#endif console_state_saved = 0;}intconsole_input_available (){ fd_set fdset; struct timeval timeout; if (mapped_io) { timeout.tv_sec = 0; timeout.tv_usec = 0; FD_ZERO (&fdset); FD_SET ((int) console_in.i, &fdset); return (select (sizeof (fdset) * 8, &fdset, NULL, NULL, &timeout)); } else return (0);}charget_console_char (){ char buf; read ((int) console_in.i, &buf, 1); if (buf == 3) /* ^C */ control_c_seen (0); return (buf);}voidput_console_char (char c){ putc (c, console_out.f); fflush (console_out.f);}static intread_token (){ int token = yylex (); if (token == 0) /* End of file */ { console_to_spim (); exit (0); } else { return (token); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -