UNPKG

@specy/mips

Version:

The MARS mips interpreter in JS

420 lines (418 loc) 12.1 kB
type JsInstructionToken = { sourceLine: number; sourceColumn: number; originalSourceLine: number; value: string; type: string; }; declare enum DialogType { ERROR_MESSAGE = 0, INFORMATION_MESSAGE = 1, WARNING_MESSAGE = 2, QUESTION_MESSAGE = 3 } declare enum ConfirmResult { YES = 0, NO = 1, CANCEL = 2 } type HandlerMap = { openFile: { in: [filename: string, flags: number, append: boolean]; out: number; }; closeFile: { in: [fileDescriptor: number]; out: void; }; writeFile: { in: [fileDescriptor: number, buffer: number[]]; out: void; }; readFile: { in: [fileDescriptor: number, destination: number[], length: number]; out: number; }; confirm: { in: [message: string]; out: ConfirmResult; }; inputDialog: { in: [message: string]; out: string; }; outputDialog: { in: [message: string, type: DialogType]; out: void; }; askDouble: { in: [message: string]; out: number; }; askFloat: { in: [message: string]; out: number; }; askInt: { in: [message: string]; out: number; }; askString: { in: [message: string]; out: string; }; readDouble: { in: []; out: number; }; readFloat: { in: []; out: number; }; readInt: { in: []; out: number; }; readString: { in: []; out: string; }; readChar: { in: []; out: string; }; logLine: { in: [message: string]; out: void; }; log: { in: [message: string]; out: void; }; printChar: { in: [c: string]; out: void; }; printDouble: { in: [d: number]; out: void; }; printFloat: { in: [f: number]; out: void; }; printInt: { in: [i: number]; out: void; }; printString: { in: [l: string]; out: void; }; sleep: { in: [milliseconds: number]; out: void; }; stdIn: { in: [buffer: number[], length: number]; out: void; }; stdOut: { in: [buffer: number[]]; out: void; }; }; type JsInstruction = { name: string; example: string; description: string; tokens: JsInstructionToken[]; }; type MipsTokenizedLine = { line: string; tokens: JsInstructionToken[]; }; type MIPSAssembleError = { isWarning: boolean; message: string; macroExpansionHistory: string; filename: string; lineNumber: number; columnNumber: number; }; type MIPSAssembleResult = { report: string; errors: MIPSAssembleError[]; hasErrors: boolean; }; declare class MIPS { static makeMipsFromSource: typeof makeMipsfromSource; static initializeMIPS: typeof initializeMIPS; static getInstructionSet(): JsInstruction[]; } type JsMipsStackFrame = { /** * The program counter value at the moment the stack frame was created. */ pc: number; /** * The address of the target instruction. */ toAddress: number; /** * The stack pointer value at the moment the stack frame was created. */ sp: number; /** * The frame pointer value at the moment the stack frame was created. */ fp: number; /** * The values of all registers at the moment the stack frame was created. */ registers: number[]; }; /** * Represents a statement in the assembled program. */ interface JsProgramStatement { /** * The line number in the original source code. */ readonly sourceLine: number; /** * The memory address of the instruction. */ readonly address: number; /** * The binary representation of the instruction. */ readonly binaryStatement: number; /** * The original source code line. */ readonly source: string; /** * The machine code representation of the instruction. */ readonly machineStatement: string; /** * The assembly representation of the instruction. */ readonly assemblyStatement: string; } /** * Enum representing the types of "undo" actions. */ declare enum BackStepAction { MEMORY_RESTORE_RAW_WORD = 0, MEMORY_RESTORE_WORD = 1, MEMORY_RESTORE_HALF = 2, MEMORY_RESTORE_BYTE = 3, REGISTER_RESTORE = 4, PC_RESTORE = 5, COPROC0_REGISTER_RESTORE = 6, COPROC1_REGISTER_RESTORE = 7, COPROC1_CONDITION_CLEAR = 8, COPROC1_CONDITION_SET = 9, DO_NOTHING = 10 } /** * Represents a back step in the simulation undo stack. */ interface JsBackStep { /** * The action performed (e.g., register write, memory write). */ readonly action: BackStepAction; /** * Information about the action */ readonly param1: number; /** * Information about the action */ readonly param2: number; /** * The program counter value before the action. */ readonly pc: number; } /** * All MIPS register names. */ type RegisterName = '$zero' | '$at' | '$v0' | '$v1' | '$a0' | '$a1' | '$a2' | '$a3' | '$t0' | '$t1' | '$t2' | '$t3' | '$t4' | '$t5' | '$t6' | '$t7' | '$s0' | '$s1' | '$s2' | '$s3' | '$s4' | '$s5' | '$s6' | '$s7' | '$t8' | '$t9' | '$k0' | '$k1' | '$gp' | '$sp' | '$fp' | '$ra'; type HandlerName = keyof HandlerMap; type HandlerMapFns = { [K in HandlerName]: (...args: HandlerMap[K]['in']) => HandlerMap[K]['out']; }; declare function registerHandlers(mips: JsMips, handlers: HandlerMapFns): void; declare function unimplementedHandler(name: HandlerName): () => never; /** * Interface for interacting with a MIPS simulator. */ interface JsMips { /** * Assembles the program. */ assemble(): MIPSAssembleResult; /** * Initializes the simulator. * @param startAtMain If true, starts execution at the 'main' label. Otherwise, starts at the first instruction. */ initialize(startAtMain: boolean): void; /** * Executes a single instruction. * @returns True if the execution is complete, false otherwise. */ step(): boolean; /** * Gets the 8 condition flags. */ getConditionFlags(): number[]; /** * Sets the size of the undo stack, must be called before assembling the program. * @param size */ setUndoSize(size: number): void; /** * Undoes the last instruction executed. */ undo(): void; /** * Gets the statement at the given address. * @param address */ getStatementAtAddress(address: number): JsProgramStatement; /** * Gets the statement at the given source line. * @param line */ getStatementAtSourceLine(line: number): JsProgramStatement; getTokenizedLines(): MipsTokenizedLine[]; /** * Checks if the simulation can be undone. * @returns True if the simulation can be undone, false otherwise. * */ canUndo: boolean; /** * Gets the call stack. * @returns An array of memory addresses representing the call stack. */ getCallStack(): JsMipsStackFrame[]; /** * Gets the compiled statements. * @returns An array of `JsProgramStatement` objects representing the compiled program. */ getCompiledStatements(): JsProgramStatement[]; getParsedStatements(): JsInstructionToken[]; getHi(): number; getLo(): number; /** * Gets the label at the given address. * @param address The memory address. * @returns The label at the given address, or null if no label is found. */ getLabelAtAddress(address: number): string | null; /** * Sets whether the undo feature is enabled. * @param enabled True to enable the undo feature, false to disable it. */ setUndoEnabled(enabled: boolean): void; /** * Simulates the program for a limited number of instructions. * @param limit The maximum number of instructions to execute. * @returns True if the execution is complete, false otherwise. */ simulateWithLimit(limit: number): boolean; /** * Simulates the program until a breakpoint is reached. * @param breakpoints An array of memory addresses where the simulation should pause. * @returns True if the execution is complete, false otherwise. */ simulateWithBreakpoints(breakpoints: number[]): boolean; /** * Simulates the program with both breakpoints and a limit. * @param breakpoints An array of memory addresses where the simulation should pause. * @param limit The maximum number of instructions to execute. * @returns True if the execution is complete, false otherwise. */ simulateWithBreakpointsAndLimit(breakpoints: number[], limit: number): boolean; /** * Gets the value of a register. * @param register The name of the register. * @returns The value of the register. */ getRegisterValue(register: RegisterName): number; /** * Registers a handler function for a specific event or condition. * @param name The name of the event or condition. * @param handler The handler function to be called when the event occurs. The function signature depends on the event name. */ registerHandler<T extends HandlerName>(name: T, handler: (...args: HandlerMap[T]['in']) => HandlerMap[T]['out']): void; /** * Gets the current value of the stack pointer. * @returns The value of the stack pointer. */ stackPointer: number; /** * Gets the current value of the program counter. * @returns The value of the program counter. */ programCounter: number; /** * Gets the values of all registers. * @returns An array containing the register values. The order of the values is implementation defined. */ getRegistersValues(): number[]; /** * Gets the undo stack. * @returns An array of `JsBackStep` objects representing the history of the simulation. */ getUndoStack(): JsBackStep[]; /** * Reads a sequence of bytes from memory. * @param address The starting memory address. * @param length The number of bytes to read. * @returns An array of bytes read from memory. */ readMemoryBytes(address: number, length: number): number[]; /** * Writes a sequence of bytes to memory. * @param address The starting memory address. * @param bytes An array of bytes to write to memory. */ setMemoryBytes(address: number, bytes: number[]): void; /** * Gets the index of the current statement in the assembled program. * @returns The index of the current statement. */ getCurrentStatementIndex(): number; /** * Gets the next statement to be executed. * @returns The next `JsProgramStatement`. */ getNextStatement(): JsProgramStatement; /** * Sets the value of a register. * @param register The name of the register. * @param value The value to set the register to. */ setRegisterValue(register: RegisterName, value: number): void; /** * Checks if the simulation has terminated. * @returns True if the simulation has terminated, false otherwise. */ terminated: boolean; } /** * Creates a new MIPS simulator from the given source code. * @param source The source code to assemble. * @returns A new `JsMips` object. */ declare function makeMipsfromSource(source: string): JsMips; /** * Initializes the MIPS simulator. */ declare function initializeMIPS(): void; export { BackStepAction, ConfirmResult, DialogType, type HandlerMap, type HandlerMapFns, type JsBackStep, type JsInstruction, type JsInstructionToken, type JsMips, type JsMipsStackFrame, type JsProgramStatement, MIPS, type MIPSAssembleError, type MIPSAssembleResult, type MipsTokenizedLine, type RegisterName, registerHandlers, unimplementedHandler };